Domain Create Modal anpassen Fehler auf Null
parent
5d15a757b3
commit
a78767809d
|
|
@ -8,8 +8,8 @@ use Illuminate\Database\Eloquent\Relations\HasMany;
|
|||
|
||||
class MailAlias extends Model
|
||||
{
|
||||
protected $fillable = ['domain_id','local','type','group_name','is_active','notes'];
|
||||
protected $casts = ['is_active' => 'bool'];
|
||||
protected $fillable = ['domain_id','local','type','group_name','is_active','is_system','notes'];
|
||||
protected $casts = ['is_active' => 'bool', 'is_system' => 'bool'];
|
||||
|
||||
public function domain(): BelongsTo
|
||||
{
|
||||
|
|
@ -18,7 +18,7 @@ class MailAlias extends Model
|
|||
|
||||
public function recipients(): HasMany
|
||||
{
|
||||
return $this->hasMany(MailAliasRecipient::class, 'alias_id');
|
||||
return $this->hasMany(MailAliasRecipient::class, 'alias_id')->orderBy('position');
|
||||
}
|
||||
|
||||
public function getAddressAttribute(): string
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ return new class extends Migration
|
|||
|
||||
$table->boolean('is_system')->default(false)->index(); // oft nach Systemkonten filtern
|
||||
$table->boolean('is_active')->default(true)->index();
|
||||
$table->boolean('can_login')->default(true)->index();
|
||||
|
||||
$table->unsignedInteger('quota_mb')->default(0); // 0 = unlimited
|
||||
$table->unsignedInteger('rate_limit_per_hour')->nullable();
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ return new class extends Migration
|
|||
$table->enum('type', ['single','group'])->default('single');
|
||||
$table->string('group_name', 80)->nullable();
|
||||
$table->boolean('is_active')->default(true)->index();
|
||||
$table->boolean('is_system')->default(false)->after('is_active')->index();
|
||||
$table->text('notes')->nullable();
|
||||
$table->timestamps();
|
||||
|
||||
|
|
|
|||
|
|
@ -13,22 +13,12 @@ return new class extends Migration
|
|||
{
|
||||
Schema::create('mail_alias_recipients', function (Blueprint $table) {
|
||||
$table->id();
|
||||
|
||||
$table->foreignId('alias_id')
|
||||
->constrained('mail_aliases')
|
||||
->cascadeOnDelete();
|
||||
|
||||
// interner Empfänger (MailUser) ODER externer Empfänger (E-Mail)
|
||||
$table->foreignId('mail_user_id')
|
||||
->nullable()
|
||||
->constrained('mail_users') // <-- richtige Tabelle!
|
||||
->nullOnDelete();
|
||||
|
||||
$table->foreignId('alias_id')->constrained('mail_aliases')->cascadeOnDelete();
|
||||
$table->foreignId('mail_user_id')->nullable()->constrained('mail_users')->nullOnDelete();
|
||||
$table->string('email', 320)->nullable(); // externer Empfänger
|
||||
$table->unsignedSmallInteger('position')->default(0);
|
||||
$table->timestamps();
|
||||
|
||||
// Duplikate vermeiden:
|
||||
$table->unique(['alias_id','mail_user_id']);
|
||||
$table->unique(['alias_id','email']);
|
||||
});
|
||||
|
|
@ -4,11 +4,15 @@ namespace Database\Seeders;
|
|||
|
||||
use App\Models\DkimKey;
|
||||
use App\Models\Domain;
|
||||
use App\Models\MailAlias;
|
||||
use App\Models\MailAliasRecipient;
|
||||
use App\Models\MailUser;
|
||||
use App\Models\TlsaRecord;
|
||||
use App\Services\DnsRecordService;
|
||||
use App\Services\TlsaService;
|
||||
use Illuminate\Database\Seeder;
|
||||
use Illuminate\Foundation\Auth\User;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class SystemDomainSeeder extends Seeder
|
||||
{
|
||||
|
|
@ -137,7 +141,7 @@ class SystemDomainSeeder extends Seeder
|
|||
}
|
||||
|
||||
// System-Absender (no-reply) – ohne Passwort (kein Login)
|
||||
MailUser::firstOrCreate(
|
||||
$noReply = MailUser::firstOrCreate(
|
||||
['email' => "no-reply@{$systemFqdn}"],
|
||||
[
|
||||
'domain_id' => $systemDomain->id,
|
||||
|
|
@ -149,35 +153,27 @@ class SystemDomainSeeder extends Seeder
|
|||
]
|
||||
);
|
||||
|
||||
// DKIM – Key erzeugen, falls keiner aktiv existiert
|
||||
if (!$systemDomain->dkimKeys()->where('is_active', true)->exists()) {
|
||||
[$privPem, $pubTxt] = $this->generateDkimKeyPair();
|
||||
$selector = 'mwl1'; // frei wählbar, später rotieren
|
||||
$seedGroup = function(string $local, array $emails) use ($systemDomain, $noReply) {
|
||||
$alias = MailAlias::updateOrCreate(
|
||||
['domain_id' => $systemDomain->id, 'local' => $local],
|
||||
['type' => 'group', 'is_active' => true, 'is_system' => true]
|
||||
);
|
||||
$alias->recipients()->delete();
|
||||
$pos=0;
|
||||
foreach ($emails as $addr) {
|
||||
MailAliasRecipient::create([
|
||||
'alias_id' => $alias->id,
|
||||
'email' => $addr,
|
||||
'position' => $pos++,
|
||||
]);
|
||||
}
|
||||
};
|
||||
|
||||
DkimKey::create([
|
||||
'domain_id' => $systemDomain->id,
|
||||
'selector' => $selector,
|
||||
'private_key_pem' => $privPem,
|
||||
'public_key_txt' => $pubTxt,
|
||||
'is_active' => true,
|
||||
]);
|
||||
|
||||
$this->command->info("DKIM angelegt: Host = {$selector}._domainkey.{$systemFqdn}");
|
||||
}
|
||||
|
||||
$dk = $systemDomain->dkimKeys()->where('is_active', true)->latest()->first();
|
||||
$dkimTxt = $dk ? "v=DKIM1; k=rsa; p={$dk->public_key_txt}" : null;
|
||||
|
||||
app(DnsRecordService::class)->provision(
|
||||
$systemDomain,
|
||||
dkimSelector: $dk?->selector,
|
||||
dkimTxt: $dkimTxt,
|
||||
opts: [
|
||||
'dmarc_policy' => 'none',
|
||||
'spf_tail' => '-all',
|
||||
// optional: 'ipv4' => $serverIp, 'ipv6' => ...
|
||||
]
|
||||
);
|
||||
// alle vier erst einmal nur ans no-reply Postfach
|
||||
$seedGroup('system', [$noReply->email]);
|
||||
$seedGroup('bounces', [$noReply->email]);
|
||||
$seedGroup('postmaster', [$noReply->email]);
|
||||
$seedGroup('abuse', [$noReply->email]);
|
||||
|
||||
$this->command->info("System-Domain '{$systemFqdn}' fertig. SPF/DMARC/DKIM & DNS-Empfehlungen eingetragen.");
|
||||
$this->printDnsHints($systemDomain);
|
||||
|
|
|
|||
Loading…
Reference in New Issue