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->is_admin = true;
|
||||
$user->password = Hash::make($this->form_admin_password);
|
||||
$user->must_change_pw = true;
|
||||
$user->required_change_password = true;
|
||||
$user->save();
|
||||
|
||||
// 3) Zertifikat jetzt ausstellen (optional)
|
||||
|
|
|
|||
|
|
@ -31,7 +31,6 @@ class MailboxCreateModal extends ModalComponent
|
|||
public int $quota_mb = 0;
|
||||
public ?int $rate_limit_per_hour = null;
|
||||
public bool $is_active = true;
|
||||
public bool $must_change_pw = true;
|
||||
|
||||
// Limits / Status
|
||||
public ?int $limit_max_mailboxes = null;
|
||||
|
|
@ -85,7 +84,6 @@ class MailboxCreateModal extends ModalComponent
|
|||
'quota_mb' => ['required', 'integer', 'min:0', 'max:' . $cap],
|
||||
'rate_limit_per_hour' => ['nullable', 'integer', 'min:1'],
|
||||
'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->is_system = false;
|
||||
$u->is_active = (bool)$data['is_active'];
|
||||
$u->must_change_pw = (bool)$data['must_change_pw'];
|
||||
$u->quota_mb = (int)$data['quota_mb'];
|
||||
$u->rate_limit_per_hour = $data['rate_limit_per_hour'];
|
||||
$u->save();
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ class MailboxEditModal extends ModalComponent
|
|||
public int $quota_mb = 0;
|
||||
public ?int $rate_limit_per_hour = null;
|
||||
public bool $is_active = true;
|
||||
public bool $must_change_pw = true;
|
||||
|
||||
// UI
|
||||
public string $email_readonly = '';
|
||||
|
|
@ -42,7 +41,6 @@ class MailboxEditModal extends ModalComponent
|
|||
$this->quota_mb = (int)$this->mailbox->quota_mb;
|
||||
$this->rate_limit_per_hour = $this->mailbox->rate_limit_per_hour;
|
||||
$this->is_active = (bool)$this->mailbox->is_active;
|
||||
$this->must_change_pw = (bool)$this->mailbox->must_change_pw;
|
||||
|
||||
$dom = $this->mailbox->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],
|
||||
'rate_limit_per_hour' => ['nullable', 'integer', 'min:1'],
|
||||
'is_active' => ['boolean'],
|
||||
'must_change_pw' => ['boolean'],
|
||||
];
|
||||
}
|
||||
|
||||
|
|
@ -121,12 +118,10 @@ class MailboxEditModal extends ModalComponent
|
|||
$u->display_name = $this->display_name ?: null;
|
||||
if (!empty($this->password)) {
|
||||
$u->password_hash = Hash::make($this->password);
|
||||
$u->must_change_pw = true;
|
||||
}
|
||||
$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->is_active = (bool)$this->is_active;
|
||||
$u->must_change_pw = (bool)$this->must_change_pw;
|
||||
$u->save();
|
||||
|
||||
$mailbox = $u->localpart . '@' . $d->domain;
|
||||
|
|
|
|||
|
|
@ -11,14 +11,13 @@ class MailUser extends Model
|
|||
|
||||
protected $fillable = [
|
||||
'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 $casts = [
|
||||
'is_active'=>'bool',
|
||||
'is_system' => 'boolean',
|
||||
'must_change_pw'=>'bool',
|
||||
'quota_mb'=>'int',
|
||||
'last_login_at'=>'datetime',
|
||||
];
|
||||
|
|
|
|||
|
|
@ -17,9 +17,10 @@ class User extends Authenticatable
|
|||
'name',
|
||||
'username',
|
||||
'email',
|
||||
'admin_email',
|
||||
'password',
|
||||
'is_active',
|
||||
'must_change_pw',
|
||||
'required_change_password',
|
||||
'role',
|
||||
];
|
||||
|
||||
|
|
@ -29,10 +30,10 @@ class User extends Authenticatable
|
|||
];
|
||||
|
||||
protected $casts = [
|
||||
'email_verified_at' => 'datetime',
|
||||
'is_active' => 'boolean',
|
||||
'must_change_pw' => 'boolean',
|
||||
'role' => Role::class,
|
||||
'email_verified_at' => 'datetime',
|
||||
'is_active' => 'boolean',
|
||||
'required_change_password' => 'boolean',
|
||||
'role' => Role::class,
|
||||
];
|
||||
|
||||
/** Quick helper: check if user is admin */
|
||||
|
|
@ -41,6 +42,19 @@ class User extends Authenticatable
|
|||
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()
|
||||
{
|
||||
return $this->hasMany(\App\Models\TwoFactorMethod::class);
|
||||
|
|
|
|||
|
|
@ -16,6 +16,10 @@ class DomainObserver
|
|||
*/
|
||||
public function created(Domain $domain): void
|
||||
{
|
||||
if ($domain->is_server) {
|
||||
return;
|
||||
}
|
||||
|
||||
$selector = (string) config('mailpool.defaults.dkim_selector', 'mwl1');
|
||||
$bits = (int) config('mailpool.defaults.dkim_bits', 2048);
|
||||
|
||||
|
|
@ -51,6 +55,8 @@ class DomainObserver
|
|||
]
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// public function created(Domain $domain): void
|
||||
// {
|
||||
// // Standardwerte aus Config oder .env
|
||||
|
|
|
|||
|
|
@ -16,10 +16,11 @@ return new class extends Migration
|
|||
$table->string('name')->unique();
|
||||
$table->string('username')->nullable()->unique();
|
||||
$table->string('email')->unique();
|
||||
$table->string('admin_email', 255)->nullable()->index();
|
||||
$table->timestamp('email_verified_at')->nullable();
|
||||
$table->string('password');
|
||||
$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_email_enabled')->default(false);
|
||||
$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_active')->default(true)->index();
|
||||
$table->boolean('must_change_pw')->default(true)->index();
|
||||
|
||||
$table->unsignedInteger('quota_mb')->default(0); // 0 = unlimited
|
||||
$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(
|
||||
['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)
|
||||
->where('id', '!=', $serverDomain->id)
|
||||
->update(['is_server' => false]);
|
||||
|
|
@ -71,8 +101,37 @@ class SystemDomainSeeder extends Seeder
|
|||
// =========================================================================
|
||||
$systemDomain = Domain::firstOrCreate(
|
||||
['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) {
|
||||
$this->command->line("System-Domain angelegt: {$systemDomain->domain}");
|
||||
}
|
||||
|
|
@ -81,13 +140,12 @@ class SystemDomainSeeder extends Seeder
|
|||
MailUser::firstOrCreate(
|
||||
['email' => "no-reply@{$systemFqdn}"],
|
||||
[
|
||||
'domain_id' => $systemDomain->id,
|
||||
'localpart' => 'no-reply',
|
||||
'password_hash' => null,
|
||||
'is_active' => true,
|
||||
'is_system' => true,
|
||||
'must_change_pw' => false,
|
||||
'quota_mb' => 0,
|
||||
'domain_id' => $systemDomain->id,
|
||||
'localpart' => 'no-reply',
|
||||
'password_hash' => null,
|
||||
'is_active' => true,
|
||||
'is_system' => true,
|
||||
'quota_mb' => 0,
|
||||
]
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -164,15 +164,15 @@
|
|||
<span class="text-white/80 text-sm">Postfach aktivieren</span>
|
||||
</label>
|
||||
|
||||
<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">
|
||||
<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
|
||||
group-hover:border-white/25 transition">
|
||||
<i class="ph ph-check text-[12px] text-sky-300 opacity-0 peer-checked:opacity-100 transition"></i>
|
||||
</span>
|
||||
<span class="text-white/80 text-sm">Passwort bei erstem Login ändern</span>
|
||||
</label>
|
||||
{{-- <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">--}}
|
||||
{{-- <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--}}
|
||||
{{-- group-hover:border-white/25 transition">--}}
|
||||
{{-- <i class="ph ph-check text-[12px] text-sky-300 opacity-0 peer-checked:opacity-100 transition"></i>--}}
|
||||
{{-- </span>--}}
|
||||
{{-- <span class="text-white/80 text-sm">Passwort bei erstem Login ändern</span>--}}
|
||||
{{-- </label>--}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Reference in New Issue