Backpack PermissionManager

repository·main·Indexed 20 days ago

https://github.com/laravel-backpack/permissionmanager

An administrative user interface for managing users, roles, and permissions in Laravel. It serves as a UI layer for the spatie/laravel-permission package, allowing administrators to assign roles and permissions through the Laravel Backpack dashboard.

Tokens
6.9K
Snippets
17
Records
23
Agent score
69%

What's inside laravel-backpack-permissionmanager

  1. How to overwrite package functionality

    main

    To modify the behavior of the PermissionManager, follow these patterns:

    1. Routes: Create routes/backpack/permissionmanager.php to override package routes.
    2. Controllers/Models: Create classes that extend the package's base classes. Use these new classes in your custom routes file.
    3. User Model: When creating custom controllers or seeders, always use the User model defined in your Backpack configuration rather than a hardcoded App\User class. This ensures compatibility with your specific setup.

    Use config('backpack.base.user_model_fqn') to get the correct fully qualified namespace for the User model.

  2. Enable @can directive in Backpack routes

    main

    By default, spatie/laravel-permission uses the Auth facade, which uses the default guard from config/auth.php, not the backpack guard. To use Laravel's native @can directive inside Backpack routes, you have two options:

    Option A: Change the Backpack guard to default

    In config/backpack/base.php, set the guard to null so it uses the default web guard:

    'guard' => null,

    Note: New roles/permissions will be saved with the "web" guard.

    Option B: Add Middleware

    Add the UseBackpackAuthGuardInsteadOfDefaultAuthGuard middleware to your Backpack routes in config/backpack/base.php:

    'middleware_class' => [
        App\Http\Middleware\CheckIfAdmin::class,
        \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
        Backpack\CRUD\app\Http\Middleware\UseBackpackAuthGuardInsteadOfDefaultAuthGuard::class,
    ],

    Note: New roles/permissions will be saved with the "backpack" guard.

    Alternative: If you don't want to change guards, you can always use backpack_user()->can('permission-name') which works regardless of the guard configuration.

    // Option A: config/backpack/base.php
    'guard' => null,
    
    // Option B: config/backpack/base.php
    'middleware_class' => [
        // ...
        Backpack\CRUD\app\Http\Middleware\UseBackpackAuthGuardInsteadOfDefaultAuthGuard::class,
    ],
  3. Customize the UserCrudController

    main

    To add custom fields to the User management interface, bind your own controller to overwrite the package's default UserCrudController. This should be done in a Service Provider (e.g., AppServiceProvider).

    $this->app->bind(
        \Backpack\PermissionManager\app\Http\Controllers\UserCrudController::class,
        \App\Http\Controllers\Admin\UserCrudController::class
    );
    // In AppServiceProvider.php
    public function register()
    {
        $this->app->bind(
            \Backpack\PermissionManager\app\Http\Controllers\UserCrudController::class,
            \App\Http\Controllers\Admin\UserCrudController::class
        );
    }
  4. Bind custom UserCrudController to the package

    main

    If you have extended the UserCrudController with a trait or custom logic, you must tell Laravel to use your controller when the package requests the original one. Register this binding in a Service Provider:

    $this->app->bind(
        \Backpack\PermissionManager\app\Http\Controllers\UserCrudController::class, // package controller
        \App\Http\Controllers\Admin\UserCrudController::class // your custom controller
    );
    $this->app->bind(
        \Backpack\PermissionManager\app\Http\Controllers\UserCrudController::class,
        \App\Http\Controllers\Admin\UserCrudController::class
    );
  5. Install Backpack​PermissionManager

    main

    Follow these steps to install the package and its dependency, spatie/laravel-permission.

    1. Install via Composer

    composer require backpack/permissionmanager

    2. Setup Spatie​Permission

    Since this package is a UI for spatie/laravel-permission, you must complete its installation steps:

    1. Publish migrations: php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider" --tag="permission-migrations"
    2. Run migrations: php artisan migrate
    3. Publish config: php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider" --tag="permission-config"
    4. Add the Spatie\Permission\Traits\HasRoles trait to your User model.

    3. Setup Backpack​PermissionManager

    1. Publish the package config and migrations:
    php artisan vendor:publish --provider="Backpack\PermissionManager\PermissionManagerServiceProvider" --tag="config" --tag="migrations"
    1. Run migrations: php artisan migrate

    4. Configure your User Model

    Ensure your User model (defined in config/backpack/permissionmanager.php) uses both the CrudTrait and the HasRoles trait:

    <?php namespace App\
    Models;
    
    use Backpack\CRUD\app\Models\Traits\CrudTrait;
    use Spatie\Permission\Traits\HasRoles;
    use Illuminate\
    Foundation\\Auth\\User as Authenticatable;
    
    class User extends Authenticatable
    {
        use CrudTrait;
        use HasRoles;
    
        // ...
    }
    composer require backpack/permissionmanager
    
    # Spatie setup
    php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider" --tag="permission-migrations"
    php artisan migrate
    php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider" --tag="permission-config"
    
    # PermissionManager setup
    php artisan vendor:publish --provider="Backpack\PermissionManager\PermissionManagerServiceProvider" --tag="config" --tag="migrations"
    php artisan migrate
  6. Upgrade from PermissionManager 3.x to 4.x

    main

    Follow these steps to upgrade:

    1. Upgrade spatie/laravel-permission to version 2.28.2 or higher (note: database schema changes occur here).
    2. Update composer.json to require backpack/permissionmanager: 4.0.*.
    3. Delete your existing config/backpack/permissionmanager.php file.
    4. Re-run the installation steps for version 4.x.
    5. Laravel 8+ Note: If you are on Laravel 8 or newer, verify that your config/backpack/permissionmanager.php uses the correct User model path (e.g., App\Models\User::class instead of App\User::class).
  7. Apply permission-based access to UserCrudController

    main

    To use the CrudPermissionTrait in your UserCrudController, extend the package's UserCrudController and call your permission logic in the setup() method.

    Note: You must ensure your application routes point to your custom controller instead of the package default. You can do this by binding the package controller to your custom one in a Service Provider or by defining custom routes.

    namespace App\Http\Controllers\Admin;
    
    use Backpack\PermissionManager\app\Http\Controllers\UserCrudController as BackpackUserCrudController;
    
    class UserCrudController extends BackpackUserCrudController
    {
        use \App\Traits\CrudPermissionTrait;
    
        public function setup()
        {
            parent::setup();
            $this->setAccessUsingPermissions();
        }
    }
  8. Overwrite PermissionManager routes

    main

    To completely customize the routes used by the PermissionManager (e.g., to use your own controllers for role or permission), create a file at routes/backpack/permissionmanager.php. The package will prioritize this file over its internal routes.

    In this file, you can define groups for your custom controllers and separate groups for the original package controllers to maintain standard functionality for other resources.

    // routes/backpack/permissionmanager.php
    
    Route::group([
        'namespace'  => 'App\Http\Controllers\Admin',
        'prefix'     => config('backpack.base.route_prefix', 'admin'),
        'middleware' => ['web', backpack_middleware()],
    ],
    function () {
        Route::crud('user', 'UserCrudController');
    });
    
    Route::group([
        'namespace'  => '\Backpack\PermissionManager\app\Http\Controllers',
        'prefix'     => config('backpack.base.route_prefix', 'admin'),
        'middleware' => ['web', backpack_middleware()],
    ],
    function () {
        Route::crud('permission', 'PermissionCrudController');
        Route::crud('role', 'RoleCrudController');
    });
  9. Link Spatie permissions to CRUD access

    main

    You can dynamically control CRUD operation access (navigation buttons and security guards) based on Spatie permissions. This is achieved by using $this->crud->allowAccess() and $this->crud->denyAccess() within your controller's setup() method.

    To implement this cleanly, create a trait that maps permission levels (e.g., see, edit) to specific CRUD operations (e.g., list, show, create, update, delete) and call it from your CrudController.

    namespace App	raits;
    
    use Backpack\CRUD\app\Library\CrudPanel\CrudPanelFacade as CRUD;
    
    trait CrudPermissionTrait
    {
        public array $operations = ['list', 'show', 'create', 'update', 'delete'];
    
        public function setAccessUsingPermissions()
        {
            $this->crud->denyAccess($this->operations);
            $table = CRUD::getModel()->getTable();
            $user = request()->user();
    
            if (!$user) return;
    
            foreach ([
                'see' => ['list', 'show'],
                'edit' => ['list', 'show', 'create', 'update', 'delete'],
            ] as $level => $operations) {
                if ($user->can("$table.$level")) {
                    $this->crud->allowAccess($operations);
                }
            }
        }
    }
  10. Understand RoleCrudController behavior and columns

    main

    The RoleCrudController manages roles using the following default column configurations in the list view:

    • name: The name of the role.
    • users_count: A count of users assigned to the role. This uses Laravel's withCount('users') to ensure performance. Clicking this column redirects to the User CRUD with a role filter (e.g., backpack_url('user?role={id}')).
    • guard_name: Displayed only if config('backpack.permissionmanager.multiple_guards') is set to true.
    • permissions: A select_multiple column showing the permissions associated with the role via a many-to-many relationship.

    When creating or updating roles, the controller uses a checklist field for permissions and automatically clears the Spatie PermissionRegistrar cache to ensure changes take effect immediately.

  11. Customize UserCrudController for Permission Management

    main

    The UserCrudController is the central controller for managing users within the Backpack admin interface. It integrates roles and permissions into the standard CRUD operations. When customizing your own user management, you can leverage its patterns for handling password hashing and relationship management.

    Key features implemented in this controller include:

    • Password Handling: Automatically hashes the password field if provided and cleans up password_confirmation from the request.
    • Relationship Management: Uses checklist_dependency to manage the interconnected relationship between Roles and Permissions.
    • Filtering: (Requires Backpack Pro) Adds dropdown and select2 filters for role and permissions to the list view.
    <?php
    
    namespace Backpack\PermissionManager\app\Http\Controllers;
    
    use Backpack\CRUD\app\Http\Controllers\CrudController;
    
    class UserCrudController extends CrudController
    {
        // Implementation details for managing users with roles and permissions
    }
  12. Publish PermissionManager assets

    main

    You can publish the configuration, translation, route, and migration files to your application using the standard Laravel vendor:publish command. This allows you to customize the package behavior and appearance.

    # Publish configuration
    php artisan vendor:publish --tag=config
    
    # Publish translations
    php artisan vendor:publish --tag=lang
    
    # Publish routes
    php artisan vendor:publish --tag=routes
    
    # Publish migrations
    php artisan vendor:publish --tag=migrations