Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Filament Spatie Permissions Laravel Package

madbox-99/filament-spatie-permissions

View on GitHub
Deep Wiki
Context7

Getting Started

This package wires Spatie's spatie/laravel-permission into a Filament panel, giving you a Role/Permission management UI plus form components for assigning them — so you can stop hand-crafting role screens and seeding permission rows manually.

Minimal setup:

  1. composer require madbox-99/filament-spatie-permissions and install spatie/laravel-permission if it isn't already present (the package builds on its tables, models, and cache).
  2. Publish and run migrations: php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider" then php artisan migrate.
  3. Add Spatie\Permission\Traits\HasRoles to your User model — nothing in the UI works until the trait is on the authenticatable model.
  4. Register the plugin on your panel provider (->plugin(FilamentSpatiePermissionsPlugin::make())), then php artisan filament:optimize-clear if you have caches warmed.
  5. Create a first super-admin user (php artisan make:filament-user), assign the admin role via tinker, and log in.

Your first use case should be: create a role in the generated Roles resource, tick a handful of permissions from the grouped checkbox list, assign that role to a user, then verify with $user->can('view_any_post') and a canAccessPanel() / canViewAny() override on a resource.

Where to look first: the published config file (guards, permission key naming, entity discovery), the generated RoleResource/PermissionResource classes if they're publishable in your version, and the permission-list form component you'll reuse on your User form.

v2.1.0 note: this is a minor release off v2.0.1 with no documented breaking changes or deprecations (the changelog is a bare compare link). Treat it as a safe in-range bump — use ^2.1 and run your panel's test suite after upgrading, since Filament minor bumps are the usual source of UI regressions.

Implementation Patterns

Role management as a panel resource. The default pattern is to let the plugin own Roles and Permissions entirely and keep them out of your domain seeders. Seed only the base roles (admin, editor), and let permissions be generated from your resources/policies.

Permission naming that survives refactors. Spatie permissions are strings, so pick a convention on day one and stick to it — typically {action}_{model} (view_any_post, update_post). If the plugin exposes a prefix/naming option in config, set it before creating any rows; renaming later means migrating role assignments.

Driving the checkbox list from policies instead of the DB. The most maintainable integration is to derive the permission list from your Filament resources (which map to viewAny, view, create, update, delete, deleteAny, restore, forceDelete). Group by resource label in the form's ->options() so admins see "Post → Update" rather than update_post. Generate permissions in a seeder from the same source, so UI and code can't drift.

Assigning roles on the User form. Reuse the package's role/permission select component inside your own UserResource schema, usually as a Select::make('roles')->relationship('roles', 'name')->multiple()->preload(). For per-user overrides (rare, but real), add a separate permissions field above the role field and be explicit that direct permissions are additive on top of role permissions.

Gate::before for super admin. Give yourself an escape hatch in AuthServiceProvider::boot():

Gate::before(fn ($user) => $user->hasRole('super_admin') ? true : null);

Return null, not false, or you'll short-circuit every other check.

Panel-level access control. In canAccessPanel(), check a role or ->can(...) rather than ->hasRole() where you want permission granularity. This is the one integration point every project needs and it's easy to forget until a non-admin logs into /admin.

Policy + Filament wiring. Permissions only become authorization once your policies call $user->can(...). Filament's default policies already map actions to those permission names, so php artisan make:policy PostPolicy --model=Post plus the generated permission rows gets you 90% there.

Multi-panel setups. If you run several panels (admin, staff, customer), scope roles per guard and set the plugin's guard explicitly per panel. Sharing a single guard across panels with different role sets gets confusing fast.

Teams / tenancy. If you use Spatie's teams feature, set teams => true in the Spatie config before migrating, and add the team_id context to your panel (usually via a tenant relationship). The generated UI assumes a non-tenant permission set unless you've configured teams, so verify role scoping early — retrofitting teams onto populated tables is painful.

Gotchas and Tips

The permission cache is the #1 debugging trap. Spatie caches the permission table. After seeding, importing, or editing rows outside the UI you'll see stale can() results. Run php artisan permission:cache-reset (or cache:forget spatie.permission.cache) and remember that your deployment script should do this whenever permissions ship in a seeder.

Guard mismatches produce silent failures. If your panel uses the web guard but roles were created under sanctum, hasRole() returns false with no error. Check config/auth.php defaults, then confirm the guard_name column on the roles/permissions rows actually matches. This is the second most common "the plugin is broken" report and it never is.

HasRoles missing on the model. If the Roles resource renders but assignment does nothing, the trait isn't on User (or you're using a different authenticatable model than the config assumes).

Role deletion vs. cascade. Deleting a role in the UI removes assignments via Spatie's own logic, but direct permissions assigned to users persist. Audit model_has_permissions after any bulk role cleanup.

Don't edit the generated resources in place if they're publishable. Publish them into your app so upgrades don't overwrite your customizations — but note that publishing also means you own merges on every release. For v2.1.0 this matters: if you published v2.0.1 resources, diff them before assuming the bump is free.

Extend via the plugin object and config, not by forking. Most day-to-day needs (navigation group, label, guard, hiding the Permissions resource from non-supers) are configuration or ->navigationLabel() style calls. The permission-options callback on the form component is the intended extension point for custom grouping — use it rather than subclassing the resource.

N+1 in role tables. The Roles list eager-loads permissions per row by default; with many roles and hundreds of permissions, add ->modifyQueryUsing(fn ($q) => $q->withCount('permissions')) and show a count column instead of badges.

Testing. Use RefreshDatabase plus a seeder that creates roles/permissions, then actingAs($admin) in Filament tests. Call app(PermissionRegistrar::class)->forgetCachedPermissions() in setUp() to avoid cross-test bleed.

Watch the Filament major version. This plugin tracks Filament's component API; a Filament major bump (v3 → v4) will be the breaking event, not this package's minor. Pin both and upgrade them together.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums
rlacerda83/query-parser
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings