259 lines
10 KiB
PHP
259 lines
10 KiB
PHP
<?php
|
|
|
|
namespace App\Livewire\Ui\Domain\Modal;
|
|
|
|
use App\Models\Domain;
|
|
use App\Services\MailStorage;
|
|
use Illuminate\Validation\ValidationException;
|
|
use LivewireUI\Modal\ModalComponent;
|
|
|
|
class DomainLimitsModal extends ModalComponent
|
|
{
|
|
public int $domainId;
|
|
|
|
// Eingabe-Felder
|
|
public int $max_aliases;
|
|
public int $max_mailboxes;
|
|
public int $default_quota_mb;
|
|
public ?int $max_quota_per_mailbox_mb = null; // null = kein per-Mailbox-Maximum
|
|
public int $total_quota_mb; // 0 = unbegrenzt
|
|
public ?int $rate_limit_per_hour = null; // null = kein Limit
|
|
public bool $rate_limit_override = false;
|
|
|
|
// intern für Checks
|
|
private int $current_total_quota_mb = 0;
|
|
|
|
public function mount(int $domainId, MailStorage $pool): void
|
|
{
|
|
$d = Domain::findOrFail($domainId);
|
|
if ($d->is_system) {
|
|
$this->dispatch('toast', type: 'error', text: 'System-Domain Limits können hier nicht geändert werden.');
|
|
$this->dispatch('closeModal');
|
|
return;
|
|
}
|
|
|
|
$this->domainId = $domainId;
|
|
$this->max_aliases = (int)$d->max_aliases;
|
|
$this->max_mailboxes = (int)$d->max_mailboxes;
|
|
$this->default_quota_mb = (int)$d->default_quota_mb;
|
|
$this->max_quota_per_mailbox_mb = $d->max_quota_per_mailbox_mb !== null ? (int)$d->max_quota_per_mailbox_mb : null;
|
|
$this->total_quota_mb = (int)$d->total_quota_mb;
|
|
$this->rate_limit_per_hour = $d->rate_limit_per_hour !== null ? (int)$d->rate_limit_per_hour : null;
|
|
$this->rate_limit_override = (bool)$d->rate_limit_override;
|
|
|
|
// Für Pool-Delta-Check merken
|
|
$this->current_total_quota_mb = (int)$d->total_quota_mb;
|
|
}
|
|
|
|
protected function rules(): array
|
|
{
|
|
return [
|
|
'max_aliases' => ['required', 'integer', 'min:0'],
|
|
'max_mailboxes' => ['required', 'integer', 'min:0'],
|
|
'default_quota_mb' => ['required', 'integer', 'min:0'],
|
|
'max_quota_per_mailbox_mb' => ['nullable', 'integer', 'min:1'],
|
|
'total_quota_mb' => ['required', 'integer', 'min:0'], // 0 = unbegrenzt
|
|
'rate_limit_per_hour' => ['nullable', 'integer', 'min:1'], // null = kein Limit
|
|
'rate_limit_override' => ['boolean'],
|
|
];
|
|
}
|
|
|
|
public function save(MailStorage $pool): void
|
|
{
|
|
$this->validate();
|
|
|
|
// 1) Innere Konsistenz der neuen Limits
|
|
if ($this->max_quota_per_mailbox_mb !== null && $this->default_quota_mb > $this->max_quota_per_mailbox_mb) {
|
|
throw ValidationException::withMessages([
|
|
'default_quota_mb' => 'Die Standard-Quota darf die maximale Mailbox-Quota nicht überschreiten.',
|
|
]);
|
|
}
|
|
if ($this->total_quota_mb > 0 && $this->default_quota_mb > $this->total_quota_mb) {
|
|
throw ValidationException::withMessages([
|
|
'default_quota_mb' => 'Die Standard-Quota darf die Domain-Gesamtquota nicht überschreiten.',
|
|
]);
|
|
}
|
|
|
|
// 2) Bestandsdaten laden (für Abwärts-Checks)
|
|
$d = Domain::query()
|
|
->withCount(['mailUsers', 'mailAliases'])
|
|
->withSum('mailUsers as sum_user_quota_mb', 'quota_mb')
|
|
->withMax('mailUsers as max_user_quota_mb', 'quota_mb')
|
|
->withMax('mailUsers as max_user_rate', 'rate_limit_per_hour')
|
|
->findOrFail($this->domainId);
|
|
|
|
$existingUsers = (int)$d->mail_users_count;
|
|
$existingAliases = (int)$d->mail_aliases_count;
|
|
$sumQuota = (int)($d->sum_user_quota_mb ?? 0);
|
|
$maxUserQuota = (int)($d->max_user_quota_mb ?? 0);
|
|
$maxUserRate = (int)($d->max_user_rate ?? 0);
|
|
|
|
// 3) Abwärts-Checks
|
|
if ($this->max_mailboxes < $existingUsers) {
|
|
throw ValidationException::withMessages([
|
|
'max_mailboxes' => "Es existieren bereits {$existingUsers} Mailboxen. "
|
|
. "Der Wert darf nicht unter diese Anzahl gesenkt werden.",
|
|
]);
|
|
}
|
|
|
|
if ($this->max_aliases < $existingAliases) {
|
|
throw ValidationException::withMessages([
|
|
'max_aliases' => "Es existieren bereits {$existingAliases} Aliasse. "
|
|
. "Der Wert darf nicht unter diese Anzahl gesenkt werden.",
|
|
]);
|
|
}
|
|
|
|
if ($this->max_quota_per_mailbox_mb !== null && $this->max_quota_per_mailbox_mb < $maxUserQuota) {
|
|
throw ValidationException::withMessages([
|
|
'max_quota_per_mailbox_mb' => "Mindestens ein Postfach hat {$maxUserQuota} MiB. "
|
|
. "Das Limit darf nicht darunter liegen.",
|
|
]);
|
|
}
|
|
|
|
if ($this->total_quota_mb > 0 && $this->total_quota_mb < $sumQuota) {
|
|
throw ValidationException::withMessages([
|
|
'total_quota_mb' => "Bestehende Postfächer summieren sich auf {$sumQuota} MiB. "
|
|
. "Das Domain-Gesamtlimit darf nicht darunter liegen.",
|
|
]);
|
|
}
|
|
|
|
if (!$this->rate_limit_override && $this->rate_limit_per_hour !== null && $maxUserRate > 0
|
|
&& $this->rate_limit_per_hour < $maxUserRate) {
|
|
throw ValidationException::withMessages([
|
|
'rate_limit_per_hour' => "Mindestens ein Postfach hat ein höheres stündliches Limit ({$maxUserRate}). "
|
|
. "Ohne Overrides darf der Domain-Wert nicht darunter liegen.",
|
|
]);
|
|
}
|
|
|
|
// 4) Pool-Check (nur bei Erhöhung der Domain-Gesamtquota)
|
|
$delta = $this->total_quota_mb - $this->current_total_quota_mb;
|
|
if ($delta > 0) {
|
|
$remaining = (int)$pool->remainingPoolMb();
|
|
if ($delta > $remaining) {
|
|
throw ValidationException::withMessages([
|
|
'total_quota_mb' => 'Nicht genügend Speicher im Pool. Erhöhung um '
|
|
. number_format($delta) . ' MiB nicht möglich. Frei: ' . number_format($remaining) . ' MiB.',
|
|
]);
|
|
}
|
|
}
|
|
|
|
// 5) Persist
|
|
$d->max_aliases = $this->max_aliases;
|
|
$d->max_mailboxes = $this->max_mailboxes;
|
|
$d->default_quota_mb = $this->default_quota_mb;
|
|
$d->max_quota_per_mailbox_mb = $this->max_quota_per_mailbox_mb;
|
|
$d->total_quota_mb = $this->total_quota_mb;
|
|
$d->rate_limit_per_hour = $this->rate_limit_per_hour;
|
|
$d->rate_limit_override = $this->rate_limit_override;
|
|
$d->save();
|
|
|
|
// 6) UI
|
|
$this->dispatch('domain-updated');
|
|
$this->dispatch('closeModal');
|
|
$this->dispatch('toast',
|
|
type: 'done',
|
|
badge: 'Domain-Limits',
|
|
title: 'Domain-Limits aktualisiert',
|
|
text: 'Die Domain-Limits wurden erfolgreich aktualisiert.',
|
|
duration: 6000,
|
|
);
|
|
}
|
|
|
|
public static function modalMaxWidth(): string
|
|
{
|
|
return '3xl';
|
|
}
|
|
|
|
public function render()
|
|
{
|
|
return view('livewire.ui.domain.modal.domain-limits-modal');
|
|
}
|
|
}
|
|
//
|
|
//namespace App\Livewire\Ui\Domain\Modal;
|
|
//
|
|
//use App\Models\Domain;
|
|
//use App\Services\MailStorage;
|
|
//use Illuminate\Validation\ValidationException;
|
|
//use LivewireUI\Modal\ModalComponent;
|
|
//
|
|
//
|
|
//class DomainLimitsModal extends ModalComponent
|
|
//{
|
|
// public int $domainId;
|
|
// public int $max_aliases;
|
|
// public int $max_mailboxes;
|
|
// public int $default_quota_mb;
|
|
// public ?int $max_quota_per_mailbox_mb = null;
|
|
// public int $total_quota_mb;
|
|
// public ?int $rate_limit_per_hour = null;
|
|
// public bool $rate_limit_override = false;
|
|
//
|
|
// public function mount(int $domainId, MailStorage $pool)
|
|
// {
|
|
// $d = Domain::findOrFail($domainId);
|
|
// if ($d->is_system) { $this->dispatch('toast', type:'error', text:'System-Domain Limits können hier nicht geändert werden.'); $this->dispatch('closeModal'); return; }
|
|
//
|
|
// $this->domainId = $domainId;
|
|
// $this->max_aliases = (int)$d->max_aliases;
|
|
// $this->max_mailboxes = (int)$d->max_mailboxes;
|
|
// $this->default_quota_mb = (int)$d->default_quota_mb;
|
|
// $this->max_quota_per_mailbox_mb = $d->max_quota_per_mailbox_mb;
|
|
// $this->total_quota_mb = (int)$d->total_quota_mb;
|
|
// $this->rate_limit_per_hour = $d->rate_limit_per_hour;
|
|
// $this->rate_limit_override = (bool)$d->rate_limit_override;
|
|
// }
|
|
//
|
|
// public function save(MailStorage $pool)
|
|
// {
|
|
// $this->validate([
|
|
// 'max_aliases' => 'required|integer|min:0',
|
|
// 'max_mailboxes' => 'required|integer|min:0',
|
|
// 'default_quota_mb' => 'required|integer|min:0',
|
|
// 'max_quota_per_mailbox_mb' => 'nullable|integer|min:0',
|
|
// 'total_quota_mb' => 'required|integer|min:0',
|
|
// 'rate_limit_per_hour' => 'nullable|integer|min:0',
|
|
// 'rate_limit_override' => 'boolean',
|
|
// ]);
|
|
//
|
|
// if ($this->max_quota_per_mailbox_mb !== null &&
|
|
// $this->default_quota_mb > $this->max_quota_per_mailbox_mb) {
|
|
// throw ValidationException::withMessages([
|
|
// 'default_quota_mb' => 'Die Standard-Quota darf die maximale Mailbox-Quota nicht überschreiten.',
|
|
// ]);
|
|
// }
|
|
//
|
|
// $remaining = $pool->remainingPoolMb();
|
|
// if ($this->total_quota_mb > $remaining) {
|
|
// throw ValidationException::withMessages([
|
|
// 'total_quota_mb' => 'Nicht genügend Speicher verfügbar. Maximal möglich: '.number_format($remaining).' MiB.',
|
|
// ]);
|
|
// }
|
|
//
|
|
// Domain::whereKey($this->domainId)->update([
|
|
// 'max_aliases' => $this->max_aliases,
|
|
// 'max_mailboxes' => $this->max_mailboxes,
|
|
// 'default_quota_mb' => $this->default_quota_mb,
|
|
// 'max_quota_per_mailbox_mb' => $this->max_quota_per_mailbox_mb,
|
|
// 'total_quota_mb' => $this->total_quota_mb,
|
|
// 'rate_limit_per_hour' => $this->rate_limit_per_hour,
|
|
// 'rate_limit_override' => $this->rate_limit_override,
|
|
// ]);
|
|
//
|
|
// $this->dispatch('domain-updated');
|
|
// $this->dispatch('closeModal');
|
|
// $this->dispatch('toast',
|
|
// type: 'done',
|
|
// badge: 'Domain-Limits',
|
|
// title: 'Domain-Limits aktualisiert',
|
|
// text: 'Die Domain-Limits wurde erfolgreich aktualisiert. Alle Änderungen sind sofort aktiv.',
|
|
// duration: 6000,
|
|
// );
|
|
// }
|
|
//
|
|
// public function render()
|
|
// {
|
|
// return view('livewire.ui.domain.modal.domain-limits-modal');
|
|
// }
|
|
//}
|