Download the PHP package kirchdev/laravel-pbac without Composer
On this page you can find all versions of the php package kirchdev/laravel-pbac. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download kirchdev/laravel-pbac
More information about kirchdev/laravel-pbac
Files in kirchdev/laravel-pbac
Package laravel-pbac
Short Description Policy-based access control for Laravel: roles, permissions, organisation-scoped authorization, Gate integration, and a decision cache.
License MIT
Homepage https://github.com/kirchDev/laravel-pbac
Informations about the package laravel-pbac
That's it. Tenant-aware authorization in one line, native Laravel Gate semantics, no manual scope plumbing.
β¨ Features
- π Roles & permissions β plain Eloquent models you can swap out for your own (UUID / ULID / int keys).
- π’ Organisation/tenant scoping β first-class, with a pluggable
OrganisationResolver. Scopes never bleed across tenants. - πͺ Native
Gateintegration β$user->can(),Gate::allows(),Gate::inspect()all Just Work, with fallback to native Laravel gates. - β‘ Per-request decision cache β repeated checks within a request are free. Auto-invalidates on role/permission mutations.
- π Decision trace β opt-in audit trail of why a check returned what it did. Redacted in production by default.
- π Octane-aware β optional reset listeners on
RequestTerminated,TaskTerminated,TickTerminated. No stale state across requests. - π§° Heavy configuration β model / table / column / key types all overridable. UUID setups supported out of the box.
- π§ͺ Library-grade β Pest 4 + Testbench, no host app needed.
π¦ Installation
Publish and run the migrations:
Optionally publish the config:
π Quick start
Add the HasRoles trait to whichever model should be authorizable:
Create roles, attach permissions, assign, check:
π’ Multi-tenant authorization
Enable organisation scoping:
Scope authorization for the current request:
The decision cache resets on scope enter/exit, so checks never bleed across tenants.
Assigning global roles when org scoping is enabled
To prevent silent mis-targeting, role mutations by name refuse to resolve a global role unless the caller signals intent. Pass global: true, or wrap the call in Pbac::withoutOrganisation() and assign by Role instance:
Inside an active organisation scope, $user->assignRole('owner') resolves the org-scoped row only β global rows with the same name are deliberately invisible to mutations without the explicit flag.
Bring your own resolver (e.g. backed by a tenancy package or route binding):
Wire it via pbac.organisation.resolver.
π Decision trace
Wondering why a permission check returned what it did? Turn on tracing:
Gate::inspect() carries the decision's reason code via Response::message():
For the human-readable trace, reach for the last decision through the Pbac facade:
Production redacts trace context arrays by default (step names stay; values are stripped). Opt in to the full trace per request when you need it β e.g. for an admin debug route:
π§Ή Cascade behaviour on delete
Foreign keys are deliberately set to ON DELETE CASCADE so the indexes never carry stale grants or assignments. Mark this on your operational checklist:
| When you delete⦠| These rows go away automatically |
|---|---|
A Role |
All role_has_permissions rows for that role + all model_has_roles rows. |
A Permission |
All role_has_permissions rows referencing it. |
A host model (e.g. User) row |
Not automatic. model_has_roles rows on the morph side are orphaned. |
The host-model side is polymorphic (model_type + model_id), so no FK enforces it. Hook your model's deleting/deleted events or run a periodic prune job if user/team deletions are part of your normal flow. If you need an audit trail of historical grants/assignments, capture it before deletion β once the cascade fires, the rows are gone.
βοΈ Configuration highlights
config/pbac.php is heavily parameterised β see the file for inline docs. Most common knobs:
| Key | What it controls |
|---|---|
models.* |
Swap any of the 4 Eloquent models (Role / Permission / RoleAssignment / RolePermission). |
table_names.* |
Override defaults if they collide with existing tables. |
keys.* |
id / uuid / ulid for primary keys, model morphs, target morphs, org FK. Set before migrations. |
column_names.* |
Pivot and morph key column names (handy for UUID setups). |
organisation.enabled / .resolver |
Toggle multi-tenancy, plug a custom resolver. |
gate.fallback_to_laravel_gates |
Whether unmatched abilities fall back to native Laravel gates. |
trace.enabled |
Capture per-decision explanations. Redacted in prod by default. |
cache.decision_store |
Decision cache backend (request by default). |
register_octane_reset_listener |
Reset scoped state at Octane worker boundaries. |
π Migrating from spatie/laravel-permission
Coming from spatie/laravel-permission? See the dedicated guide for schema, API,
and multi-tenancy differences plus a copy-pasteable data-migration script:
docs/migration-from-spatie-laravel-permission.md.
π§ͺ Testing
The test suite runs via Testbench + in-memory SQLite β no host app required.
π€ Contributing
PRs welcome. Conventional Commits required (enforced via commitlint). Husky runs Pint + Larastan + oxlint + oxfmt on git commit, so you can mostly forget about style.
[!TIP] Run
pnpm check:fix(Node tooling) andcomposer pint:fix(PHP) before pushing β CI will catch what husky missed.
π£οΈ Versioning
Semantic Versioning. Release notes in release-please.
π License
IT-Dienstleistungen Titus Kirch
All versions of laravel-pbac with dependencies
illuminate/auth Version ^13.0
illuminate/contracts Version ^13.0
illuminate/database Version ^13.0
illuminate/events Version ^13.0
illuminate/support Version ^13.0