Use Policies rather then overriding can*() functions

This commit is contained in:
RMartinOscar 2025-10-27 16:15:16 +00:00
parent 3bcdeea800
commit bceb8a057e
27 changed files with 257 additions and 169 deletions

View File

@ -6,7 +6,6 @@ use App\Filament\Admin\Resources\Users\Pages\EditUser;
use App\Filament\Components\Tables\Columns\DateTimeColumn;
use App\Filament\Server\Resources\Activities\Pages\ListActivities;
use App\Models\ActivityLog;
use App\Models\Permission;
use App\Models\Role;
use App\Models\Server;
use App\Models\User;
@ -164,11 +163,6 @@ class ActivityResource extends Resource
});
}
public static function canViewAny(): bool
{
return user()?->can(Permission::ACTION_ACTIVITY_READ, Filament::getTenant());
}
/** @return array<string, PageRegistration> */
public static function getDefaultPages(): array
{

View File

@ -23,7 +23,6 @@ use Filament\Tables\Columns\IconColumn;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Columns\TextInputColumn;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Model;
class AllocationResource extends Resource
{
@ -116,26 +115,6 @@ class AllocationResource extends Resource
]);
}
public static function canViewAny(): bool
{
return user()?->can(Permission::ACTION_ALLOCATION_READ, Filament::getTenant());
}
public static function canCreate(): bool
{
return user()?->can(Permission::ACTION_ALLOCATION_CREATE, Filament::getTenant());
}
public static function canEdit(Model $record): bool
{
return user()?->can(Permission::ACTION_ALLOCATION_UPDATE, Filament::getTenant());
}
public static function canDelete(Model $record): bool
{
return user()?->can(Permission::ACTION_ALLOCATION_DELETE, Filament::getTenant());
}
/** @return array<string, PageRegistration> */
public static function getDefaultPages(): array
{

View File

@ -40,7 +40,6 @@ use Filament\Support\Enums\IconSize;
use Filament\Tables\Columns\IconColumn;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Http\Client\ConnectionException;
use Illuminate\Http\Request;
use Symfony\Component\HttpKernel\Exception\HttpException;
@ -296,21 +295,6 @@ class BackupResource extends Resource
]);
}
public static function canViewAny(): bool
{
return user()?->can(Permission::ACTION_BACKUP_READ, Filament::getTenant());
}
public static function canCreate(): bool
{
return user()?->can(Permission::ACTION_BACKUP_CREATE, Filament::getTenant());
}
public static function canDelete(Model $record): bool
{
return user()?->can(Permission::ACTION_BACKUP_DELETE, Filament::getTenant());
}
/** @return array<string, PageRegistration> */
public static function getDefaultPages(): array
{

View File

@ -31,7 +31,6 @@ use Filament\Schemas\Schema;
use Filament\Support\Enums\IconSize;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Str;
class DatabaseResource extends Resource
@ -208,31 +207,6 @@ class DatabaseResource extends Resource
]);
}
public static function canViewAny(): bool
{
return user()?->can(Permission::ACTION_DATABASE_READ, Filament::getTenant());
}
public static function canView(Model $record): bool
{
return user()?->can(Permission::ACTION_DATABASE_READ, Filament::getTenant());
}
public static function canCreate(): bool
{
return user()?->can(Permission::ACTION_DATABASE_CREATE, Filament::getTenant());
}
public static function canEdit(Model $record): bool
{
return user()?->can(Permission::ACTION_DATABASE_UPDATE, Filament::getTenant());
}
public static function canDelete(Model $record): bool
{
return user()?->can(Permission::ACTION_DATABASE_DELETE, Filament::getTenant());
}
/** @return array<string, PageRegistration> */
public static function getDefaultPages(): array
{

View File

@ -7,14 +7,11 @@ use App\Filament\Server\Resources\Files\Pages\EditFiles;
use App\Filament\Server\Resources\Files\Pages\ListFiles;
use App\Filament\Server\Resources\Files\Pages\SearchFiles;
use App\Models\File;
use App\Models\Permission;
use App\Traits\Filament\BlockAccessInConflict;
use App\Traits\Filament\CanCustomizePages;
use App\Traits\Filament\CanCustomizeRelations;
use Filament\Facades\Filament;
use Filament\Resources\Pages\PageRegistration;
use Filament\Resources\Resource;
use Illuminate\Database\Eloquent\Model;
class FileResource extends Resource
{
@ -30,26 +27,6 @@ class FileResource extends Resource
protected static bool $isScopedToTenant = false;
public static function canViewAny(): bool
{
return user()?->can(Permission::ACTION_FILE_READ, Filament::getTenant());
}
public static function canCreate(): bool
{
return user()?->can(Permission::ACTION_FILE_CREATE, Filament::getTenant());
}
public static function canEdit(Model $record): bool
{
return user()?->can(Permission::ACTION_FILE_UPDATE, Filament::getTenant());
}
public static function canDelete(Model $record): bool
{
return user()?->can(Permission::ACTION_FILE_DELETE, Filament::getTenant());
}
/** @return array<string, PageRegistration> */
public static function getDefaultPages(): array
{

View File

@ -13,7 +13,6 @@ use App\Filament\Server\Resources\Schedules\Pages\ListSchedules;
use App\Filament\Server\Resources\Schedules\Pages\ViewSchedule;
use App\Filament\Server\Resources\Schedules\RelationManagers\TasksRelationManager;
use App\Helpers\Utilities;
use App\Models\Permission;
use App\Models\Schedule;
use App\Traits\Filament\BlockAccessInConflict;
use App\Traits\Filament\CanCustomizePages;
@ -26,7 +25,6 @@ use Filament\Actions\CreateAction;
use Filament\Actions\DeleteAction;
use Filament\Actions\EditAction;
use Filament\Actions\ViewAction;
use Filament\Facades\Filament;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\Toggle;
@ -46,7 +44,6 @@ use Filament\Support\Exceptions\Halt;
use Filament\Tables\Columns\IconColumn;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\HtmlString;
use Throwable;
@ -64,26 +61,6 @@ class ScheduleResource extends Resource
protected static string|\BackedEnum|null $navigationIcon = 'tabler-clock';
public static function canViewAny(): bool
{
return user()?->can(Permission::ACTION_SCHEDULE_READ, Filament::getTenant());
}
public static function canCreate(): bool
{
return user()?->can(Permission::ACTION_SCHEDULE_CREATE, Filament::getTenant());
}
public static function canEdit(Model $record): bool
{
return user()?->can(Permission::ACTION_SCHEDULE_UPDATE, Filament::getTenant());
}
public static function canDelete(Model $record): bool
{
return user()?->can(Permission::ACTION_SCHEDULE_DELETE, Filament::getTenant());
}
/**
* @throws Exception
*/
@ -358,7 +335,8 @@ class ScheduleResource extends Resource
->state(fn (Schedule $schedule) => $schedule->status === ScheduleStatus::Active ? $schedule->next_run_at : null),
])
->recordActions([
ViewAction::make(),
ViewAction::make()
->hidden(fn ($record) => static::canEdit($record)),
EditAction::make(),
DeleteAction::make()
->after(function (Schedule $schedule) {

View File

@ -37,7 +37,6 @@ use Filament\Support\Enums\IconSize;
use Filament\Tables\Columns\ImageColumn;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Model;
class UserResource extends Resource
{
@ -63,26 +62,6 @@ class UserResource extends Resource
return $server->subusers->count();
}
public static function canViewAny(): bool
{
return user()?->can(Permission::ACTION_USER_READ, Filament::getTenant());
}
public static function canCreate(): bool
{
return user()?->can(Permission::ACTION_USER_CREATE, Filament::getTenant());
}
public static function canEdit(Model $record): bool
{
return user()?->can(Permission::ACTION_USER_UPDATE, Filament::getTenant());
}
public static function canDelete(Model $record): bool
{
return user()?->can(Permission::ACTION_USER_DELETE, Filament::getTenant());
}
public static function defaultTable(Table $table): Table
{
/** @var Server $server */

View File

@ -1,6 +1,6 @@
<?php
namespace App\Policies;
namespace App\Policies\Admin;
class ApiKeyPolicy
{

View File

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

View File

@ -1,6 +1,6 @@
<?php
namespace App\Policies;
namespace App\Policies\Admin;
use App\Models\User;
use Illuminate\Database\Eloquent\Model;

View File

@ -1,6 +1,6 @@
<?php
namespace App\Policies;
namespace App\Policies\Admin;
class EggPolicy
{

View File

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

View File

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

View File

@ -1,6 +1,6 @@
<?php
namespace App\Policies;
namespace App\Policies\Admin;
class RolePolicy
{

View File

@ -1,6 +1,6 @@
<?php
namespace App\Policies;
namespace App\Policies\Admin;
use App\Models\User;
use Illuminate\Database\Eloquent\Model;

View File

@ -1,6 +1,6 @@
<?php
namespace App\Policies;
namespace App\Policies\Admin;
class WebhookConfigurationPolicy
{

View File

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

View File

@ -0,0 +1,21 @@
<?php
namespace App\Policies\Server;
use App\Models\Permission;
use Filament\Facades\Filament;
class ActivityLogPolicy
{
protected string $modelName = 'activityLog';
public static function viewAny(): bool
{
return user()?->can(Permission::ACTION_ACTIVITY_READ, Filament::getTenant());
}
public static function view(): bool
{
return user()?->can(Permission::ACTION_ACTIVITY_READ, Filament::getTenant());
}
}

View File

@ -0,0 +1,32 @@
<?php
namespace App\Policies\Server;
use App\Models\Permission;
use Filament\Facades\Filament;
use Illuminate\Database\Eloquent\Model;
class AllocationPolicy
{
protected string $modelName = 'allocation';
public static function viewAny(): bool
{
return user()?->can(Permission::ACTION_ALLOCATION_READ, Filament::getTenant());
}
public static function create(): bool
{
return user()?->can(Permission::ACTION_ALLOCATION_CREATE, Filament::getTenant());
}
public static function edit(Model $record): bool
{
return user()?->can(Permission::ACTION_ALLOCATION_UPDATE, Filament::getTenant());
}
public static function delete(Model $record): bool
{
return user()?->can(Permission::ACTION_ALLOCATION_DELETE, Filament::getTenant());
}
}

View File

@ -0,0 +1,27 @@
<?php
namespace App\Policies\Server;
use App\Models\Permission;
use Filament\Facades\Filament;
use Illuminate\Database\Eloquent\Model;
class BackupPolicy
{
protected string $modelName = 'backup';
public static function viewAny(): bool
{
return user()?->can(Permission::ACTION_BACKUP_READ, Filament::getTenant());
}
public static function create(): bool
{
return user()?->can(Permission::ACTION_BACKUP_CREATE, Filament::getTenant());
}
public static function delete(Model $record): bool
{
return user()?->can(Permission::ACTION_BACKUP_DELETE, Filament::getTenant());
}
}

View File

@ -0,0 +1,37 @@
<?php
namespace App\Policies\Server;
use App\Models\Permission;
use Filament\Facades\Filament;
use Illuminate\Database\Eloquent\Model;
class DatabasePolicy
{
protected string $modelName = 'database';
public static function viewAny(): bool
{
return user()?->can(Permission::ACTION_DATABASE_READ, Filament::getTenant());
}
public static function view(Model $record): bool
{
return user()?->can(Permission::ACTION_DATABASE_READ, Filament::getTenant());
}
public static function create(): bool
{
return user()?->can(Permission::ACTION_DATABASE_CREATE, Filament::getTenant());
}
public static function edit(Model $record): bool
{
return user()?->can(Permission::ACTION_DATABASE_UPDATE, Filament::getTenant());
}
public static function delete(Model $record): bool
{
return user()?->can(Permission::ACTION_DATABASE_DELETE, Filament::getTenant());
}
}

View File

@ -0,0 +1,16 @@
<?php
namespace App\Policies\Server;
trait DefaultPolicies
{
/**
* This is a horrendous hack to avoid Laravel's "smart" behavior that does
* not call the before() function if there isn't a function matching the
* policy permission.
*/
public function __call(string $name, mixed $arguments): void
{
// do nothing
}
}

View File

@ -0,0 +1,32 @@
<?php
namespace App\Policies\Server;
use App\Models\Permission;
use Filament\Facades\Filament;
use Illuminate\Database\Eloquent\Model;
class FilePolicy
{
protected string $modelName = 'file';
public static function viewAny(): bool
{
return user()?->can(Permission::ACTION_FILE_READ, Filament::getTenant());
}
public static function create(): bool
{
return user()?->can(Permission::ACTION_FILE_CREATE, Filament::getTenant());
}
public static function edit(Model $record): bool
{
return user()?->can(Permission::ACTION_FILE_UPDATE, Filament::getTenant());
}
public static function delete(Model $record): bool
{
return user()?->can(Permission::ACTION_FILE_DELETE, Filament::getTenant());
}
}

View File

@ -0,0 +1,32 @@
<?php
namespace App\Policies\Server;
use App\Models\Permission;
use Filament\Facades\Filament;
use Illuminate\Database\Eloquent\Model;
class SchedulePolicy
{
protected string $modelName = 'schedule';
public static function viewAny(): bool
{
return user()?->can(Permission::ACTION_SCHEDULE_READ, Filament::getTenant());
}
public static function create(): bool
{
return user()?->can(Permission::ACTION_SCHEDULE_CREATE, Filament::getTenant());
}
public static function edit(Model $record): bool
{
return user()?->can(Permission::ACTION_SCHEDULE_UPDATE, Filament::getTenant());
}
public static function delete(Model $record): bool
{
return user()?->can(Permission::ACTION_SCHEDULE_DELETE, Filament::getTenant());
}
}

View File

@ -1,6 +1,6 @@
<?php
namespace App\Policies;
namespace App\Policies\Server;
use App\Models\Permission;
use App\Models\Server;
@ -43,14 +43,4 @@ class ServerPolicy
// Return null to let default policies take over
return null;
}
/**
* This is a horrendous hack to avoid Laravel's "smart" behavior that does
* not call the before() function if there isn't a function matching the
* policy permission.
*/
public function __call(string $name, mixed $arguments): void
{
// do nothing
}
}

View File

@ -0,0 +1,32 @@
<?php
namespace App\Policies\Server;
use App\Models\Permission;
use Filament\Facades\Filament;
use Illuminate\Database\Eloquent\Model;
class UserPolicy
{
protected string $modelName = 'user';
public static function viewAny(): bool
{
return user()?->can(Permission::ACTION_USER_READ, Filament::getTenant());
}
public static function create(): bool
{
return user()?->can(Permission::ACTION_USER_CREATE, Filament::getTenant());
}
public static function edit(Model $record): bool
{
return user()?->can(Permission::ACTION_USER_UPDATE, Filament::getTenant());
}
public static function delete(Model $record): bool
{
return user()?->can(Permission::ACTION_USER_DELETE, Filament::getTenant());
}
}

View File

@ -26,6 +26,7 @@ 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 Filament\Forms\Components\Field;
use Filament\Forms\Components\TextInput\Actions\CopyAction;
use Filament\Support\Colors\Color;
@ -169,8 +170,21 @@ class AppServiceProvider extends ServiceProvider
]);
}
Gate::before(function (User $user, $ability) {
return $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', [