Installation:
composer require bezhansalleh/filament-shield
Publish the config and migrations:
php artisan vendor:publish --provider="BezhanSalleh\FilamentShield\FilamentShieldServiceProvider"
php artisan migrate
Register the Plugin:
Add to app/Providers/Filament/AdminPanelProvider.php:
public function panel(Panel $panel): Panel
{
return $panel
->plugins([
\BezhanSalleh\FilamentShield\FilamentShieldPlugin::make(),
]);
}
First Use Case:
admin, editor).config/filament-shield.php (customize default roles/permissions).database/migrations/..._create_permission_tables.php (if extending tables).Role-Permission Assignment:
create posts, manage users).User Role Management:
use BezhanSalleh\FilamentShield\Enums\PermissionGroup;
use BezhanSalleh\FilamentShield\Enums\PermissionName;
if (auth()->user()->can(PermissionName::MANAGE_USERS)) {
// Allow action
}
Policy Integration:
PostPolicy) to use Shield permissions:
public function create(User $user)
{
return $user->can(PermissionName::CREATE_POSTS);
}
Filament Resources: Disable actions conditionally:
public static function getPages(): array
{
return [
'index' => fn() => auth()->user()->can(PermissionName::VIEW_POSTS),
'create' => fn() => auth()->user()->can(PermissionName::CREATE_POSTS),
];
}
Middleware:
Use Can middleware for API routes:
Route::get('/admin/posts', [PostController::class, 'index'])
->middleware(['auth', new Can(PermissionName::VIEW_POSTS)]);
Custom Groups:
Define permission groups in config/filament-shield.php:
'groups' => [
'posts' => [
'create_posts',
'edit_posts',
'delete_posts',
],
],
Permission Caching:
php artisan cache:clear
auth()->user()->syncPermissions() manually.Filament Version Mismatch:
filament-shield matches your Filament version (4.x vs. 5.x). Check the release notes.Overlapping Roles:
edit_posts and delete_posts to non-admin roles). Use role hierarchies in Shield.Migration Conflicts:
spatie/laravel-permission tables, run:
php artisan permission:table
before migrating.Permission Checks: Log user permissions for debugging:
\Log::info('User permissions:', auth()->user()->getAllPermissions()->toArray());
Widget Visibility: Hide the Shield widget for non-admins:
\BezhanSalleh\FilamentShield\FilamentShieldPlugin::make()
->visible(fn() => auth()->user()->can(PermissionName::MANAGE_ROLES)),
Custom Permission Models:
Extend HasPermissions trait to add fields:
use BezhanSalleh\FilamentShield\Traits\HasPermissions;
class User extends Authenticatable
{
use HasPermissions;
protected $casts = [
'permissions' => 'array',
'role' => 'string',
];
}
Dynamic Permissions: Fetch permissions from an external API:
public function boot()
{
\BezhanSalleh\FilamentShield\Permission::created(fn($permission) => $this->syncExternalPermission($permission));
}
Localization:
Translate permission names/groups in resources/lang/en/permissions.php:
return [
'create_posts' => 'Create Posts',
];
Bulk Actions: Use the Shield > Roles bulk select to assign permissions to multiple roles at once.
Audit Logging:
Combine with spatie/laravel-activitylog to track permission changes:
\Spatie\Activitylog\Models\Activity::create([
'log_name' => 'permission_updated',
'properties' => ['permission' => $permission->name],
]);
Testing: Mock permissions in tests:
$user = User::factory()->create();
$user->givePermissionTo('edit_posts');
$this->actingAs($user);
How can I help you explore Laravel packages today?