Domain Create Modal anpassen Fehler auf Null
parent
33abdc7c7f
commit
0730f53a72
|
|
@ -0,0 +1,52 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Jobs;
|
||||||
|
|
||||||
|
use App\Models\Domain;
|
||||||
|
use App\Models\DkimKey;
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Foundation\Bus\Dispatchable;
|
||||||
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
|
||||||
|
class InstallDkimKey implements ShouldQueue
|
||||||
|
{
|
||||||
|
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
public int $domainId,
|
||||||
|
public int $dkimKeyId,
|
||||||
|
public string $privPath,
|
||||||
|
public string $dnsTxtContent,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public function handle(): void
|
||||||
|
{
|
||||||
|
$domain = Domain::findOrFail($this->domainId);
|
||||||
|
$dk = DkimKey::findOrFail($this->dkimKeyId);
|
||||||
|
|
||||||
|
$domainName = $domain->domain; // z.B. example.com
|
||||||
|
$selector = $dk->selector; // z.B. mwl1
|
||||||
|
|
||||||
|
// TXT temporär für Helper speichern (optional, damit /etc/mailwolt/dns gefüllt wird)
|
||||||
|
$tmpTxt = tempnam(sys_get_temp_dir(), 'dkim_txt_');
|
||||||
|
file_put_contents($tmpTxt, $this->dnsTxtContent);
|
||||||
|
|
||||||
|
// Root-Helper aufrufen (sudoers hast du im Installer angelegt)
|
||||||
|
$cmd = sprintf(
|
||||||
|
'sudo /usr/local/sbin/mailwolt-install-dkim %s %s %s %s',
|
||||||
|
escapeshellarg($domainName),
|
||||||
|
escapeshellarg($selector),
|
||||||
|
escapeshellarg($this->privPath),
|
||||||
|
escapeshellarg($tmpTxt)
|
||||||
|
);
|
||||||
|
|
||||||
|
exec($cmd, $out, $rc);
|
||||||
|
@unlink($tmpTxt);
|
||||||
|
|
||||||
|
if ($rc !== 0) {
|
||||||
|
throw new \RuntimeException("mailwolt-install-dkim failed (rc={$rc})");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Jobs;
|
||||||
|
|
||||||
|
use App\Models\Domain;
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Foundation\Bus\Dispatchable;
|
||||||
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
|
||||||
|
class RemoveDkimKey implements ShouldQueue
|
||||||
|
{
|
||||||
|
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
public int $domainId,
|
||||||
|
public string $selector
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public function handle(): void
|
||||||
|
{
|
||||||
|
$domain = Domain::withTrashed()->findOrFail($this->domainId);
|
||||||
|
|
||||||
|
$cmd = sprintf(
|
||||||
|
'sudo /usr/local/sbin/mailwolt-remove-dkim %s %s',
|
||||||
|
escapeshellarg($domain->domain),
|
||||||
|
escapeshellarg($this->selector)
|
||||||
|
);
|
||||||
|
|
||||||
|
exec($cmd, $out, $rc);
|
||||||
|
if ($rc !== 0) {
|
||||||
|
throw new \RuntimeException("mailwolt-remove-dkim failed (rc={$rc})");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
namespace App\Livewire\Ui\Domain\Modal;
|
namespace App\Livewire\Ui\Domain\Modal;
|
||||||
|
|
||||||
|
use App\Jobs\InstallDkimKey;
|
||||||
use App\Models\DkimKey;
|
use App\Models\DkimKey;
|
||||||
use App\Models\Domain;
|
use App\Models\Domain;
|
||||||
use App\Models\Setting;
|
use App\Models\Setting;
|
||||||
|
|
@ -271,7 +272,7 @@ class DomainCreateModal extends ModalComponent
|
||||||
// DKIM + DNS
|
// DKIM + DNS
|
||||||
$dkim = app(DkimService::class)->generateForDomain($domain, $this->dkim_bits, $this->dkim_selector);
|
$dkim = app(DkimService::class)->generateForDomain($domain, $this->dkim_bits, $this->dkim_selector);
|
||||||
|
|
||||||
DkimKey::create([
|
$dk = DkimKey::create([
|
||||||
'domain_id' => $domain->id,
|
'domain_id' => $domain->id,
|
||||||
'selector' => $dkim['selector'],
|
'selector' => $dkim['selector'],
|
||||||
'private_key_pem' => $dkim['private_pem'],
|
'private_key_pem' => $dkim['private_pem'],
|
||||||
|
|
@ -279,6 +280,13 @@ class DomainCreateModal extends ModalComponent
|
||||||
'is_active' => true,
|
'is_active' => true,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
dispatch(new InstallDkimKey(
|
||||||
|
domainId: $domain->id,
|
||||||
|
dkimKeyId: $dk->id,
|
||||||
|
privPath: $dkim['priv_path'],
|
||||||
|
dnsTxtContent: $dkim['dns_txt']
|
||||||
|
));
|
||||||
|
|
||||||
app(DnsRecordService::class)->provision(
|
app(DnsRecordService::class)->provision(
|
||||||
$domain,
|
$domain,
|
||||||
$dkim['selector'] ?? null,
|
$dkim['selector'] ?? null,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Observers;
|
||||||
|
|
||||||
|
use App\Jobs\InstallDkimKey;
|
||||||
|
use App\Jobs\RemoveDkimKey;
|
||||||
|
use App\Models\DkimKey;
|
||||||
|
use App\Models\Domain;
|
||||||
|
use App\Services\DkimService;
|
||||||
|
|
||||||
|
class DomainObserver
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* DKIM bei neuen Domains erzeugen + in OpenDKIM installieren.
|
||||||
|
* Läuft NUR, wenn die Domain aktiv ist (anpassbar).
|
||||||
|
*/
|
||||||
|
public function created(Domain $domain): void
|
||||||
|
{
|
||||||
|
// Standardwerte aus Config oder .env
|
||||||
|
$selector = config('mailwolt.dkim.selector', 'mwl1');
|
||||||
|
$bits = (int) config('mailwolt.dkim.bits', 2048);
|
||||||
|
|
||||||
|
// Keypair erzeugen
|
||||||
|
$res = app(DkimService::class)->generateForDomain(
|
||||||
|
domainId: $domain,
|
||||||
|
bits: $bits,
|
||||||
|
selector: $selector
|
||||||
|
);
|
||||||
|
|
||||||
|
// In dkim_keys speichern
|
||||||
|
$dk = DkimKey::create([
|
||||||
|
'domain_id' => $domain->id,
|
||||||
|
'selector' => $res['selector'],
|
||||||
|
'private_key_pem' => $res['private_pem'],
|
||||||
|
'public_key_txt' => preg_replace('/^v=DKIM1; k=rsa; p=/', '', $res['dns_txt']),
|
||||||
|
'is_active' => true,
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Helper-Job zum Installieren starten
|
||||||
|
InstallDkimKey::dispatch(
|
||||||
|
domainId: $domain->id,
|
||||||
|
dkimKeyId: $dk->id,
|
||||||
|
privPath: $res['priv_path'],
|
||||||
|
dnsTxtContent: $res['dns_txt']
|
||||||
|
)->afterCommit();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Beim Löschen alle DKIM-Selector dieser Domain aus OpenDKIM entfernen.
|
||||||
|
*/
|
||||||
|
public function deleted(Domain $domain): void
|
||||||
|
{
|
||||||
|
// Falls SoftDeletes im Spiel, willst du evtl. forceDeleted spiegeln (s.u.)
|
||||||
|
foreach ($domain->dkimKeys()->get() as $dk) {
|
||||||
|
RemoveDkimKey::dispatch(
|
||||||
|
domainId: $domain->id,
|
||||||
|
selector: $dk->selector
|
||||||
|
)->afterCommit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function forceDeleted(Domain $domain): void
|
||||||
|
{
|
||||||
|
$this->deleted($domain);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
namespace App\Providers;
|
namespace App\Providers;
|
||||||
|
|
||||||
|
use App\Models\Domain;
|
||||||
|
use App\Observers\DomainObserver;
|
||||||
use App\Support\SettingsRepository;
|
use App\Support\SettingsRepository;
|
||||||
use Illuminate\Support\Facades\URL;
|
use Illuminate\Support\Facades\URL;
|
||||||
use Illuminate\Support\ServiceProvider;
|
use Illuminate\Support\ServiceProvider;
|
||||||
|
|
@ -21,6 +23,9 @@ class AppServiceProvider extends ServiceProvider
|
||||||
*/
|
*/
|
||||||
public function boot(\App\Support\SettingsRepository $settings): void
|
public function boot(\App\Support\SettingsRepository $settings): void
|
||||||
{
|
{
|
||||||
|
|
||||||
|
Domain::observe(DomainObserver::class);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$S = app(\App\Support\SettingsRepository::class);
|
$S = app(\App\Support\SettingsRepository::class);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -54,9 +54,6 @@ class DkimService
|
||||||
throw new \RuntimeException("DKIM: Public-Key schreiben fehlgeschlagen: {$pubRel}");
|
throw new \RuntimeException("DKIM: Public-Key schreiben fehlgeschlagen: {$pubRel}");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4) DNS-Record bauen
|
|
||||||
// $p = preg_replace('/-----BEGIN PUBLIC KEY-----|-----END PUBLIC KEY-----|\s+/', '', $publicKeyPem);
|
|
||||||
// $dnsTxt = "v=DKIM1; k=rsa; p={$p}";
|
|
||||||
|
|
||||||
$publicKeyBase64 = self::extractPublicKeyBase64($publicKeyPem);
|
$publicKeyBase64 = self::extractPublicKeyBase64($publicKeyPem);
|
||||||
Log::debug('dkim.p.len', ['len' => strlen($publicKeyBase64)]);
|
Log::debug('dkim.p.len', ['len' => strlen($publicKeyBase64)]);
|
||||||
|
|
|
||||||
|
|
@ -4,4 +4,10 @@ return [
|
||||||
'base_domain' => env('BASE_DOMAIN', 'example.com'),
|
'base_domain' => env('BASE_DOMAIN', 'example.com'),
|
||||||
'sysmail_sub' => env('SYSMAIL_SUB', 'sysmail'),
|
'sysmail_sub' => env('SYSMAIL_SUB', 'sysmail'),
|
||||||
'dkim_selector' => env('DKIM_SELECTOR', 'mwl1'),
|
'dkim_selector' => env('DKIM_SELECTOR', 'mwl1'),
|
||||||
|
|
||||||
|
'dkim' => [
|
||||||
|
'selector' => env('DKIM_SELECTOR', 'mwl1'),
|
||||||
|
'bits' => (int) env('DKIM_BITS', 2048),
|
||||||
|
],
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue