Open source
Permissions for Laravel
composer require roundly-consulting/permissions-for-laravelOverview
Native roles and permissions for Laravel. Give any Eloquent model roles and direct permissions, resolve effective permissions (direct ∪ via roles), and let Laravel’s own Gate, can: middleware and $user->can() authorize against them — without ever overriding your model policies. Single-guard, cache-backed with automatic invalidation, and additive by default, so independent modules can register their own grants safely. One Permissions facade covers the catalog and every grant, and Permissions::fake() records each write in your tests. MIT-licensed, with zero third-party runtime dependencies.
What you get
Roles & direct permissions
Give any Eloquent model roles and direct grants. Effective permissions are direct ∪ via-roles, de-duplicated.
Native Gate integration
can: middleware, $user->can() and Gate resolve permissions out of the box — model policies keep the final say.
Additive by default
givePermissionTo() never strips another caller’s grants; syncPermissions() sets the exact set when you mean it.
Self-invalidating cache
The permission catalog is cached and flushed once every grant or role/permission change commits — Octane- and queue-safe.
Enums & any key type
Pass strings or backed enums everywhere and bootstrap the catalog with syncFrom(); holders may use bigint, UUID or ULID keys.
Facade, DI or actions
Use the Permissions facade, inject PermissionsManager or call an action; Permissions::fake() records every write for your tests.
Translatable descriptions
Per-locale role and permission descriptions with a deliberate, non-disclosing fallback chain.
Orphan-safe cleanup
forgetAllAuthorization() and pruneOrphans() stop a new record from inheriting a deleted holder’s grants.
Documentation
Installation
Install via Composer, publish the config first, then publish and run the publish-only migrations.
Configuration
Every config key and its default — models, table names, holder key type, Gate hook, description fallback and cache.
Database schema & key types
The five tables, their fixed columns, and how key_type types model_id for bigint, UUID or ULID holder models.
The HasRoles trait
Add HasRoles to any authenticatable model to give it roles, direct permissions and effective-permission resolution.
The Permissions facade
Every entry point on one facade: the role and permission catalog, enum sync, per-holder grants, cache, pruning and the fake.
DI and actions
Inject PermissionsManager instead of the facade, or call the single-purpose actions directly — with the facade-to-action map.
Roles & permissions
Create roles and permissions idempotently through the facade, look them up, seed them safely on every deploy and read their relations.
Granting permissions
Grant, revoke and sync permissions on roles or directly on a model — additive by default, authoritative when you ask.
Assigning roles
Assign, remove and sync roles on any holder; permissions granted to a role flow to every model that holds it.
Checking access
Check roles and effective permissions, list names and grants, eager-load for bulk checks, and query holders by role.
Backed enums
Pass your own backed enums anywhere a role or permission name is accepted — persisted as the enum’s value.
Gate & middleware
Authorize with can: middleware, $user->can() and Gate — without ever overriding your model policies.
Translatable descriptions
Per-locale role and permission descriptions via translatable-for-laravel, with a deliberate, configurable fallback.
Caching
The cached permission catalog, its after-commit invalidation, bulk-write caveats and Octane and queue-worker behaviour.
Deleting holders
Stop a new record from inheriting a deleted holder’s grants — detach on delete, or prune orphaned pivot rows.
Custom models & tables
Swap in your own Role and Permission subclasses, rename the tables, and resolve the configured setup in code.
Artisan commands
Flush the permission cache, prune orphaned grant rows, and inspect the package setup with php artisan about.
Exceptions
One exception family — PermissionException, RoleDoesNotExist and PermissionDoesNotExist — with translatable messages.
Testing
Record every role and permission write with Permissions::fake() and 26 assertions, then test end-to-end with factories and HTTP.
Requirements
PHP 8.4+, Laravel 12 or 13, and three Roundly packages that Composer installs for you.
Show your open-source love
This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.
More ways to support, including cryptoBy donating, you agree to our donation terms.
Want this built into your product?
We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.