Domain Create Modal anpassen Fehler auf Null
parent
50202b5245
commit
5d15a757b3
|
|
@ -112,7 +112,7 @@ class Wizard extends Component
|
||||||
$user->name = $this->form_admin_name;
|
$user->name = $this->form_admin_name;
|
||||||
$user->is_admin = true;
|
$user->is_admin = true;
|
||||||
$user->password = Hash::make($this->form_admin_password);
|
$user->password = Hash::make($this->form_admin_password);
|
||||||
$user->must_change_pw = true;
|
$user->required_change_password = true;
|
||||||
$user->save();
|
$user->save();
|
||||||
|
|
||||||
// 3) Zertifikat jetzt ausstellen (optional)
|
// 3) Zertifikat jetzt ausstellen (optional)
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,6 @@ class MailboxCreateModal extends ModalComponent
|
||||||
public int $quota_mb = 0;
|
public int $quota_mb = 0;
|
||||||
public ?int $rate_limit_per_hour = null;
|
public ?int $rate_limit_per_hour = null;
|
||||||
public bool $is_active = true;
|
public bool $is_active = true;
|
||||||
public bool $must_change_pw = true;
|
|
||||||
|
|
||||||
// Limits / Status
|
// Limits / Status
|
||||||
public ?int $limit_max_mailboxes = null;
|
public ?int $limit_max_mailboxes = null;
|
||||||
|
|
@ -85,7 +84,6 @@ class MailboxCreateModal extends ModalComponent
|
||||||
'quota_mb' => ['required', 'integer', 'min:0', 'max:' . $cap],
|
'quota_mb' => ['required', 'integer', 'min:0', 'max:' . $cap],
|
||||||
'rate_limit_per_hour' => ['nullable', 'integer', 'min:1'],
|
'rate_limit_per_hour' => ['nullable', 'integer', 'min:1'],
|
||||||
'is_active' => ['boolean'],
|
'is_active' => ['boolean'],
|
||||||
'must_change_pw' => ['boolean'],
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -256,7 +254,6 @@ class MailboxCreateModal extends ModalComponent
|
||||||
$u->password_hash = $this->password ? Hash::make($this->password) : null;
|
$u->password_hash = $this->password ? Hash::make($this->password) : null;
|
||||||
$u->is_system = false;
|
$u->is_system = false;
|
||||||
$u->is_active = (bool)$data['is_active'];
|
$u->is_active = (bool)$data['is_active'];
|
||||||
$u->must_change_pw = (bool)$data['must_change_pw'];
|
|
||||||
$u->quota_mb = (int)$data['quota_mb'];
|
$u->quota_mb = (int)$data['quota_mb'];
|
||||||
$u->rate_limit_per_hour = $data['rate_limit_per_hour'];
|
$u->rate_limit_per_hour = $data['rate_limit_per_hour'];
|
||||||
$u->save();
|
$u->save();
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,6 @@ class MailboxEditModal extends ModalComponent
|
||||||
public int $quota_mb = 0;
|
public int $quota_mb = 0;
|
||||||
public ?int $rate_limit_per_hour = null;
|
public ?int $rate_limit_per_hour = null;
|
||||||
public bool $is_active = true;
|
public bool $is_active = true;
|
||||||
public bool $must_change_pw = true;
|
|
||||||
|
|
||||||
// UI
|
// UI
|
||||||
public string $email_readonly = '';
|
public string $email_readonly = '';
|
||||||
|
|
@ -42,7 +41,6 @@ class MailboxEditModal extends ModalComponent
|
||||||
$this->quota_mb = (int)$this->mailbox->quota_mb;
|
$this->quota_mb = (int)$this->mailbox->quota_mb;
|
||||||
$this->rate_limit_per_hour = $this->mailbox->rate_limit_per_hour;
|
$this->rate_limit_per_hour = $this->mailbox->rate_limit_per_hour;
|
||||||
$this->is_active = (bool)$this->mailbox->is_active;
|
$this->is_active = (bool)$this->mailbox->is_active;
|
||||||
$this->must_change_pw = (bool)$this->mailbox->must_change_pw;
|
|
||||||
|
|
||||||
$dom = $this->mailbox->domain;
|
$dom = $this->mailbox->domain;
|
||||||
$this->email_readonly = $this->mailbox->localpart . '@' . $dom->domain;
|
$this->email_readonly = $this->mailbox->localpart . '@' . $dom->domain;
|
||||||
|
|
@ -105,7 +103,6 @@ class MailboxEditModal extends ModalComponent
|
||||||
'quota_mb' => ['required', 'integer', 'min:0', 'max:' . $cap],
|
'quota_mb' => ['required', 'integer', 'min:0', 'max:' . $cap],
|
||||||
'rate_limit_per_hour' => ['nullable', 'integer', 'min:1'],
|
'rate_limit_per_hour' => ['nullable', 'integer', 'min:1'],
|
||||||
'is_active' => ['boolean'],
|
'is_active' => ['boolean'],
|
||||||
'must_change_pw' => ['boolean'],
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -121,12 +118,10 @@ class MailboxEditModal extends ModalComponent
|
||||||
$u->display_name = $this->display_name ?: null;
|
$u->display_name = $this->display_name ?: null;
|
||||||
if (!empty($this->password)) {
|
if (!empty($this->password)) {
|
||||||
$u->password_hash = Hash::make($this->password);
|
$u->password_hash = Hash::make($this->password);
|
||||||
$u->must_change_pw = true;
|
|
||||||
}
|
}
|
||||||
$u->quota_mb = (int)$this->quota_mb;
|
$u->quota_mb = (int)$this->quota_mb;
|
||||||
$u->rate_limit_per_hour = $this->rate_limit_readonly ? $d->rate_limit_per_hour : $this->rate_limit_per_hour;
|
$u->rate_limit_per_hour = $this->rate_limit_readonly ? $d->rate_limit_per_hour : $this->rate_limit_per_hour;
|
||||||
$u->is_active = (bool)$this->is_active;
|
$u->is_active = (bool)$this->is_active;
|
||||||
$u->must_change_pw = (bool)$this->must_change_pw;
|
|
||||||
$u->save();
|
$u->save();
|
||||||
|
|
||||||
$mailbox = $u->localpart . '@' . $d->domain;
|
$mailbox = $u->localpart . '@' . $d->domain;
|
||||||
|
|
|
||||||
|
|
@ -11,14 +11,13 @@ class MailUser extends Model
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
'domain_id','localpart','email','display_name','password_hash',
|
'domain_id','localpart','email','display_name','password_hash',
|
||||||
'is_active','must_change_pw','quota_mb','is_system'
|
'is_active','quota_mb','is_system'
|
||||||
];
|
];
|
||||||
|
|
||||||
protected $hidden = ['password_hash'];
|
protected $hidden = ['password_hash'];
|
||||||
protected $casts = [
|
protected $casts = [
|
||||||
'is_active'=>'bool',
|
'is_active'=>'bool',
|
||||||
'is_system' => 'boolean',
|
'is_system' => 'boolean',
|
||||||
'must_change_pw'=>'bool',
|
|
||||||
'quota_mb'=>'int',
|
'quota_mb'=>'int',
|
||||||
'last_login_at'=>'datetime',
|
'last_login_at'=>'datetime',
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -17,9 +17,10 @@ class User extends Authenticatable
|
||||||
'name',
|
'name',
|
||||||
'username',
|
'username',
|
||||||
'email',
|
'email',
|
||||||
|
'admin_email',
|
||||||
'password',
|
'password',
|
||||||
'is_active',
|
'is_active',
|
||||||
'must_change_pw',
|
'required_change_password',
|
||||||
'role',
|
'role',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
@ -31,7 +32,7 @@ class User extends Authenticatable
|
||||||
protected $casts = [
|
protected $casts = [
|
||||||
'email_verified_at' => 'datetime',
|
'email_verified_at' => 'datetime',
|
||||||
'is_active' => 'boolean',
|
'is_active' => 'boolean',
|
||||||
'must_change_pw' => 'boolean',
|
'required_change_password' => 'boolean',
|
||||||
'role' => Role::class,
|
'role' => Role::class,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
@ -41,6 +42,19 @@ class User extends Authenticatable
|
||||||
return $this->role === Role::Admin;
|
return $this->role === Role::Admin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fallback: admin_email || email
|
||||||
|
public function getSystemNotifyEmailAttribute(): string
|
||||||
|
{
|
||||||
|
$admin = trim((string)$this->admin_email);
|
||||||
|
return filter_var($admin, FILTER_VALIDATE_EMAIL) ? $admin : $this->email;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wenn du Laravel Notifications nutzt:
|
||||||
|
public function routeNotificationForMail($notification): string
|
||||||
|
{
|
||||||
|
return $this->system_notify_email;
|
||||||
|
}
|
||||||
|
|
||||||
public function twoFactorMethods()
|
public function twoFactorMethods()
|
||||||
{
|
{
|
||||||
return $this->hasMany(\App\Models\TwoFactorMethod::class);
|
return $this->hasMany(\App\Models\TwoFactorMethod::class);
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,10 @@ class DomainObserver
|
||||||
*/
|
*/
|
||||||
public function created(Domain $domain): void
|
public function created(Domain $domain): void
|
||||||
{
|
{
|
||||||
|
if ($domain->is_server) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$selector = (string) config('mailpool.defaults.dkim_selector', 'mwl1');
|
$selector = (string) config('mailpool.defaults.dkim_selector', 'mwl1');
|
||||||
$bits = (int) config('mailpool.defaults.dkim_bits', 2048);
|
$bits = (int) config('mailpool.defaults.dkim_bits', 2048);
|
||||||
|
|
||||||
|
|
@ -51,6 +55,8 @@ class DomainObserver
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// public function created(Domain $domain): void
|
// public function created(Domain $domain): void
|
||||||
// {
|
// {
|
||||||
// // Standardwerte aus Config oder .env
|
// // Standardwerte aus Config oder .env
|
||||||
|
|
|
||||||
|
|
@ -16,10 +16,11 @@ return new class extends Migration
|
||||||
$table->string('name')->unique();
|
$table->string('name')->unique();
|
||||||
$table->string('username')->nullable()->unique();
|
$table->string('username')->nullable()->unique();
|
||||||
$table->string('email')->unique();
|
$table->string('email')->unique();
|
||||||
|
$table->string('admin_email', 255)->nullable()->index();
|
||||||
$table->timestamp('email_verified_at')->nullable();
|
$table->timestamp('email_verified_at')->nullable();
|
||||||
$table->string('password');
|
$table->string('password');
|
||||||
$table->boolean('is_active')->default(true)->index();
|
$table->boolean('is_active')->default(true)->index();
|
||||||
$table->boolean('must_change_pw')->default(true)->index();
|
$table->boolean('required_change_password')->default(false)->index();
|
||||||
$table->boolean('two_factor_enabled')->default(false);
|
$table->boolean('two_factor_enabled')->default(false);
|
||||||
$table->boolean('two_factor_email_enabled')->default(false);
|
$table->boolean('two_factor_email_enabled')->default(false);
|
||||||
$table->string('totp_secret')->nullable();
|
$table->string('totp_secret')->nullable();
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,6 @@ return new class extends Migration
|
||||||
|
|
||||||
$table->boolean('is_system')->default(false)->index(); // oft nach Systemkonten filtern
|
$table->boolean('is_system')->default(false)->index(); // oft nach Systemkonten filtern
|
||||||
$table->boolean('is_active')->default(true)->index();
|
$table->boolean('is_active')->default(true)->index();
|
||||||
$table->boolean('must_change_pw')->default(true)->index();
|
|
||||||
|
|
||||||
$table->unsignedInteger('quota_mb')->default(0); // 0 = unlimited
|
$table->unsignedInteger('quota_mb')->default(0); // 0 = unlimited
|
||||||
$table->unsignedInteger('rate_limit_per_hour')->nullable();
|
$table->unsignedInteger('rate_limit_per_hour')->nullable();
|
||||||
|
|
|
||||||
|
|
@ -1,46 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Database\Seeders;
|
|
||||||
|
|
||||||
use App\Models\User;
|
|
||||||
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
|
|
||||||
use Illuminate\Database\Seeder;
|
|
||||||
use Illuminate\Support\Facades\Hash;
|
|
||||||
use Illuminate\Support\Str;
|
|
||||||
|
|
||||||
class AdminUserSeeder extends Seeder
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Run the database seeds.
|
|
||||||
*/
|
|
||||||
public function run(): void
|
|
||||||
{
|
|
||||||
$name = env('APP_ADMIN_USER', 'mailwolt');
|
|
||||||
$email = env('APP_ADMIN_EMAIL', 'admin@localhost');
|
|
||||||
$pass = env('APP_ADMIN_PASS', 'ChangeMe'); // Wird beim ersten Login geändert
|
|
||||||
|
|
||||||
$user = User::firstOrCreate(
|
|
||||||
['email' => $email],
|
|
||||||
[
|
|
||||||
'name' => $name,
|
|
||||||
'username' => $name,
|
|
||||||
'password' => Hash::make($pass),
|
|
||||||
'is_active' => true,
|
|
||||||
'must_change_pw' => true,
|
|
||||||
'role' => 'admin',
|
|
||||||
'email_verified_at' => now(),
|
|
||||||
'remember_token' => Str::random(10),
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
// falls es den User schon gab, Flags sicher setzen
|
|
||||||
if (!$user->wasRecentlyCreated) {
|
|
||||||
$user->forceFill([
|
|
||||||
'is_active' => true,
|
|
||||||
'must_change_pw' => true,
|
|
||||||
'role' => 'admin',
|
|
||||||
])->save();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Database\Seeders;
|
|
||||||
|
|
||||||
use App\Models\User;
|
|
||||||
// use Illuminate\Database\Console\Seeds\WithoutModelEvents;
|
|
||||||
use Illuminate\Database\Seeder;
|
|
||||||
|
|
||||||
class DatabaseSeeder extends Seeder
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Seed the application's database.
|
|
||||||
*/
|
|
||||||
public function run(): void
|
|
||||||
{
|
|
||||||
// User::factory(10)->create();
|
|
||||||
|
|
||||||
User::factory()->create([
|
|
||||||
'name' => 'Test User',
|
|
||||||
'email' => 'test@example.com',
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -32,9 +32,39 @@ class SystemDomainSeeder extends Seeder
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
$serverDomain = Domain::firstOrCreate(
|
$serverDomain = Domain::firstOrCreate(
|
||||||
['domain' => $serverFqdn],
|
['domain' => $serverFqdn],
|
||||||
['is_active' => true, 'is_system' => false, 'is_server' => true]
|
[
|
||||||
|
'is_active' => true,
|
||||||
|
'is_system' => false,
|
||||||
|
'is_server' => true,
|
||||||
|
|
||||||
|
// nix anlegen unter mx.<base>
|
||||||
|
'max_mailboxes' => 0,
|
||||||
|
'max_aliases' => 0,
|
||||||
|
|
||||||
|
// Quotas praktisch sperren
|
||||||
|
'default_quota_mb' => 0,
|
||||||
|
'max_quota_per_mailbox_mb' => 0,
|
||||||
|
'total_quota_mb' => 0,
|
||||||
|
|
||||||
|
// kein Versand über diese Domain
|
||||||
|
'rate_limit_per_hour' => 0,
|
||||||
|
'rate_limit_override' => false,
|
||||||
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$serverDomain->fill([
|
||||||
|
'is_active' => true,
|
||||||
|
'is_system' => false,
|
||||||
|
'is_server' => true,
|
||||||
|
'max_mailboxes' => 0,
|
||||||
|
'max_aliases' => 0,
|
||||||
|
'default_quota_mb' => 0,
|
||||||
|
'max_quota_per_mailbox_mb' => 0,
|
||||||
|
'total_quota_mb' => 0,
|
||||||
|
'rate_limit_per_hour' => 0,
|
||||||
|
'rate_limit_override' => false,
|
||||||
|
])->save();
|
||||||
|
|
||||||
Domain::where('is_server', true)
|
Domain::where('is_server', true)
|
||||||
->where('id', '!=', $serverDomain->id)
|
->where('id', '!=', $serverDomain->id)
|
||||||
->update(['is_server' => false]);
|
->update(['is_server' => false]);
|
||||||
|
|
@ -71,8 +101,37 @@ class SystemDomainSeeder extends Seeder
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
$systemDomain = Domain::firstOrCreate(
|
$systemDomain = Domain::firstOrCreate(
|
||||||
['domain' => $systemFqdn],
|
['domain' => $systemFqdn],
|
||||||
['is_active' => true, 'is_system' => true]
|
[
|
||||||
|
'is_active' => true,
|
||||||
|
'is_system' => true,
|
||||||
|
|
||||||
|
// Limits
|
||||||
|
'max_aliases' => 20,
|
||||||
|
'max_mailboxes'=> 1,
|
||||||
|
|
||||||
|
// Quota
|
||||||
|
'default_quota_mb' => 512,
|
||||||
|
'max_quota_per_mailbox_mb' => 2048,
|
||||||
|
'total_quota_mb' => 2048,
|
||||||
|
|
||||||
|
// Rate limiting
|
||||||
|
'rate_limit_per_hour' => 600,
|
||||||
|
'rate_limit_override' => false,
|
||||||
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$systemDomain->fill([
|
||||||
|
'is_active' => true,
|
||||||
|
'is_system' => true,
|
||||||
|
'max_aliases' => 20,
|
||||||
|
'max_mailboxes' => 1,
|
||||||
|
'default_quota_mb' => 512,
|
||||||
|
'max_quota_per_mailbox_mb' => 2048,
|
||||||
|
'total_quota_mb' => 2048,
|
||||||
|
'rate_limit_per_hour' => 600,
|
||||||
|
'rate_limit_override' => false,
|
||||||
|
])->save();
|
||||||
|
|
||||||
if ($systemDomain->wasRecentlyCreated) {
|
if ($systemDomain->wasRecentlyCreated) {
|
||||||
$this->command->line("System-Domain angelegt: {$systemDomain->domain}");
|
$this->command->line("System-Domain angelegt: {$systemDomain->domain}");
|
||||||
}
|
}
|
||||||
|
|
@ -86,7 +145,6 @@ class SystemDomainSeeder extends Seeder
|
||||||
'password_hash' => null,
|
'password_hash' => null,
|
||||||
'is_active' => true,
|
'is_active' => true,
|
||||||
'is_system' => true,
|
'is_system' => true,
|
||||||
'must_change_pw' => false,
|
|
||||||
'quota_mb' => 0,
|
'quota_mb' => 0,
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -164,15 +164,15 @@
|
||||||
<span class="text-white/80 text-sm">Postfach aktivieren</span>
|
<span class="text-white/80 text-sm">Postfach aktivieren</span>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label class="inline-flex items-center gap-2 cursor-pointer select-none group">
|
{{-- <label class="inline-flex items-center gap-2 cursor-pointer select-none group">--}}
|
||||||
<input type="checkbox" wire:model="must_change_pw" class="peer sr-only">
|
{{-- <input type="checkbox" wire:model="must_change_pw" class="peer sr-only">--}}
|
||||||
<span class="w-5 h-5 flex items-center justify-center rounded-md border border-white/15 bg-white/5
|
{{-- <span class="w-5 h-5 flex items-center justify-center rounded-md border border-white/15 bg-white/5--}}
|
||||||
peer-checked:bg-sky-500/20 peer-checked:border-sky-400/40
|
{{-- peer-checked:bg-sky-500/20 peer-checked:border-sky-400/40--}}
|
||||||
group-hover:border-white/25 transition">
|
{{-- group-hover:border-white/25 transition">--}}
|
||||||
<i class="ph ph-check text-[12px] text-sky-300 opacity-0 peer-checked:opacity-100 transition"></i>
|
{{-- <i class="ph ph-check text-[12px] text-sky-300 opacity-0 peer-checked:opacity-100 transition"></i>--}}
|
||||||
</span>
|
{{-- </span>--}}
|
||||||
<span class="text-white/80 text-sm">Passwort bei erstem Login ändern</span>
|
{{-- <span class="text-white/80 text-sm">Passwort bei erstem Login ändern</span>--}}
|
||||||
</label>
|
{{-- </label>--}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue