Laravel 12 Roles and Permissions with Admin Panel Backpack: A Complete Guide
Implementing a robust roles and permissions system is a critical requirement for most web applications. Laravel provides excellent built-in tools for authorization, and when combined with Backpack for Laravel (a popular admin panel solution), you can create a powerful administrative interface with minimal effort.
In this comprehensive guide, we'll walk through setting up roles and permissions in Laravel 12 using the Backpack admin panel. We'll cover installation, configuration, CRUD interfaces for roles and permissions, and how to implement authorization throughout your application.
Prerequisites
Before we begin, ensure you have:
- Laravel 12 installed
- Composer installed
- Basic knowledge of Laravel
- MySQL or another database system
Step 1: Install Laravel Backpack
First, let's install Backpack for Laravel:
composer require backpack/crud
Then, publish the necessary files:
php artisan backpack:install
This will install Backpack and set up the basic admin panel structure.
Step 2: Install Spatie Laravel-Permission
For roles and permissions, we'll use the popular spatie/laravel-permission package:
composer require spatie/laravel-permission
Publish the migration and config file:
php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider"
Run the migrations:
php artisan migrate
Step 3: Configure User Model
Update your User model to use the HasRoles trait:
<?php
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Spatie\Permission\Traits\HasRoles;
class User extends Authenticatable
{
use HasRoles;
// ... rest of your model code
}
Step 4: Create Backpack CRUDs for Roles and Permissions
Now, let's create CRUD interfaces for managing roles and permissions.
Create Permission CRUD
Generate a Permission CRUD:
php artisan backpack:crud permission
Update the generated PermissionCrudController:
<?php
namespace App\Http\Controllers\Admin;
use Backpack\CRUD\app\Http\Controllers\CrudController;
use Backpack\CRUD\app\Library\CrudPanel\CrudPanelFacade as CRUD;
use Spatie\Permission\Models\Permission;
class PermissionCrudController extends CrudController
{
use \Backpack\CRUD\app\Http\Controllers\Operations\ListOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\CreateOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\UpdateOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\DeleteOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\ShowOperation;
public function setup()
{
CRUD::setModel(Permission::class);
CRUD::setRoute(config('backpack.base.route_prefix') . '/permission');
CRUD::setEntityNameStrings('permission', 'permissions');
}
protected function setupListOperation()
{
CRUD::column('id');
CRUD::column('name')->label('Permission Name');
CRUD::column('guard_name');
CRUD::column('created_at');
CRUD::column('updated_at');
}
protected function setupCreateOperation()
{
CRUD::setValidation([
'name' => 'required|min:2|max:255|unique:permissions,name',
'guard_name' => 'required|min:2|max:255',
]);
CRUD::field('name')->label('Permission Name');
CRUD::field('guard_name')->default('web');
}
protected function setupUpdateOperation()
{
$this->setupCreateOperation();
}
}
Create Role CRUD
Generate a Role CRUD:
php artisan backpack:crud role
Update the generated RoleCrudController:
<?php
namespace App\Http\Controllers\Admin;
use Backpack\CRUD\app\Http\Controllers\CrudController;
use Backpack\CRUD\app\Library\CrudPanel\CrudPanelFacade as CRUD;
use Spatie\Permission\Models\Role;
use Spatie\Permission\Models\Permission;
class RoleCrudController extends CrudController
{
use \Backpack\CRUD\app\Http\Controllers\Operations\ListOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\CreateOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\UpdateOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\DeleteOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\ShowOperation;
public function setup()
{
CRUD::setModel(Role::class);
CRUD::setRoute(config('backpack.base.route_prefix') . '/role');
CRUD::setEntityNameStrings('role', 'roles');
}
protected function setupListOperation()
{
CRUD::column('id');
CRUD::column('name')->label('Role Name');
CRUD::column('guard_name');
CRUD::column('permissions')->label('Permissions')
->type('relationship_count')
->suffix(' permissions');
CRUD::column('created_at');
CRUD::column('updated_at');
}
protected function setupCreateOperation()
{
CRUD::setValidation([
'name' => 'required|min:2|max:255|unique:roles,name',
'guard_name' => 'required|min:2|max:255',
]);
CRUD::field('name')->label('Role Name');
CRUD::field('guard_name')->default('web');
CRUD::field('permissions')
->label('Permissions')
->type('select2_multiple')
->entity('permissions')
->model(Permission::class)
->attribute('name')
->pivot(true);
}
protected function setupUpdateOperation()
{
$this->setupCreateOperation();
}
}
Create User CRUD with Role Assignment
Generate a User CRUD if you don't have one:
php artisan backpack:crud user
Update the UserCrudController to include role management:
<?php
namespace App\Http\Controllers\Admin;
use Backpack\CRUD\app\Http\Controllers\CrudController;
use Backpack\CRUD\app\Library\CrudPanel\CrudPanelFacade as CRUD;
use App\Models\User;
use Spatie\Permission\Models\Role;
class UserCrudController extends CrudController
{
use \Backpack\CRUD\app\Http\Controllers\Operations\ListOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\CreateOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\UpdateOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\DeleteOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\ShowOperation;
public function setup()
{
CRUD::setModel(User::class);
CRUD::setRoute(config('backpack.base.route_prefix') . '/user');
CRUD::setEntityNameStrings('user', 'users');
}
protected function setupListOperation()
{
CRUD::column('id');
CRUD::column('name');
CRUD::column('email');
CRUD::column('roles')
->label('Roles')
->type('relationship_count')
->suffix(' roles');
CRUD::column('created_at');
CRUD::column('updated_at');
}
protected function setupCreateOperation()
{
CRUD::setValidation([
'name' => 'required|min:2|max:255',
'email' => 'required|email|unique:users,email',
'password' => 'required|min:6',
]);
CRUD::field('name');
CRUD::field('email');
CRUD::field('password')->type('password');
CRUD::field('roles')
->label('Roles')
->type('select2_multiple')
->entity('roles')
->model(Role::class)
->attribute('name')
->pivot(true);
}
protected function setupUpdateOperation()
{
CRUD::setValidation([
'name' => 'required|min:2|max:255',
'email' => 'required|email|unique:users,email,'.CRUD::getCurrentEntryId(),
'password' => 'nullable|min:6',
]);
CRUD::field('name');
CRUD::field('email');
CRUD::field('password')->type('password');
CRUD::field('roles')
->label('Roles')
->type('select2_multiple')
->entity('roles')
->model(Role::class)
->attribute('name')
->pivot(true);
}
}
Step 5: Add Menu Items to Admin Panel
Add the new CRUDs to the Backpack menu. Open app/Providers/AppServiceProvider.php and update the boot() method:
use Backpack\MenuCRUD\app\Models\MenuItem;
public function boot()
{
// Create default menu items
if (MenuItem::count() === 0) {
MenuItem::create([
'name' => 'Dashboard',
'type' => 'link',
'link' => backpack_url('dashboard'),
'icon' => 'la la-home',
]);
MenuItem::create([
'name' => 'Users',
'type' => 'link',
'link' => backpack_url('user'),
'icon' => 'la la-user',
]);
MenuItem::create([
'name' => 'Roles',
'type' => 'link',
'link' => backpack_url('role'),
'icon' => 'la la-id-badge',
]);
MenuItem::create([
'name' => 'Permissions',
'type' => 'link',
'link' => backpack_url('permission'),
'icon' => 'la la-key',
]);
}
}
Step 6: Protect Backpack Routes with Middleware
To ensure only authorized users can access the admin panel, update the Backpack configuration. In config/backpack/base.php:
'middleware_class' => [
App\Http\Middleware\CheckIfAdmin::class,
\Illuminate\Foundation\Http\Middleware\PreventRequestsDuringMaintenance::class,
\Illuminate\Cookie\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\Spatie\Permission\Middlewares\PermissionMiddleware::class,
],
Create a new middleware to check for admin access:
php artisan make:middleware CheckIfAdmin
Update the CheckIfAdmin middleware:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
class CheckIfAdmin
{
public function handle($request, Closure $next)
{
if (Auth::check() && Auth::user()->hasRole('admin')) {
return $next($request);
}
abort(403, 'Unauthorized access');
}
}
Register the middleware in bootstrap/app.php:
->withMiddleware(function ($middleware) {
$middleware->alias([
'admin' => \App\Http\Middleware\CheckIfAdmin::class,
'role' => \Spatie\Permission\Middlewares\RoleMiddleware::class,
'permission' => \Spatie\Permission\Middlewares\PermissionMiddleware::class,
]);
})
Step 7: Seed Initial Roles and Permissions
Create a seeder for initial roles and permissions:
php artisan make:seeder RolesAndPermissionsSeeder
Update the seeder:
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use Spatie\Permission\Models\Role;
use Spatie\Permission\Models\Permission;
use App\Models\User;
class RolesAndPermissionsSeeder extends Seeder
{
public function run()
{
// Reset cached roles and permissions
app()[\Spatie\Permission\PermissionRegistrar::class]->forgetCachedPermissions();
// Create permissions
$permissions = [
'user_management_access',
'permission_create',
'permission_edit',
'permission_show',
'permission_delete',
'permission_access',
'role_create',
'role_edit',
'role_show',
'role_delete',
'role_access',
'user_create',
'user_edit',
'user_show',
'user_delete',
'user_access',
];
foreach ($permissions as $permission) {
Permission::create(['name' => $permission]);
}
// Create roles and assign created permissions
$role = Role::create(['name' => 'admin']);
$role->givePermissionTo(Permission::all());
$role = Role::create(['name' => 'user']);
$role->givePermissionTo(['user_show']);
// Create admin user
$user = User::create([
'name' => 'Admin',
'email' => 'admin@example.com',
'password' => bcrypt('password'),
]);
$user->assignRole('admin');
// Create regular user
$user = User::create([
'name' => 'User',
'email' => 'user@example.com',
'password' => bcrypt('password'),
]);
$user->assignRole('user');
}
}
Run the seeder:
php artisan db:seed --class=RolesAndPermissionsSeeder
Step 8: Implement Authorization in Your Application
Now that we have our roles and permissions system set up, let's see how to use it in your application.
In Controllers
public function index()
{
// Only users with 'user_access' permission can access this
$this->authorize('user_access');
// Or check for a role
if (!auth()->user()->hasRole('admin')) {
abort(403);
}
// Your controller logic
}
In Blade Views
@can('user_create')
<a href="{{ route('users.create') }}">Create New User</a>
@endcan
@role('admin')
<p>This is only visible to admin users</p>
@endrole
In Routes
Route::group(['middleware' => ['role:admin']], function () {
Route::resource('users', UserController::class);
});
Route::group(['middleware' => ['permission:user_access']], function () {
Route::get('/dashboard', 'DashboardController@index');
});
Step 9: Customizing the Admin Panel
Add Permission Checks to Backpack Operations
You can customize which operations are available based on permissions. For example, in your CRUD controllers:
protected function setupListOperation()
{
if (!backpack_user()->can('user_access')) {
abort(403);
}
// ... rest of your setup
}
protected function setupCreateOperation()
{
if (!backpack_user()->can('user_create')) {
abort(403);
}
// ... rest of your setup
}
Create a Custom Operation for Assigning Roles and Permissions
You can create a custom operation to manage user roles and permissions more granularly. First, create a new operation:
php artisan backpack:operation AssignRolesAndPermissions
Then implement it in your UserCrudController:
use \App\Http\Controllers\Operations\AssignRolesAndPermissionsOperation;
// ...
public function setupAssignRolesAndPermissionsOperation()
{
CRUD::set('entity', 'user');
// Add fields for roles and permissions
CRUD::field('roles')
->label('Roles')
->type('select2_multiple')
->entity('roles')
->model(Role::class)
->attribute('name')
->pivot(true);
CRUD::field('permissions')
->label('Direct Permissions')
->type('select2_multiple')
->entity('permissions')
->model(Permission::class)
->attribute('name')
->pivot(true);
}
Step 10: Testing Your Implementation
It's crucial to test your roles and permissions system:
- Try logging in as the admin user and verify you can access all sections
- Log in as a regular user and verify access restrictions
- Test creating new roles and assigning permissions
- Verify that permission checks work in controllers, views, and routes
Conclusion
In this guide, we've created a comprehensive roles and permissions system in Laravel 12 using Backpack for the admin panel. We've:
- Installed and configured Backpack and Spatie's laravel-permission package
- Created CRUD interfaces for users, roles, and permissions
- Implemented middleware to protect routes
- Seeded initial data
- Shown how to use authorization throughout your application
- Added customizations to enhance the admin panel
This setup provides a solid foundation for managing access control in your Laravel application. You can extend it further by:
- Adding more granular permissions
- Implementing permission groups
- Creating a more sophisticated user interface for permission management
- Adding audit logging for permission changes
Remember to always follow the principle of least privilege when assigning permissions and regularly review your access control setup to ensure it remains secure as your application evolves.
Projects related to this guide
Use the concepts from this article in practical source-code projects.
Flask Authentication System (Free Version) - Kritim Yantra
🛠 Features✔ Google & GitHub Authentication✔ User Registration & Login✔ Profile/Dashboard Access✔ Secure...
Python Flask Blog Project with Admin Panel
Are you ready to launch a powerful, modern, and fully customizable blog? Look no further! Introducing the Flask-...
Laravel 12 + ReactJS Starter Kit: Add Multi-Language Support (Arabic, English, Spanish) with Blog CRUD
🚀 Installation & Setup Download & Extract Get the ZIP from kritimyantra.com and extract it. Includes pr...
Comments
No comments yet. Be the first to comment.
Sign in to join the discussion.