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:
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).
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:
[
'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
:
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:
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:
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
Route::get('/', [
'as' => 'blog.index', // Will check for 'blog.index' permission
'uses' => 'BlogController@index',
]);
Custom Permission Flag
You can specify a custom permission flag:
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:
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:
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:
public function edit($id)
{
if (!Auth::user()->hasPermission('blog.edit')) {
abort(403, 'Unauthorized action.');
}
// Continue with edit logic...
}
Or for checking multiple permissions:
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:
@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:
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
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
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:
$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
Use Hierarchical Permissions: Organize permissions hierarchically using parent flags for better organization.
Consistent Naming: Follow a consistent naming convention for permission flags (e.g.,
resource.action
).Check Permissions Early: Check permissions at the beginning of controller methods to fail fast.
Use Route Permissions: Leverage the built-in route permission system whenever possible.
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.