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 Gatekeeper Laravel Package

laraarabdev/filament-gatekeeper

Filament Gatekeeper adds a streamlined authorization management layer to Filament panels, helping you organize and control access to resources and actions. It simplifies defining permissions and assigning them to users, so teams can manage who can do what directly from the admin UI.

View on GitHub
Deep Wiki
Context7

Getting Started

Install the package and publish its assets/config:

composer require laraarabdev/filament-gatekeeper
php artisan vendor:publish --tag="filament-gatekeeper-config"
php artisan vendor:publish --tag="filament-gatekeeper-migrations"
php artisan migrate

Register the plugin on each panel you want guarded in your PanelProvider:

->plugin(GatekeeperPlugin::make())

Then run the discovery pass that writes permissions for your Filament resources:

php artisan gatekeeper:discover

Where to look first:

  1. config/filament-gatekeeper.php — discovery toggles, naming/prefix conventions, cache settings, super-admin bypass.
  2. The generated permissions table (permissions / package table) — this is the source of truth the panel reads from.
  3. Your first Resource — the fastest sanity check is a single Resource with one form field and one table column.

First use case: open a Resource, run discovery, and confirm two permission entries appear (one for the field, one for the column). Log in as a user without them and verify the field/column is hidden. That end-to-end loop (discover → assign → verify) is the whole package in miniature; everything else is scaling it up.

Implementation Patterns

Auto-discovery as the default workflow. The package walks your Filament resources, extracts form fields and table columns, and derives permission names from them. Rather than hand-writing a policy per resource, you let discovery generate the keys and then attach them to roles. v1.1.5 deduplicates this discovery, so a field that appears in both a form schema and a table (or a column repeated across a resource and its relation manager) resolves to a single permission instead of duplicated entries — see the rewritten README for the full auto-discovery contract (what gets scanned, how names are built, how to opt out).

Discovery in the deploy pipeline. Treat gatekeeper:discover as a deploy step, not a one-off. A typical flow:

php artisan migrate --force
php artisan gatekeeper:discover --no-interaction
php artisan permission:cache-reset   # or the package's cache command
php artisan optimize

Discovery is idempotent, so running it on every deploy keeps permissions in sync as resources evolve. Run it after migrations and before config/route caching so newly added fields exist when the panel boots.

Resource-scoped permission naming. Discovery derives names from the resource and the field/column key, which means renaming a field silently orphans its permission. If you need long-lived keys, set the field name explicitly and keep it stable:

TextInput::make('internal_notes') // permission key derived from 'internal_notes'

Where the package exposes a prefix/grouping option in the config, use it to namespace by panel or domain — this makes role assignment far more legible in the UI and keeps multi-panel installs from colliding.

Layering with policies. Discovery gives you the keys; policies give you the rules. Keep coarse access (viewAny, view, create, update, delete) in policies as usual, and use the package's field/column permissions for the finer-grained "can this user see this specific input" question. Don't duplicate the coarse checks in field permissions — you'll end up debugging two competing sources of truth.

Progressive hardening. Roll out per-resource, not globally. Enable discovery for one Resource group, verify, then widen via the config allow/deny list. This keeps the blast radius small when a naming convention doesn't match your expectations.

Relation managers and nested schemas. Resources with relation managers produce additional discovered entries. Verify a resource with at least one relation manager before assuming the flat case generalizes — nested schemas are the most common source of unexpected duplicates (and the area v1.1.5's dedup most directly improves).

Gotchas and Tips

  • Upgrade to v1.1.5 means re-run discovery. Deduplication changes the number and potentially the shape of generated permissions. If you seeded roles against duplicated entries, re-run gatekeeper:discover and re-check role assignments — a role pointing at a now-collapsed duplicate may end up with a permission that no longer exists.
  • Dynamically built schemas are not discoverable. Fields constructed inside closures, ->when() conditionals, or loops over runtime data won't be seen as static schema components. If a field must be guarded, declare it statically and gate it with ->visible() instead.
  • Repeaters, builders, and wizard steps. Components nested inside these are discovered by their nested path, not their bare name. Check the generated names before wiring roles to them — items.name and name are different keys.
  • Renaming a field is a breaking change to your permission graph. There is no automatic migration of permission names. Either keep field names stable or write a one-off migration renaming the corresponding rows.
  • Stale permission cache after discovery. Discovery writes rows; the panel reads from cache. Always clear the permission/cache layer after running discovery, especially in CI where the artisan commands run in a fresh container.
  • Super-admin bypass masks bugs. With the bypass enabled, an admin account will see everything regardless of whether discovery actually produced the right keys. Test as an unprivileged user before concluding discovery works.
  • Table columns are a separate surface from form fields. A user who can see the input may still be denied the column. Verify both states per permission, plus the "column hidden but sortable/filterable" case, which often leaks data through filters.
  • Debugging: inspect the discovered map. Before assigning anything, dump what discovery resolved (verbose flag or the artisan command output) and diff it against the resource you expect. Most "permission doesn't exist" reports are a discovery miss, not a role assignment error.
  • Extension points. Where the config exposes a custom resolver/naming strategy, prefer it over post-processing generated permissions — post-processing drifts the moment someone adds a resource and forgets the step.
  • Not in this release: the CI fix (grep over bash regex) is internal only and affects nothing at runtime. The functional change to care about in v1.1.5 is deduplication, and the practical change is that the README now documents the auto-discovery contract properly — read it before assuming which of your components get scanned.
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