Filament Shield Documentation

repository·main·Indexed 25 days ago

https://github.com/bezhansalleh/filament-shield

An access management solution for Filament panels that automates permission and policy management for resources, pages, and widgets. It features automatic policy generation, support for custom ad-hoc permissions, multi-tenancy, and super admin role interception. Compatible with Filament versions 4.x and 5.x.

Tokens
8.4K
Snippets
18
Records
51
Agent score
78%

What's inside Filament Shield

  1. Overview of Filament Shield

    main
    Filament Shield is an access management package for Filament panels. It provides complete authorization management for Resources, Pages, and Widgets, along with automatic policy generation and support for custom (ad-hoc) permissions. It also supports multi-tenancy, super admin role interception, and localized permission labels.
  2. Configure the Auth Provider for Shield

    main

    To use Shield, you must configure your authentication provider model (e.g., User) to work with the package.

    1. Publish the configuration file:
      php artisan vendor:publish --tag="filament-shield-config"
    2. Set the auth_provider_model in config/filament-shield.php to your User model class.
    3. Add the Spati\\Permission\\\|Traits\\\|HasRoles trait to your User model.
    php artisan vendor:publish --tag="filament-shield-config"
  3. Upgrade from 3.x to 4.x

    main

    Upgrading to 4.x involves significant architectural changes. Follow these steps:

    1. Backup your database.
    2. Remove old files: Delete filament-shield.php config and any published RoleResource.
    3. Update: Run composer require bezhansalleh/filament-shield.
    4. Publish new assets:
      • php artisan vendor:publish --tag="filament-shield-config"
      • php artisan shield:publish --panel=admin
    5. Handle Permissions:
      • Clean Slate: Run php artisan shield:setup --fresh.
      • Preserve Data: If you need to keep existing roles, you must manually add a FilamentShield::buildPermissionKeyUsing() closure to your AppServiceProvider to replicate the old permission key pattern (snake_case vs the new pattern).
    6. Regenerate: Run shield:generate to ensure policies are up to date.
  4. Enforce Shield-generated Policies

    main

    If your models are located in directories that Laravel's automatic policy discovery cannot find (such as nested under a custom policies.path or for vendor models), you must manually register them.

    The easiest way is to use the FilamentShield::enforcePolicies() method in your application's boot() method within a Service Provider.

    Features:

    • Lazy Evaluation: You can pass a closure to gate enforcement per panel or tenant.
    • Exclusions: Use the except parameter to skip specific models.
    • Priority: Explicit Gate::policy() registrations always take precedence over Shield's enforcement.
  5. Enforce Page and Widget Permissions with Traits

    main

    To automatically hide navigation items or restrict access to Pages and Widgets based on permissions, use the provided Shield traits within your class.

    For Pages: Use the HasPageShield trait.

    For Widgets: Use the HasWidgetShield trait.

    // For Pages
    namespace App\Filament\Pages;
    
    use ...;
    use BezhanSalleh\FilamentShield\Traits\HasPageShield;
    
    class MyPage extends Page
    {
        use HasPageShield;
        ...
    }
    
    // For Widgets
    namespace App\Filament\Widgets;
    
    use ...;
    use BezhanSalleh\FilamentShield\Traits\HasWidgetShield;
    
    class IncomeWidget extends LineChartWidget
    {
        use HasWidgetShield;
    }
  6. Prohibit destructive Shield commands in production

    main

    To prevent accidental data loss in production environments, you can prohibit destructive Shield commands (like generate, install, setup, etc.) by calling the prohibit method in your service provider's boot() method.

    You can prohibit commands individually or use the FilamentShield::prohibitDestructiveCommands() helper to prohibit all of them at once.

    use BezhanSallehilament-shield//Facades\
    use BezhanSalleh\FilamentShield\Commands;
    
    public function boot(): void
    {
        // Prohibit all destructive commands at once
        FilamentShield::prohibitDestructiveCommands($this->app->isProduction());
    }
  7. Define Custom Permissions

    main

    You can define ad-hoc permissions that do not belong to Resource, Page, or Widget categories by adding them to the custom_permissions array in your configuration file. These permissions will appear in a Custom Permissions tab within the Role Resource if the tab is enabled.

    To enable the Custom Permissions tab in the Role Resource, set shield_resource.tabs.custom_permissions to true in your configuration.

    'custom_permissions' => [
        'Impersonate:User' => 'Impersonate User',
        'Export:Order' => 'Export Orders',
    ],
  8. Configure Custom Permission Formatting

    main

    Custom permission keys are formatted based on your case and separator settings. Shield's formatter is fault-tolerant and normalizes various input formats (snake_case, kebab-case, camelCase, etc.) before applying the target case.

    If your permissions are managed by external providers (like Terraform or Keycloak) and must retain their exact key names, set format_custom_permission_keys to false in the permissions configuration block. This prevents any case conversion from being applied to custom permissions.

    'permissions' => [
        'separator' => ':',
        'case' => 'pascal',
        'generate' => true,
        'format_custom_permission_keys' => false,
    ],
  9. Configure Page and Widget Permissions

    main

    Shield provides permission models for Filament Pages and Widgets. By default, they require view permissions.

    Pages Configuration

    'pages' => [
        'subject' => 'class',
        'prefix' => 'view',
        'exclude' => [
            \Filament\Pages\Dashboard::class,
        ],
    ],

    Widgets Configuration

    'widgets' => [
        'subject' => 'class',
        'prefix' => 'view',
        'exclude' => [
            \Filament\Widgets\AccountWidget::class,
            \Filament\Widgets\FilamentInfoWidget::class,
        ],
    ],

    Options

    • subject: class (uses class name) or model (uses static getModel()).
    • prefix: A string prepended to permission keys (e.g., Page:IconLibrary).
    • exclude: List of entities to skip.
  10. Configure permission key generation settings

    main

    You can customize how permission keys are generated (naming conventions, separators, and casing) in the filament-shield.php configuration file.

    Important Compatibility Rule: The separator must not conflict with the chosen case delimiter. For example, using _ with snake or - with kebab will throw an InvalidArgumentException because the system cannot distinguish the affix from the subject.

    'permissions' => [
        'separator' => ':',
        'case' => 'pascal',
        'generate' => true,
        'format_custom_permission_keys' => true,
    ],