Skip to content

Roles & Permissions ​

Introduction ​

Botble CMS includes a powerful role-based access control system that allows you to control what users can do in your application. The system consists of two main components:

  1. Roles: Stored in the database, roles are collections of permissions assigned to users. You can create as many roles as needed (e.g., Admin, Editor, Author).

  2. Permissions: Defined in code, permissions are specific actions that users can perform. Each permission has a unique flag (e.g., posts.create, users.edit).

Understanding Permissions ​

Permission Structure ​

Permissions are defined in configuration files with the following structure:

php
[
    'name' => 'Users',           // Display name of the permission
    'flag' => 'users.index',      // Unique identifier for the permission
    'parent_flag' => 'core.system' // Optional parent permission
]

Each permission has:

  • name: Human-readable name displayed in the admin interface
  • flag: Unique identifier used to check permissions programmatically
  • parent_flag: Optional parent permission for hierarchical organization

Core Permissions ​

Core permissions are defined in platform/core/acl/config/permissions.php:

php
return [
    [
        'name' => 'Users',
        'flag' => 'users.index',
        'parent_flag' => 'core.system',
    ],
    [
        'name' => 'Create',
        'flag' => 'users.create',
        'parent_flag' => 'users.index',
    ],
    // ...
];

Adding Custom Permissions ​

Plugin Permissions ​

When you create a plugin, a permissions configuration file is automatically generated at platform/plugins/your-plugin/config/permissions.php. You can modify this file to define permissions for your plugin:

php
return [
    [
        'name' => 'Blog',
        'flag' => 'blog.index',
    ],
    [
        'name' => 'Create',
        'flag' => 'blog.create',
        'parent_flag' => 'blog.index',
    ],
    [
        'name' => 'Edit',
        'flag' => 'blog.edit',
        'parent_flag' => 'blog.index',
    ],
    [
        'name' => 'Delete',
        'flag' => 'blog.destroy',
        'parent_flag' => 'blog.index',
    ],
];

Updating Permission Database ​

After modifying permission configuration files, you need to update the database by running:

bash
php artisan cms:user:rebuild-permissions

This command scans all permission configuration files and updates the database accordingly.

Using Permissions in Routes ​

Botble CMS automatically checks permissions for routes in the admin panel. By default, it uses the route name as the permission flag.

Basic Route Permission ​

php
Route::get('/', [
    'as' => 'blog.index',    // Will check for 'blog.index' permission
    'uses' => 'BlogController@index',
]);

Custom Permission Flag ​

You can specify a custom permission flag:

php
Route::get('/delete/{id}', [
    'as' => 'blog.destroy',
    'uses' => 'BlogController@destroy',
    'permission' => 'blog.edit',  // Will check for 'blog.edit' permission instead
]);

Disabling Permission Check ​

To disable permission checking for a route:

php
Route::get('/preview/{id}', [
    'as' => 'blog.preview',
    'uses' => 'BlogController@preview',
    'permission' => false,  // No permission check
]);

Super User Only Routes ​

To restrict a route to super users only:

php
Route::get('/system-settings', [
    'as' => 'system.settings',
    'uses' => 'SystemController@settings',
    'permission' => 'superuser',  // Only super users can access
]);

Checking Permissions in Code ​

In Controllers ​

You can check permissions in controllers using the hasPermission and hasAnyPermission methods:

php
public function edit($id)
{
    if (!Auth::user()->hasPermission('blog.edit')) {
        abort(403, 'Unauthorized action.');
    }

    // Continue with edit logic...
}

Or for checking multiple permissions:

php
if (Auth::user()->hasAnyPermission(['blog.edit', 'blog.create'])) {
    // User has at least one of these permissions
}

In Blade Templates ​

You can check permissions in Blade templates:

blade
@if (Auth::user()->hasPermission('blog.create'))
    <a href="{{ route('blog.create') }}" class="btn btn-primary">Create Post</a>
@endif

@if (Auth::user()->hasAnyPermission(['blog.edit', 'blog.destroy']))
    <div class="action-buttons">
        @if (Auth::user()->hasPermission('blog.edit'))
            <a href="{{ route('blog.edit', $post->id) }}" class="btn btn-sm btn-info">Edit</a>
        @endif

        @if (Auth::user()->hasPermission('blog.destroy'))
            <button class="btn btn-sm btn-danger delete-button">Delete</button>
        @endif
    </div>
@endif

Checking for Super User ​

To check if a user is a super user:

php
if (Auth::user()->isSuperUser()) {
    // User is a super user
}

Super users automatically have all permissions in the system.

Managing Roles and Users ​

Creating Roles Programmatically ​

php
use Botble\ACL\Models\Role;

$role = Role::query()->create([
    'name' => 'Editor',
    'description' => 'Editor role with content management permissions',
    'permissions' => [
        'posts.index' => true,
        'posts.create' => true,
        'posts.edit' => true,
        'categories.index' => true,
        'categories.create' => true,
        'categories.edit' => true,
    ],
]);

Assigning Roles to Users ​

php
use Botble\ACL\Models\User;
use Botble\ACL\Models\Role;

$user = User::query()->find(1);
$role = Role::query()->where('name', 'Editor')->first();

// Assign a role to a user
$user->roles()->sync([$role->id]);

// The RoleAssignmentEvent will automatically update user permissions

Updating User Permissions Directly ​

You can also update a user's permissions directly without assigning a role:

php
$user = User::query()->find(1);

// Add a permission
$user->updatePermission('blog.publish', true);

// Remove a permission
$user->updatePermission('blog.publish', false);

// Save changes
$user->save();

Best Practices ​

  1. Use Hierarchical Permissions: Organize permissions hierarchically using parent flags for better organization.

  2. Consistent Naming: Follow a consistent naming convention for permission flags (e.g., resource.action).

  3. Check Permissions Early: Check permissions at the beginning of controller methods to fail fast.

  4. Use Route Permissions: Leverage the built-in route permission system whenever possible.

  5. Rebuild After Changes: Always run php artisan cms:user:rebuild-permissions after modifying permission configurations.

Troubleshooting ​

  • Permission Not Working: Ensure the permission flag exists in the configuration and the database has been updated with cms:user:rebuild-permissions.

  • Route Access Issues: Check that the route name matches the permission flag or that a custom permission is correctly specified.

  • Role Assignment Problems: Verify that the role has the necessary permissions and that the user is correctly assigned to the role.