creativecrafts/laravel-role-permission-manager

A simple package to manager an application role and permissions.

1.0.1 2025-01-18 07:15 UTC

This package is auto-updated.

Last update: 2025-02-03 01:02:22 UTC


README

Latest Version on Packagist GitHub Tests Action Status GitHub Code Style Action Status Total Downloads

Laravel Role Permission Manager is a powerful yet simple package designed to streamline the management of roles and permissions in Laravel applications. It provides an intuitive interface for creating, assigning, and managing user roles and their associated permissions, allowing developers to implement complex authorization systems with ease.

This package is perfect for applications of all sizes, from small projects to large-scale enterprise systems, offering flexibility and scalability in handling user access control. Whether you're building a simple blog with admin roles or a complex multi-tenant application with granular permissions, Laravel Role Permission Manager has got you covered.

Features

  • Easy integration with Laravel's authentication system
  • Flexible role and permission management
  • Middleware for protecting routes based on roles and permissions
  • Blade directives for easy view-level access control
  • Easily extendable and customizable
  • Comprehensive testing suite ensuring reliability
  • Clear and concise API for programmatic access control

Table of Contents

  1. Getting Started
  2. Usage
  3. Authorization Policies
  4. Frontend Integration
  5. Contributing
  6. Security
  7. Credits
  8. License

Getting Started

Installation

  1. Install the package via Composer:
composer require creativecrafts/laravel-role-permission-manager
  1. Publish and run the migrations:
php artisan vendor:publish --tag="role-permission-manager-migrations"
php artisan migrate
  1. Optionally, publish the config file:
php artisan vendor:publish --tag="role-permission-manager-config"

Publishing TypeScript Files

To use the TypeScript helper files in your application, you can publish them using the following command:

php artisan vendor:publish --tag="laravel-role-permission-manager-typescript"

Configuration

Customize the package behavior by editing the published config file config/role-permission-manager.php.

Key configuration options:

- user_model: Specify the User model used by your application
- roles_table: Define the name for the roles table
- permissions_table: Define the name for the permissions table
- cache_expiration_time: Set the cache expiration time for roles and permissions
- default_guard: Specify the default guard for role and permission checks
- use_package_routes: If set to true, the package will register its routes automatically.
- route_middleware: Define the middleware to be applied to the package routes
- route_prefix: Set the prefix for the package routes
- super_admin_role: Define the role that should be considered as a super admin
- auto_create_permissions: Enable or disable automatic creation of permissions
- enable_wildcard_permission: Enable or disable wildcard permissions
- case_sensitive_permissions: Choose whether permission names should be case-sensitive

Registering Your User Model

After installing the package, you need to register your User model. This step is crucial for the package to work correctly with your application's user model.

Add the following code to your AppServiceProvider or a custom service provider:

use CreativeCrafts\LaravelRolePermissionManager\LaravelRolePermissionManagerServiceProvider;

public function boot()
{
    LaravelRolePermissionManagerServiceProvider::registerUserModel(\App\Models\User::class);
}

Database Migrations

The package includes migrations for creating the necessary database tables. These will be published when you run the vendor publish command for migrations.

Usage

Models

Permission Model

The Permission model represents individual permissions in your application.

Key features:

  • Automatic slug generation
  • Wildcard permissions support
  • Scope support

Usage example:

use CreativeCrafts\LaravelRolePermissionManager\Models\Permission;

$permission = Permission::create([
    'name' => 'Edit Posts',
    'description' => 'Allow user to edit posts',
    'scope' => 'blog'
]);

Role Model

The Role model represents roles that can be assigned to users and associated with permissions.

Key features:

  • Automatic slug generation
  • Role hierarchy support
  • Permission checking methods

Usage example:

use CreativeCrafts\LaravelRolePermissionManager\Models\Role;

$role = Role::create([
    'name' => 'Editor',
    'description' => 'Can edit and publish content'
]);

if ($role->hasPermissionTo('edit-posts')) {
    // Allow editing posts
}

Middleware

HandleInertiaRequests Middleware

The HandleInertiaRequests middleware is designed to work with Inertia.js applications, sharing the authenticated user's permissions with the frontend.

Key Features

  1. Inertia Request Detection: Automatically detects if the current request is an Inertia request.

  2. Permission Sharing: Shares the authenticated user's permissions with Inertia, making them available on the frontend.

  3. Caching: Uses Laravel's cache system to store user permissions, improving performance by reducing database queries.

How it Works

  1. The middleware checks if the request is an Inertia request.
  2. If it is, it retrieves the authenticated user's permissions.
  3. These permissions are then shared with Inertia, making them available in the frontend as auth.permissions.

Usage

To use this middleware, add it to your app/Http/Kernel.php file in the web middleware group:

protected $middlewareGroups = [
    'web' => [
        // ... other middleware
        \CreativeCrafts\LaravelRolePermissionManager\Middleware\HandleInertiaRequests::class,
    ],
];

Once added, the middleware will automatically share the authenticated user's permissions with your Inertia frontend.

Accessing Permissions in the Frontend

Example: In your Vue components, you can access the user's permissions like this:

const permissions = this.$page.props.auth.permissions;

// Check if user has a specific permission
if (permissions.includes('edit-posts')) {
    // User can edit posts
}

This middleware enhances the integration between your Laravel backend and Inertia.js frontend, making it easier to implement permission-based UI logic.

PermissionMiddleware

The PermissionMiddleware is designed to protect routes based on user permissions. It checks if the authenticated user has the required permission(s) before allowing access to a route.

Key Features

  1. Route Protection: Allows you to specify required permissions for accessing specific routes.
  2. Multiple Permission Support: Can check for multiple permissions, granting access if the user has any of them.
  3. Authentication Check: Ensures the user is authenticated before checking permissions.
  4. JSON Response Support: Returns a JSON response for unauthorized actions if the request expects JSON.

Usage

To use this middleware, you can add it to your routes or controllers:

  1. In your app/Http/Kernel.php, add an alias for the middleware:
protected $routeMiddleware = [
    // ... other middleware
    'permission' => \CreativeCrafts\LaravelRolePermissionManager\Middleware\PermissionMiddleware::class,
];
  1. Use it in your routes:
Route::get('/admin/posts', [PostController::class, 'index'])->middleware('permission:view-posts');
  1. Or use it in your controllers:
public function __construct()
{
    $this->middleware('permission:edit-posts')->only('edit', 'update');
}

Multiple Permissions

You can specify multiple permissions. The middleware will allow access if the user has any of the specified permissions:

Route::get('/admin/users', [UserController::class, 'index'])->middleware('permission:view-users,manage-users');

Handling Unauthorized Access

When a user doesn't have the required permission:

  • For regular requests, it will abort with a 403 status and "Unauthorized action." message.
  • For JSON requests, it will return a JSON response with a 403 status and an "Unauthorized action." message. This middleware provides a robust way to implement permission-based access control in your Laravel application, integrating seamlessly with the Laravel Role Permission Manager package.

RoleMiddleware

The RoleMiddleware is designed to protect routes based on user roles. It checks if the authenticated user has the required role(s) before allowing access to a route.

Key Features

  1. Route Protection: Allows you to specify required roles for accessing specific routes.
  2. Multiple Role Support: Can check for multiple roles, granting access if the user has any of them.
  3. Authentication Check: Ensures the user is authenticated before checking roles.
  4. JSON Response Support: Returns a JSON response for unauthorized actions if the request expects JSON.

Usage

To use this middleware, you can add it to your routes or controllers:

  1. In your app/Http/Kernel.php, add an alias for the middleware:
protected $routeMiddleware = [
    // ... other middleware
    'role' => \CreativeCrafts\LaravelRolePermissionManager\Middleware\RoleMiddleware::class,
];
  1. Use it in your routes:
Route::get('/admin', [AdminController::class, 'index'])->middleware('role:admin');
  1. Or use it in your controllers:
public function __construct()
{
    $this->middleware('role:editor')->only('create', 'store');
}

Multiple Roles

You can specify multiple roles. The middleware will allow access if the user has any of the specified roles:

Route::get('/dashboard', [DashboardController::class, 'index'])->middleware('role:admin,manager');

Handling Unauthorized Access

When a user doesn't have the required role:

  • For regular requests, it will abort with a 403 status and "Unauthorized action." message.
  • For JSON requests, it will return a JSON response with a 403 status and an "Unauthorized action." message. This middleware provides a straightforward way to implement role-based access control in your Laravel application, complementing the permission-based middleware and integrating seamlessly with the Laravel Role Permission Manager package.

Facade

The package provides a facade for easy access to role and permission management functions.

Key methods:

  • createRole(string $name, string $slug, ?string $description = null, ?Role $parent = null): Role
  • createPermission(string $name, string $slug, ?string $description = null): Permission
  • givePermissionToRole(Role $role, Permission|string $permission, ?string $scope = null): void
  • revokePermissionFromRole(Role $role, Permission|string $permission, ?string $scope = null): void
  • syncPermissions(Role $role, array $permissions): void
  • hasPermissionTo(mixed $user, string $permission, ?string $scope = null): bool
  • getSubRoles(Role $role): Collection
  • grantPermissionToRoleAndSubRoles(Role $role, Permission|string $permission): void
  • revokePermissionFromRoleAndSubRoles(Role $role, Permission|string $permission): void

Usage example:

use CreativeCrafts\LaravelRolePermissionManager\Facades\LaravelRolePermissionManager;

// Create a role
$role = LaravelRolePermissionManager::createRole('Editor', 'editor');

// Create a permission
$permission = LaravelRolePermissionManager::createPermission('Edit Posts', 'edit-posts');

// Give permission to role
LaravelRolePermissionManager::givePermissionToRole($role, $permission);

// Grant permission to role and its sub-roles
LaravelRolePermissionManager::grantPermissionToRoleAndSubRoles($role, 'edit-posts');

// Revoke permission from role and its sub-roles
LaravelRolePermissionManager::revokePermissionFromRoleAndSubRoles($role, 'edit-posts');

// Check if user has permission
$hasPermission = LaravelRolePermissionManager::hasPermissionTo($user, 'edit-posts');

// Get all sub-roles of a given role
$parentRole = Role::findByName('manager');
$subRoles = LaravelRolePermissionManager::getSubRoles($parentRole);

// Grant a permission to a role and all its sub-roles
$role = Role::findByName('manager');
LaravelRolePermissionManager::grantPermissionToRoleAndSubRoles($role, 'edit_posts');

// Revoke a permission from a role and all its sub-roles
LaravelRolePermissionManager::revokePermissionFromRoleAndSubRoles($role, 'delete_users');

These new methods allow for more granular control over role hierarchies and permissions. The getSubRoles method retrieves all sub-roles of a given role, while grantPermissionToRoleAndSubRoles and revokePermissionFromRoleAndSubRoles apply permission changes to both the specified role and all its sub-roles.

Artisan Commands

The package provides several Artisan commands to manage roles and permissions:

- create:role: Create a new role
- create:permission: Create a new permission
- assign:permission: Assign a permission to a role
- remove:permission: Remove a permission from a role
- list:roles-permissions: List all roles and permissions
- sync:permissions: Synchronize permissions for a role

Automatic Route Registration

By default, the package registers the following routes:

  • GET /roles: List all roles
  • GET /permissions: List all permissions
  • GET /user/{userId}/roles: Get roles for a specific user
  • GET /user/{userId}/permissions: Get permissions for a specific user
  • GET /user/{userId}/permissions/{scope}: Get scoped permissions for a specific user

These routes are protected by middleware and can be accessed via the RolePermissionController included with the package.

Customizing Route Registration

You can customize the route registration by setting the use_package_routes configuration option to false. it is set to true by default.

'use_package_routes' => false,
'route_prefix' => 'api',
'route_middleware' => ['api'],

Authorization Policies

The Laravel Role Permission Manager package comes with pre-defined authorization policies for the Role and Permission models. These policies are automatically registered when you use the package.

Policy Registration

The policies are registered in the AuthServiceProvider that comes with the package:

use CreativeCrafts\LaravelRolePermissionManager\Models\Permission;
use CreativeCrafts\LaravelRolePermissionManager\Models\Role;
use CreativeCrafts\LaravelRolePermissionManager\Policies\PermissionPolicy;
use CreativeCrafts\LaravelRolePermissionManager\Policies\RolePolicy;

class AuthServiceProvider extends ServiceProvider
{
    protected $policies = [
        Role::class => RolePolicy::class,
        Permission::class => PermissionPolicy::class,
    ];

    public function boot(): void
    {
        $this->registerPolicies();
    }
}

Using the Policies

These policies allow you to control who can perform various actions on roles and permissions. You can use them in your controllers or other parts of your application like this:

// In a controller
public function update(Role $role)
{
    $this->authorize('update', $role);
    
    // Update logic here...
}

Or in a Blade template:

@can('update', $role)
    <!-- Show update button or form -->
@endcan

Custom Policies

If you need to customize these policies, you can publish them to your application:

php artisan vendor:publish --tag="laravel-role-permission-manager-policies"

This will copy the policies to your app/Policies directory, where you can modify them as needed.

Available Policy Methods

Both the RolePolicy and PermissionPolicy typically include methods for standard CRUD operations:

- viewAny: Determine whether the user can view any roles/permissions.
- view: Determine whether the user can view the role/permission.
- create: Determine whether the user can create roles/permissions.
- update: Determine whether the user can update the role/permission.
- delete: Determine whether the user can delete the role/permission.

Remember to adjust your application's authorization logic in these policies according to your specific requirements.

Frontend Integration

Accessing Permissions in the Frontend

Permissions are shared with the Inertia.js frontend and can be accessed in Vue components.

Vue Permission Helper Functions

The package includes TypeScript-friendly utility functions for managing user permissions in Vue components.

Key Functions

  1. can(permission: string, scope: string | null = null): boolean

    • Checks if the user has a specific permission, optionally within a given scope.
  2. getScopedPermissions(scope: string): Permission[]

    • Retrieves all permissions for a specific scope.
  3. hasAnyPermissionInScope(scope: string): boolean

    • Checks if the user has any permission in a given scope.
  4. hasAllPermissions(permissionSlugs: string[]): boolean

    • Checks if the user has all specified permissions.
  5. hasAnyPermission(permissionSlugs: string[]): boolean

    • Checks if the user has any of the specified permissions.
  6. getAllScopes(): string[]

    • Retrieves all unique scopes from the user's permissions.

Usage in Vue Components

To use these helpers in your Vue components:

  1. Import the helper functions:
import {can, hasAnyPermission} from '@/path/to/permissions';
  1. Use them in your component:
<template>
  <div v-if="can('edit-posts')">
    <!-- Edit post content -->
  </div>
  <div v-if="hasAnyPermission(['manage-users', 'view-users'])">
    <!-- User management content -->
  </div>
</template>

<script lang="ts">
import { defineComponent } from 'vue';
import { can, hasAnyPermission } from '@/path/to/permissions';

export default defineComponent({
  setup() {
    return {
      can,
      hasAnyPermission,
    };
  },
});
</script>

Note on Permissions Data

These helpers expect the permissions data to be available on window.Laravel.permissions. Ensure this data is properly populated on your frontend, typically by sharing it through your backend views or API responses.

This TypeScript module provides a robust and type-safe way to manage permissions in your Vue.js frontend, complementing the backend permission management provided by the Laravel Role Permission Manager package.

React Permission Hooks

For React applications, the package provides a custom hook usePermissions.

Key Features

  1. Inertia.js Integration: Works seamlessly with Inertia.js to access shared permissions data.
  2. Memoized Functions: All permission checks are memoized for improved performance.
  3. Scoped Permissions: Supports checking permissions within specific scopes.

Usage

To use the usePermissions hook in your React components:

  1. Import the hook:
import {usePermissions} from '@/path/to/usePermissions';
  1. Use it in your component:
import React from 'react';
import {usePermissions} from '@/path/to/usePermissions';

const MyComponent: React.FC = () => {
    const {can, hasAnyPermission, hasAllPermissions} = usePermissions();

    return (
        <div>
            {can('edit-posts') && <button>Edit Post</button>}
            {hasAnyPermission(['manage-users', 'view-users']) && <UserManagement/>}
            {hasAllPermissions(['create-post', 'publish-post']) && <CreatePostForm/>}
        </div>
    );
};

Available Functions

- can(permission: string, scope?: string): boolean
    Checks if the user has a specific permission, optionally within a given scope.
- hasAnyPermission(permissions: string[]): boolean
    Checks if the user has any of the specified permissions.
- hasAllPermissions(permissions: string[]): boolean
    Checks if the user has all of the specified permissions.
- getScopedPermissions(scope: string): Permission[]
    Retrieves all permissions for a specific scope.
- hasAnyPermissionInScope(scope: string): boolean
    Checks if the user has any permission in a given scope.

Note on Permissions Data

This hook expects the permissions data to be available in the Inertia page props under auth.permissions. Ensure this data is properly shared from your Laravel backend when using Inertia.js.

This React hook provides a convenient and type-safe way to manage permissions in your React frontend when using Inertia.js, complementing the Laravel Role Permission Manager package's backend functionality.

Testing

To run the tests, use:

composer test

Changelog

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

Contributing

Please see CONTRIBUTING for details.

Security Vulnerabilities

Please review our security policy on how to report security vulnerabilities.

Credits

- [Godspower Oduose](https://github.com/rockblings)
- [All Contributors](../../contributors)

License

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