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 Inverse Shield Laravel Package

drafolin/filament-inverse-shield

A Filament plugin that inverts the usual Shield permissions workflow, letting your existing Laravel policies and gates drive access control in Filament panels instead of pre-generated permission records. Keeps authorization logic in one place.

View on GitHub
Deep Wiki
Context7

Getting Started

drafolin/filament-inverse-shield flips the usual Filament Shield workflow: instead of generating one permission per resource/action and then hand-assigning them to roles, you define roles (and their abilities) up front, and the plugin enforces those roles across your panel's resources, pages and widgets. Day to day, that means less permission-table churn and more "which role owns this screen" thinking.

Minimal path to a working setup:

  1. composer require drafolin/filament-inverse-shield — this is a ^1.4 line; no breaking changes in 1.4.8, so bumping a patch is safe.
  2. Publish the package's config (and any migrations/seeders it ships) via the vendor:publish tags listed in the README, then php artisan migrate.
  3. Register the plugin on your panel in app/Providers/Filament/*PanelProvider.php — the standard Filament v3 shape:
    ->plugin(\Drafolin\FilamentInverseShield\FilamentInverseShieldPlugin::make())
    
  4. Run the package's seed command/seeder to bootstrap the admin role, then attach that role to your own user and log in.
  5. First use case: lock a whole panel down to admins. Create a second user with no role, hit /admin, and confirm you get a 403 rather than a dashboard. Do this before you build any resources — retrofitting access control onto a half-built panel is where most of the pain lives.

Where to look first: the published config (it drives the role/ability mapping and guard selection), then the plugin class, then your User model — the package expects the role relationship to be reachable from the authenticatable model.

Implementation Patterns

Role-first modelling. Decide your role taxonomy before writing resources: something like super_admin, admin, editor, viewer. Each resource then falls into a role's bucket, and adding a new resource becomes "which role should see this?" rather than "which twelve permissions do I create?"

Seeder-driven role definitions. Keep role definitions in code (a seeder or a small config array) and run it as part of deploy. This is exactly what 1.4.8 touches: previously the seeder could clobber attributes on an existing admin role; now all attributes are preserved on re-seed. Practically, this makes re-running the seeder in a deploy hook safe and idempotent — you can add it to your release script without fearing it will reset customised role metadata every deploy.

Per-panel guards. If you run multiple panels (e.g. admin and app), set the guard per panel in config rather than relying on the default web guard. Mixed guards are the single most common cause of "the user has the role but nothing is allowed."

Custom pages and widgets. Package enforcement is strongest on resources it can resolve to a model. For custom Filament Pages and dashboard widgets, add public static function canAccess(): bool (pages) or canView() (widgets) and delegate to the same role check the plugin uses. Don't assume registration alone protects them.

Fine-grained overrides. Where a role needs a narrower slice than "full CRUD on this resource", drop a policy in app/Policies — Laravel's policy resolution wins, and the plugin's coarse role gate stays as the outer boundary.

Testing. Use RefreshDatabase plus your role seeder, then actingAs($user) and assert assertForbidden() / assertOk() per resource page. One test per role per panel catches almost every regression when a new resource is added without an access decision.

Gotchas and Tips

  • Permission cache. Spatie's permission cache survives seeding. After changing roles in code or in a seeder, run php artisan permission:cache-reset (or cache:forget spatie.permission.cache) in deploy. Symptom is "the role exists in the DB but the UI still says no."
  • Seeder drift. Since 1.4.8 preserves attributes on re-seed, manual edits to the admin role in production will now persist rather than being silently normalised. That's the desired behaviour, but it means prod can drift from code — treat the seeder as source of truth and don't hand-edit roles in the UI.
  • canAccessPanel() is not optional. Filament lets any authenticated user into a panel unless the model implements canAccessPanel(). The plugin gates resources, not the panel shell. A user with zero roles can still land on an empty dashboard if you skip this.
  • Gate::before super-admin bypass. If you register a Gate::before for super admins, it bypasses everything, including your custom policies. Convenient, but it hides bugs during development — test as a non-super-admin.
  • Stale caches after adding resources. php artisan filament:optimize-clear (and optimize:clear in CI) after adding resources/pages, otherwise navigation and access decisions lag behind your code.
  • Guard mismatch debugging. When access silently fails, dump $user->getRoleNames() and $user->roles->pluck('guard_name') — if the guard doesn't match the panel's auth guard, nothing else matters. Check the published config's guard setting first.
  • Don't install alongside bezhansalleh/filament-shield. They solve the problem from opposite directions and will fight over policies and permission naming. Pick one.
  • Extension points. The plugin class and published config are the intended hooks — subclass the plugin to change resource-to-role resolution, and publish views if you want the role UI to match your admin theme. Prefer that over editing vendor files, which a patch release like 1.4.8 will overwrite.
  • Upgrading. 1.4.8 is a bugfix on the seeder path only; no migration or config changes required. If you were working around the attribute-clobbering by re-setting role attributes post-seed, that workaround can be removed.
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.
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle