diff --git a/app/Http/Middleware/EnsureAdmin.php b/app/Http/Middleware/EnsureAdmin.php index 110de1c..1b06cb0 100644 --- a/app/Http/Middleware/EnsureAdmin.php +++ b/app/Http/Middleware/EnsureAdmin.php @@ -13,7 +13,8 @@ class EnsureAdmin */ public function handle(Request $request, Closure $next): Response { - abort_unless((bool) $request->user()?->can('console.view'), 403); + // console.view via RBAC, or the legacy is_admin flag as a safety net. + abort_unless((bool) $request->user()?->isOperator(), 403); return $next($request); } diff --git a/app/Livewire/Admin/Datacenters.php b/app/Livewire/Admin/Datacenters.php index 514ace2..dd55569 100644 --- a/app/Livewire/Admin/Datacenters.php +++ b/app/Livewire/Admin/Datacenters.php @@ -16,54 +16,10 @@ class Datacenters extends Component #[Validate('required|string|max:255')] public string $name = ''; - #[Validate('nullable|string|max:255')] + // Country picked from config/countries.php (no manual code typos). + #[Validate('nullable|string|max:2')] public string $location = ''; - // Inline edit state (code is immutable once created — it is referenced by hosts). - public ?string $editingUuid = null; - - public string $editName = ''; - - public string $editLocation = ''; - - public function edit(string $uuid): void - { - $this->authorize('datacenters.manage'); - $dc = Datacenter::query()->where('uuid', $uuid)->first(); - if ($dc === null) { - return; - } - $this->editingUuid = $uuid; - $this->editName = $dc->name; - $this->editLocation = (string) $dc->location; - } - - public function cancelEdit(): void - { - $this->reset('editingUuid', 'editName', 'editLocation'); - } - - public function update(): void - { - $this->authorize('datacenters.manage'); - if ($this->editingUuid === null) { - return; - } - - $data = $this->validate([ - 'editName' => 'required|string|max:255', - 'editLocation' => 'nullable|string|max:255', - ]); - - Datacenter::query()->where('uuid', $this->editingUuid)->update([ - 'name' => $data['editName'], - 'location' => $data['editLocation'] ?: null, - ]); - - $this->cancelEdit(); - $this->dispatch('notify', message: __('datacenters.updated')); - } - public function save(): void { $this->authorize('datacenters.manage'); @@ -95,6 +51,7 @@ class Datacenters extends Component { return view('livewire.admin.datacenters', [ 'datacenters' => Datacenter::query()->withCount('hosts')->orderBy('name')->get(), + 'countries' => config('countries'), ]); } } diff --git a/app/Livewire/Admin/EditDatacenter.php b/app/Livewire/Admin/EditDatacenter.php new file mode 100644 index 0000000..bc8f7da --- /dev/null +++ b/app/Livewire/Admin/EditDatacenter.php @@ -0,0 +1,58 @@ +where('uuid', $uuid)->firstOrFail(); + $this->uuid = $uuid; + $this->code = $dc->code; + $this->name = $dc->name; + $this->location = (string) $dc->location; + } + + public function save() + { + $this->authorize('datacenters.manage'); + $data = $this->validate(); + + Datacenter::query()->where('uuid', $this->uuid)->update([ + 'name' => $data['name'], + 'location' => $data['location'] ?: null, + ]); + + $this->dispatch('notify', message: __('datacenters.updated')); + + return $this->redirectRoute('admin.datacenters', navigate: true); + } + + public function render() + { + return view('livewire.admin.edit-datacenter', [ + 'countries' => config('countries'), + ]); + } +} diff --git a/app/Models/User.php b/app/Models/User.php index 239ab1c..85829fb 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -22,10 +22,14 @@ class User extends Authenticatable /** The five operator roles that grant access to the admin console. */ public const OPERATOR_ROLES = ['Owner', 'Admin', 'Support', 'Billing', 'Read-only']; - /** True when this user is a CluPilot operator (has any admin role). */ + /** + * True when this user is a CluPilot operator. Prefers RBAC roles, but keeps + * the legacy is_admin flag as a fallback so an operator can never be locked + * out of the console by a stale permission cache or a missing role. + */ public function isOperator(): bool { - return $this->hasAnyRole(self::OPERATOR_ROLES); + return $this->is_admin || $this->hasAnyRole(self::OPERATOR_ROLES); } /** diff --git a/config/countries.php b/config/countries.php new file mode 100644 index 0000000..a65211c --- /dev/null +++ b/config/countries.php @@ -0,0 +1,36 @@ + 'Deutschland', + 'AT' => 'Österreich', + 'CH' => 'Schweiz', + 'FI' => 'Finnland', + 'SE' => 'Schweden', + 'NO' => 'Norwegen', + 'DK' => 'Dänemark', + 'NL' => 'Niederlande', + 'BE' => 'Belgien', + 'LU' => 'Luxemburg', + 'FR' => 'Frankreich', + 'GB' => 'Vereinigtes Königreich', + 'IE' => 'Irland', + 'ES' => 'Spanien', + 'PT' => 'Portugal', + 'IT' => 'Italien', + 'PL' => 'Polen', + 'CZ' => 'Tschechien', + 'SK' => 'Slowakei', + 'HU' => 'Ungarn', + 'SI' => 'Slowenien', + 'HR' => 'Kroatien', + 'RO' => 'Rumänien', + 'BG' => 'Bulgarien', + 'GR' => 'Griechenland', + 'EE' => 'Estland', + 'LV' => 'Lettland', + 'LT' => 'Litauen', + 'US' => 'USA', + 'CA' => 'Kanada', +]; diff --git a/lang/de/datacenters.php b/lang/de/datacenters.php index 09ddd2e..0ba0940 100644 --- a/lang/de/datacenters.php +++ b/lang/de/datacenters.php @@ -18,6 +18,8 @@ return [ 'updated' => 'Rechenzentrum aktualisiert.', 'actions' => 'Aktionen', 'edit' => 'Bearbeiten', + 'edit_title' => 'Rechenzentrum bearbeiten', + 'no_country' => 'Kein Land', 'save' => 'Speichern', 'cancel' => 'Abbrechen', 'delete' => 'Löschen', diff --git a/lang/en/datacenters.php b/lang/en/datacenters.php index f290ec9..d7a0530 100644 --- a/lang/en/datacenters.php +++ b/lang/en/datacenters.php @@ -18,6 +18,8 @@ return [ 'updated' => 'Datacenter updated.', 'actions' => 'Actions', 'edit' => 'Edit', + 'edit_title' => 'Edit datacenter', + 'no_country' => 'No country', 'save' => 'Save', 'cancel' => 'Cancel', 'delete' => 'Delete', diff --git a/resources/views/livewire/admin/datacenters.blade.php b/resources/views/livewire/admin/datacenters.blade.php index fb608ec..52064b9 100644 --- a/resources/views/livewire/admin/datacenters.blade.php +++ b/resources/views/livewire/admin/datacenters.blade.php @@ -24,49 +24,32 @@ @foreach ($datacenters as $dc) {{ $dc->code }} - @if ($editingUuid === $dc->uuid) - -
- - -
- @error('editName')

{{ $message }}

@enderror - - -
- - -
- - @else - {{ $dc->name }} - @if ($dc->location)· {{ $dc->location }}@endif - - {{ $dc->hosts_count }} - - + + +
+ - - -
- - -
- - @endif + +
+ @endforeach @@ -79,7 +62,15 @@

{{ __('datacenters.add') }}

- +
+ + +
{{ __('datacenters.add') }} diff --git a/resources/views/livewire/admin/edit-datacenter.blade.php b/resources/views/livewire/admin/edit-datacenter.blade.php new file mode 100644 index 0000000..a8763de --- /dev/null +++ b/resources/views/livewire/admin/edit-datacenter.blade.php @@ -0,0 +1,29 @@ +
+
+

{{ __('datacenters.edit_title') }}

+ {{ $code }} +
+ +
+
+ + + @error('name')

{{ $message }}

@enderror +
+
+ + + @error('location')

{{ $message }}

@enderror +
+
+ +
+ {{ __('datacenters.cancel') }} + {{ __('datacenters.save') }} +
+
diff --git a/resources/views/vendor/wire-elements-modal/modal.blade.php b/resources/views/vendor/wire-elements-modal/modal.blade.php index cdab72a..d68a94b 100644 --- a/resources/views/vendor/wire-elements-modal/modal.blade.php +++ b/resources/views/vendor/wire-elements-modal/modal.blade.php @@ -14,33 +14,32 @@ class="fixed inset-0 z-[70] overflow-y-auto" style="display: none;" > -
-
-
-
- - + {{-- Backdrop --}} +
+ {{-- Centered panel with a fixed, contextual max width (max-w-lg is + compiled statically; the package's dynamic modalWidth class would be + purged by Tailwind and collapse the modal to full width). --}} +