mailwolt/app/Livewire/Ui/Domain/Modal/DomainLimitsModal.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');
// }
//}