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
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\CanCustomizeHeaderWidgets;
use Filament\Actions\Action;
@ -10,12 +10,12 @@ use Filament\Actions\ActionGroup;
use Filament\Resources\Pages\ListRecords;
use Illuminate\Contracts\Support\Htmlable;
class ListUsers extends ListRecords
class ListSubusers extends ListRecords
{
use CanCustomizeHeaderActions;
use CanCustomizeHeaderWidgets;
protected static string $resource = UserResource::class;
protected static string $resource = SubuserResource::class;
/** @return array<Action|ActionGroup> */
protected function getDefaultHeaderActions(): array

View File

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

View File

View File

@ -1,6 +1,6 @@
<?php
namespace App\Policies\Server;
namespace App\Policies;
use App\Models\Permission;
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
namespace App\Policies\Server;
namespace App\Policies;
use App\Models\Permission;
use App\Models\User;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,6 +1,6 @@
<?php
namespace App\Policies\Server;
namespace App\Policies;
use App\Models\Permission;
use App\Models\Server;
@ -8,6 +8,10 @@ use App\Models\User;
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.
*/

View File

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

View File

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

View File

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

View File

@ -26,7 +26,6 @@ use App\Services\Helpers\SoftwareVersionService;
use Dedoc\Scramble\Scramble;
use Dedoc\Scramble\Support\Generator\OpenApi;
use Dedoc\Scramble\Support\Generator\SecurityScheme;
use Filament\Facades\Filament;
use Illuminate\Config\Repository;
use Illuminate\Database\Eloquent\Relations\Relation;
use Illuminate\Foundation\Application;
@ -109,21 +108,6 @@ class AppServiceProvider extends ServiceProvider
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', [
'Panel Version' => $versionService->currentPanelVersion(),
'Latest Version' => $versionService->latestPanelVersion(),