Easy, native Laravel user authorization.

Overview

An easy, native role / permission management system for Laravel.

Index

Installation

Note: Laravel 5.5 or greater is required.

To get started, install Authorization via the Composer package manager:

composer require directorytree/authorization

The Authorization service provider registers its own database migration directory with the framework, so you should migrate your database after installing the package. The Authorization migrations will create the tables your application needs to store roles and permissions:

php artisan migrate

Now insert the DirectoryTree\Authorization\Traits\Authorizable onto your App\Models\User model:

<?php

namespace App\Models;

use DirectoryTree\Authorization\Traits\Authorizable;
use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable
{
    use Authorizable;

    // ...
}

You can now perform user authorization.

Migration Customization

If you would not like to use Authorization's default migrations, you should call the Authorization::ignoreMigrations method in the register method of your AppServiceProvider. You may export the default migrations using php artisan vendor:publish --tag=authorization-migrations.

use DirectoryTree\Authorization\Authorization;

/**
 * Register any application services.
 *
 * @return void
 */
public function register()
{
    Authorization::ignoreMigrations();
}

Model Customization

By default, the App\Models\User class is registered as the authorizable user model.

You're free to extend the models used internally by Authorization, or create your own.

Instruct Authorization to use your own models via the Authorization class in your AuthServiceProvider:

use App\Models\User;
use App\Models\Role;
use App\Models\Permission;
use DirectoryTree\Authorization\Authorization;

/**
 * Register any authentication / authorization services.
 *
 * @return void
 */
public function boot()
{
    $this->registerPolicies();

    Authorization::useUserModel(User::class);
    Authorization::useRoleModel(Role::class);
    Authorization::usePermissionModel(Permission::class);
}

Be sure to add the relevant traits for each of your custom models:

Role Model:

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use DirectoryTree\Authorization\Traits\ManagesPermissions;

class Role extends Model
{
    use ManagesPermissions;
}

Permission Model:

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use DirectoryTree\Authorization\Traits\HasUsers;
use DirectoryTree\Authorization\Traits\HasRoles;
use DirectoryTree\Authorization\Traits\ClearsCachedPermissions;

class Permission extends Model
{
    use HasUsers, HasRoles, ClearsCachedPermissions;
}

Usage

Authorization uses native Laravel relationships, so there's no need to learn a new API if you don't want to.

Due to Authorization's trait based implementation, all of Authorization's functionality can be overridden or extended with you own implementation.

Managing Roles & Permissions

Create a permission:

$createUsers = Permission::create([
    'name' => 'users.create',
    'label' => 'Create Users',
]);

Create a role:

$admin = Role::create([
    'name' => 'administrator',
    'label' => 'Admin',
]);

Grant the permission to a role:

$admin->permissions()->save($createUsers);

Now assign the role to the user:

$user->roles()->save($admin);

You may also use the grant() or revoke() method on a Role model:

// Using the permission's name:
$admin->grant('users.create');

// Using a permission model:
$admin->grant($permission);

// Granting multiple permissions:
$admin->grant(['users.create', 'users.edit']);

// Granting a collection of models:
$admin->grant(Permission::all());

// Using a mix of models and permission name:
$admin->grant([$createUsers, 'users.edit']);

You may also sync a role's permissions using the grantOnly() method:

// All permissions will be removed except, except for the given:
$admin->grantOnly('users.create');
// Using the permission's name:
$admin->revoke('users.create');

// Using a permission model:
$admin->revoke($permission);

// Revoking multiple permissions:
$admin->revoke(['users.create', 'users.edit']);

// Revoking a collection of models:
$admin->revoke(Permission::all());

// Using a mix of models and permission name:
$admin->revoke([$createUsers, 'users.edit']);

You may also detach all permissions from a role using revokeAll():

$admin->revokeAll();

Managing Users & Permissions

You can also create user specific permissions:

$createUsers = Permission::create([
    'name' => 'users.create',
    'label' => 'Create Users',
]);

$user->permissions()->save($createUsers);

As with roles, may also use the grant() or revoke() method on an authorizable User model:

// Using the permission's name:
$user->grant('users.create');

// Using a permission model:
$user->grant($permission);

// Granting multiple permissions:
$user->grant(['users.create', 'users.edit']);

// Granting a collection of models:
$user->grant(Permission::all());

// Using a mix of models and permission name:
$user->grant([$createUsers, 'users.edit']);

You may also sync a users' permissions using the grantOnly() method:

// All permissions will be removed except, except for the given:
$user->grantOnly('users.create');
// Using the permission's name:
$user->revoke('users.create');

// Using a permission model:
$user->revoke($permission);

// Granting multiple permissions:
$user->revoke(['users.create', 'users.edit']);

// Granting a collection of models:
$user->revoke(Permission::all());

// Using a mix of models and permission name:
$user->revoke([$createUsers, 'users.edit']);

Checking Permissions & Roles

Using Laravel's native can() method:

if (Auth::user()->can('users.create')) {
    // This user can create other users.
}

Using Laravel's native authorize() method in your controllers:

public function create()
{
    $this->authorize('users.create');

    User::create(['...']);
}

Using Laravel's native Gate facade:

if (Gate::allows('users.create')) {
    //
}

Using Laravel's native @can directive in your views:

@can('users.create')
    <!-- This user can create other users. -->
@endcan

Checking Permissions & Roles (Using Authorization Package Methods)

Checking for permission:

// Using the permissions name.
if ($user->hasPermission('users.create')) {
    //
}

// Using the permissions model.
if ($user->hasPermission($createUsers)) {
    //
}

Checking for multiple permissions:

if ($user->hasPermissions(['users.create', 'users.edit'])) {
    // This user has both creation and edit rights.
} else {
    // It looks like the user doesn't have one of the specified permissions.
}

Checking if the user has any permissions:

if ($user->hasAnyPermissions(['users.create', 'users.edit', 'users.destroy'])) {
    // This user either has create, edit or destroy permissions.
} else {
    // It looks like the user doesn't have any of the specified permissions.
}

Checking if the user has a role:

if ($user->hasRole('administrator')) {
    // This user is an administrator.
} else {
    // It looks like the user isn't an administrator.
}

Checking if the user has specified roles:

if ($user->hasRoles(['administrator', 'member'])) {
    // This user is an administrator and a member.
} else {
    // It looks like the user isn't an administrator or member.
}

Checking if the user has any specified roles:

if ($user->hasAnyRoles(['administrator', 'member', 'guest'])) {
    // This user is either an administrator, member or guest.
} else {
    // It looks like the user doesn't have any of these roles.
}

Caching

By default all permissions are cached to prevent them from being retrieved on every request.

This cache is automatically flushed when permissions are created, updated, or deleted.

If you would like to disable the cache, call Authorization::disablePermissionCache in your AuthServiceProvider:

use DirectoryTree\Authorization\Authorization;

/**
 * Register any authentication / authorization services.
 *
 * @return void
 */
public function boot()
{
    $this->registerPolicies();

    Authorization::disablePermissionCache();
}

Cache Key

By default, the permission cache key is authorization.permissions.

To alter the cache key, call Authorization::cacheKey in your AuthServiceProvider:

use DirectoryTree\Authorization\Authorization;

/**
 * Register any authentication / authorization services.
 *
 * @return void
 */
public function boot()
{
    $this->registerPolicies();

    Authorization::cacheKey('my-key');
}

Cache Expiry

By default, the permission cache will expire daily.

To alter this expiry date, call Authorization::cacheExpiresIn in your AuthServiceProvider:

use DirectoryTree\Authorization\Authorization;

/**
 * Register any authentication / authorization services.
 *
 * @return void
 */
public function boot()
{
    $this->registerPolicies();

    Authorization::cacheExpiresIn(now()->addWeek());
}

Gate Registration

By default all permissions you create are registered in Laravel's Gate.

If you would like to disable this, call Authorization::disableGateRegistration in your AuthServiceProvider:

use DirectoryTree\Authorization\Authorization;

/**
 * Register any authentication / authorization services.
 *
 * @return void
 */
public function boot()
{
    $this->registerPolicies();

    Authorization::disableGateRegistration();
}

Middleware

Authorization includes two useful middleware classes you can utilize for your routes.

Insert them into your app/Http/Kernel.php:

/**
 * The application's route middleware.
 *
 * These middleware may be assigned to groups or used individually.
 *
 * @var array
 */
protected $routeMiddleware = [
    'auth' => \App\Http\Middleware\Authenticate::class,
    'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
    'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
    'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,

    // The role middleware:
    'role' => \DirectoryTree\Authorization\Middleware\RoleMiddleware::class,

    // The permission middleware:
    'permission' => \DirectoryTree\Authorization\Middleware\PermissionMiddleware::class,
];

Once you've added them, you can start using them.

Note: When a user does not meet the requirements using the middleware, a 403 HTTP exception is thrown.

To guard a route to only allow specific permissions:

Route::get('users', [
    'uses' => 'UsersController@index',
    'middleware' => 'permission:users.index',
]);

// Multiple permissions:
Route::get('users', [
    'uses' => 'UsersController@index',
    // Users must have index **and** create rights to access this route.
    'middleware' => 'permission:users.index,users.create',
]);

To guard a route to allow a specific role:

Route::get('users', [
    'uses' => 'UsersController@index',
    'middleware' => 'role:administrator',
]);

// Multiple roles:
Route::get('users', [
    'uses' => 'UsersController@index',
    // Users must be an administrator **and** a member to access this route.
    'middleware' => 'role:administrator,member',
]);

Running Tests

To run your applications tests, you must instantiate the PermissionRegistrar inside your TestCase::setUp() method before running your tests for permissions to register properly:

use DirectoryTree\Authorization\PermissionRegistrar;
protected function setUp() : void
{
    parent::setUp();

    app(PermissionRegistrar::class)->register();
}
You might also like...
An authorization library that supports access control models like ACL, RBAC, ABAC in PHP .
An authorization library that supports access control models like ACL, RBAC, ABAC in PHP .

PHP-Casbin Documentation | Tutorials | Extensions Breaking News: Laravel-authz is now available, an authorization library for the Laravel framework. P

It's authorization form, login button handler and login to your personal account, logout button
It's authorization form, login button handler and login to your personal account, logout button

Authorization-form It's authorization form, login button handler and login to your personal account, logout button Each file is: header.php - html-fil

Authentication and authorization library for Codeigniter 4

Authentication and Authorization Library for CodeIgniter 4. This library provides an easy and simple way to create login, logout, and user registratio

This is a basic Oauth2 authorization/authentication server implemented using Mezzio.
This is a basic Oauth2 authorization/authentication server implemented using Mezzio.

Mezzio-OAuth2-Authorization-Authentication-Server This is a basic OAuth2 authorization/authentication server implemented using Mezzio. I have found so

Symfony bundle which provides OAuth 2.0 authorization/resource server capabilities

Symfony bundle which provides OAuth 2.0 authorization/resource server capabilities. The authorization and resource server actors are implemented using the thephpleague/oauth2-server library.

An authorization library that supports access control models like ACL, RBAC, ABAC for webman plugin

An authorization library that supports access control models like ACL, RBAC, ABAC for webman plugin

Authentication, authorization and access control for PHP
Authentication, authorization and access control for PHP

Jasny Auth Authentication, authorization and access control for PHP. Features Multiple authorization strategies, like groups (for acl) and levels. Aut

This package brings back the policy authorization for MenuItem

This package brings back the policy authorization for MenuItem. Also, the well-known canSee method is added to MenuItem and MenuSection. Empty menu sections are automatically hidden.

Comments
  • [Help] Question about testing

    [Help] Question about testing

    Hi, I'm having a bit of trouble with testing routes protected by permissions.

    First, I am not using the provided permission middleware, I am using Laravel's can so that super users need not pass individual permission checks:

    Route::group(['middleware' => 'can:test permission'] ...
    

    Super user middleware:

    Gate::before(fn ($user) => $user->hasRole('super admin') ? true : null);
    

    Test class:

    protected function setUp() : void
    {
        parent::setUp();
    
        app(PermissionRegistrar::class)->register();
    }
    
    public function testThePageLoads()
    {
        $user = User::factory()->create();
        $permission = Permission::create(['name' => 'test permission']);
    
        $user->grant($permission);
    
        $response = $this->actingAs($user)->get(route('test.index'));
    
        $response
            ->assertStatus(200)
            ->assertInertia(fn (Assert $page) => $page->component('Pages/Test'));
    }
    

    This test fails with a 403. Oddly on my frontend it works fine, additionally switching to the permission middleware fixes the test, but breaks the super user middleware check and therefore the frontend app as well for users who are not explicitly given permissions (role only).

    opened by benjivm 4
  • The script tried to access a property on an incomplete object

    The script tried to access a property on an incomplete object

    In the process of switching from Larapacks to DirectoryTree and failing at the composer require, I've tried blowing away my vendor/ and re-installing with no luck:

    Generating optimized autoload files
    composer/package-versions-deprecated: Generating version class...
    composer/package-versions-deprecated: ...done generating version class
    > Illuminate\Foundation\ComposerScripts::postAutoloadDump
    > @php artisan package:discover --ansi
    
       ErrorException
    
      DirectoryTree\Authorization\PermissionRegistrar::register(): The script tried to access a property on an incomplete object. Please ensure that the class definition "Larapacks\Authorization\Permission" of the object you are trying to operate on was loaded _before_ unserialize() gets called or provide an autoloader to load the class definition
    
      at [...]\vendor\directorytree\authorization\src\PermissionRegistrar.php:46
         42▕     public function register()
         43▕     {
         44▕         // Dynamically register permissions with Laravel's Gate.
         45▕         foreach ($this->getPermissions() as $permission) {
      ➜  46▕             $this->gate->define($permission->name, function ($user) use ($permission) {
         47▕                 return $user->hasPermission($permission);
         48▕             });
         49▕         }
         50▕     }
    
      1   [...]\vendor\directorytree\authorization\src\PermissionRegistrar.php:46
          Illuminate\Foundation\Bootstrap\HandleExceptions::handleError("DirectoryTree\Authorization\PermissionRegistrar::register(): The script tried to access a property on an incomplete object. Please ensure that the class definition "Larapacks\Authorization\Permission" of the object you are trying to operate on was loaded _before_ unserialize() gets called or provide an autoloader to load the class definition", "[...]\vendor\directorytree\authorization\src\PermissionRegistrar.php")
    
      2   [...]\vendor\directorytree\authorization\src\AuthorizationServiceProvider.php:26
          DirectoryTree\Authorization\PermissionRegistrar::register()
    Script @php artisan package:discover --ansi handling the post-autoload-dump event returned with error code 1
    
    opened by benjivm 3
Releases(v1.1.0)
Owner
DirectoryTree
An open source company.
DirectoryTree
Auth is a module for the Yii PHP framework that provides a web user interface for Yii's built-in authorization manager

Auth is a module for the Yii PHP framework that provides a web user interface for Yii's built-in authorization manager (CAuthManager). You can read more about Yii's authorization manager in the framework documentation under Authentication and Authorization.

Christoffer Niska 134 Oct 22, 2022
Laravel Auth is a Complete Build of Laravel 8 with Email Registration Verification, Social Authentication, User Roles and Permissions, User Profiles, and Admin restricted user management system.

Laravel Auth is a Complete Build of Laravel 8 with Email Registration Verification, Social Authentication, User Roles and Permissions, User Profiles, and Admin restricted user management system. Built on Bootstrap 4.

Jeremy Kenedy 2.8k Dec 31, 2022
EvaOAuth provides a standard interface for OAuth1.0(a) / OAuth2.0 client authorization, it is easy to integrate with any PHP project by very few lines code.

EvaOAuth EvaOAuth provides a standard interface for OAuth1.0 / OAuth2.0 client authorization, it is easy to integrate with any PHP project by very few

AlloVince 256 Nov 16, 2022
EvaOAuth provides a standard interface for OAuth1.0(a) / OAuth2.0 client authorization, it is easy to integrate with any PHP project by very few lines code.

EvaOAuth EvaOAuth provides a standard interface for OAuth1.0 / OAuth2.0 client authorization, it is easy to integrate with any PHP project by very few

AlloVince 261 Jan 17, 2022
Declarative style of authorization and validation in laravel.

Laravel Hey Man Readability Counts. In fact, Readability is the primary value of your code !!! ?? Heyman continues where the other role-permission pac

Iman 860 Jan 1, 2023
Minimalistic token-based authorization for Laravel API endpoints.

Bearer Minimalistic token-based authorization for Laravel API endpoints. Installation You can install the package via Composer: composer require ryang

Ryan Chandler 74 Jun 17, 2022
Files Course Laravel Micro Auth and Authorization

About Laravel Laravel is a web application framework with expressive, elegant syntax. We believe development must be an enjoyable and creative experie

EspecializaTi 8 Oct 22, 2022
Manage authorization with granular role-based permissions in your Laravel Apps.

Governor For Laravel Manage authorization with granular role-based permissions in your Laravel apps. Goal Provide a simple method of managing ACL in a

GeneaLabs, LLC 149 Dec 23, 2022
An authorization library that supports access control models like ACL, RBAC, ABAC in Laravel.

Laravel Authorization Laravel-authz is an authorization library for the laravel framework. It's based on Casbin, an authorization library that support

PHP-Casbin 243 Jan 4, 2023
A framework agnostic authentication & authorization system.

Sentinel Sentinel is a PHP 7.3+ framework agnostic fully-featured authentication & authorization system. It also provides additional features such as

Cartalyst 1.4k Dec 30, 2022