coffeecodemx/wildcard-permissions

0.0.4 2024-03-23 01:44 UTC

This package is auto-updated.

Last update: 2024-04-23 02:00:52 UTC


README

License Latest Stable Version Total Downloads Build Status

A powerful permission management library for Laravel applications.

Features

  • Role-based access control (RBAC)
  • Fine-grained permission management
  • Flexible permission assignment
  • Easy integration with Laravel's authentication system
  • Lightweight and efficient

Installation

You can install this package via Composer. Run the following command:

composer require coffeecodemx/wildcard-permissions

Then add the service provider in your Laravel project

<?php
return [
    ...
    'providers' => ServiceProvider::defaultProviders()->merge([
            /*
            * Package Service Providers...
            */
            CoffeeCode\WildcardPermissions\WildcardPermissionsServiceProvider::class,
    ...
];

Next you need to publish the configuration and migration files with the following command

php artisan vendor:publish --provider="CoffeeCode\WildcardPermissions\WildcardPermissionsServiceProvider"

Now you'll see a new configuration file in /config directory, just do the changes needed for table names and classes. A recommended change for a basic usage is to change under pivot_names.model_id to you model id which usually is user_id

Now run the migrations

php artisan migrate

Add the traits to the model you wish to have permissions

<?php

namespace App\Models;

use CoffeeCode\WildcardPermissions\Traits\HasPermissions;
use CoffeeCode\WildcardPermissions\Traits\HasRoles;
...

class User extends Authenticatable
{
    use ..., HasRoles, HasPermissions;

    ...
}

That's it!

Usage and examples

Create new Permission

To create a new permission you just need to run the following command.

$permission = WildcardPermission::create([
    "short_name" => "ModuleA Create Permission",
    "guard_name" => "modulea:create",
    "description" => "Permission in module to create something"
]);

Short name and description are very descriptive, however guard_name is the special one, this field will only accepts alphabetic upper and lowecase and : symbol to separate namespaces, modules, you name it!

You can combine multiple namespaces like this:

module:submodule:write

Find Permission

Since guard name is unique, you can easyly find a permission using guard name or if you want to find it using other fields just check the following examples.

$permission1 = WildcardPermission::findByGuardName("modulea:create");
$permission2 = WildcardPermission::findByShortName("ModuleA Create Permission");
$permission3 = WildcardPermission::findById(1);

Assign direct permissions to a Model

First your model should have the Trait HasPermissions, then is just

$permission1 = WildcardPermission::findByGuardName("modulea:create");
$permission2 = WildcardPermission::findByGuardName("modulea:read");
$user = User::find(1);
$user->givePermissionTo($permission1, $permission2);

And if you want to revoke a permission is using the following

$permission1 = WildcardPermission::findByGuardName("modulea:create");
$permission2 = WildcardPermission::findByGuardName("modulea:read");
$user = User::find(1);
$user->revokePermissionsTo($permission1, $permission2);

Create new Role

Roles are basically a collection of permissions and the way to create a new one is using the following command

$role = Role::create([
    "short_name" => "Module Reader",
    "guard_name" => "module:reader",
    "description" => "Role for readers"
]);

Now for assigning or revoking permissions is the same as we do with models

$permission1 = WildcardPermission::findByGuardName("modulea:create");
$permission2 = WildcardPermission::findByGuardName("modulea:read");
$role->givePermissionTo($permission1, $permission2);

or revoking permissions

$permission1 = WildcardPermission::findByGuardName("modulea:create");
$permission2 = WildcardPermission::findByGuardName("modulea:read");
$role->revokePermissionsTo($permission1, $permission2);

Assigning roles to a user

First your model should have the Trait HasRoles, then is just

$role1 = Role::findByGuardName("module:reader");
$role2 = Role::findByGuardName("module:writer");
$user->assignRole($role1, $role2);

or you can unassign it

$role1 = Role::findByGuardName("module:reader");
$role2 = Role::findByGuardName("module:writer");
$user->unassignRole($role1, $role2);

Check if your user has one or more roles

If you want to check for roles you have 3 operations

$role1 = Role::findByGuardName("module:reader");
$role2 = Role::findByGuardName("module:writer");

$user->assignRole($role1);
// For the 3 operations you can use ID, guard_name or Role object
$user->hasRole($role1);// true
$user->hasRole("module:reader");// true
$user->hasRole(1);// true
$user->hasAnyRole($role1, $role1);// true
$user->hasAllRoles($role1, $role2);// false

Check if the user has permissions

For checking permissions you can search by permission object, by guard_name or by wildcard

$user = User::find(1);
$role = Role::findByGuardName("module:reader"); // Only the :read

$permission1String = "modulea:create";// Permission name
$permission2String = "modulea:read";// Permission name
$permission3String = "moduleb:read";// Permission name

$permission1 = WildcardPermission::findByGuardName($permission1String);
$permission2 = WildcardPermission::findByGuardName($permission2String);
$permission3 = WildcardPermission::findByGuardName($permission3String);

$role->givePermissionTo($permission2);
$role->givePermissionTo($permission3);
$user->givePermissionTo($permission1);
$user->assignRole($role);// User can read in module a and b also create in module a

echo $user->hasPermissionTo($permission1); // true
echo $user->hasPermissionTo($permission2); // true
echo $user->hasDirectPermission($permission1); // true
echo $user->hasDirectPermission($permission2); // false
echo $user->hasPermissionViaRole($permission1); // false
echo $user->hasPermissionViaRole($permission2); // true
echo $user->hasRole($role); // true
echo $user->hasRole("module:reader"); // true
echo $user->hasRole(1); // true
echo $user->hasAllRoles($role, 2); // false
echo $user->hasAnyRole($role, 2); // true

echo $user->hasPermissionTo("modulea:create,read"); // false should have permission to read and create in module A
echo $user->hasPermissionTo("modulea:create|read"); // true should have permission to read or create in module A
echo $user->hasPermissionTo("modulea:*"); // true should have any permission for module A

Middlewares

This package comes with RoleMiddleware, PermissionMiddleware and RoleOrPermissionMiddleware middleware. You can add them inside your app/Http/Kernel.php file to be able to use them through aliases.

protected $middlewareAliases = [
    // ...
    'role' => \CoffeeCode\WildcardPermissions\Middlewares\RoleMiddleware::class,
    'permission' => \CoffeeCode\WildcardPermissions\Middlewares\PermissionMiddleware::class,
    'role_or_permission' => \CoffeeCode\WildcardPermissions\Middlewares\RoleOrPermissionMiddleware::class,
];

Middleware via Routes

You can protect your routes using middleware rules:

Route::group(['middleware' => ['role:reader']], function () {
    //
});
// To add more permissions like an array use the & character
Route::group(['middleware' => ['permission:module:*&&moduleb:read']], function () {
    //
});

Route::group(['middleware' => ['role_or_permission:reader']], function () {
    //
});

Use middleware static methods

For a better usage and to avoid confusion between laravel convetion using colon : to separate the alias from the parameters and since the guard_names are using the same character for namespaces, alternatively you can use this syntax.

// You can send a single string
Route::group(['middleware' => [\CoffeeCode\WildcardPermissions\Middlewares\RoleMiddleware::using('reader')]], function () {
    //
});
// You can send a single string with multiple permissions using &
Route::group(['middleware' => [\CoffeeCode\WildcardPermissions\Middlewares\PermissionMiddleware::using('module:*&moduleb:read')]], function () {
    //
});

// Or better, you can send an array
Route::group(['middleware' => [\CoffeeCode\WildcardPermissions\Middlewares\RoleOrPermissionMiddleware::using(['manager', 'module:*'])]], function () {
    //
});