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

iracode-com/filament-organizational-shield

Filament Organizational Shield brings hierarchical, organization-based access control to Filament panels, letting you scope resources, queries, and actions to a user's department or branch so admins only see and manage records within their own part of the company tree.

View on GitHub
Deep Wiki
Context7

Getting Started

  • Install with composer require iracode-com/filament-organizational-shield, publish config (and migrations/stubs if tagged) via vendor:publish, then run migrations. The migrations should add organization/department/team tables, pivots, and an organization_id-style FK on users and other tenant-owned tables. Confirm the service provider is auto-discovered; otherwise register it in bootstrap/providers.php.
  • Look first at the published config file. That is where model class names, the user→organization relation, tenant column names, and hierarchy settings live. Every mismatch between the package defaults and your schema shows up here, not in vendor code.
  • Register the plugin in your panel provider (->plugin(...)) and confirm the panel's tenant/context resolver is configured, since the shield needs to know the current organization before it can scope anything.
  • First use case: scope a single resource to the current user's organization. Apply the package trait/interface to the model and resource, write the policy, then log in as two users in different organizations and verify (a) the index only lists their own records and (b) hitting another org's record URL returns 403. Do this before scaling to every resource.
  • Expect to read source. The package is very small (2 stars, last release 2024-08-27) and docs are thin — confirm the exact trait names, method signatures, and config keys in vendor/iracode-com/filament-organizational-shield before wiring anything up.

Implementation Patterns

  • Scope at the model, authorize at the policy. Let Eloquent global scopes filter queries so list views, relation managers, and widgets are all covered at once; use policies/gates for per-action decisions. Doing only one of the two leaves a hole — policies don't filter index queries, and scopes don't stop direct ID access.
  • Resolve tenant context early. Set the current organization from the authenticated user (or Filament's panel tenant) in middleware or panel configuration. Everything downstream assumes context is non-null; a null context is the classic unscoped-data bug.
  • Hierarchy checks via the configured relations. For "own department and descendants" rules, traverse the department/team tree using the package's configured relations, and cache the resolved subtree per request so policy checks don't cause N+1 queries.
  • Per-page field configuration. Keep index columns, create fields, and edit fields separate. v1.1.1 removes password from the User resource create page — that only works cleanly if the create form and edit form are defined independently.
  • Pair user creation with your own flow. Since create no longer collects a password, seed it from an invite token, generated password, or a separate "set password" step so the users row satisfies your constraints. On edit, keep password nullable with a hashed cast (blank = keep existing).
  • One panel per boundary, or explicit tenant switching. The package is advertised as multi-tenant ready; choose deliberately between separate admin/org-admin panels and a single panel with a tenant switcher, and document which. Mixing both usually produces confusing scope behavior.
  • Test the boundaries, not the happy path. Feature tests that log in as users from different branches and assert 200/403 and record counts are the cheapest guard against scope regressions, especially since upstream support is minimal.

Gotchas and Tips

  • The v1.1.1 fix is a stub change. composer update will not modify your already-published UserResource. You must remove the password field from the create form yourself or regenerate — don't assume the update fixed your UI.
  • Password confirmation mismatch. Dropping password from create while leaving password_confirmation breaks confirmed validation. Remove both, or keep both and hash correctly.
  • Hashing is not automatic. Any password field that survives (notably on edit) must be hashed via cast or mutator. Writing a raw string to the column silently locks the user out.
  • Direct-access bypass. A global scope hides records from lists but a policy gap still allows /resource/{id}/edit. Test cross-org URL access explicitly; this is where most leaks appear.
  • Null tenant context. If the resolver runs after the query, or the user has no organization, scoping silently degrades to "see everything." Fail closed rather than open.
  • Hierarchy integrity. Cycles or orphaned parent IDs in department/team trees break descendant queries. Enforce FK constraints and consider a level/path column for cheap traversal.
  • Caching masks changes. After editing config, policies, or resources, run php artisan optimize:clear. Stale cached config is the usual explanation for "scoping still isn't applied."
  • Debugging checklist: php artisan route:list for the endpoint, toSql() on the resource's index query to confirm the scope is present, dump the resolved tenant inside the policy, and verify policy discovery (class name and location).
  • Extension points: override the resource's form/table methods, write custom policies, and use published config/stubs — never edit vendor files. The package is low-activity, so published stubs rarely change; diff them on each release and pin the version.
  • Wrap the package. Because docs are sparse and method names may shift, put the traits and config lookups behind your own base resource/policy class so an upstream rename is a one-file change.
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.
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
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