Consolidate policies and use Subuser model for subuser resource (#1978)

This commit is contained in:
Boy132 2025-12-11 13:16:57 +01:00 committed by GitHub
parent 3939c409c1
commit cdc928a15b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
22 changed files with 54 additions and 82 deletions

View File

@ -1,8 +1,8 @@
<?php <?php
namespace App\Filament\Server\Resources\Users\Pages; namespace App\Filament\Server\Resources\Subusers\Pages;
use App\Filament\Server\Resources\Users\UserResource; use App\Filament\Server\Resources\Subusers\SubuserResource;
use App\Traits\Filament\CanCustomizeHeaderActions; use App\Traits\Filament\CanCustomizeHeaderActions;
use App\Traits\Filament\CanCustomizeHeaderWidgets; use App\Traits\Filament\CanCustomizeHeaderWidgets;
use Filament\Actions\Action; use Filament\Actions\Action;
@ -10,12 +10,12 @@ use Filament\Actions\ActionGroup;
use Filament\Resources\Pages\ListRecords; use Filament\Resources\Pages\ListRecords;
use Illuminate\Contracts\Support\Htmlable; use Illuminate\Contracts\Support\Htmlable;
class ListUsers extends ListRecords class ListSubusers extends ListRecords
{ {
use CanCustomizeHeaderActions; use CanCustomizeHeaderActions;
use CanCustomizeHeaderWidgets; use CanCustomizeHeaderWidgets;
protected static string $resource = UserResource::class; protected static string $resource = SubuserResource::class;
/** @return array<Action|ActionGroup> */ /** @return array<Action|ActionGroup> */
protected function getDefaultHeaderActions(): array protected function getDefaultHeaderActions(): array

View File

@ -1,12 +1,12 @@
<?php <?php
namespace App\Filament\Server\Resources\Users; namespace App\Filament\Server\Resources\Subusers;
use App\Facades\Activity; use App\Facades\Activity;
use App\Filament\Server\Resources\Users\Pages\ListUsers; use App\Filament\Server\Resources\Subusers\Pages\ListSubusers;
use App\Models\Permission; use App\Models\Permission;
use App\Models\Server; use App\Models\Server;
use App\Models\User; use App\Models\Subuser;
use App\Services\Subusers\SubuserCreationService; use App\Services\Subusers\SubuserCreationService;
use App\Services\Subusers\SubuserDeletionService; use App\Services\Subusers\SubuserDeletionService;
use App\Services\Subusers\SubuserUpdateService; use App\Services\Subusers\SubuserUpdateService;
@ -38,7 +38,7 @@ use Filament\Tables\Columns\ImageColumn;
use Filament\Tables\Columns\TextColumn; use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Table; use Filament\Tables\Table;
class UserResource extends Resource class SubuserResource extends Resource
{ {
use BlockAccessInConflict; use BlockAccessInConflict;
use CanCustomizePages; use CanCustomizePages;
@ -46,14 +46,12 @@ class UserResource extends Resource
use CanModifyTable; use CanModifyTable;
use HasLimitBadge; use HasLimitBadge;
protected static ?string $model = User::class; protected static ?string $model = Subuser::class;
protected static ?int $navigationSort = 5; protected static ?int $navigationSort = 5;
protected static string|\BackedEnum|null $navigationIcon = 'tabler-users'; protected static string|\BackedEnum|null $navigationIcon = 'tabler-users';
protected static ?string $tenantOwnershipRelationshipName = 'subServers';
protected static function getBadgeCount(): int protected static function getBadgeCount(): int
{ {
/** @var Server $server */ /** @var Server $server */
@ -104,24 +102,23 @@ class UserResource extends Resource
->visibleFrom('lg') ->visibleFrom('lg')
->label('') ->label('')
->alignCenter()->circular() ->alignCenter()->circular()
->defaultImageUrl(fn (User $user) => Filament::getUserAvatarUrl($user)), ->defaultImageUrl(fn (Subuser $subuser) => Filament::getUserAvatarUrl($subuser->user)),
TextColumn::make('username') TextColumn::make('user.username')
->label(trans('server/user.username')) ->label(trans('server/user.username'))
->searchable(), ->searchable(),
TextColumn::make('email') TextColumn::make('user.email')
->label(trans('server/user.email')) ->label(trans('server/user.email'))
->searchable(), ->searchable(),
TextColumn::make('permissions') TextColumn::make('permissions')
->label(trans('server/user.permissions.title')) ->label(trans('server/user.permissions.title'))
->state(fn (User $user) => count($server->subusers->where('user_id', $user->id)->first()->permissions)), ->state(fn (Subuser $subuser) => count($subuser->permissions) - 1),
]) ])
->recordActions([ ->recordActions([
DeleteAction::make() DeleteAction::make()
->label(trans('server/user.delete')) ->label(trans('server/user.delete'))
->hidden(fn (User $user) => user()?->id === $user->id) ->hidden(fn (Subuser $subuser) => user()?->id === $subuser->user->id)
->successNotificationTitle(null) ->successNotificationTitle(null)
->action(function (User $user, SubuserDeletionService $subuserDeletionService) use ($server) { ->action(function (Subuser $subuser, SubuserDeletionService $subuserDeletionService) use ($server) {
$subuser = $server->subusers->where('user_id', $user->id)->first();
$subuserDeletionService->handle($subuser, $server); $subuserDeletionService->handle($subuser, $server);
Notification::make() Notification::make()
@ -131,13 +128,11 @@ class UserResource extends Resource
}), }),
EditAction::make() EditAction::make()
->label(trans('server/user.edit')) ->label(trans('server/user.edit'))
->hidden(fn (User $user) => user()?->id === $user->id) ->hidden(fn (Subuser $subuser) => user()?->id === $subuser->user->id)
->authorize(fn () => user()?->can(Permission::ACTION_USER_UPDATE, $server)) ->authorize(fn () => user()?->can(Permission::ACTION_USER_UPDATE, $server))
->modalHeading(fn (User $user) => trans('server/user.editing', ['user' => $user->email])) ->modalHeading(fn (Subuser $subuser) => trans('server/user.editing', ['user' => $subuser->user->email]))
->successNotificationTitle(null) ->successNotificationTitle(null)
->action(function (array $data, SubuserUpdateService $subuserUpdateService, User $user) use ($server) { ->action(function (array $data, SubuserUpdateService $subuserUpdateService, Subuser $subuser) use ($server) {
$subuser = $server->subusers->where('user_id', $user->id)->first();
$permissions = collect($data) $permissions = collect($data)
->forget('email') ->forget('email')
->flatMap(fn ($permissions, $key) => collect($permissions)->map(fn ($permission) => "$key.$permission")) ->flatMap(fn ($permissions, $key) => collect($permissions)->map(fn ($permission) => "$key.$permission"))
@ -172,7 +167,8 @@ class UserResource extends Resource
'sm' => 1, 'sm' => 1,
'md' => 4, 'md' => 4,
'lg' => 5, 'lg' => 5,
]), ])
->formatStateUsing(fn (Subuser $subuser) => $subuser->user->email),
Actions::make([ Actions::make([
Action::make('assignAll') Action::make('assignAll')
->label(trans('server/user.assign_all')) ->label(trans('server/user.assign_all'))
@ -195,12 +191,10 @@ class UserResource extends Resource
->schema($tabs), ->schema($tabs),
]), ]),
]) ])
->mutateRecordDataUsing(function ($data, User $user) use ($server) { ->mutateRecordDataUsing(function ($data, Subuser $subuser) {
$permissionsArray = $server->subusers->where('user_id', $user->id)->first()->permissions;
$transformedPermissions = []; $transformedPermissions = [];
foreach ($permissionsArray as $permission) { foreach ($subuser->permissions as $permission) {
[$group, $action] = explode('.', $permission, 2); [$group, $action] = explode('.', $permission, 2);
$transformedPermissions[$group][] = $action; $transformedPermissions[$group][] = $action;
} }
@ -312,7 +306,7 @@ class UserResource extends Resource
public static function getDefaultPages(): array public static function getDefaultPages(): array
{ {
return [ return [
'index' => ListUsers::route('/'), 'index' => ListSubusers::route('/'),
]; ];
} }

View File

View File

@ -1,6 +1,6 @@
<?php <?php
namespace App\Policies\Server; namespace App\Policies;
use App\Models\Permission; use App\Models\Permission;
use App\Models\User; use App\Models\User;

View File

@ -1,10 +0,0 @@
<?php
namespace App\Policies\Admin;
class ServerPolicy
{
use DefaultPolicies;
protected string $modelName = 'server';
}

View File

@ -1,6 +1,6 @@
<?php <?php
namespace App\Policies\Server; namespace App\Policies;
use App\Models\Permission; use App\Models\Permission;
use App\Models\User; use App\Models\User;

View File

@ -1,10 +1,10 @@
<?php <?php
namespace App\Policies\Admin; namespace App\Policies;
class ApiKeyPolicy class ApiKeyPolicy
{ {
use DefaultPolicies; use DefaultAdminPolicies;
protected string $modelName = 'apiKey'; protected string $modelName = 'apiKey';
} }

View File

@ -1,6 +1,6 @@
<?php <?php
namespace App\Policies\Server; namespace App\Policies;
use App\Models\Permission; use App\Models\Permission;
use App\Models\User; use App\Models\User;

View File

@ -1,13 +1,13 @@
<?php <?php
namespace App\Policies\Admin; namespace App\Policies;
use App\Models\DatabaseHost; use App\Models\DatabaseHost;
use App\Models\User; use App\Models\User;
class DatabaseHostPolicy class DatabaseHostPolicy
{ {
use DefaultPolicies; use DefaultAdminPolicies;
protected string $modelName = 'databaseHost'; protected string $modelName = 'databaseHost';

View File

@ -1,6 +1,6 @@
<?php <?php
namespace App\Policies\Server; namespace App\Policies;
use App\Models\Permission; use App\Models\Permission;
use App\Models\User; use App\Models\User;

View File

@ -1,11 +1,11 @@
<?php <?php
namespace App\Policies\Admin; namespace App\Policies;
use App\Models\User; use App\Models\User;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
trait DefaultPolicies trait DefaultAdminPolicies
{ {
public function viewAny(User $user): bool public function viewAny(User $user): bool
{ {

View File

@ -1,10 +1,10 @@
<?php <?php
namespace App\Policies\Admin; namespace App\Policies;
class EggPolicy class EggPolicy
{ {
use DefaultPolicies; use DefaultAdminPolicies;
protected string $modelName = 'egg'; protected string $modelName = 'egg';
} }

View File

@ -1,6 +1,6 @@
<?php <?php
namespace App\Policies\Server; namespace App\Policies;
use App\Models\Permission; use App\Models\Permission;
use App\Models\User; use App\Models\User;

View File

@ -1,13 +1,13 @@
<?php <?php
namespace App\Policies\Admin; namespace App\Policies;
use App\Models\Mount; use App\Models\Mount;
use App\Models\User; use App\Models\User;
class MountPolicy class MountPolicy
{ {
use DefaultPolicies; use DefaultAdminPolicies;
protected string $modelName = 'mount'; protected string $modelName = 'mount';

View File

@ -1,13 +1,13 @@
<?php <?php
namespace App\Policies\Admin; namespace App\Policies;
use App\Models\Node; use App\Models\Node;
use App\Models\User; use App\Models\User;
class NodePolicy class NodePolicy
{ {
use DefaultPolicies; use DefaultAdminPolicies;
protected string $modelName = 'node'; protected string $modelName = 'node';

View File

@ -1,10 +1,10 @@
<?php <?php
namespace App\Policies\Admin; namespace App\Policies;
class RolePolicy class RolePolicy
{ {
use DefaultPolicies; use DefaultAdminPolicies;
protected string $modelName = 'role'; protected string $modelName = 'role';
} }

View File

@ -1,6 +1,6 @@
<?php <?php
namespace App\Policies\Server; namespace App\Policies;
use App\Models\Permission; use App\Models\Permission;
use App\Models\User; use App\Models\User;

View File

@ -1,6 +1,6 @@
<?php <?php
namespace App\Policies\Server; namespace App\Policies;
use App\Models\Permission; use App\Models\Permission;
use App\Models\Server; use App\Models\Server;
@ -8,6 +8,10 @@ use App\Models\User;
class ServerPolicy class ServerPolicy
{ {
use DefaultAdminPolicies;
protected string $modelName = 'server';
/** /**
* Runs before any of the functions are called. Used to determine if the (sub-)user has permissions. * Runs before any of the functions are called. Used to determine if the (sub-)user has permissions.
*/ */

View File

@ -1,13 +1,13 @@
<?php <?php
namespace App\Policies\Server; namespace App\Policies;
use App\Models\Permission; use App\Models\Permission;
use App\Models\User; use App\Models\User;
use Filament\Facades\Filament; use Filament\Facades\Filament;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
class UserPolicy class SubuserPolicy
{ {
public function viewAny(User $user): bool public function viewAny(User $user): bool
{ {

View File

@ -1,13 +1,13 @@
<?php <?php
namespace App\Policies\Admin; namespace App\Policies;
use App\Models\User; use App\Models\User;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
class UserPolicy class UserPolicy
{ {
use DefaultPolicies { use DefaultAdminPolicies {
update as defaultUpdate; update as defaultUpdate;
delete as defaultDelete; delete as defaultDelete;
} }

View File

@ -1,10 +1,10 @@
<?php <?php
namespace App\Policies\Admin; namespace App\Policies;
class WebhookConfigurationPolicy class WebhookConfigurationPolicy
{ {
use DefaultPolicies; use DefaultAdminPolicies;
protected string $modelName = 'webhook'; protected string $modelName = 'webhook';
} }

View File

@ -26,7 +26,6 @@ use App\Services\Helpers\SoftwareVersionService;
use Dedoc\Scramble\Scramble; use Dedoc\Scramble\Scramble;
use Dedoc\Scramble\Support\Generator\OpenApi; use Dedoc\Scramble\Support\Generator\OpenApi;
use Dedoc\Scramble\Support\Generator\SecurityScheme; use Dedoc\Scramble\Support\Generator\SecurityScheme;
use Filament\Facades\Filament;
use Illuminate\Config\Repository; use Illuminate\Config\Repository;
use Illuminate\Database\Eloquent\Relations\Relation; use Illuminate\Database\Eloquent\Relations\Relation;
use Illuminate\Foundation\Application; use Illuminate\Foundation\Application;
@ -109,21 +108,6 @@ class AppServiceProvider extends ServiceProvider
Gate::before(fn (User $user, $ability) => $user->isRootAdmin() ? true : null); Gate::before(fn (User $user, $ability) => $user->isRootAdmin() ? true : null);
Gate::guessPolicyNamesUsing(function (string $modelClass) {
$panelId = mb_ucfirst(Filament::getCurrentOrDefaultPanel()->getId());
if ($panelId === 'App') {
return;
}
$modelName = class_basename($modelClass);
$class = "App\\Policies\\{$panelId}\\{$modelName}Policy";
if (class_exists($class)) {
return $class;
}
});
AboutCommand::add('Pelican', [ AboutCommand::add('Pelican', [
'Panel Version' => $versionService->currentPanelVersion(), 'Panel Version' => $versionService->currentPanelVersion(),
'Latest Version' => $versionService->latestPanelVersion(), 'Latest Version' => $versionService->latestPanelVersion(),