teksite / authorize
Authorization package for managing roles and permissions in Laravel applications
Requires
- php: ^8.3
- laravel/framework: ^13.0
Requires (Dev)
- orchestra/testbench: ^11.0
- phpunit/phpunit: ^11.5|^12.5
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
A flexible and model-independent authorization package for Laravel.
Teksite Authorize provides a simple way to manage:
- Permissions
- Roles
- Role hierarchy
- Direct model permissions
- Model roles
- Role-based permissions
- Laravel Gates
- Authorization caching
- Super administrator access
- Polymorphic authorization relationships
The package is designed to work with any Eloquent model, not only User.
Features
- Model-independent authorization
- Polymorphic roles
- Polymorphic permissions
- Direct permissions for any Eloquent model
- Role-based permissions
- Multiple roles per model
- Multiple permissions per model
- Permission and role lookup by ID or title
- Laravel Gate integration
- Super administrator support
- Role hierarchy
- Authorization cache
- Cache invalidation helpers
- Artisan installation command
- Factory support
- Validation rule helpers
Requirements
This package requires a Laravel application using Eloquent ORM.
The package uses modern Laravel features such as PHP attributes, so make sure your Laravel and PHP versions support the features used by your installed package version.
Installation
Install the package through Composer:
composer require teksite/authorize
Then run the installation command:
php artisan authorize:install
This command creates the required authorization migrations inside:
database/migrations
After that, run:
php artisan migrate
Configuration
The package configuration is available at:
config/authorize.php
Example:
<?php return [ /* |-------------------------------------------------------------------------- | Boot Gates |-------------------------------------------------------------------------- */ 'boot_gates' => true, 'boot_gates_in_console' => false, /* |-------------------------------------------------------------------------- | Cache |-------------------------------------------------------------------------- */ 'cache_enabled' => true, 'cache_ttl' => 2,592,000, /* |-------------------------------------------------------------------------- | Super Admin |-------------------------------------------------------------------------- */ 'super_admin_role' => 'administrator', ];
Configuration options
boot_gates
Determines whether permissions should be registered as Laravel Gates.
'boot_gates' => true,
Set to false if you do not want the package to register Gates automatically.
boot_gates_in_console
Determines whether authorization Gates should be booted while Laravel is running in console mode.
Default:
'boot_gates_in_console' => false,
This is useful for avoiding unnecessary database access when running Artisan commands.
cache_enabled
Enables or disables authorization caching.
'cache_enabled' => true,
When disabled, authorization data is loaded directly from the database.
cache_ttl
Defines the authorization cache lifetime in seconds.
'cache_ttl' => 2,592,000,
The default value is 24 hours.
super_admin_role
Defines the role that should bypass permission checks.
'super_admin_role' => 'administrator',
If the authenticated or authorized model has this role, permission checks return true.
Set it to null if you do not want to use a super administrator role.
Database Structure
The package creates five tables.
auth_permissions
Stores permissions.
| Column | Description |
|---|---|
id |
Permission ID |
title |
Unique permission name |
description |
Optional description |
created_at |
Creation timestamp |
updated_at |
Update timestamp |
Example:
posts.read
posts.create
posts.update
posts.delete
auth_roles
Stores roles.
| Column | Description |
|---|---|
id |
Role ID |
title |
Unique role name |
description |
Optional description |
hierarchy |
Role hierarchy level |
created_at |
Creation timestamp |
updated_at |
Update timestamp |
Example roles:
administrator
manager
editor
author
auth_permission_role
Connects permissions to roles.
A role can have many permissions, and a permission can belong to many roles.
auth_permission_models
Connects permissions directly to any Eloquent model using a polymorphic relationship.
auth_role_models
Connects roles to any Eloquent model using a polymorphic relationship.
Basic Usage
Add HasAuthorization to a Model
Any Eloquent model can use the authorization system.
For example:
<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; use Teksite\Authorize\Traits\HasAuthorization; class User extends Model { use HasAuthorization; }
The package is not limited to User.
For example:
class Admin extends Model { use HasAuthorization; }
Or:
class Customer extends Model { use HasAuthorization; }
Or:
class Employee extends Model { use HasAuthorization; }
As long as the model is an Eloquent model, it can use the Trait.
Permissions
Creating a Permission
use Teksite\Authorize\Models\Permission; $permission = Permission::create([ 'title' => 'posts.read', 'description' => 'Read posts', ]);
Finding a Permission
By ID:
$permission = Permission::find(1);
By title:
$permission = Permission::where('title', 'posts.read')->first();
Roles
Creating a Role
use Teksite\Authorize\Models\Role; $role = Role::create([ 'title' => 'editor', 'description' => 'Post editor', 'hierarchy' => 30, ]);
Assigning Permissions to a Role
$role->permissions()->sync([ $permission->id, ]);
Multiple permissions can be assigned:
$role->permissions()->sync([ $readPermission->id, $createPermission->id, $updatePermission->id, ]);
Assigning Roles to a Model
$user->assignRole('editor');
The role can also be specified by ID:
$user->assignRole(1);
Or by Role model:
$user->assignRole($role);
Multiple roles:
$user->assignRole([ 'editor', 'author', ]);
By default, assignRole() replaces the existing roles.
To keep existing roles:
$user->assignRole('editor', false);
Assigning Direct Permissions
Permissions can be assigned directly to a model without using a role.
$user->syncPermissions('posts.delete');
By ID:
$user->syncPermissions(5);
Using a Permission model:
$user->syncPermissions($permission);
Multiple permissions:
$user->syncPermissions([ 'posts.read', 'posts.create', 'posts.update', ]);
By default, existing direct permissions are replaced.
To keep existing permissions:
$user->syncPermissions([ 'posts.read', 'posts.create', ], false);
Checking Roles
Check whether a model has a role:
$user->hasRole('editor');
By ID:
$user->hasRole(1);
Using a Role model:
$user->hasRole($role);
Multiple roles:
$user->hasRole([ 'editor', 'author', ]);
By default, hasRole() checks whether any requested role exists.
To require all roles:
$user->hasRole([ 'editor', 'author', ], false);
Checking Permissions
Check a permission:
$user->hasPermission('posts.read');
By ID:
$user->hasPermission(1);
Using a Permission model:
$user->hasPermission($permission);
Multiple permissions:
$user->hasPermission([ 'posts.read', 'posts.update', ]);
By default, hasPermission() checks whether any requested permission exists.
To require all permissions:
$user->hasPermission([ 'posts.read', 'posts.update', ], false);
Permission Sources
A model can receive permissions from two sources:
- Direct permissions
- Permissions inherited from roles
For example:
User
├── Direct Permissions
│ ├── posts.delete
│ └── users.read
│
└── Roles
└── editor
├── posts.read
├── posts.create
└── posts.update
hasPermission() considers both sources.
Getting Permissions
Get All Permissions
By default, only permission IDs are returned:
$user->getAllPermissions();
Example:
[
1,
2,
3,
]
To get permission titles:
$user->getAllPermissions(false);
Example:
[
1 => 'posts.read',
2 => 'posts.update',
3 => 'posts.delete',
]
Get Direct Permissions
This only returns permissions directly assigned to the model.
$user->getDirectPermissions();
Example:
[
1 => 'posts.delete',
2 => 'users.read',
]
Role permissions are not included.
Get Permissions Through Roles
$user->getPermissionsByRoles();
Example:
[
'editor' => [
1 => 'posts.read',
2 => 'posts.create',
3 => 'posts.update',
],
]
Getting Roles
Get role IDs:
$user->getDirectRoles(true);
Example:
[
1,
2,
]
Get roles with their titles:
$user->getDirectRoles();
Example:
[
1 => 'editor',
2 => 'author',
]
Super Administrator
The package supports a configurable super administrator role.
Configuration:
'super_admin_role' => 'administrator',
If a model has this role:
$user->hasRole('administrator');
then:
$user->hasPermission('anything');
will return:
true
You can also check it directly:
$user->isSuperAdmin();
Laravel Gates
The package automatically registers every permission as a Laravel Gate.
For example, if the database contains:
posts.read
posts.create
posts.update
posts.delete
you can use:
Gate::allows('posts.read');
Or:
Gate::authorize('posts.update');
In Blade:
@can('posts.delete') <button>Delete</button> @endcan
The Gate internally uses the model's:
hasPermission()
method.
Route Authorization
Because permissions are registered as Laravel Gates, Laravel's normal authorization features can be used.
Example:
Route::get('/posts', function () { // })->middleware('can:posts.read');
Role Hierarchy
Roles have a hierarchy value.
For example:
administrator = 100
manager = 70
editor = 40
author = 20
A lower hierarchy value can access a higher hierarchy value according to the package's hierarchy comparison logic.
The model's minimum hierarchy can be retrieved with:
$user->hierarchy();
The maximum hierarchy:
$user->hierarchy(false, true);
Both values:
$user->hierarchy(false, true);
or:
$user->hierarchy(false, true);
returns:
[
'min' => ...,
'max' => ...,
]
Comparing Model Hierarchy
A model can be compared against another authorization model:
$user->canAccessModelByHierarchy($anotherUser);
Possible results:
true
false
or:
null
null means the target model does not have a hierarchy value.
The target model must use:
HasAuthorization
Comparing Against a Role
A model can also be compared against a Role:
$user->canAccessRoleByHierarchy('manager');
By ID:
$user->canAccessRoleByHierarchy(2);
Using a Role model:
$user->canAccessRoleByHierarchy($role);
Authorization Cache
Authorization data is cached by default.
The package caches:
- Model permissions
- Model roles
- Model hierarchy
- Permission Gate list
Cache can be configured using:
'cache_enabled' => true, 'cache_ttl' => 2,592,000,
Clearing Authorization Cache
Clear all authorization caches for a model:
$user->clearAuthorizationCache();
Warming Authorization Cache
You can pre-load authorization information:
$user->warmAuthorizationCache();
This loads:
- Permissions
- Roles
- Hierarchy
into the authorization cache.
Cache Architecture
The package creates model-specific cache keys using the model's morph class and primary key.
Example:
authorize:permissions:App\Models\User:1
authorize:roles:App\Models\User:1
authorize:hierarchy:App\Models\User:1
This prevents collisions between different model types that have the same primary key.
For example:
User #1
Admin #1
will have different authorization cache keys.
Polymorphic Authorization
One of the main features of the package is that authorization is not tied to a specific model.
For example:
$user->assignRole('editor'); $admin->assignRole('administrator'); $customer->syncPermissions('orders.read'); $employee->syncPermissions([ 'reports.read', 'reports.create', ]);
All of these models can use the same authorization system.
This is achieved through Laravel polymorphic relationships.
Model Relationships
Models using HasAuthorization receive:
$user->roles();
and:
$user->permissions();
Both relationships are polymorphic.
Role Relationships
A Role has many permissions:
$role->permissions;
A Role can be assigned to many models through the polymorphic relation.
Permission Relationships
A Permission belongs to many roles:
$permission->roles;
A Permission can also be directly assigned to many models.
Validation Rules
Both Permission and Role provide suggested validation rules.
Permission
Create:
Permission::rules('create');
Update:
Permission::rules('update', $permission->id);
Role
Create:
Role::rules('create');
Update:
Role::rules('update', $role->id);
The Role rules include validation for permissions and hierarchy.
Factories
The package provides factories for Permission and Role.
Permission factory:
Permission::factory()->create();
Multiple permissions:
Permission::factory()->count(10)->create();
Role factory:
Role::factory()->create();
Multiple roles:
Role::factory()->count(5)->create();
Example
A complete example:
use App\Models\User; use Teksite\Authorize\Models\Permission; use Teksite\Authorize\Models\Role; $read = Permission::create([ 'title' => 'posts.read', ]); $create = Permission::create([ 'title' => 'posts.create', ]); $update = Permission::create([ 'title' => 'posts.update', ]); $editor = Role::create([ 'title' => 'editor', 'description' => 'Can manage posts', 'hierarchy' => 40, ]); $editor->permissions()->sync([ $read->id, $create->id, $update->id, ]); $user = User::find(1); $user->assignRole($editor); $user->hasRole('editor'); $user->hasPermission('posts.read'); $user->getAllPermissions();
Direct Permission Example
Roles are not mandatory.
A model can receive permissions directly:
$user->syncPermissions([ 'posts.read', 'posts.update', ]);
Then:
$user->hasPermission('posts.read');
returns:
true
Authorization Flow
The authorization flow can be summarized as:
Model
|
+-- Direct Permissions
|
+-- Roles
|
+-- Permissions
When checking:
$model->hasPermission('posts.update');
the package checks:
1. Is the requested permission valid?
2. Is the model a super administrator?
3. Does the model have the permission directly?
4. Does any assigned role provide the permission?
5. Return the authorization result.
Cache Invalidation
The package automatically clears relevant model caches when authorization-related models are changed.
Examples include:
- Permission created
- Permission updated
- Permission deleted
- Role saved
- Role deleted
- Authorization model saved
The package also provides cache helper methods for relationship/pivot changes.
For custom direct manipulation of authorization pivot relationships, make sure the relevant authorization cache is invalidated.
For example, when changing role permissions directly:
$role->permissions()->sync($permissionIds);
you should ensure affected authorization model caches are cleared appropriately.
For package-level integrations, the methods available in AuthorizationCache can be used for this purpose.
Artisan Command
Install authorization migrations:
php artisan authorize:install
The command creates:
create_permissions_table.php
create_roles_table.php
inside:
database/migrations
Existing migration files are not overwritten.
Disabling Gate Booting
If you do not want automatic Laravel Gate registration:
'boot_gates' => false,
The model authorization methods such as:
hasPermission()
hasRole()
remain available.
Disabling Cache
To disable authorization caching:
'cache_enabled' => false,
Authorization data will then be resolved directly without using the package cache.
Recommended Permission Naming
It is recommended to use a consistent permission naming convention.
For example:
users.read
users.create
users.update
users.delete
posts.read
posts.create
posts.update
posts.delete
orders.read
orders.create
orders.update
orders.delete
This makes permissions easier to organize and use with Laravel Gates.
Recommended Role Structure
A typical application could use:
administrator
manager
editor
author
viewer
with hierarchy values such as:
administrator = 100
manager = 70
editor = 50
author = 30
viewer = 10
The exact hierarchy values are application-dependent.
Summary
Model Methods
assignRole() syncPermissions() hasRole() hasPermission() getAllPermissions() getDirectPermissions() getPermissionsByRoles() getDirectRoles() isSuperAdmin() hierarchy() canAccessModelByHierarchy() canAccessRoleByHierarchy() clearAuthorizationCache() warmAuthorizationCache()
Model Relationships
roles()
permissions()
Permission Methods
Permission::rules() Permission::factory() $permission->roles()
Role Methods
Role::rules() Role::factory() $role->permissions()
License
This package is open-source software.
Add your project's license information here.
Contributing
Contributions, bug reports, feature requests, and pull requests are welcome.
Before submitting a pull request, make sure that:
- The code follows Laravel conventions.
- Existing functionality is not broken.
- New functionality is covered by tests where appropriate.
- Authorization cache behavior is considered for authorization-related changes.
Security
If you discover a security vulnerability, please report it privately to the package maintainer instead of opening a public issue.
Credits
Developed by Teksite.
Package:
teksite/authorize
A model-independent authorization system for Laravel.