abdulbaset/laravel-roles-permissions

A Laravel package for managing roles and permissions

v4.0.0 2025-06-08 20:51 UTC

This package is auto-updated.

Last update: 2025-06-08 20:52:10 UTC


README

A simple and flexible package for handling roles and permissions in Laravel applications.

Requirements

  • PHP 8.1 or higher
  • Laravel 10.x, 11.x, or 12.x

Features

  • Role-based access control (RBAC)
  • Permission management
  • Blade directives for easy role and permission checks in views
  • Artisan commands for managing roles and permissions
  • Support for multiple roles per user
  • Lightweight and easy to integrate

Installation

You can install the package via Composer:

composer require abdulbaset/laravel-roles-permissions

Publish the configuration file and migrations:

php artisan vendor:publish --provider="Abdulbaset\RolesPermissions\RolesPermissionsServiceProvider" --tag=roles-config
php artisan vendor:publish --provider="Abdulbaset\RolesPermissions\RolesPermissionsServiceProvider" --tag=roles-migrations

Run the migrations:

php artisan migrate

Usage

Add HasRoles Trait to User Model

Add the HasRoles trait to your User model:

use Abdulbaset\RolesPermissions\Traits\HasRoles;
use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable
{
    use HasRoles;
    
    // ...
}

Important: Each user can have only one role. The system enforces this constraint at the database level.

Available Methods

User Model Methods

// Get the user's role
$role = $user->role;

// Check if user has a specific role
$user->hasRole('admin');

// Check if user has any of the specified roles
$user->hasAnyRole(['admin', 'editor']);

// Check if user has a permission
$user->hasPermission('edit-posts');

// Check if user has any of the given permissions
$user->hasAnyPermission(['edit-posts', 'delete-posts']);

// Check if user has all of the given permissions
$user->hasAllPermissions(['edit-posts', 'delete-posts']);

// Assign a role to a user (replaces any existing role)
$user->giveRole('editor');

// Sync role (alias for giveRole)
$user->syncRoles('editor');

// Remove the user's role
$user->removeRole();

Role Model Methods

// Create a new role with description
$role = Role::create([
    'name' => 'Editor',
    'slug' => 'editor',
    'description' => 'Can edit and manage content'
]);

// Update role description
$role->update(['description' => 'Updated role description']);

// Get role description
$description = $role->description;

Permission Model Methods

// Create a new permission with description
$editPosts = Permission::create([
    'name' => 'Edit Posts',
    'slug' => 'edit-posts',
    'description' => 'Allows editing of existing posts'
]);

// Update permission description
$permission->update(['description' => 'Updated permission description']);

// Get permission description
$description = $permission->description;
Example Usage:
// Assign a role to a user
$user->giveRole('admin');

// Check user's role
if ($user->hasRole('admin')) {
    // User is an admin
}

// Get the role name
$roleName = $user->role ? $user->role->name : 'No role';

// Remove role
$user->removeRole();

// Check if user has any of these roles
if ($user->hasAnyRole(['admin', 'moderator'])) {
    // User is either admin or moderator
}

Role Model Methods

// Check if role has a permission
$role->hasPermission('edit-posts');

// Give permission to a role
$role->givePermission('edit-posts');

// Sync all permissions for a role (removes all existing permissions and adds the given ones)
$role->syncPermissions(['edit-posts', 'delete-posts']);

// Remove a specific permission from a role
$role->removePermission('edit-posts');  // Returns boolean

// Remove multiple permissions from a role
$removedCount = $role->removePermissions(['edit-posts', 'delete-posts']);  // Returns number of permissions removed

// Remove all permissions from a role
$removedCount = $role->removeAllPermissions();  // Returns number of permissions removed
Example Usage:
use Abdulbaset\RolesPermissions\Models\Role;

// Get a role
$adminRole = Role::where('slug', 'admin')->first();

// Add a permission
$adminRole->givePermission('delete-users');

// Check if role has permission
if ($adminRole->hasPermission('delete-users')) {
    // Role has the permission
}

// Remove a permission
$adminRole->removePermission('delete-users');

// Remove multiple permissions
$adminRole->removePermissions(['edit-posts', 'delete-posts']);

// Remove all permissions
$removedCount = $adminRole->removeAllPermissions();

Permissions Methods

Using getPermissions()

// Get all permissions for a role
$rolePermissions = $role->getPermissions();

// Get all permissions for a user's role
$userPermissions = $user->getPermissions();

// Example: Loop through permissions
foreach ($user->getPermissions() as $permission) {
    echo $permission->name; // e.g., 'edit-posts'
    echo $permission->description; // e.g., 'Can edit posts'
}

// Check if user has any permissions
if ($user->getPermissions()->isNotEmpty()) {
    // User has permissions
}

// Check if role has any permissions
if ($role->getPermissions()->isNotEmpty()) {
    // Role has permissions
}

Authorization Methods

1. Using FormRequest

You can check permissions directly in your FormRequest classes:

use Illuminate\Foundation\Http\FormRequest;

class StoreProductRequest extends FormRequest
{
    public function authorize()
    {
        return $this->user() && $this->user()->hasPermission('create-product');
    }

    public function rules()
    {
        return [
            'name' => 'required|string|max:255',
            'price' => 'required|numeric|min:0',
        ];
    }
}

2. Using Policies

  1. First, create a policy:
php artisan make:policy ProductPolicy --model=Product
  1. Implement the policy methods:
namespace App\Policies;

use App\Models\Product;
use App\Models\User;

class ProductPolicy
{
    public function viewAny(User $user)
    {
        return $user->hasPermission('view-products');
    }

    public function view(User $user, Product $product)
    {
        return $user->hasPermission('view-product');
    }

    public function create(User $user)
    {
        return $user->hasPermission('create-product');
    }
    
    // ... other methods
}
  1. Register the policy in AuthServiceProvider:
protected $policies = [
    Product::class => ProductPolicy::class,
];

3. Using Middleware

  1. Register the middleware in app/Http/Kernel.php:
protected $routeMiddleware = [
    'permission' => \App\Http\Middleware\CheckPermission::class,
];
  1. Create the middleware:
php artisan make:middleware CheckPermission
  1. Implement the middleware:
namespace App\Http\Middleware;

use Closure;

class CheckPermission
{
    public function handle($request, Closure $next, $permission)
    {
        if (!auth()->check() || !auth()->user()->hasPermission($permission)) {
            abort(403, 'Unauthorized action.');
        }

        return $next($request);
    }
}
  1. Use in routes:
Route::middleware(['auth', 'permission:create-product'])->group(function () {
    Route::get('/products/create', [ProductController::class, 'create']);
    Route::post('/products', [ProductController::class, 'store']);
});

4. Directly in Controller

You can also check permissions directly in your controller methods:

public function store(Request $request)
{
    // Check permission
    if (!auth()->user()->hasPermission('create-product')) {
        abort(403, 'Unauthorized action.');
    }

    // Validation
    $validated = $request->validate([
        'name' => 'required|string|max:255',
        'price' => 'required|numeric|min:0',
    ]);

    // Create the product
    $product = Product::create($validated);

    return response()->json($product, 201);
}

Blade Directives

@role('admin')
    // This content will be shown only to users with the 'admin' role
@endrole

@hasanyrole(['admin', 'editor'])
    // This content will be shown to users with either 'admin' or 'editor' role
@endhasanyrole

@hasallroles(['admin', 'editor'])
    // This content will be shown only to users with both 'admin' and 'editor' roles
@endhasallroles

@haspermission('edit-posts')
    // This content will be shown only to users with the 'edit-posts' permission
@endhaspermission

@hasanypermission(['edit-posts', 'delete-posts'])
    // This content will be shown to users with either 'edit-posts' or 'delete-posts' permission
@endhasanypermission

@hasallpermissions(['edit-posts', 'delete-posts'])
    // This content will be shown only to users with both 'edit-posts' and 'delete-posts' permissions
@endhasallpermissions

Artisan Commands

1. Managing Roles

Sync Roles (Dangerous ⚠️)

php artisan roles:sync

This command will synchronize roles between your config file and database. It will:

  • Create any new roles from your config file
  • Update existing roles with new names
  • Delete any roles that are not in your config file

⚠️ Warning: This will remove any roles (and their relationships) that are not in your config file.

Seed/Update Roles (Safe ✅)

php artisan roles:seed

This command will safely seed or update roles from your config file. It will:

  • Create any roles that don't exist
  • Update existing roles with new names
  • Never delete any existing roles or permissions

2. Managing Permissions

Sync Permissions (Dangerous ⚠️)

php artisan permissions:sync

This command will synchronize permissions between your config file and database. It will:

  • Create any new permissions from your config file
  • Update existing permissions if their names change
  • Delete any permissions not in your config file

⚠️ Warning: This will remove any permissions (and their relationships) that are not in your config file.

Seed/Update Permissions (Safe ✅)

php artisan permissions:seed

This command will safely seed or update permissions from your config file. It will:

  • Create any new permissions that don't exist
  • Update existing permissions with new names
  • Restore any soft-deleted permissions
  • Never delete any existing permissions

When to Use Each Command

Command Safe? Best For
roles:seed ✅ Safe Initial setup or adding new roles without affecting existing ones
roles:sync ⚠️ Dangerous Cleaning up old roles and ensuring database matches config exactly
permissions:seed ✅ Safe Adding new permissions without affecting existing ones
permissions:sync ⚠️ Dangerous Cleaning up old permissions and ensuring database matches config exactly

Recommended Workflow

  1. Use the safe roles:seed and permissions:seed for normal development
  2. Only use roles:sync and permissions:sync when you need to clean up old data
  3. Always backup your database before running sync commands
  4. In production, consider running sync commands in a controlled manner after thorough testing

Configuration

You can customize the package by publishing the configuration file:

php artisan vendor:publish --provider="Abdulbaset\RolesPermissions\RolesPermissionsServiceProvider" --tag=roles-config

Testing

composer test

Changelog

Please see CHANGELOG for more information on what has changed recently.

Contributing

Please see CONTRIBUTING for details.

Security Vulnerabilities

If you discover any security related issues, please email abdulbasetredasayedhf@gmail.com instead of using the issue tracker.

License

The MIT License (MIT). Please see License File for more information.