Skip to content

A 100% database-driven, automated role-permission system for Laravel with zero-code setup, auto-discovery, and complete REST API

License

Notifications You must be signed in to change notification settings

kiurd-gentleman/role-based-access-control

Repository files navigation

Laravel Role-Based Access Control (RBAC)

A 100% database-driven, automated role-permission system for Laravel with zero-code setup.

🚀 Key Features

  • 🎯 Zero-Code Setup: No middleware in routes or controllers - everything is automatic
  • 🔄 Global Auto-Enforcement: Enable once, all routes are protected automatically
  • 🛠️ Complete REST API: Manage everything through API/UI without touching code
  • 🔍 Auto-Discovery: Automatically scan and sync permissions from your controllers
  • ⚡ Dynamic Management: Create roles, assign permissions, manage users - all in real-time
  • 🔒 Multi-Guard Support: Support for multiple authentication guards (web, api, etc.)
  • 📊 Granular Permissions: Module + Action based permission system
  • 🎨 Admin-Friendly: Build any admin UI with provided API endpoints

📖 Two Ways to Use This Package

1. Zero-Code Dynamic Setup (Recommended) ⚡

Perfect for projects where admins manage permissions through a UI without touching code.

👉 Read DYNAMIC_SETUP.md for the complete guide

Quick Overview:

# Just add this to .env
ENABLE_GLOBAL_PERMISSION_MIDDLEWARE=true
  • No middleware in routes - Everything automatic
  • Complete REST API - Build any admin UI
  • Database-driven - Users control everything
  • Zero code changes - Add controllers, sync, done!

2. Traditional Manual Setup 🔧

For projects where you want more control and explicit permission definitions.

👉 Continue reading this README for traditional setup


Installation

Step 1: Add Package to Your Project

Create a packages folder in your project root and clone this repository:

mkdir packages
cd packages
git clone https://github.com/imtiaz-kolpolok/role-based-access-control.git

Step 2: Update composer.json

Add the following to your composer.json:

{
    "require": {
        "kiurd/role-based-access-control": "dev-master"
    },
    "repositories": [
        {
            "type": "path",
            "url": "./packages/role-based-access-control"
        }
    ]
}

Step 3: Install Dependencies

composer update

Step 4: Publish Configuration and Migrations

php artisan vendor:publish --tag=role-permissions-config
php artisan vendor:publish --tag=role-permissions-migrations
php artisan migrate

Step 5: Add Trait to User Model

Add the HasRolesAndPermissions trait to your User model:

use Kiurd\RolePermissions\Traits\HasRolesAndPermissions;

class User extends Authenticatable
{
    use HasRolesAndPermissions;

    // ... rest of your model
}

Automated Permission Discovery

Auto-Sync Permissions from Controllers

The package can automatically scan your controllers and create permissions:

# Preview what will be synced (recommended first)
php artisan permissions:sync --preview

# Sync from routes
php artisan permissions:sync --source=routes

# Sync from controllers directory
php artisan permissions:sync --source=controllers

# Sync with specific guard
php artisan permissions:sync --guard=api

# Sync from custom path
php artisan permissions:sync --source=controllers --path=/path/to/controllers

How it works:

  • Scans your controllers and extracts public methods
  • Converts controller names to module names (e.g., UserControllerusers)
  • Maps methods to actions (e.g., storecreate, indexlist)
  • Automatically creates modules, actions, and permissions in your database

Method to Action Mapping

The package automatically maps controller methods to permission actions:

Controller Method Permission Action
index() list
show() read
create() create
store() create
edit() update
update() update
destroy() delete
delete() delete
Other methods snake_case of method name

You can customize this mapping in config/role_permissions.php.

Artisan Commands

Create a Role

php artisan role:create admin --description="Administrator role"
php artisan role:create editor --guard=api

Assign Permission to Role

# Assign single permission (auto-creates module and action if needed)
php artisan role:assign-permission admin users create
php artisan role:assign-permission editor posts update --guard=web

Assign All Permissions to Role

Assign multiple permissions at once instead of one by one:

# Assign ALL permissions to a role
php artisan role:assign-all-permissions super-admin

# Assign all permissions for a specific module
php artisan role:assign-all-permissions manager --module=users

# Assign all permissions for a specific action across all modules
php artisan role:assign-all-permissions reader --action=read

# Combine filters: all 'create' permissions for 'users' module
php artisan role:assign-all-permissions editor --module=users --action=create

# Skip confirmation prompt
php artisan role:assign-all-permissions admin --force

# With specific guard
php artisan role:assign-all-permissions admin --guard=api

Example Output:

🎭 Role: manager

📋 Permissions to be assigned (4):
   📦 users
      • create
      • read
      • update
      • delete

🔍 Filters applied: Module: users

✅ Permissions assigned successfully!

+----------------------------+-------+
| Status                     | Count |
+----------------------------+-------+
| Newly assigned             | 4     |
| Already assigned           | 0     |
| Total permissions for role | 4     |
+----------------------------+-------+

List All Permissions

# List all permissions
php artisan permissions:list

# Filter by role
php artisan permissions:list --role=admin

# Filter by module
php artisan permissions:list --module=users

# Filter by guard
php artisan permissions:list --guard=api

View Relationships

Show User's Roles and Permissions

Find out which roles and permissions are assigned to a specific user:

# By user ID
php artisan user:show 1

# By email
php artisan user:show [email protected]

# With specific guard
php artisan user:show 1 --guard=api

Example Output:

👤 User Information
   ID: 1
   Name: John Doe
   Email: [email protected]

🎭 Roles (2)
+----+---------+-------------------------+
| ID | Role    | Description             |
+----+---------+-------------------------+
| 1  | admin   | Administrator role      |
| 2  | editor  | Content editor          |
+----+---------+-------------------------+

🔐 Permissions (15)
   📦 users
      • create
      • read
      • update
      • delete
   📦 posts
      • create
      • update
   📦 products
      • read

✅ Summary:
   • 2 role(s)
   • 15 permission(s)
   • 3 module(s)

Show Role's Permissions and Users

Find out which permissions belong to a role and which users have that role:

# By role name
php artisan role:show admin

# By role ID
php artisan role:show 1

# Include users with this role
php artisan role:show admin --with-users

# With specific guard
php artisan role:show admin --guard=web

Example Output:

🎭 Role Information
   ID: 1
   Name: admin
   Description: Administrator role
   Guard: web

🔐 Permissions (12)
   📦 users
      • create (ID: 1)
      • read (ID: 2)
      • update (ID: 3)
      • delete (ID: 4)
   📦 posts
      • create (ID: 5)
      • update (ID: 6)
      • delete (ID: 7)

👥 Users with this role (3)
+----+------------+---------------------+
| ID | Name       | Email               |
+----+------------+---------------------+
| 1  | John Doe   | [email protected]    |
| 2  | Jane Smith | [email protected]    |
| 3  | Bob Wilson | [email protected]     |
+----+------------+---------------------+

✅ Summary:
   • 12 permission(s)
   • 2 module(s)
   • 3 user(s)

Show Module's Permissions and Roles

Find out which actions (permissions) belong to a module and which roles have access:

# By module name
php artisan module:show users

# By module ID
php artisan module:show 1

# Include roles with access
php artisan module:show users --with-roles

# With specific guard
php artisan module:show users --guard=web

Example Output:

📦 Module Information
   ID: 1
   Name: users
   Description: User management module
   Guard: web

🔐 Available Actions (5)
+---------------+--------+------------------+
| Permission ID | Action | Description      |
+---------------+--------+------------------+
| 1             | create | Create operation |
| 2             | read   | Read operation   |
| 3             | update | Update operation |
| 4             | delete | Delete operation |
| 5             | list   | List operation   |
+---------------+--------+------------------+

🎭 Roles with access to this module (3)
   • admin → create, read, update, delete, list
   • editor → read, update
   • viewer → read, list

✅ Summary:
   • 5 action(s) available
   • 3 role(s) have access

Middleware Usage

1. Auto-Discovery Middleware (Recommended)

Automatically discovers and checks permissions based on the controller and method:

// In your routes or controller constructor
Route::middleware(['auth', 'permission.auto'])->group(function () {
    Route::resource('users', UserController::class);
});

// Or in controller constructor
public function __construct()
{
    $this->middleware('permission.auto');
}

Auto-Create Permissions: Enable in .env to automatically create permissions on first access:

AUTO_CREATE_PERMISSIONS=true

2. Manual Permission Middleware

Check specific module and action permissions:

// Simple permission check
Route::middleware(['auth', 'permission:users,create'])->group(function () {
    Route::post('/users', [UserController::class, 'store']);
});

// Method-based permission mapping
Route::middleware(['auth', 'permission.check:users,create:store|update:update|delete:destroy'])
    ->group(function () {
        Route::resource('users', UserController::class);
    });

Usage in Code

Check User Roles

// Check if user has a role
if (auth()->user()->hasRole('admin')) {
    // User is admin
}

// Check multiple roles (OR logic)
if (auth()->user()->hasRole(['admin', 'editor'])) {
    // User has admin OR editor role
}

// Get user's first role
$role = auth()->user()->getRole();

// Get all user's roles
$roles = auth()->user()->roles;

Assign Roles to Users

// Assign single role
$user->assignRole('admin');

// Assign multiple roles
$user->assignRole(['admin', 'editor']);

// Assign with specific guard
$user->assignRole('admin', 'api');

Check User Permissions

// Check if user has permission
if (auth()->user()->hasPermission('users', 'create')) {
    // User can create users
}

// Check with specific guard
if (auth()->user()->hasPermission('posts', 'delete', 'api')) {
    // User can delete posts via API
}

// Get all user permissions
$permissions = auth()->user()->getAllPermissions();

Query Relationships Programmatically

Besides artisan commands, you can also check relationships in your code:

use App\Models\User;
use Kiurd\RolePermissions\Models\Role;
use Kiurd\RolePermissions\Models\Module;

// Find which users have a specific role
$adminRole = Role::where('name', 'admin')->first();
$adminUsers = User::whereHas('roles', function($q) use ($adminRole) {
    $q->where('id', $adminRole->id);
})->get();

// Find which roles have permission for a specific module
$userModule = Module::where('name', 'users')->first();
$rolesWithAccess = Role::whereHas('permissions', function($q) use ($userModule) {
    $q->where('module_id', $userModule->id);
})->with(['permissions' => function($q) use ($userModule) {
    $q->where('module_id', $userModule->id)->with('action');
}])->get();

// Get all permissions for a specific module
$userModule = Module::where('name', 'users')->first();
$permissions = $userModule->permissions()->with('action')->get();

// Get all users with a specific permission
$permission = Permission::whereHas('module', function($q) {
    $q->where('name', 'users');
})->whereHas('action', function($q) {
    $q->where('name', 'delete');
})->first();

$usersWithPermission = User::whereHas('roles.permissions', function($q) use ($permission) {
    $q->where('permissions.id', $permission->id);
})->get();

// Check if a role has access to a specific module-action combination
$role = Role::where('name', 'editor')->first();
$hasAccess = $role->permissions()
    ->whereHas('module', function($q) {
        $q->where('name', 'posts');
    })
    ->whereHas('action', function($q) {
        $q->where('name', 'create');
    })
    ->exists();

Dynamic Permission Management

Using PermissionHelper

use Kiurd\RolePermissions\Helpers\PermissionHelper;

// Create a single permission
$permission = PermissionHelper::createPermission('users', 'create');

// Create multiple permissions
$permissions = PermissionHelper::createPermissions([
    ['module' => 'users', 'action' => 'create'],
    ['module' => 'users', 'action' => 'update'],
    ['module' => 'posts', 'action' => 'delete'],
]);

// Create full CRUD permissions for a module
$permissions = PermissionHelper::createCrudPermissions('products');
// Creates: products.create, products.read, products.update, products.delete, products.list

// Assign permissions to a role
PermissionHelper::assignPermissionsToRole('admin', [
    ['module' => 'users', 'action' => 'create'],
    ['module' => 'users', 'action' => 'delete'],
]);

// Check if permission exists
if (PermissionHelper::permissionExists('users', 'create')) {
    // Permission exists
}

// Get all permissions for a module
$userPermissions = PermissionHelper::getModulePermissions('users');

// Delete a permission
PermissionHelper::deletePermission('users', 'create');

Manual Permission Management

use Kiurd\RolePermissions\Models\Role;
use Kiurd\RolePermissions\Models\Module;
use Kiurd\RolePermissions\Models\Action;
use Kiurd\RolePermissions\Models\Permission;

// Create a module
$module = Module::create([
    'name' => 'products',
    'guard_name' => 'web',
    'description' => 'Product management'
]);

// Create an action
$action = Action::create([
    'name' => 'create',
    'guard_name' => 'web',
    'description' => 'Create operation'
]);

// Create a permission (module + action)
$permission = Permission::create([
    'module_id' => $module->id,
    'action_id' => $action->id,
    'guard_name' => 'web'
]);

// Create a role
$role = Role::create([
    'name' => 'product-manager',
    'guard_name' => 'web',
    'description' => 'Manages products'
]);

// Assign permission to role
$role->givePermissionTo($permission);

// Remove permission from role
$role->awayPermissionTo($permission);

// Sync permissions (replaces all existing)
$role->syncPermissions([$permission1, $permission2]);

// Assign role to user
$user->assignRole('product-manager');

Configuration

Edit config/role_permissions.php to customize:

return [
    // Enable auto-creation of permissions
    'auto_create_permissions' => env('AUTO_CREATE_PERMISSIONS', false),

    // Controller paths to scan
    'controller_paths' => [
        app_path('Http/Controllers'),
    ],

    // Controllers to exclude from scanning
    'excluded_controllers' => [
        'App\Http\Controllers\Controller',
    ],

    // Customize method to action mapping
    'method_action_map' => [
        'index' => 'list',
        'show' => 'read',
        'store' => 'create',
        // ... add your custom mappings
    ],
];

Example Workflow

1. Initial Setup

# Sync permissions from your controllers
php artisan permissions:sync --preview
php artisan permissions:sync

# Create roles
php artisan role:create admin
php artisan role:create editor
php artisan role:create viewer

2. Assign Permissions to Roles

# Give admin full access
php artisan role:assign-permission admin users create
php artisan role:assign-permission admin users read
php artisan role:assign-permission admin users update
php artisan role:assign-permission admin users delete

# Give editor limited access
php artisan role:assign-permission editor users read
php artisan role:assign-permission editor users update

3. Assign Roles to Users

// In your application code
$adminUser = User::find(1);
$adminUser->assignRole('admin');

$editorUser = User::find(2);
$editorUser->assignRole('editor');

4. Protect Your Routes

// Use auto-discovery middleware
Route::middleware(['auth', 'permission.auto'])->group(function () {
    Route::resource('users', UserController::class);
    Route::resource('posts', PostController::class);
    Route::resource('products', ProductController::class);
});

Database Schema

The package creates the following tables:

  • roles - Stores user roles
  • modules - Stores resource modules (users, posts, etc.)
  • actions - Stores actions (create, read, update, delete, etc.)
  • permissions - Junction of modules and actions
  • role_permissions - Assigns permissions to roles
  • user_roles - Assigns roles to users

Multi-Guard Support

The package supports multiple authentication guards:

// Assign role with specific guard
$user->assignRole('admin', 'api');

// Check permission with guard
$user->hasPermission('users', 'create', 'api');

// Sync permissions with guard
php artisan permissions:sync --guard=api

Best Practices

  1. Run sync after adding new controllers: Always sync permissions after creating new controllers or methods
  2. Use preview first: Use --preview flag to see what will be synced before actually syncing
  3. Enable auto-create in development: Set AUTO_CREATE_PERMISSIONS=true in development for rapid prototyping
  4. Disable auto-create in production: Keep it false in production for security and performance
  5. Use auto-discovery middleware: Use permission.auto middleware for automatic permission checking
  6. Create meaningful module names: Structure your controllers with clear, meaningful names

Troubleshooting

Permissions not working

  1. Make sure you've added the HasRolesAndPermissions trait to your User model
  2. Run php artisan permissions:sync to sync permissions
  3. Verify user has the correct role assigned
  4. Check that the role has the required permissions

Auto-create not working

  1. Ensure AUTO_CREATE_PERMISSIONS=true in your .env
  2. Verify you're using the permission.auto middleware
  3. Check file permissions on your database

License

MIT License

Contributing

Contributions are welcome! Please submit pull requests or open issues on GitHub.

About

A 100% database-driven, automated role-permission system for Laravel with zero-code setup, auto-discovery, and complete REST API

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages