Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix server access for admins without subuser #919

Merged
merged 12 commits into from
Jan 17, 2025
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class ListServers extends ListRecords

public function table(Table $table): Table
{
$baseQuery = auth()->user()->can('viewList server') ? Server::query() : auth()->user()->accessibleServers();
$baseQuery = auth()->user()->accessibleServers();

return $table
->paginated(false)
Expand Down
5 changes: 5 additions & 0 deletions app/Filament/Server/Pages/Console.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
// use App\Filament\Server\Widgets\ServerNetworkChart;
use App\Filament\Server\Widgets\ServerOverview;
use App\Livewire\AlertBanner;
use App\Models\Permission;
use App\Models\Server;
use Filament\Actions\Action;
use Filament\Facades\Filament;
Expand Down Expand Up @@ -94,16 +95,19 @@ protected function getHeaderActions(): array
->color('primary')
->size(ActionSize::ExtraLarge)
->action(fn () => $this->dispatch('setServerState', state: 'start', uuid: $server->uuid))
->authorize(fn () => auth()->user()->can(Permission::ACTION_CONTROL_START, $server))
->disabled(fn () => $server->isInConflictState() || !$this->status->isStartable()),
Action::make('restart')
->color('gray')
->size(ActionSize::ExtraLarge)
->action(fn () => $this->dispatch('setServerState', state: 'restart', uuid: $server->uuid))
->authorize(fn () => auth()->user()->can(Permission::ACTION_CONTROL_RESTART, $server))
->disabled(fn () => $server->isInConflictState() || !$this->status->isRestartable()),
Action::make('stop')
->color('danger')
->size(ActionSize::ExtraLarge)
->action(fn () => $this->dispatch('setServerState', state: 'stop', uuid: $server->uuid))
->authorize(fn () => auth()->user()->can(Permission::ACTION_CONTROL_STOP, $server))
->hidden(fn () => $this->status->isStartingOrStopping() || $this->status->isKillable())
->disabled(fn () => $server->isInConflictState() || !$this->status->isStoppable()),
Action::make('kill')
Expand All @@ -114,6 +118,7 @@ protected function getHeaderActions(): array
->modalSubmitActionLabel('Kill Server')
->size(ActionSize::ExtraLarge)
->action(fn () => $this->dispatch('setServerState', state: 'kill', uuid: $server->uuid))
->authorize(fn () => auth()->user()->can(Permission::ACTION_CONTROL_STOP, $server))
->hidden(fn () => $server->isInConflictState() || !$this->status->isKillable()),
];
}
Expand Down
7 changes: 6 additions & 1 deletion app/Filament/Server/Widgets/ServerConsole.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,14 @@ protected function getSocket(): string
return $socket;
}

protected function authorizeSendCommand(): bool
{
return $this->user->can(Permission::ACTION_CONTROL_CONSOLE, $this->server);
}

protected function canSendCommand(): bool
{
return !$this->server->isInConflictState() && $this->server->retrieveStatus() === 'running';
return $this->authorizeSendCommand() && !$this->server->isInConflictState() && $this->server->retrieveStatus() === 'running';
}

public function up(): void
Expand Down
17 changes: 13 additions & 4 deletions app/Models/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -289,11 +289,15 @@ public function activity(): MorphToMany
}

/**
* Returns all the servers that a user can access by way of being the owner of the
* server, or because they are assigned as a subuser for that server.
* Returns all the servers that a user can access.
* Either because they are an admin or because they are the owner/ a subuser of the server.
*/
public function accessibleServers(): Builder
{
if ($this->canned('viewList server')) {
return Server::query();
}

return Server::query()
->select('servers.*')
->leftJoin('subusers', 'subusers.server_id', '=', 'servers.id')
Expand All @@ -315,7 +319,12 @@ public function subServers(): BelongsToMany

protected function checkPermission(Server $server, string $permission = ''): bool
{
if ($this->isRootAdmin() || $server->owner_id === $this->id) {
if ($this->isRootAdmin() || $this->canned('edit server', $server) || $server->owner_id === $this->id) {
return true;
}

// If the user only has "view" permissions allow viewing the console
if ($permission === Permission::ACTION_WEBSOCKET_CONNECT && $this->canned('view server', $server)) {
return true;
}

Expand Down Expand Up @@ -401,7 +410,7 @@ public function getTenants(Panel $panel): array|Collection
public function canAccessTenant(IlluminateModel $tenant): bool
{
if ($tenant instanceof Server) {
if ($this->isRootAdmin() || $tenant->owner_id === $this->id) {
if ($this->isRootAdmin() || $this->canned('view server', $tenant) || $tenant->owner_id === $this->id) {
return true;
}

Expand Down
36 changes: 19 additions & 17 deletions resources/views/filament/components/server-console.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,25 @@

<div id="terminal" wire:ignore></div>

<div class="flex items-center w-full border-top overflow-hidden dark:bg-gray-900"
style="border-bottom-right-radius: 10px; border-bottom-left-radius: 10px;">
<x-filament::icon
icon="tabler-chevrons-right"
/>
<input
class="w-full focus:outline-none focus:ring-0 border-none dark:bg-gray-900"
type="text"
:readonly="{{ $this->canSendCommand() ? 'false' : 'true' }}"
title="{{ $this->canSendCommand() ? '' : 'Can\'t send command when the server is Offline' }}"
placeholder="{{ $this->canSendCommand() ? 'Type a command...' : 'Server Offline...' }}"
wire:model="input"
wire:keydown.enter="enter"
wire:keydown.up.prevent="up"
wire:keydown.down="down"
>
</div>
@if ($this->authorizeSendCommand())
<div class="flex items-center w-full border-top overflow-hidden dark:bg-gray-900"
style="border-bottom-right-radius: 10px; border-bottom-left-radius: 10px;">
<x-filament::icon
icon="tabler-chevrons-right"
/>
<input
class="w-full focus:outline-none focus:ring-0 border-none dark:bg-gray-900"
type="text"
:readonly="{{ $this->canSendCommand() ? 'false' : 'true' }}"
title="{{ $this->canSendCommand() ? '' : 'Can\'t send command when the server is Offline' }}"
placeholder="{{ $this->canSendCommand() ? 'Type a command...' : 'Server Offline...' }}"
wire:model="input"
wire:keydown.enter="enter"
wire:keydown.up.prevent="up"
wire:keydown.down="down"
>
</div>
@endif
RMartinOscar marked this conversation as resolved.
Show resolved Hide resolved

@script
<script>
Expand Down
Loading