ezappslab / laravel-dominion
Laravel package for roles and permissions
Installs: 0
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/ezappslab/laravel-dominion
Requires
- php: ^8.2
- illuminate/contracts: ^11.0|^12.0
- spatie/laravel-package-tools: ^1.16
Requires (Dev)
- larastan/larastan: ^v3.8
- laravel/pint: ^v1.25
- orchestra/testbench: ^v10.8
- pestphp/pest: ^v4.1
- pestphp/pest-plugin: ^v4.0
- pestphp/pest-plugin-arch: ^v4.0
- pestphp/pest-plugin-laravel: ^v4.0
- pestphp/pest-plugin-mutate: ^v4.0
This package is not auto-updated.
Last update: 2025-12-28 05:40:13 UTC
README
Laravel Dominion is a comprehensive authorization package for Laravel that provides tenant-aware, polymorphic roles and permissions. It is designed for applications that require fine-grained access control across multiple tenants while maintaining a clean, developer-friendly API.
Dominion solves the complexity of managing permissions in multi-tenant environments by providing explicit allow/deny rules, deterministic precedence, and seamless integration with Laravel's native authorization system.
Key Use Cases
- Multi-tenant RBAC: Manage roles and permissions that can be either global or scoped to specific tenants.
- Polymorphic Authorization: Assign roles and permissions to any Eloquent model (e.g., Users, API Clients, Teams).
- Tenant-Aware Gate & Policies: Automatically resolve the current tenant context for authorization checks.
- Catalog Syncing: Keep your database-backed roles and permissions in sync with your codebase using PHP Enums.
Core Concepts
Dominion is built around several key concepts that work together to provide a robust authorization engine:
- Domains & Tenancy: Authorization can be global (applies everywhere) or tenant-scoped (applies only within a specific tenant).
- Roles: Logical groupings of permissions (e.g.,
admin,editor). - Permissions: Granular abilities represented by strings (e.g.,
posts.update). - Policies: Dominion integrates with Laravel's policy system to map model actions to permission strings.
- Services: Configurable components that handle tenant resolution and value normalization.
- Allow / Deny: Explicitly grant or block permissions for a specific principal. Deny always takes precedence over Allow.
Precedence Rules
When checking if a principal has a permission for a specific tenant, Dominion follows these deterministic rules:
- Tenant Deny: Explicitly denied for the principal in the current tenant.
- Global Deny: Explicitly denied for the principal globally.
- Tenant Allow: Explicitly allowed for the principal in the current tenant.
- Global Allow: Explicitly allowed for the principal globally.
- Role-based Permission: Granted via an assigned role (either tenant-scoped or global).
- Default Deny: If no rules match, access is denied.
Architecture
Dominion is structured into several layers to ensure flexibility and maintainability:
- Traits: Provide the public API (
HasRoles,HasPermissions) for your Eloquent models. - Authorization Engine: The core logic (
AuthorizationResolver) that evaluates the precedence rules. - Contracts: Replaceable interfaces (
TenantContext,PermissionValueResolver,RoleValueResolver) that allow you to customize core behavior. - Persistence: Database tables for roles, permissions, and their polymorphic assignments (
roleables,permissionables). - Gate Integration: Hooks into Laravel's
Gate::beforeto provide seamless$user->can()checks.
Authorization Flow
- Gate Check: When
$user->can('posts.update')is called, Dominion'sGate::beforehook intercepts the call. - Tenant Resolution: The
TenantContextservice identifies the current tenant ID. - Resolution: The
AuthorizationResolverevaluates the precedence rules against the database and returns a boolean.
Installation
Requirements
- PHP 8.2+
- Laravel 11 or 12
Steps
-
Install via Composer:
composer require ezappslab/laravel-dominion
-
Run the Installer: This command publishes the configuration file (
config/dominion.php).php artisan dominion:install
-
Run Migrations:
php artisan migrate
Configuration
The config/dominion.php file allows you to customize almost every aspect of the package.
Tenancy Configuration
Define your tenant table and foreign key:
'tenant' => [ 'table' => 'tenants', 'foreign_key' => 'tenant_id', ],
Service Overrides
You can swap default implementations with your own by updating the services array:
'services' => [ 'tenant_context' => App\Services\CustomTenantContext::class, 'permission_value_resolver' => Infinity\Dominion\Services\DefaultPermissionValueResolver::class, 'role_value_resolver' => Infinity\Dominion\Services\DefaultRoleValueResolver::class, ],
Roles & Permissions
To get started, add the HasRoles and HasPermissions traits to your model (e.g., User model).
Assigning Roles
$user->addRole('admin'); // Global role $user->addRole('member', $tenant); // Tenant-scoped role $user->removeRole('admin');
Managing Permissions
$user->allow('posts.update'); // Global allow $user->allow('posts.update', $tenant); // Tenant-scoped allow $user->deny('posts.delete'); // Global deny
Checking Access
$user->hasRole('admin'); $user->hasPermission('posts.update'); // Native Laravel Gate integration $user->can('posts.update');
Policies
Dominion ships with a DefaultPolicy that maps Laravel's policy methods to permission strings using the convention {table}.{ability}.
Enabling the Default Policy
Register your models in config/dominion.php:
'policy' => [ 'class' => Infinity\Dominion\Policies\DefaultPolicy::class, 'models' => [ App\Models\Post::class, // maps update() -> posts.update ], ],
Custom Policy Mapping
You can also map specific models to your own policy classes:
'models' => [ App\Models\Invoice::class => App\Policies\InvoicePolicy::class, ],
Enums
Dominion encourages the use of string-backed PHP Enums for type-safe roles and permissions.
Defining Enums
enum Role: string { case Admin = 'admin'; } enum PostPermissions: string { case Update = 'posts.update'; }
Usage
$user->addRole(Role::Admin); $user->allow(PostPermissions::Update);
Services
Dominion relies on internal services that you can extend or replace:
TenantContext: Responsible for determining the current tenant ID during authorization checks.PermissionValueResolver: Normalizes permission inputs (strings or enums) into a consistent format.RoleValueResolver: Normalizes role inputs into a consistent format.
To implement a custom service, implement the corresponding contract in Infinity\Dominion\Contracts and update your config.
Tenancy Support
Dominion is "tenancy-aware" by design. Every role assignment and permission grant can be associated with a tenant_id.
Resolution Flow
When an authorization check is performed without an explicit tenant, Dominion calls TenantContext::currentTenantId(). This allows you to resolve the tenant from the session, a route parameter, or a header.
Tenant Argument
Most methods accept an optional $tenant argument, which can be:
- An Eloquent model instance.
- A primary key (
intorstring). nullfor global scope.
Sync Command
The dominion:sync command allows you to synchronize your PHP Enums with the database catalogs.
Configuration
Register your enums in config/dominion.php:
'role_enum' => App\Enums\Role::class, 'permission_enums' => [ App\Enums\PostPermissions::class, ],
Usage
# Basic sync php artisan dominion:sync # Preview changes php artisan dominion:sync --dry-run # Remove records no longer in enums php artisan dominion:sync --prune
Testing & CI
When testing applications using Dominion:
- Seed Permissions: Use
php artisan dominion:syncin your test setup to ensure the catalogs are populated. - Tenant Context: If testing tenant-aware logic, ensure your
TenantContextservice is properly mocked or configured for the test environment. - Cache: Dominion caches authorization results. Use
php artisan cache:clearif you are manually modifying database records during tests.
Design Principles
- Explicitness: Precedence rules are clear and deterministic. Deny always wins.
- Safety: Using Enums prevents typos and ensures a single source of truth for your permission set.
- Predictability: Dominion honors Laravel's native authorization patterns while adding multi-tenancy.
- Laravel-Native: Built to feel like a natural extension of the Laravel framework.
License
The MIT License (MIT). Please see License File for more information.