maxiviper117 / laravel-access
Simple explicit scoped permissions for Laravel applications.
Fund package maintenance!
Requires
- php: ^8.4
- illuminate/contracts: ^11.0||^12.0||^13.0
- spatie/laravel-package-tools: ^1.16
Requires (Dev)
- larastan/larastan: ^3.0
- laravel/pint: ^1.14
- nunomaduro/collision: ^8.8
- orchestra/testbench: ^11.0.0||^10.0.0||^9.0.0
- pestphp/pest: ^4.0
- pestphp/pest-plugin-arch: ^4.0
- pestphp/pest-plugin-laravel: ^4.0
- phpstan/extension-installer: ^1.4
- phpstan/phpstan-deprecation-rules: ^2.0
- phpstan/phpstan-phpunit: ^2.0
- rector/rector: ^2.4
- dev-main
- v0.1.1
- v0.1.0
- dev-dependabot/github_actions/actions/checkout-6
- dev-dependabot/github_actions/actions/setup-node-6
- dev-dependabot/github_actions/actions/upload-pages-artifact-5
- dev-dependabot/github_actions/actions/deploy-pages-5
- dev-dependabot/github_actions/pnpm/action-setup-6
- dev-release-please--branches--main--components--maxiviper117/laravel-access
- dev-codex/access-seeder-command
This package is auto-updated.
Last update: 2026-05-23 00:23:01 UTC
README
Explicit scoped authorization for Laravel — permission enums, polymorphic scopes, and zero implicit state.
Documentation → — tutorials, how-to guides, reference, and explanation.
Laravel Access gives you explicit, scoped role-permission authorization for multi-tenant Laravel applications. Unlike packages that assume one user = one set of permissions, Laravel Access is built for apps where users have different roles in different scopes — companies, teams, workspaces, or any Eloquent model.
Permissions are PHP BackedEnums (not strings): compile-time safety, IDE autocomplete, single source of truth. The API makes scope explicit at every call site — $user->in($company)->can(Permission::UsersInvite) — no global state, no team_id hacks.
$user->in($company)->can(Permission::UsersInvite);
Installation
composer require maxiviper117/laravel-access php artisan access:install --enum php artisan migrate php artisan access:sync
Add the trait to your user model:
use Maxiviper117\Access\Concerns\HasAccess; class User extends Authenticatable { use HasAccess; }
Configuration
Define your permission enum in app/Enums/Permission.php, then configure roles and global roles in config/access.php.
return [ 'permission_enums' => [ App\Enums\Permission::class, ], 'roles' => [ 'Owner' => [ App\Enums\Permission::UsersView, App\Enums\Permission::UsersInvite, ], ], 'global_roles' => [ 'Platform Admin' => [ App\Enums\Permission::SystemManage, ], ], 'gate_before' => [ 'enabled' => false, 'global_role' => 'Platform Admin', ], ];
Sync enums and configured roles into the database:
php artisan access:sync
Or define roles in code with Access::role():
use Maxiviper117\Access\Facades\Access; Access::role('Owner')->allows([Permission::UsersView, Permission::UsersInvite]); Access::role('Platform Admin', global: true)->allows([Permission::SystemManage]);
Scoped Usage
Assign and check roles inside a scope:
$user->in($company)->assignRole('Owner'); $user->in($company)->hasRole('Owner'); $user->in($company)->removeRole('Owner');
Check permissions resolved through role inheritance and direct grants:
$user->in($company)->can(Permission::UsersInvite); $user->in($company)->cannot(Permission::RolesManage);
Grant or revoke permissions directly (bypassing roles):
$user->in($company)->givePermission(Permission::UsersInvite); $user->in($company)->revokePermission(Permission::UsersInvite);
Check any role in a set:
$user->in($company)->hasAnyRole(['Owner', 'Admin']);
Use inside policies:
public function inviteUsers(User $user, Company $company): bool { return $user->in($company)->can(Permission::UsersInvite); }
Global Usage
Global roles and permissions live outside any scope:
$user->assignGlobalRole('Platform Admin'); $user->hasGlobalRole('Platform Admin'); $user->removeGlobalRole('Platform Admin'); $user->canGlobally(Permission::SystemManage); $user->giveGlobalPermission(Permission::SystemManage);
Dynamic Roles
Create and manage runtime roles per scope:
$user->in($company)->createRole('custom-manager', 'Custom Manager', 'Description'); $user->in($company)->syncRolePermissions('custom-manager', [Permission::UsersView]); $user->in($company)->assignRole('custom-manager'); $user->in($company)->deleteRole('custom-manager');
Permission Maps
Build an Inertia-friendly permission map:
Access::for($user)->in($company)->toArray([ Permission::UsersInvite, Permission::RolesManage, ]); // ['users.invite' => true, 'roles.manage' => false]
Scoped Gates
Register Laravel Gates for all enum cases at once:
Access::defineScopedGates(Permission::class, Company::class); // Gate::authorize('users.invite', $company);
Middleware
Guard routes with the access middleware:
Route::middleware('access:users.invite,company') ->get('/companies/{company}/invite', ...);
Commands
php artisan access:install --enum # Publish config, migration, Permission enum php artisan access:sync --dry-run # Preview changes php artisan access:sync --prune # Delete stale permissions and roles php artisan access:scope --name=company # Scaffold team/workspace membership php artisan access:debug user@example.com --scope=company:1 php artisan access:clear # Invalidate permission cache
Testing
composer test
License
The MIT License (MIT). Please see License File for more information.