obrainwave / access-tree
This package allows you to manage user permissions and roles in a database for Laravel project
Installs: 452
Dependents: 0
Suggesters: 0
Security: 0
Stars: 1
Watchers: 1
Forks: 0
Open Issues: 0
pkg:composer/obrainwave/access-tree
Requires
- php: ^8.1
- illuminate/contracts: *
- spatie/laravel-package-tools: ^1.14.0
Requires (Dev)
- laravel/pint: ^1.0
- nunomaduro/collision: ^6.1
- nunomaduro/larastan: ^2.0.1
- orchestra/testbench: ^8.0
- pestphp/pest: ^1.21
- pestphp/pest-plugin-laravel: ^1.1
- phpstan/extension-installer: ^1.1
- phpstan/phpstan-deprecation-rules: ^1.0
- phpstan/phpstan-phpunit: ^1.0
- phpunit/phpunit: ^9.6
- spatie/laravel-ray: ^1.26
README
AccessTree 2.0.0 is a major release. Version 1.x is deprecated.
Please follow the Upgrade Guide before updating.
A comprehensive Laravel package for managing user permissions and roles with database-driven access control.
This package is a lightweight, database-driven RBAC (roles & permissions) package for Laravel with convenient helpers, facades, caching, seeding and middleware.
Quick Start (2 minutes)
# 1) Require package composer require obrainwave/access-tree # 2) Publish migrations & config php artisan vendor:publish --tag="accesstree-migrations" php artisan vendor:publish --tag="accesstree-config" # 3) Migrate & seed (optional) php artisan migrate php artisan accesstree:seed
Add trait to your User model:
use Obrainwave\AccessTree\Traits\HasRole; class User extends Authenticatable { use HasRole; }
You're done — roles, permissions and a seeded admin are ready (if seeding enabled).
Features
- Role-Based Access Control (RBAC): Create and manage roles with specific permissions
- User Role Assignment: Assign multiple roles to users with easy synchronization
- Permission Checking: Helper functions for checking permissions and roles
- Root User Bypass: Special superuser capability that bypasses all permission checks
- Caching System: Built-in caching for optimal performance
- Blade Directives: Easy-to-use directives for view-level authorization
- Customisable Seeder: Seeder with default permissions/roles (publishable for customisation)
- Flexible API: Service classes, Facades, and global helper functions
Requirements & Compatibility
- PHP: 8.1+
- Laravel: 8.x, 9.x, 10.x, 11.x, 12.x
- The package is continuously tested on the latest stable Laravel versions.
- Please open an issue
Installation
1. Require via Composer
composer require obrainwave/access-tree
Publish and Run Migrations
php artisan vendor:publish --tag="accesstree-migrations"
php artisan migrate
After running migration, a new column is_root_user
will be added to the users table.
Configuration
Publish Config File
php artisan vendor:publish --tag="accesstree-config"
Config File Options
After publishing the config file (config/accesstree.php)
, you can customize the package behavior:
return [ 'seed_permissions' => true, 'seed_roles' => true, 'assign_first_user_as_admin' => true, 'cache_refresh_time' => 5, 'forbidden_redirect' => 'home', ];
Publish Seeder (Optional)
php artisan vendor:publish --tag="accesstree-seeders"
Seeding Features
The package includes a powerful seeding system that can automatically set up your permissions and roles:
Default Permissions Created:
- User Management:
view user
,add user
,edit user
,delete user
- Role Management:
view role
,add role
,edit role
,delete role
- Permission Management:
view permission
,add permission
,edit permission
,delete permission
- Content Management: Common CRUD operations for your application
Default Roles Created:
- Super Admin: Has all permissions
- Admin: Has all permissions except permission control
- Editor: Can create, read, and update content
Seeding
After publishing the seeder, you can customize it at database/seeders/PermissionSeeder.php
and run:
php artisan accesstree:seed
Automatic First User as Admin
If enabled in the config file:
// config/accesstree.php 'assign_first_user_as_admin' => true,
The package will automatically assign the very first registered user the Admin role (if it exists).
- Ensures you always have at least one administrator.
- Works only on the first user (ID=1 typically).
- If you don’t want this behavior, simply set:
'assign_first_user_as_admin' => false,
Add Trait to User Model
namespace App\Models; use Illuminate\Foundation\Auth\User as Authenticatable; use Obrainwave\AccessTree\Traits\HasRole; class User extends Authenticatable { use HasRole; }
Basic Usage
Creating Permissions and Roles
Using service class or the service facade
use Obrainwave\AccessTree\Facades\AccessTree; or use AccessTree; // Create permission AccessTree::createAccess([ 'name' => 'Edit Articles', 'status' => 1 ], 'Permission'); // Create role with permissions AccessTree::createAccess([ 'name' => 'Editor', 'status' => 1 ], 'Role', [1, 2, 3]); // Permission IDs
Using Helper Functions
// Create permission createAccess(['name' => 'Delete Articles'], 'Permission'); // Create role createAccess(['name' => 'Admin'], 'Role', [1, 2, 3, 4]);
Managing User Roles
$user = User::find(1); // Assign a single role $user->assignRole('admin'); // Assign multiple roles $user->assignRoles(['editor', 'moderator']); // Sync roles (removes existing, adds new ones) $user->syncRoles([1, 2, 3]); // Using helper function createUserRole([1, 2], $user->id);
Checking Permissions and Roles
// Check single permission if (checkPermission('edit_articles')) { // User has permission } // Check multiple permissions (strict - all required) if (checkPermissions(['edit_articles', 'delete_articles'], true)) { // User has ALL permissions } // Check multiple permissions (any - at least one) if (checkPermissions(['edit_articles', 'delete_articles'], false)) { // User has AT LEAST ONE permission } // Check role if (checkRole('admin')) { // User has role } // Using model methods if ($user->hasRole('admin')) { // User is admin } if ($user->hasPermission('edit_articles')) { // User can edit articles }
Blade Directives
@if(checkPermission('edit_articles')) <button>Edit Article</button> @endif @if(checkRole('admin')) <div class="admin-panel">Admin Controls</div> @endif @if(checkPermissions(['edit_articles', 'delete_articles'], true)) <div>User can both edit and delete articles</div> @endif
Root User Feature
// Mark user as root $user = User::find(1); $user->is_root_user = true; $user->save(); // Check if current user is root if (isRootUser()) { // Bypasses all permission checks } // Check if specific user is root if (isRootUser($user->id)) { // User has full access }
Middleware Usage
Protect your routes:
// Single permission Route::get('/admin', [AdminController::class, 'index']) ->middleware('accesstree:add_permission'); // Multiple permissions (any) Route::post('/articles', [ArticleController::class, 'store']) ->middleware('accesstree:create_articles,edit_articles'); // Role check Route::delete('/articles/{id}', [ArticleController::class, 'destroy']) ->middleware('accesstree:role:admin');
Middleware supports role:slug
prefix to explicitly request role checks. It returns JSON 403 for XHR or redirects back/route with danger
flash message.
Artisan Commands
Available Commands
# Seed default permissions and roles php artisan accesstree:seed # Fresh seed (WARNING: clears all access-tree tables before reseeding!) php artisan accesstree:seed --fresh # Publish package assets php artisan vendor:publish --tag=accesstree-config php artisan vendor:publish --tag=accesstree-migrations php artisan vendor:publish --tag=accesstree-seeders
Warning:
Unlike php artisan migrate:fresh
, this command does not wipe your entire database.
It will only truncate AccessTree-related tables defined in config/accesstree.php
(by default):
permissions
roles
role_has_permissions
user_roles
This ensures your application data remains safe while reseeding roles & permissions.
Advanced Usage
Using Service Directly
use Obrainwave\AccessTree\Services\AccessTreeService; $accessService = new AccessTreeService(); // Update role $result = $accessService->updateAccess([ 'data_id' => 1, 'name' => 'Senior Editor', 'status' => 1 ], 'Role', [1, 2, 3, 4, 5]); // Delete permission $result = $accessService->deleteAccess(1, 'Permission');
Data Retrieval
// Get all active permissions $permissions = fetchActivePermissions(); // Get roles with pagination $roles = fetchRoles([ 'paginate' => true, 'per_page' => 15, 'with_relation' => true, 'order' => 'asc', 'order_ref' => 'name' ]); // Get specific role with permissions $role = fetchRole(1); // Get user's roles $userRoles = fetchUserRoles($user->id); // Get role permissions $rolePermissions = fetchRolePermissions($roleId);
Available Methods
Service Class Methods
createAccess(array $data, string $model, array $permission_ids = [])
updateAccess(array $data, string $model, array $permission_ids = [])
deleteAccess(int $data_id, string $model)
HasRole Trait Methods
roles()
- Relationship to user's rolesassignRole($role)
- Assign single roleassignRoles($roles)
- Assign multiple rolessyncRoles($roles)
- Sync user roleshasRole($role)
- Check if user has rolepermissions()
- Get user's permissionshasPermission($permission)
- Check if user has permission
Helper Functions
checkPermission(string $permission): bool
checkPermissions(array $permissions, bool $strict = false): bool
checkRole(string $role): bool
checkRoles(array $roles, bool $strict = false): bool
isRootUser(int $user_id = null): bool
createAccess(array $data, string $model, array $permission_ids = []): string
updateAccess(array $data, string $model, array $permission_ids = []): string
fetchPermissions(array $options = [], int $status = 0): object
fetchRoles(array $options = [], int $status = 0): object
fetchUserRoles(int $user_id, bool $with_relation = true): object
Database Schema
The package creates these tables:
permissions
- Stores permission recordsroles
- Stores role recordsrole_has_permissions
- Role-permission relationshipsuser_roles
- User-role relationships
Caching & Performance
- Permission and role checks are cached per-user for
cache_refresh_time
(config). - Use
config('accesstree.cache_refresh_time')
to control minutes. - If you change permissions/role assignments programmatically, make sure to clear/refresh cache for affected users if necessary.
Testing
Quick example using Laravel feature testing:
public function test_admin_can_access_dashboard() { $user = User::factory()->create(); AccessTree::assignRoles($user->id, ['Admin']); // or assign role id $this->actingAs($user) ->get('/admin') ->assertStatus(200); }
Seeders can be run in tests to prepare default roles/permissions.
API Responses & AJAX (example)
When using the package with AJAX (e.g., to modify roles/permissions), the package returns JSON from service controllers (if you build them) and helper functions can be adapted to return structured responses (status/message). Keep errors user-friendly in production, and enable dev logging in local env.
Security
If you discover any security issues, please email the maintainers at (olaiwolaakeem@gmail.com) instead of using the issue tracker.
License
The MIT License (MIT). Please see LICENSE.md for more information.
Contributing
We welcome contributions! Please see CONTRIBUTING.md for coding standards, testing instructions, and local development setup.
Roadmap
Planned improvements:
- Admin UI scaffolding (optional)
- Livewire / Inertia / Filament integration examples
- Per-tenant role scoping (multitenancy)
- Artisan command to clear package caches
If you want any roadmap item prioritized — open an issue or PR.
Acknowledgements
Inspired by common RBAC patterns (and packages like spatie/laravel-permission). Access Tree focuses on lightweight, configurable seeding and an intuitive helper API.