Skip to content
This repository has been archived by the owner on Apr 27, 2021. It is now read-only.

Latest commit

 

History

History
365 lines (298 loc) · 9.6 KB

README.md

File metadata and controls

365 lines (298 loc) · 9.6 KB

Central management of Laravel authorization with database and user roles for Laravel 5.1, 5.2, and 5.3.

Ever thought about a way to put a policy or condition on every permission as a restriction, something like: allow authenticated user to modify posts Only if he is the post author or Only if he is in the same group as the author or Only if the post is not published ... etc

Not like other roles based packages, this package fills this gap by restricting user's role permission with a condition/policy, as it follows Attribute-Based Access Controll (ABAC) approach as Laravel authorize does.

Database tables will be installed to store abilities, user roles, permissions, and custom condition/policy per each permission you give.

AuzoTools package is required and will be installed, it provides several great tools that facilitates Laravel authorize management.

What you can do with this package:

  1. Manage Abilities
  2. Manage Roles
  3. Manage Conditions/Policies
  4. Manage Permissions
  5. Generate abilities

Installation

You can install the package via composer:

composer require kordy/auzo

This service provider must be installed.

// config/app.php
'providers' => [
    ...
    Kordy\Auzo\AuzoServiceProvider::class,
    Kordy\AuzoTools\AuzoToolsServiceProvider::class,
];

You can publish the migrations with:

php artisan vendor:publish --provider="Kordy\Auzo\AuzoServiceProvider" --tag="migrations"

After the migration has been published you can create the role- and permission-tables by running the migrations:

php artisan migrate

You can publish the config file with:

php artisan vendor:publish --provider="Kordy\Auzo\AuzoServiceProvider" --tag="config"

Finally, you have to add the HasRoleTrait trait to the user's model where you want to assign roles to them.

// App\User.php

class User extends ...
{
    use ..., Kordy\Auzo\Traits\HasRoleTrait;
    ...

Customization

You can replace or extend any model of the package through the configuration file, create your own class, use the model trait, modify any function, and just add the new class path in the config/auzo.php file.

config/auzo.php contents:

/*
    /*
    |--------------------------------------------------------------------------
    | Auzo Authorize Registrar
    |--------------------------------------------------------------------------
    |
    | You may here add custom registrar where the Laravel Gate abilities are defined
    |
    */

    'registrar' => \Kordy\Auzo\Services\PermissionRegistrar::class,

    /*
    |--------------------------------------------------------------------------
    | Auzo models paths
    |--------------------------------------------------------------------------
    |
    | You may here add custom models paths to be used instead of models included
    | with the package
    |
    */

    'models' => [

        'user' => $user_model,

        'ability' => \Kordy\Auzo\Models\Ability::class,

        'policy' => \Kordy\Auzo\Models\Policy::class,

        'permission' => \Kordy\Auzo\Models\Permission::class,

        'role' => \Kordy\Auzo\Models\Role::class,
    ],

Usage

Abilities

By default Laravel authorize abilities are defined statically through the service provider, this package gives more flexibility by creating them in the database and automatically defines them.

Manage abilities using AuzoAbility Facade:

AuzoAbility::create([
    'name' => 'ability.name',
    'label' => 'Abiliy Label',
    'tag' => 'ability.tag'
]);

Manage abilities using auzo:ability artisan command:

# create new ability
php artisan auzo:ability create 'ability.index' --label='Ability Index' --tag='ability'
# delete ability
php artisan auzo:ability delete 'ability.index'

Roles

Auzo approaches Role Based Access Control (RBAC) methodology, All users get their permissions "only" through their role, that is for better usability and scalability, and to maintain solid and non-conflict polices from different roles, "only" single role is allowed per user.

Manage roles using AuzoRole Facade:

$role = AuzoRole::create([
    'name' => 'testRole',
    'description' => 'test role description'
]);

Manage roles using auzo:role artisan command:

# create new role
php artisan auzo:role create 'testRole' --description='testing role'
# delete role
php artisan auzo:role delete 'testRole'

Assign role to a user using hasRole trait relationship:

// by role instance
$user->assignRole($role);
// or by role id
$user->assignRole(2);
// or by role name
$user->assignRole('testRole');

Manage user role assignment using auzo:user artisan command:

# assign role to users
php artisan auzo:user assign '1,2,3' 'SomeRole'
# revoke role from users
php artisan auzo:user revoke '1,2,3' 'SomeRole'

Policies

You can define custom conditions or as we name it here "policies", policy is a custom function (that you have created somewhere) which defines some conditions that have to be met before granting the permission to a user.

example: grant a user permission if the user is the owner of the post.

// App\Post
public function owner($ability, $role, $user, $model) {
    return $user->id == $model->usr_id;
}

see src/Services/AccessPolicies.php for more examples.

Manage policies through AuzoPolicy Facade:

$policy = AuzoPolicy::create([
    'name'   => 'Post Owner',
    'method' => 'App\Post@owner',
]);

Manage policies using auzo:policy artisan command:

# create new policy
php artisan auzo:policy create --name='Test Policy' --method='Controller@policy'
# delete policy by id
php artisan auzo:policy delete --id=1

Permissions

Give role a permission to an ability:

// by ability instance
$role->givePermissionTo($ability);
// or by ability id
$role->givePermissionTo(3);
// or by array of abilities ids
$role->givePermissionTo([1,3]);
// or by ability name
$role->givePermissionTo('ability.name');
// remove permission by passing ability name
$role->removePermissionTo('ability.name');

Give role a permission to an ability restricted by policy:

$role->givePermissionTo($ability->name)
    ->addPolicy($policy1)
    ->addPolicy([$policy2->id => ['operator' => 'or']]);

Using auzo:permission artisan command to manage permissions:

php artisan auzo:permission give 'testRole' 'ability.test,ability.test2' --policies='1,2:||'

if multiple policies applied, a default "AND" is applied between policies, unless you specified an operator at the time of adding policies to the permission.

Generate abilities

This will use GenerateAbilities from AuzoTools to generate all abilities (by default matching route source scheme) for a model and its fields, and saves them to the database abilities table.

Through the GeneratAbilitiesToDB class:

$generator = new Kordy\Auzo\Services\GenerateAbilitiesToDB();
// generate only model CRUD abilities
$generator->modelAbilities($model)->saveModelToDB();
// generate only fields CRUD abilities
$generator->fieldsAbilities($model)->saveFieldsToDB();
// generate both model and fields CRUD abilities
$generator->fullCrudAbilities($model)->saveToDB();

Through the artisan command

php artisan auzo:ability generate 'App\Post'
# or to generate only model abilities
php artisan auzo:ability generate 'App\Post' --option=model
# or to generate only fields abilities
php artisan auzo:ability generate 'App\Post' --option=fields

This will generate and save all abilities below to abilities table:

[
    [
        'name' => 'post.index',
        'tag'  => 'post',
    ],

    [
        'name' => 'post.create',
        'tag'  => 'post',
    ],

    [
        'name' => 'post.store',
        'tag'  => 'post',
    ],

    [
        'name' => 'post.show',
        'tag'  => 'post',
    ],

    [
        'name' => 'post.edit',
        'tag'  => 'post',
    ],

    [
        'name' => 'post.update',
        'tag'  => 'post',
    ],

    [
        'name' => 'post.destroy',
        'tag'  => 'post',
    ],

    [
        'name' => 'post.index.id',
        'tag'  => 'post.index',
    ],

    [
        'name' => 'post.create.id',
        'tag'  => 'post.create',
    ],

    [
        'name' => 'post.store.id',
        'tag'  => 'post.store',
    ],

    [
        'name' => 'post.show.id',
        'tag'  => 'post.show',
    ],

    [
        'name' => 'post.edit.id',
        'tag'  => 'post.edit',
    ],

    [
        'name' => 'post.update.id',
        'tag'  => 'post.update',
    ],

    [
        'name' => 'post.destroy.id',
        'tag'  => 'post.destroy',
    ],

    [
        'name' => 'post.index.name',
        'tag'  => 'post.index',
    ],

    [
        'name' => 'post.create.name',
        'tag'  => 'post.create',
    ],

    [
        'name' => 'post.store.name',
        'tag'  => 'post.store',
    ],
    ....

Credits

  1. Based on laravel-permission package which is considered the best alternative for this package if you need multiple roles and direct permissions for users.
  2. A lot of help from my friend balping

Contributing

Please see CONTRIBUTING for details.

License

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