├── .gitattributes
├── .github
└── workflows
│ └── run-tests.yml
├── .gitignore
├── .scrutinizer.yml
├── .styleci.yml
├── README.md
├── art
├── logo.png
└── logo.svg
├── composer.json
├── database
└── migrations
│ └── 2014_10_12_200000_create_authorization_tables.php
├── license.md
├── phpunit.xml
├── src
├── Authorization.php
├── AuthorizationServiceProvider.php
├── Middleware
│ ├── AuthorizationMiddleware.php
│ ├── PermissionMiddleware.php
│ └── RoleMiddleware.php
├── Permission.php
├── PermissionPivot.php
├── PermissionRegistrar.php
├── Pivot.php
├── Role.php
├── RolePivot.php
├── Traits
│ ├── AssociatesPermissions.php
│ ├── Authorizable.php
│ ├── ClearsCachedPermissions.php
│ ├── FlushesLoadedRelations.php
│ ├── HasPermissions.php
│ ├── HasRoles.php
│ ├── HasUsers.php
│ └── ManagesPermissions.php
└── UserPivot.php
└── tests
├── AuthorizationTest.php
├── Stubs
└── User.php
└── TestCase.php
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
4 | # Custom for Visual Studio
5 | *.cs diff=csharp
6 |
7 | # Standard to msysgit
8 | *.doc diff=astextplain
9 | *.DOC diff=astextplain
10 | *.docx diff=astextplain
11 | *.DOCX diff=astextplain
12 | *.dot diff=astextplain
13 | *.DOT diff=astextplain
14 | *.pdf diff=astextplain
15 | *.PDF diff=astextplain
16 | *.rtf diff=astextplain
17 | *.RTF diff=astextplain
18 |
--------------------------------------------------------------------------------
/.github/workflows/run-tests.yml:
--------------------------------------------------------------------------------
1 | name: run-tests
2 |
3 | on:
4 | push:
5 | pull_request:
6 | schedule:
7 | - cron: "0 0 * * *"
8 |
9 | jobs:
10 | run-tests:
11 | runs-on: ${{ matrix.os }}
12 | strategy:
13 | fail-fast: false
14 | matrix:
15 | os: [ ubuntu-latest ]
16 | laravel: [ 12.*, 11.*, 10.*, 9.* ]
17 | dependency-version: [ prefer-stable ]
18 | include:
19 | - laravel: 12.*
20 | testbench: 10.*
21 | php: 8.4
22 |
23 | - laravel: 11.*
24 | testbench: 9.*
25 | php: 8.3
26 |
27 | - laravel: 10.*
28 | testbench: 8.*
29 | php: 8.3
30 |
31 | - laravel: 9.*
32 | testbench: 7.*
33 | php: 8.2
34 |
35 | name: ${{ matrix.os }} - P${{ matrix.php }} - L${{ matrix.laravel }} - ${{ matrix.dependency-version }}
36 |
37 | steps:
38 | - name: Checkout code
39 | uses: actions/checkout@v4
40 |
41 | - name: Cache dependencies
42 | uses: actions/cache@v4
43 | with:
44 | path: ~/.composer/cache/files
45 | key: dependencies-laravel-${{ matrix.laravel }}-php-${{ matrix.php }}-composer-${{ hashFiles('composer.json') }}
46 |
47 | - name: Setup PHP
48 | uses: shivammathur/setup-php@v2
49 | with:
50 | php-version: ${{ matrix.php }}
51 |
52 | - name: Install dependencies
53 | run: |
54 | composer require "laravel/framework:${{ matrix.laravel }}" "orchestra/testbench:${{ matrix.testbench }}" --no-interaction --no-update --dev
55 | composer update --${{ matrix.dependency-version }} --prefer-dist --no-interaction
56 |
57 | - name: Execute tests
58 | run: vendor/bin/phpunit
59 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /vendor
2 | composer.phar
3 | composer.lock
4 | Thumbs.db
5 | .idea
6 | .phpunit.result.cache
7 |
--------------------------------------------------------------------------------
/.scrutinizer.yml:
--------------------------------------------------------------------------------
1 | filter:
2 | excluded_paths:
3 | - tests/*
4 | build:
5 | nodes:
6 | analysis:
7 | tests:
8 | override:
9 | - command: php-scrutinizer-run
10 |
--------------------------------------------------------------------------------
/.styleci.yml:
--------------------------------------------------------------------------------
1 | preset: laravel
2 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | An easy, native role / permission management system for Laravel.
16 |
17 |
18 | ## Index
19 |
20 | - [Installation](#installation)
21 | - [Migration Customization](#migration-customization)
22 | - [Model Customization](#model-customization)
23 | - [Usage](#usage)
24 | - [Checking Permissions & Roles](#checking-permissions--roles)
25 | - [Caching](#caching)
26 | - [Gate Registration](#gate-registration)
27 | - [Middleware](#middleware)
28 | - [Testing](#running-tests)
29 |
30 | ## Installation
31 |
32 | To get started, install Authorization via the Composer package manager:
33 |
34 | composer require directorytree/authorization
35 |
36 | The Authorization service provider registers its own database migration directory
37 | with the framework, so you should migrate your database after installing the
38 | package. The Authorization migrations will create the tables your
39 | application needs to store roles and permissions:
40 |
41 | php artisan migrate
42 |
43 | Now insert the `DirectoryTree\Authorization\Traits\Authorizable` onto your `App\Models\User` model:
44 |
45 | ```php
46 | registerPolicies();
103 |
104 | Authorization::useUserModel(\App\Models\User::class);
105 | Authorization::useRoleModel(\App\Models\Role::class);
106 | Authorization::usePermissionModel(\App\Models\Permission::class);
107 | }
108 | ```
109 |
110 | Be sure to add the relevant traits for each of your custom models:
111 |
112 | **Role Model**:
113 |
114 | ```php
115 | namespace App\Models;
116 |
117 | use Illuminate\Database\Eloquent\Model;
118 | use DirectoryTree\Authorization\Traits\ManagesPermissions;
119 |
120 | class Role extends Model
121 | {
122 | use ManagesPermissions;
123 | }
124 | ```
125 |
126 | **Permission Model**:
127 |
128 | ```php
129 | namespace App\Models;
130 |
131 | use Illuminate\Database\Eloquent\Model;
132 | use DirectoryTree\Authorization\Traits\HasUsers;
133 | use DirectoryTree\Authorization\Traits\HasRoles;
134 | use DirectoryTree\Authorization\Traits\ClearsCachedPermissions;
135 |
136 | class Permission extends Model
137 | {
138 | use HasUsers, HasRoles, ClearsCachedPermissions;
139 | }
140 | ```
141 |
142 | ## Usage
143 |
144 | Authorization uses native Laravel relationships, so there's no need to learn a new API if you don't want to.
145 |
146 | > Due to Authorization's trait based implementation, all of Authorization's functionality can be overridden or extended with you own implementation.
147 |
148 | ### Managing Roles & Permissions
149 |
150 | Create a permission:
151 |
152 | ```php
153 | use DirectoryTree\Authorization\Permission;
154 |
155 | $createUsers = Permission::create([
156 | 'name' => 'users.create',
157 | 'label' => 'Create Users',
158 | ]);
159 | ```
160 |
161 | Create a role:
162 |
163 | ```php
164 | use DirectoryTree\Authorization\Role;
165 |
166 | $admin = Role::create([
167 | 'name' => 'administrator',
168 | 'label' => 'Admin',
169 | ]);
170 | ```
171 |
172 | Grant the permission to a role:
173 |
174 | ```php
175 | $admin->permissions()->save($createUsers);
176 | ```
177 |
178 | Now assign the role to the user:
179 |
180 | ```php
181 | $user->roles()->save($admin);
182 | ```
183 |
184 | You may also use the `grant()` or `revoke()` method on a `Role` model:
185 |
186 | ```php
187 | // Using the permission's name:
188 | $admin->grant('users.create');
189 |
190 | // Using a permission model:
191 | $admin->grant($permission);
192 |
193 | // Granting multiple permissions:
194 | $admin->grant(['users.create', 'users.edit']);
195 |
196 | // Granting a collection of models:
197 | $admin->grant(Permission::all());
198 |
199 | // Using a mix of models and permission name:
200 | $admin->grant([$createUsers, 'users.edit']);
201 | ```
202 |
203 | You may also sync a role's permissions using the `grantOnly()` method:
204 |
205 | ```php
206 | // All permissions will be removed except, except for the given:
207 | $admin->grantOnly('users.create');
208 | ```
209 |
210 | ```php
211 | // Using the permission's name:
212 | $admin->revoke('users.create');
213 |
214 | // Using a permission model:
215 | $admin->revoke($permission);
216 |
217 | // Revoking multiple permissions:
218 | $admin->revoke(['users.create', 'users.edit']);
219 |
220 | // Revoking a collection of models:
221 | $admin->revoke(Permission::all());
222 |
223 | // Using a mix of models and permission name:
224 | $admin->revoke([$createUsers, 'users.edit']);
225 | ```
226 |
227 | You may also detach all permissions from a role using `revokeAll()`:
228 |
229 | ```php
230 | $admin->revokeAll();
231 | ```
232 |
233 | ### Managing Users & Permissions
234 |
235 | You can also create user specific permissions:
236 |
237 | ```php
238 | $createUsers = Permission::create([
239 | 'name' => 'users.create',
240 | 'label' => 'Create Users',
241 | ]);
242 |
243 | $user->permissions()->save($createUsers);
244 | ```
245 |
246 | As with roles, may also use the `grant()` or `revoke()` method on an authorizable `User` model:
247 |
248 | ```php
249 | // Using the permission's name:
250 | $user->grant('users.create');
251 |
252 | // Using a permission model:
253 | $user->grant($permission);
254 |
255 | // Granting multiple permissions:
256 | $user->grant(['users.create', 'users.edit']);
257 |
258 | // Granting a collection of models:
259 | $user->grant(Permission::all());
260 |
261 | // Using a mix of models and permission name:
262 | $user->grant([$createUsers, 'users.edit']);
263 | ```
264 |
265 | You may also sync a users' permissions using the `grantOnly()` method:
266 |
267 | ```php
268 | // All permissions will be removed except, except for the given:
269 | $user->grantOnly('users.create');
270 | ```
271 |
272 | ```php
273 | // Using the permission's name:
274 | $user->revoke('users.create');
275 |
276 | // Using a permission model:
277 | $user->revoke($permission);
278 |
279 | // Granting multiple permissions:
280 | $user->revoke(['users.create', 'users.edit']);
281 |
282 | // Granting a collection of models:
283 | $user->revoke(Permission::all());
284 |
285 | // Using a mix of models and permission name:
286 | $user->revoke([$createUsers, 'users.edit']);
287 | ```
288 |
289 | ### Checking Permissions & Roles
290 |
291 | Using Laravel's native `can()` method:
292 |
293 | ```php
294 | if (Auth::user()->can('users.create')) {
295 | // This user can create other users.
296 | }
297 | ```
298 |
299 | Using Laravel's native `authorize()` method in your controllers:
300 |
301 | ```php
302 | public function create()
303 | {
304 | $this->authorize('users.create');
305 |
306 | User::create(['...']);
307 | }
308 | ```
309 |
310 | Using Laravel's native `Gate` facade:
311 |
312 | ```php
313 | if (Gate::allows('users.create')) {
314 | //
315 | }
316 | ```
317 |
318 | Using Laravel's native `@can` directive in your views:
319 |
320 | ```blade
321 | @can('users.create')
322 |
323 | @endcan
324 | ```
325 |
326 | ### Checking Permissions & Roles (Using Authorization Package Methods)
327 |
328 | Checking for permission:
329 |
330 | ```php
331 | // Using the permissions name.
332 | if ($user->hasPermission('users.create')) {
333 | //
334 | }
335 |
336 | // Using the permissions model.
337 | if ($user->hasPermission($createUsers)) {
338 | //
339 | }
340 | ```
341 |
342 | Checking for multiple permissions:
343 |
344 | ```php
345 | if ($user->hasPermissions(['users.create', 'users.edit'])) {
346 | // This user has both creation and edit rights.
347 | } else {
348 | // The user doesn't have one of the specified permissions.
349 | }
350 | ```
351 |
352 | Checking if the user has any permissions:
353 |
354 | ```php
355 | if ($user->hasAnyPermissions(['users.create', 'users.edit', 'users.destroy'])) {
356 | // This user either has create, edit or destroy permissions.
357 | } else {
358 | // The user doesn't have any of the specified permissions.
359 | }
360 | ```
361 |
362 | Checking if the user has a role:
363 |
364 | ```php
365 | if ($user->hasRole('administrator')) {
366 | // This user is an administrator.
367 | } else {
368 | // The user isn't an administrator.
369 | }
370 | ```
371 |
372 | Checking if the user has specified roles:
373 |
374 | ```php
375 | if ($user->hasRoles(['administrator', 'member'])) {
376 | // This user is an administrator and a member.
377 | } else {
378 | // The user isn't an administrator or member.
379 | }
380 | ```
381 |
382 | Checking if the user has any specified roles:
383 |
384 | ```php
385 | if ($user->hasAnyRoles(['administrator', 'member', 'guest'])) {
386 | // This user is either an administrator, member or guest.
387 | } else {
388 | // The user doesn't have any of these roles.
389 | }
390 | ```
391 |
392 | ### Caching
393 |
394 | By default all permissions are cached to prevent them from being retrieved on every request.
395 |
396 | This cache is automatically flushed when permissions are created, updated, or deleted.
397 |
398 | If you would like to disable the cache, call `Authorization::disablePermissionCache` in your `AuthServiceProvider`:
399 |
400 | ```php
401 | use DirectoryTree\Authorization\Authorization;
402 |
403 | /**
404 | * Register any authentication / authorization services.
405 | *
406 | * @return void
407 | */
408 | public function boot()
409 | {
410 | $this->registerPolicies();
411 |
412 | Authorization::disablePermissionCache();
413 | }
414 | ```
415 |
416 | #### Cache Key
417 |
418 | By default, the permission cache key is `authorization.permissions`.
419 |
420 | To alter the cache key, call `Authorization::cacheKey` in your `AuthServiceProvider`:
421 |
422 | ```php
423 | use DirectoryTree\Authorization\Authorization;
424 |
425 | /**
426 | * Register any authentication / authorization services.
427 | *
428 | * @return void
429 | */
430 | public function boot()
431 | {
432 | $this->registerPolicies();
433 |
434 | Authorization::cacheKey('my-key');
435 | }
436 | ```
437 |
438 | #### Cache Expiry
439 |
440 | By default, the permission cache will expire daily.
441 |
442 | To alter this expiry date, call `Authorization::cacheExpiresIn` in your `AuthServiceProvider`:
443 |
444 | ```php
445 | use DirectoryTree\Authorization\Authorization;
446 |
447 | /**
448 | * Register any authentication / authorization services.
449 | *
450 | * @return void
451 | */
452 | public function boot()
453 | {
454 | $this->registerPolicies();
455 |
456 | Authorization::cacheExpiresIn(now()->addWeek());
457 | }
458 | ```
459 |
460 | ### Gate Registration
461 |
462 | By default all permissions you create are registered in Laravel's Gate.
463 |
464 | If you would like to disable this, call `Authorization::disableGateRegistration` in your `AuthServiceProvider`:
465 |
466 | ```php
467 | use DirectoryTree\Authorization\Authorization;
468 |
469 | /**
470 | * Register any authentication / authorization services.
471 | *
472 | * @return void
473 | */
474 | public function boot()
475 | {
476 | $this->registerPolicies();
477 |
478 | Authorization::disableGateRegistration();
479 | }
480 | ```
481 |
482 | ### Middleware
483 |
484 | Authorization includes two useful middleware classes you can utilize for your routes.
485 |
486 | Insert them into your `app/Http/Kernel.php`:
487 |
488 | ```php
489 | /**
490 | * The application's route middleware.
491 | *
492 | * These middleware may be assigned to groups or used individually.
493 | *
494 | * @var array
495 | */
496 | protected $routeMiddleware = [
497 | 'auth' => \App\Http\Middleware\Authenticate::class,
498 | 'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
499 | 'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
500 | 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
501 |
502 | // The role middleware:
503 | 'role' => \DirectoryTree\Authorization\Middleware\RoleMiddleware::class,
504 |
505 | // The permission middleware:
506 | 'permission' => \DirectoryTree\Authorization\Middleware\PermissionMiddleware::class,
507 | ];
508 | ```
509 |
510 | Once you've added them, you can start using them.
511 |
512 | > **Note**: When a user does not meet the requirements using the middleware, a 403 HTTP exception is thrown.
513 |
514 | To guard a route to only allow specific permissions:
515 |
516 | ```php
517 | Route::get('users', [
518 | 'uses' => 'UsersController@index',
519 | 'middleware' => 'permission:users.index',
520 | ]);
521 |
522 | // Multiple permissions:
523 | Route::get('users', [
524 | 'uses' => 'UsersController@index',
525 | // Users must have index **and** create rights to access this route.
526 | 'middleware' => 'permission:users.index,users.create',
527 | ]);
528 | ```
529 |
530 | To guard a route to allow a specific role:
531 |
532 | ```php
533 | Route::get('users', [
534 | 'uses' => 'UsersController@index',
535 | 'middleware' => 'role:administrator',
536 | ]);
537 |
538 | // Multiple roles:
539 | Route::get('users', [
540 | 'uses' => 'UsersController@index',
541 | // Users must be an administrator **and** a member to access this route.
542 | 'middleware' => 'role:administrator,member',
543 | ]);
544 | ```
545 |
546 | ### Running Tests
547 |
548 | To run your applications tests, **you must** instantiate the `PermissionRegistrar`
549 | inside your `TestCase::setUp()` method **before** running your
550 | tests for permissions to register properly:
551 |
552 | ```php
553 | use DirectoryTree\Authorization\PermissionRegistrar;
554 | ```
555 |
556 | ```php
557 | protected function setUp() : void
558 | {
559 | parent::setUp();
560 |
561 | app(PermissionRegistrar::class)->register();
562 | }
563 | ```
564 |
--------------------------------------------------------------------------------
/art/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DirectoryTree/Authorization/803a7580a743e44f5195cd448eeec71d89e9d952/art/logo.png
--------------------------------------------------------------------------------
/art/logo.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "directorytree/authorization",
3 | "description": "Native Laravel Authorization.",
4 | "keywords": [
5 | "authorization",
6 | "laravel",
7 | "permissions",
8 | "roles",
9 | "acl"
10 | ],
11 | "license": "MIT",
12 | "type": "project",
13 | "require": {
14 | "php": ">=7.4",
15 | "illuminate/database": "^5.5|^6.20|^7.0|^8.0|^9.0|^10.0|^11.0|^12.0"
16 | },
17 | "require-dev": {
18 | "orchestra/testbench": "^3.7|^4.0|^5.0|^6.0|^7.0|^8.0|^9.0|^10.0",
19 | "phpunit/phpunit": "^7.0|^8.0|^9.0|^10.0|^11.0|^12.0"
20 | },
21 | "minimum-stability": "dev",
22 | "prefer-stable": true,
23 | "autoload": {
24 | "psr-4": {
25 | "DirectoryTree\\Authorization\\": "src/"
26 | }
27 | },
28 | "autoload-dev": {
29 | "psr-4": {
30 | "DirectoryTree\\Authorization\\Tests\\": "tests/"
31 | }
32 | },
33 | "extra": {
34 | "laravel": {
35 | "providers": [
36 | "DirectoryTree\\Authorization\\AuthorizationServiceProvider"
37 | ]
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/database/migrations/2014_10_12_200000_create_authorization_tables.php:
--------------------------------------------------------------------------------
1 | increments('id');
18 | $table->timestamps();
19 | $table->string('name')->unique()->index();
20 | $table->string('label')->nullable();
21 | });
22 |
23 | Schema::create('permissions', function (Blueprint $table) {
24 | $table->increments('id');
25 | $table->timestamps();
26 | $table->string('name')->unique()->index();
27 | $table->string('label')->nullable();
28 | });
29 |
30 | Schema::create('permission_role', function (Blueprint $table) {
31 | $table->unsignedInteger('permission_id');
32 | $table->unsignedInteger('role_id');
33 |
34 | $table->primary(['permission_id', 'role_id']);
35 | });
36 |
37 | Schema::create('permission_user', function (Blueprint $table) {
38 | $table->unsignedInteger('permission_id');
39 | $table->unsignedInteger('user_id');
40 |
41 | $table->primary(['permission_id', 'user_id']);
42 | });
43 |
44 | Schema::create('role_user', function (Blueprint $table) {
45 | $table->unsignedInteger('role_id');
46 | $table->unsignedInteger('user_id');
47 |
48 | $table->primary(['role_id', 'user_id']);
49 | });
50 | }
51 |
52 | /**
53 | * Reverse the migrations.
54 | *
55 | * @return void
56 | */
57 | public function down()
58 | {
59 | Schema::dropIfExists('role_user');
60 | Schema::dropIfExists('permission_role');
61 | Schema::dropIfExists('permission_user');
62 | Schema::dropIfExists('permissions');
63 | Schema::dropIfExists('roles');
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/license.md:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 | Copyright © Steve Bauman
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5 |
6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
7 |
8 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/phpunit.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
14 | ./tests/
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/src/Authorization.php:
--------------------------------------------------------------------------------
1 | addDay();
76 | }
77 |
78 | static::$cacheExpiresAt = $date;
79 |
80 | return new static;
81 | }
82 |
83 | /**
84 | * Get or set the cache key.
85 | *
86 | * @param string|null $cacheKey
87 | *
88 | * @return static|string
89 | */
90 | public static function cacheKey($cacheKey = null)
91 | {
92 | if (is_null($cacheKey)) {
93 | return static::$cacheKey;
94 | }
95 |
96 | static::$cacheKey = $cacheKey;
97 |
98 | return new static;
99 | }
100 |
101 | /**
102 | * Set the user model class name.
103 | *
104 | * @param $userModel
105 | */
106 | public static function useUserModel($userModel)
107 | {
108 | static::$userModel = $userModel;
109 | }
110 |
111 | /**
112 | * Get the user model class name.
113 | *
114 | * @return string
115 | */
116 | public static function userModel()
117 | {
118 | return static::$userModel;
119 | }
120 |
121 | /**
122 | * Get a new user model instance.
123 | *
124 | * @return \Illuminate\Database\Eloquent\Model
125 | */
126 | public static function user()
127 | {
128 | return new static::$userModel;
129 | }
130 |
131 | /**
132 | * Set the role model class name.
133 | *
134 | * @param $roleModel
135 | */
136 | public static function useRoleModel($roleModel)
137 | {
138 | static::$roleModel = $roleModel;
139 | }
140 |
141 | /**
142 | * Get the role model class name.
143 | *
144 | * @return string
145 | */
146 | public static function roleModel()
147 | {
148 | return static::$roleModel;
149 | }
150 |
151 | /**
152 | * Get a new role model instance.
153 | *
154 | * @return Role
155 | */
156 | public static function role()
157 | {
158 | return new static::$roleModel;
159 | }
160 |
161 | /**
162 | * Set the permission model class name.
163 | *
164 | * @param $permissionModel
165 | */
166 | public static function usePermissionModel($permissionModel)
167 | {
168 | static::$permissionModel = $permissionModel;
169 | }
170 |
171 | /**
172 | * Get the permission model class name.
173 | *
174 | * @return string
175 | */
176 | public static function permissionModel()
177 | {
178 | return static::$permissionModel;
179 | }
180 |
181 | /**
182 | * Get a new permission model instance.
183 | *
184 | * @return Permission
185 | */
186 | public static function permission()
187 | {
188 | return new static::$permissionModel;
189 | }
190 |
191 | /**
192 | * Configure Authorization to not register in the auth gate.
193 | *
194 | * @return static
195 | */
196 | public function disableGateRegistration()
197 | {
198 | static::$registersInGate = false;
199 |
200 | return new static;
201 | }
202 |
203 | /**
204 | * Configure Authorization to not cache permissions.
205 | *
206 | * @return static
207 | */
208 | public static function disablePermissionCache()
209 | {
210 | static::$cachesPermissions = false;
211 |
212 | return new static;
213 | }
214 |
215 | /**
216 | * Configure Authorization to not register its migrations.
217 | *
218 | * @return static
219 | */
220 | public static function ignoreMigrations()
221 | {
222 | static::$runsMigrations = false;
223 |
224 | return new static;
225 | }
226 | }
227 |
--------------------------------------------------------------------------------
/src/AuthorizationServiceProvider.php:
--------------------------------------------------------------------------------
1 | app->runningInConsole()) {
17 | $this->registerMigrations();
18 |
19 | $this->publishes([
20 | __DIR__.'/../database/migrations' => database_path('migrations'),
21 | ], 'authorization-migrations');
22 | }
23 |
24 | // Register the permissions.
25 | if (Authorization::$registersInGate) {
26 | app(PermissionRegistrar::class)->register();
27 | }
28 | }
29 |
30 | /**
31 | * Register Authorization migration files.
32 | *
33 | * @return void
34 | */
35 | protected function registerMigrations()
36 | {
37 | if (Authorization::$runsMigrations) {
38 | $this->loadMigrationsFrom(__DIR__.'/../database/migrations');
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/Middleware/AuthorizationMiddleware.php:
--------------------------------------------------------------------------------
1 | authorize($request->user(), $auth)) {
22 | return $this->unauthorized();
23 | }
24 |
25 | return $next($request);
26 | }
27 |
28 | /**
29 | * Abort the application request.
30 | *
31 | * @return void
32 | */
33 | protected function unauthorized()
34 | {
35 | abort(403, 'Unauthorized.');
36 | }
37 |
38 | /**
39 | * Authorize whether the user has access to the route.
40 | *
41 | * @param \App\User $user
42 | * @param array|null $auth
43 | *
44 | * @return bool
45 | */
46 | abstract protected function authorize($user, $auth = null);
47 | }
48 |
--------------------------------------------------------------------------------
/src/Middleware/PermissionMiddleware.php:
--------------------------------------------------------------------------------
1 | hasPermissions($permissions);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/Middleware/RoleMiddleware.php:
--------------------------------------------------------------------------------
1 | hasRoles($roles);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/Permission.php:
--------------------------------------------------------------------------------
1 | gate = $gate;
34 | $this->cache = $manager;
35 | }
36 |
37 | /**
38 | * Registers permissions into the gate.
39 | *
40 | * @return void
41 | */
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 | }
51 |
52 | /**
53 | * Fetch the collection of permissions.
54 | *
55 | * @return \Illuminate\Database\Eloquent\Collection|array
56 | */
57 | public function getPermissions()
58 | {
59 | try {
60 | if (Authorization::$cachesPermissions) {
61 | return $this->cache->remember(Authorization::cacheKey(), Authorization::cacheExpiresIn(), function () {
62 | return Authorization::permission()->get();
63 | });
64 | }
65 |
66 | return Authorization::permission()->get();
67 | } catch (PDOException $e) {
68 | // Migrations haven't been ran yet.
69 | }
70 |
71 | return [];
72 | }
73 |
74 | /**
75 | * Flushes the permission cache.
76 | *
77 | * @return void
78 | */
79 | public function flushCache()
80 | {
81 | $this->cache->forget(Authorization::cacheKey());
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/src/Pivot.php:
--------------------------------------------------------------------------------
1 | whereName($permissions)->first();
24 | }
25 |
26 | if ($permissions instanceof Model) {
27 | return $this->hasPermission($permissions)
28 | ? $permissions
29 | : $this->permissions()->save($permissions);
30 | }
31 |
32 | return Collection::make($permissions)->map(function ($permission) {
33 | return $this->grant($permission) instanceof Model ? $permission : false;
34 | })->filter();
35 | }
36 |
37 | /**
38 | * Grant only the given permission(s), detaching any previous permission(s).
39 | *
40 | * @param string|string[]|Model|Model[] $permissions
41 | *
42 | * @return Model|Model[]|Collection
43 | */
44 | public function grantOnly($permissions)
45 | {
46 | $this->revokeAll();
47 |
48 | return $this->grant($permissions);
49 | }
50 |
51 | /**
52 | * Revoke the given permission(s).
53 | *
54 | * Returns a collection of revoked permissions.
55 | *
56 | * @param string|string[]|Model|Model[] $permissions
57 | *
58 | * @return Model|Model[]|Collection
59 | */
60 | public function revoke($permissions)
61 | {
62 | if (is_string($permissions)) {
63 | $permissions = Authorization::permission()->whereName($permissions)->first();
64 | }
65 |
66 | if ($permissions instanceof Model) {
67 | if (! $this->hasPermission($permissions)) {
68 | return $permissions;
69 | }
70 |
71 | $this->permissions()->detach($permissions);
72 |
73 | return $permissions;
74 | }
75 |
76 | return Collection::make($permissions)->map(function ($permission) {
77 | return $this->revoke($permission) instanceof Model ? $permission : false;
78 | })->filter();
79 | }
80 |
81 | /**
82 | * Revokes all permissions.
83 | *
84 | * Returns the number of revoked permissions.
85 | *
86 | * @return int
87 | */
88 | public function revokeAll()
89 | {
90 | $detached = $this->permissions()->detach();
91 |
92 | // When permissions are completely revoked, we must purge the
93 | // permissions relation so we do not get false positives on
94 | // any following permission checks during the same request.
95 | $this->unsetRelation('permissions');
96 |
97 | return $detached;
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/src/Traits/Authorizable.php:
--------------------------------------------------------------------------------
1 | whereName($role)->firstOrFail();
24 | }
25 |
26 | return $this->roles()->save($role);
27 | }
28 |
29 | /**
30 | * Removes the specified role from the user.
31 | *
32 | * @param string|Model $role
33 | *
34 | * @return int
35 | */
36 | public function removeRole($role)
37 | {
38 | if (! $role instanceof Model) {
39 | $role = Authorization::role()->whereName($role)->firstOrFail();
40 | }
41 |
42 | return $this->roles()->detach($role);
43 | }
44 |
45 | /**
46 | * Determine if the user has the given role.
47 | *
48 | * @param string|Model $role
49 | *
50 | * @return bool
51 | */
52 | public function hasRole($role)
53 | {
54 | if (empty($role)) {
55 | return false;
56 | }
57 |
58 | $this->loadMissing('roles');
59 |
60 | return $role instanceof Model
61 | ? $this->roles->contains($role)
62 | : $this->roles->contains('name', $role);
63 | }
64 |
65 | /**
66 | * Determine if the user has all of the given roles.
67 | *
68 | * @param array $roles
69 | *
70 | * @return bool
71 | */
72 | public function hasRoles($roles)
73 | {
74 | $roles = Collection::make($roles);
75 |
76 | if ($roles->isEmpty()) {
77 | return false;
78 | }
79 |
80 | return $roles->filter(function ($role) {
81 | return $this->hasRole($role);
82 | })->count() === $roles->count();
83 | }
84 |
85 | /**
86 | * Determine if the user has any of the given roles.
87 | *
88 | * @param array $roles
89 | *
90 | * @return bool
91 | */
92 | public function hasAnyRoles($roles)
93 | {
94 | return Collection::make($roles)->filter(function ($role) {
95 | return $this->hasRole($role);
96 | })->isNotEmpty();
97 | }
98 |
99 | /**
100 | * Determine if the user has the given permission.
101 | *
102 | * @param string|Model $permission
103 | *
104 | * @return bool
105 | */
106 | public function hasPermission($permission)
107 | {
108 | if (is_string($permission)) {
109 | // If we've been given a string, then we can
110 | // assume its the permissions name. We will
111 | // attempt to fetch it from the database.
112 | $permission = Authorization::permission()->whereName($permission)->first();
113 | }
114 |
115 | if (! $permission instanceof Model) {
116 | return false;
117 | }
118 |
119 | // Here we will check if the user has been granted
120 | // explicit this permission explicitly. If so, we
121 | // can return here. No further check is needed.
122 | if ($this->permissions()->find($permission->getKey())) {
123 | return true;
124 | }
125 |
126 | // Otherwise, we'll determine their permission by gathering
127 | // the roles that the permission belongs to and checking
128 | // if the user is a member of any of the fetched roles.
129 | $roles = $permission->roles()->get()->map(function ($role) {
130 | return $role->getKey();
131 | });
132 |
133 | return $this->roles()
134 | ->whereIn($this->roles()->getRelatedPivotKeyName(), $roles)
135 | ->count() > 0;
136 | }
137 |
138 | /**
139 | * Determine if the user has all of the given permissions.
140 | *
141 | * @param array|\Illuminate\Support\Collection $permissions
142 | *
143 | * @return bool
144 | */
145 | public function hasPermissions($permissions)
146 | {
147 | $permissions = Collection::make($permissions);
148 |
149 | if ($permissions->isEmpty()) {
150 | return false;
151 | }
152 |
153 | return $permissions->filter(function ($permission) {
154 | return $this->hasPermission($permission);
155 | })->count() === $permissions->count();
156 | }
157 |
158 | /**
159 | * Determine if the user has any of the permissions.
160 | *
161 | * @param array|\Illuminate\Support\Collection $permissions
162 | *
163 | * @return bool
164 | */
165 | public function hasAnyPermissions($permissions)
166 | {
167 | return Collection::make($permissions)->filter(function ($permission) {
168 | return $this->hasPermission($permission);
169 | })->isNotEmpty();
170 | }
171 |
172 | /**
173 | * Determine if the user does not have the given permission.
174 | *
175 | * @param string|Model $permission
176 | *
177 | * @return bool
178 | */
179 | public function doesNotHavePermission($permission)
180 | {
181 | return ! $this->hasPermission($permission);
182 | }
183 |
184 | /**
185 | * Determine if the user does not have all of the given permissions.
186 | *
187 | * @param array|\Illuminate\Support\Collection $permissions
188 | *
189 | * @return bool
190 | */
191 | public function doesNotHavePermissions($permissions)
192 | {
193 | return ! $this->hasPermissions($permissions);
194 | }
195 |
196 | /**
197 | * Determine if the user does not have any of the given permissions.
198 | *
199 | * @param array|\Illuminate\Support\Collection $permissions
200 | *
201 | * @return bool
202 | */
203 | public function doesNotHaveAnyPermissions($permissions)
204 | {
205 | return ! $this->hasAnyPermissions($permissions);
206 | }
207 | }
208 |
--------------------------------------------------------------------------------
/src/Traits/ClearsCachedPermissions.php:
--------------------------------------------------------------------------------
1 | flushCache();
20 | });
21 |
22 | static::deleted(function () {
23 | app(PermissionRegistrar::class)->flushCache();
24 | });
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/Traits/FlushesLoadedRelations.php:
--------------------------------------------------------------------------------
1 | pivotParent->unsetRelation(static::$flushingRelation);
25 | });
26 |
27 | static::deleted(function (Pivot $pivot) {
28 | $pivot->pivotParent->unsetRelation(static::$flushingRelation);
29 | });
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/Traits/HasPermissions.php:
--------------------------------------------------------------------------------
1 | belongsToMany(Authorization::permissionModel())->using(PermissionPivot::class);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/Traits/HasRoles.php:
--------------------------------------------------------------------------------
1 | belongsToMany(Authorization::roleModel())->using(RolePivot::class);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/Traits/HasUsers.php:
--------------------------------------------------------------------------------
1 | belongsToMany(Authorization::userModel())->using(UserPivot::class);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/Traits/ManagesPermissions.php:
--------------------------------------------------------------------------------
1 | loadMissing('permissions');
27 |
28 | return $permission instanceof Model
29 | ? $this->permissions->contains($permission)
30 | : $this->permissions->contains('name', $permission);
31 | }
32 |
33 | /**
34 | * Determine if the current role has the given permissions.
35 | *
36 | * @param string|array $permissions
37 | *
38 | * @return bool
39 | */
40 | public function hasPermissions($permissions)
41 | {
42 | return Collection::make(Arr::wrap($permissions))->filter(function ($permission) {
43 | return $this->hasPermission($permission);
44 | })->count() === count($permissions);
45 | }
46 |
47 | /**
48 | * Determine if the current role has any of the given permissions.
49 | *
50 | * @param array $permissions
51 | *
52 | * @return bool
53 | */
54 | public function hasAnyPermissions($permissions)
55 | {
56 | return Collection::make(Arr::wrap($permissions))->filter(function ($permission) {
57 | return $this->hasPermission($permission);
58 | })->count() > 0;
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/src/UserPivot.php:
--------------------------------------------------------------------------------
1 | createRole([
14 | 'name' => 'administrator',
15 | 'label' => 'Admin',
16 | ]);
17 |
18 | $user = $this->createUser([
19 | 'name' => 'John Doe',
20 | ]);
21 |
22 | $user->assignRole('administrator');
23 |
24 | $this->assertCount(1, $user->roles);
25 | }
26 |
27 | public function test_assign_multiple_roles()
28 | {
29 | $this->createRole([
30 | 'name' => 'administrator',
31 | 'label' => 'Admin',
32 | ]);
33 |
34 | $this->createRole([
35 | 'name' => 'member',
36 | 'label' => 'Member',
37 | ]);
38 |
39 | $user = $this->createUser([
40 | 'name' => 'John Doe',
41 | ]);
42 |
43 | $user->assignRole('administrator');
44 | $user->assignRole('member');
45 |
46 | $this->assertCount(2, $user->roles);
47 | }
48 |
49 | public function test_assign_roles_with_model()
50 | {
51 | $admin = $this->createRole([
52 | 'name' => 'administrator',
53 | 'label' => 'Admin',
54 | ]);
55 |
56 | $member = $this->createRole([
57 | 'name' => 'member',
58 | 'label' => 'Member',
59 | ]);
60 |
61 | $user = $this->createUser([
62 | 'name' => 'John Doe',
63 | ]);
64 |
65 | $this->assertEmpty($user->roles);
66 |
67 | $user->assignRole($admin);
68 | $user->assignRole($member);
69 |
70 | $this->assertCount(2, $user->roles);
71 | }
72 |
73 | public function test_has_role()
74 | {
75 | $admin = $this->createRole([
76 | 'name' => 'administrator',
77 | 'label' => 'Admin',
78 | ]);
79 |
80 | $user = $this->createUser([
81 | 'name' => 'John Doe',
82 | ]);
83 |
84 | $this->assertFalse($user->hasRole($admin));
85 | $this->assertFalse($user->hasRole('administrator'));
86 |
87 | $user->assignRole($admin);
88 |
89 | $this->assertTrue($user->hasRole($admin));
90 | $this->assertTrue($user->hasRole('administrator'));
91 | $this->assertFalse($user->hasRole('non-existent'));
92 | }
93 |
94 | public function test_grant_permission()
95 | {
96 | $user = $this->createUser([
97 | 'name' => 'John Doe',
98 | ]);
99 |
100 | $admin = $this->createRole([
101 | 'name' => 'administrator',
102 | 'label' => 'Admin',
103 | ]);
104 |
105 | $createUsers = $this->createPermission([
106 | 'name' => 'users.create',
107 | 'label' => 'Create Users',
108 | ]);
109 |
110 | $this->assertFalse($user->hasRole($admin));
111 | $this->assertFalse($user->hasPermission($createUsers));
112 |
113 | $user->assignRole($admin);
114 |
115 | $this->assertTrue($user->hasRole($admin));
116 |
117 | $this->assertSame($createUsers, $admin->grant($createUsers));
118 |
119 | $this->assertTrue($user->hasPermission($createUsers));
120 | $this->assertTrue($admin->hasPermission($createUsers));
121 | }
122 |
123 | public function test_grant_only_permission()
124 | {
125 | $user = $this->createUser([
126 | 'name' => 'John Doe',
127 | ]);
128 |
129 | $admin = $this->createRole([
130 | 'name' => 'administrator',
131 | 'label' => 'Admin',
132 | ]);
133 |
134 | $createUsers = $this->createPermission([
135 | 'name' => 'users.create',
136 | 'label' => 'Create Users',
137 | ]);
138 |
139 | $editUsers = $this->createPermission([
140 | 'name' => 'users.edit',
141 | 'label' => 'Edit Users',
142 | ]);
143 |
144 | $this->assertFalse($user->hasRole($admin));
145 | $this->assertFalse($user->hasPermission($createUsers));
146 | $this->assertFalse($user->hasPermission($editUsers));
147 |
148 | $this->assertFalse($admin->hasPermission($createUsers));
149 | $this->assertFalse($admin->hasPermission($editUsers));
150 |
151 | $user->assignRole($admin);
152 |
153 | $this->assertTrue($user->hasRole($admin));
154 |
155 | $this->assertSame($createUsers, $admin->grantOnly($createUsers));
156 |
157 | $this->assertTrue($user->hasPermission($createUsers));
158 | $this->assertTrue($admin->hasPermission($createUsers));
159 |
160 | $this->assertFalse($user->hasPermission($editUsers));
161 | $this->assertFalse($admin->hasPermission($editUsers));
162 | }
163 |
164 | public function test_grant_permission_on_user()
165 | {
166 | $user = $this->createUser([
167 | 'name' => 'John Doe',
168 | ]);
169 |
170 | $createUsers = $this->createPermission([
171 | 'name' => 'users.create',
172 | 'label' => 'Create Users',
173 | ]);
174 |
175 | $this->assertTrue($createUsers->is($user->grant('users.create')));
176 | $this->assertTrue($user->hasPermission('users.create'));
177 | $this->assertSame($createUsers, $user->grant($createUsers));
178 |
179 | $user->revoke('users.create');
180 |
181 | $this->assertFalse($user->hasPermission('users.create'));
182 | }
183 |
184 | public function test_grant_only_permission_on_user()
185 | {
186 | $user = $this->createUser([
187 | 'name' => 'John Doe',
188 | ]);
189 |
190 | $createUsers = $this->createPermission([
191 | 'name' => 'users.create',
192 | 'label' => 'Create Users',
193 | ]);
194 |
195 | $editUsers = $this->createPermission([
196 | 'name' => 'users.edit',
197 | 'label' => 'Edit Users',
198 | ]);
199 |
200 | $user->grant([$createUsers, $editUsers]);
201 |
202 | $this->assertTrue($user->hasPermission('users.create'));
203 | $this->assertTrue($user->hasPermission('users.edit'));
204 |
205 | $user->grantOnly($createUsers);
206 |
207 | $this->assertFalse($user->hasPermission('users.edit'));
208 | $this->assertTrue($user->hasPermission('users.create'));
209 | }
210 |
211 | public function test_grant_multiple_permissions()
212 | {
213 | $user = $this->createUser([
214 | 'name' => 'John Doe',
215 | ]);
216 |
217 | $admin = $this->createRole([
218 | 'name' => 'administrator',
219 | 'label' => 'Admin',
220 | ]);
221 |
222 | $this->assertFalse($user->hasRole($admin));
223 | $this->assertFalse($user->hasRole('administrator'));
224 |
225 | $user->assignRole($admin);
226 |
227 | $this->assertTrue($user->hasRole($admin));
228 | $this->assertTrue($user->hasRole('administrator'));
229 |
230 | $createUsers = $this->createPermission([
231 | 'name' => 'users.create',
232 | 'label' => 'Create Users',
233 | ]);
234 |
235 | $editUsers = $this->createPermission([
236 | 'name' => 'users.edit',
237 | 'label' => 'Edit Users',
238 | ]);
239 |
240 | $granted = $admin->grant([$createUsers, $editUsers]);
241 |
242 | $this->assertInstanceOf(Collection::class, $granted);
243 | $this->assertCount(2, $granted);
244 |
245 | $this->assertTrue($user->hasPermission($createUsers));
246 | $this->assertTrue($user->hasPermission($editUsers));
247 |
248 | $this->assertTrue($admin->hasPermission($createUsers));
249 | $this->assertTrue($admin->hasPermission($editUsers));
250 | }
251 |
252 | public function test_grant_multiple_permissions_on_user()
253 | {
254 | $user = $this->createUser([
255 | 'name' => 'John Doe',
256 | ]);
257 |
258 | $createUsers = $this->createPermission([
259 | 'name' => 'users.create',
260 | 'label' => 'Create Users',
261 | ]);
262 |
263 | $editUsers = $this->createPermission([
264 | 'name' => 'users.edit',
265 | 'label' => 'Edit Users',
266 | ]);
267 |
268 | $granted = $user->grant([$createUsers, $editUsers, 'invalid']);
269 |
270 | $this->assertInstanceOf(Collection::class, $granted);
271 | $this->assertSame($createUsers, $granted->get(0));
272 | $this->assertSame($editUsers, $granted->get(1));
273 | $this->assertCount(2, $granted);
274 |
275 | $this->assertTrue($user->hasPermission($createUsers));
276 | $this->assertTrue($user->hasPermission($editUsers));
277 | }
278 |
279 | public function test_grant_multiple_permissions_with_non_existent_permission()
280 | {
281 | $user = $this->createUser([
282 | 'name' => 'John Doe',
283 | ]);
284 |
285 | $admin = $this->createRole([
286 | 'name' => 'administrator',
287 | 'label' => 'Admin',
288 | ]);
289 |
290 | $user->assignRole($admin);
291 |
292 | $createUsers = $this->createPermission([
293 | 'name' => 'users.create',
294 | 'label' => 'Create Users',
295 | ]);
296 |
297 | $editUsers = $this->createPermission([
298 | 'name' => 'users.edit',
299 | 'label' => 'Edit Users',
300 | ]);
301 |
302 | $this->assertEquals(2, $admin->grant([$createUsers, $editUsers, 'invalid'])->count());
303 | }
304 |
305 | public function test_revoke_permission()
306 | {
307 | $user = $this->createUser([
308 | 'name' => 'John Doe',
309 | ]);
310 |
311 | $admin = $this->createRole([
312 | 'name' => 'administrator',
313 | 'label' => 'Admin',
314 | ]);
315 |
316 | $user->assignRole($admin);
317 |
318 | $createUsers = $this->createPermission([
319 | 'name' => 'users.create',
320 | 'label' => 'Create Users',
321 | ]);
322 |
323 | $admin->grant($createUsers);
324 |
325 | $this->assertTrue($admin->hasPermission($createUsers));
326 | $this->assertTrue($user->hasPermission($createUsers));
327 |
328 | $this->assertSame($createUsers, $admin->revoke($createUsers));
329 |
330 | $this->assertFalse($admin->hasPermission($createUsers));
331 | $this->assertFalse($user->hasPermission($createUsers));
332 | }
333 |
334 | public function test_revoke_permission_on_user()
335 | {
336 | $user = $this->createUser([
337 | 'name' => 'John Doe',
338 | ]);
339 |
340 | $createUsers = $this->createPermission([
341 | 'name' => 'users.create',
342 | 'label' => 'Create Users',
343 | ]);
344 |
345 | $user->grant($createUsers);
346 |
347 | $this->assertTrue($user->hasPermission($createUsers));
348 |
349 | $this->assertSame($createUsers, $user->revoke($createUsers));
350 |
351 | $this->assertFalse($user->hasPermission($createUsers));
352 | }
353 |
354 | public function test_revoke_multiple_permissions()
355 | {
356 | $user = $this->createUser([
357 | 'name' => 'John Doe',
358 | ]);
359 |
360 | $admin = $this->createRole([
361 | 'name' => 'administrator',
362 | 'label' => 'Admin',
363 | ]);
364 |
365 | $user->assignRole($admin);
366 |
367 | $createUsers = $this->createPermission([
368 | 'name' => 'users.create',
369 | 'label' => 'Create Users',
370 | ]);
371 |
372 | $editUsers = $this->createPermission([
373 | 'name' => 'users.edit',
374 | 'label' => 'Edit Users',
375 | ]);
376 |
377 | $admin->grant([$createUsers, $editUsers]);
378 |
379 | $this->assertTrue($admin->hasPermission($editUsers));
380 | $this->assertTrue($admin->hasPermission($createUsers));
381 |
382 | $this->assertTrue($user->hasPermission($editUsers));
383 | $this->assertTrue($user->hasPermission($createUsers));
384 |
385 | $this->assertCount(2, $admin->revoke([$createUsers, $editUsers]));
386 |
387 | $this->assertFalse($admin->hasPermission($editUsers));
388 | $this->assertFalse($admin->hasPermission($createUsers));
389 |
390 | $this->assertFalse($user->hasPermission($editUsers));
391 | $this->assertFalse($user->hasPermission($createUsers));
392 | }
393 |
394 | public function test_revoke_multiple_permissions_on_user()
395 | {
396 | $user = $this->createUser([
397 | 'name' => 'John Doe',
398 | ]);
399 |
400 | $createUsers = $this->createPermission([
401 | 'name' => 'users.create',
402 | 'label' => 'Create Users',
403 | ]);
404 |
405 | $editUsers = $this->createPermission([
406 | 'name' => 'users.edit',
407 | 'label' => 'Edit Users',
408 | ]);
409 |
410 | $user->grant([$createUsers, $editUsers]);
411 |
412 | $this->assertTrue($user->hasPermission($editUsers));
413 | $this->assertTrue($user->hasPermission($createUsers));
414 |
415 | $this->assertCount(2, $user->revoke([$createUsers, $editUsers, 'invalid']));
416 |
417 | $this->assertFalse($user->hasPermission($editUsers));
418 | $this->assertFalse($user->hasPermission($createUsers));
419 | }
420 |
421 | public function test_revoke_all()
422 | {
423 | $user = $this->createUser([
424 | 'name' => 'John Doe',
425 | ]);
426 |
427 | $createUsers = $this->createPermission([
428 | 'name' => 'users.create',
429 | 'label' => 'Create Users',
430 | ]);
431 |
432 | $editUsers = $this->createPermission([
433 | 'name' => 'users.edit',
434 | 'label' => 'Edit Users',
435 | ]);
436 |
437 | $admin = $this->createRole([
438 | 'name' => 'admin',
439 | 'label' => 'Administrator',
440 | ]);
441 |
442 | $admin->grant([$createUsers, $editUsers]);
443 |
444 | $user->assignRole($admin);
445 |
446 | $this->assertTrue($admin->hasPermissions([$createUsers, $editUsers]));
447 | $this->assertTrue($user->hasPermissions([$createUsers, $editUsers]));
448 |
449 | $admin->revokeAll();
450 |
451 | $this->assertFalse($admin->hasPermissions([$createUsers, $editUsers]));
452 | $this->assertFalse($admin->hasPermission('users.create'));
453 | $this->assertFalse($admin->hasPermission('users.edit'));
454 | }
455 |
456 | public function test_revoke_all_on_user()
457 | {
458 | $user = $this->createUser([
459 | 'name' => 'John Doe',
460 | ]);
461 |
462 | $createUsers = $this->createPermission([
463 | 'name' => 'users.create',
464 | 'label' => 'Create Users',
465 | ]);
466 |
467 | $editUsers = $this->createPermission([
468 | 'name' => 'users.edit',
469 | 'label' => 'Edit Users',
470 | ]);
471 |
472 | $user->grant([$createUsers, $editUsers]);
473 |
474 | $this->assertTrue($user->hasPermissions([$createUsers, $editUsers]));
475 |
476 | $user->revokeAll();
477 |
478 | $this->assertFalse($user->hasPermissions([$createUsers, $editUsers]));
479 | $this->assertFalse($user->hasPermission('users.create'));
480 | $this->assertFalse($user->hasPermission('users.edit'));
481 | }
482 |
483 | public function test_revoke_multiple_permissions_with_non_existent_permission()
484 | {
485 | $user = $this->createUser([
486 | 'name' => 'John Doe',
487 | ]);
488 |
489 | $admin = $this->createRole([
490 | 'name' => 'administrator',
491 | 'label' => 'Admin',
492 | ]);
493 |
494 | $user->assignRole($admin);
495 |
496 | $createUsers = $this->createPermission([
497 | 'name' => 'users.create',
498 | 'label' => 'Create Users',
499 | ]);
500 |
501 | $editUsers = $this->createPermission([
502 | 'name' => 'users.edit',
503 | 'label' => 'Edit Users',
504 | ]);
505 |
506 | $admin->grant([$createUsers, $editUsers]);
507 |
508 | $this->assertEquals(2, $admin->revoke([$createUsers, $editUsers, 'invalid'])->count());
509 | }
510 |
511 | public function test_has_permission()
512 | {
513 | $admin = $this->createRole([
514 | 'name' => 'administrator',
515 | 'label' => 'Admin',
516 | ]);
517 |
518 | $permission = $this->createPermission([
519 | 'name' => 'users.create',
520 | 'label' => 'Create Users',
521 | ]);
522 |
523 | $user = $this->createUser([
524 | 'name' => 'John Doe',
525 | ]);
526 |
527 | $this->assertFalse($user->hasPermission(null));
528 |
529 | $user->assignRole($admin);
530 |
531 | $admin->grant($permission);
532 |
533 | $this->assertTrue($user->hasPermission($permission));
534 | $this->assertTrue($user->hasPermission('users.create'));
535 | $this->assertFalse($user->hasPermission('non-existent'));
536 | }
537 |
538 | public function test_has_multiple_permissions()
539 | {
540 | $admin = $this->createRole([
541 | 'name' => 'administrator',
542 | 'label' => 'Admin',
543 | ]);
544 |
545 | $createUsers = $this->createPermission([
546 | 'name' => 'users.create',
547 | 'label' => 'Create Users',
548 | ]);
549 |
550 | $editUsers = $this->createPermission([
551 | 'name' => 'users.edit',
552 | 'label' => 'Edit Users',
553 | ]);
554 |
555 | $admin->grant([$createUsers, $editUsers]);
556 |
557 | $user = $this->createUser([
558 | 'name' => 'John Doe',
559 | ]);
560 |
561 | $this->assertFalse($user->hasPermission(null));
562 | $this->assertFalse($user->hasPermissions([]));
563 | $this->assertFalse($user->hasPermissions([null]));
564 | $this->assertFalse($user->hasPermissions(collect()));
565 |
566 | $user->assignRole($admin);
567 |
568 | $this->assertTrue($user->hasPermissions([$createUsers, $editUsers]));
569 | }
570 |
571 | public function test_does_not_have_permission()
572 | {
573 | $admin = $this->createRole([
574 | 'name' => 'administrator',
575 | 'label' => 'Admin',
576 | ]);
577 |
578 | $createUsers = $this->createPermission([
579 | 'name' => 'users.create',
580 | 'label' => 'Create Users',
581 | ]);
582 |
583 | $admin->grant($createUsers);
584 |
585 | $user = $this->createUser([
586 | 'name' => 'John Doe',
587 | ]);
588 |
589 | $this->assertTrue($user->doesNotHavePermission($createUsers));
590 | $this->assertFalse($user->hasPermission($createUsers));
591 | }
592 |
593 | public function test_does_not_have_permission_multiple()
594 | {
595 | $admin = $this->createRole([
596 | 'name' => 'administrator',
597 | 'label' => 'Admin',
598 | ]);
599 |
600 | $createUsers = $this->createPermission([
601 | 'name' => 'users.create',
602 | 'label' => 'Create Users',
603 | ]);
604 |
605 | $editUsers = $this->createPermission([
606 | 'name' => 'users.edit',
607 | 'label' => 'Edit Users',
608 | ]);
609 |
610 | $admin->grant($createUsers);
611 |
612 | $user = $this->createUser([
613 | 'name' => 'John Doe',
614 | ]);
615 |
616 | $user->assignRole($admin);
617 |
618 | $this->assertTrue($user->doesNotHavePermissions([$createUsers, $editUsers]));
619 | }
620 |
621 | public function test_has_any_permissions()
622 | {
623 | $admin = $this->createRole([
624 | 'name' => 'administrator',
625 | 'label' => 'Admin',
626 | ]);
627 |
628 | $createUsers = $this->createPermission([
629 | 'name' => 'users.create',
630 | 'label' => 'Create Users',
631 | ]);
632 |
633 | $editUsers = $this->createPermission([
634 | 'name' => 'users.edit',
635 | 'label' => 'Edit Users',
636 | ]);
637 |
638 | $nonGrantedPermission = $this->createPermission([
639 | 'name' => 'other',
640 | 'label' => 'Other Permission',
641 | ]);
642 |
643 | $admin->grant([$createUsers, $editUsers]);
644 |
645 | $user = $this->createUser([
646 | 'name' => 'John Doe',
647 | ]);
648 |
649 | $user->assignRole($admin);
650 |
651 | $this->assertTrue($user->hasAnyPermissions([$editUsers, $nonGrantedPermission]));
652 | $this->assertFalse($user->hasAnyPermissions([$nonGrantedPermission]));
653 | }
654 |
655 | public function test_role_has_permission()
656 | {
657 | $admin = $this->createRole([
658 | 'name' => 'administrator',
659 | 'label' => 'Admin',
660 | ]);
661 |
662 | $createUsers = $this->createPermission([
663 | 'name' => 'users.create',
664 | 'label' => 'Create Users',
665 | ]);
666 |
667 | $editUsers = $this->createPermission([
668 | 'name' => 'users.edit',
669 | 'label' => 'Edit Users',
670 | ]);
671 |
672 | $admin->grant($createUsers);
673 |
674 | $this->assertTrue($admin->hasPermission('users.create'));
675 | $this->assertTrue($admin->hasPermission($createUsers));
676 | $this->assertFalse($admin->hasPermission('non-existent'));
677 | $this->assertFalse($admin->hasPermission($editUsers));
678 | }
679 |
680 | public function test_role_has_permissions()
681 | {
682 | $admin = $this->createRole([
683 | 'name' => 'administrator',
684 | 'label' => 'Admin',
685 | ]);
686 |
687 | $createUsers = $this->createPermission([
688 | 'name' => 'users.create',
689 | 'label' => 'Create Users',
690 | ]);
691 |
692 | $editUsers = $this->createPermission([
693 | 'name' => 'users.edit',
694 | 'label' => 'Edit Users',
695 | ]);
696 |
697 | $deleteUsers = $this->createPermission([
698 | 'name' => 'users.destroy',
699 | 'label' => 'Delete Users',
700 | ]);
701 |
702 | $admin->grant([$createUsers, $editUsers]);
703 |
704 | $this->assertTrue($admin->hasPermissions([$createUsers, $editUsers]));
705 | $this->assertFalse($admin->hasPermissions([$createUsers, $editUsers, $deleteUsers]));
706 | }
707 |
708 | public function test_role_has_any_permissions()
709 | {
710 | $admin = $this->createRole([
711 | 'name' => 'administrator',
712 | 'label' => 'Admin',
713 | ]);
714 |
715 | $createUsers = $this->createPermission([
716 | 'name' => 'users.create',
717 | 'label' => 'Create Users',
718 | ]);
719 |
720 | $editUsers = $this->createPermission([
721 | 'name' => 'users.edit',
722 | 'label' => 'Edit Users',
723 | ]);
724 |
725 | $deleteUsers = $this->createPermission([
726 | 'name' => 'users.destroy',
727 | 'label' => 'Delete Users',
728 | ]);
729 |
730 | $admin->grant([$createUsers, $editUsers]);
731 |
732 | $this->assertTrue($admin->hasAnyPermissions([$createUsers, $editUsers, 'non-existent']));
733 | $this->assertFalse($admin->hasAnyPermissions(['non-existent', 'unknown', $deleteUsers]));
734 | }
735 |
736 | public function test_user_has_role()
737 | {
738 | $admin = $this->createRole([
739 | 'name' => 'administrator',
740 | 'label' => 'Admin',
741 | ]);
742 |
743 | $member = $this->createRole([
744 | 'name' => 'member',
745 | 'label' => 'Member',
746 | ]);
747 |
748 | $user = $this->createUser([
749 | 'name' => 'John Doe',
750 | ]);
751 |
752 | $this->assertFalse($user->hasRole(null));
753 | $this->assertFalse($user->hasRole(''));
754 |
755 | $user->assignRole($admin);
756 |
757 | $this->assertTrue($user->hasRole('administrator'));
758 | $this->assertTrue($user->hasRole($admin));
759 | $this->assertFalse($user->hasRole('non-existent'));
760 | $this->assertFalse($user->hasRole($member));
761 | }
762 |
763 | public function test_user_has_roles()
764 | {
765 | $admin = $this->createRole([
766 | 'name' => 'administrator',
767 | 'label' => 'Admin',
768 | ]);
769 |
770 | $member = $this->createRole([
771 | 'name' => 'member',
772 | 'label' => 'Member',
773 | ]);
774 |
775 | $guest = $this->createRole([
776 | 'name' => 'guest',
777 | 'label' => 'Guest',
778 | ]);
779 |
780 | $user = $this->createUser([
781 | 'name' => 'John Doe',
782 | ]);
783 |
784 | $this->assertFalse($user->hasRoles(null));
785 | $this->assertFalse($user->hasRoles([]));
786 | $this->assertFalse($user->hasRoles([null]));
787 | $this->assertFalse($user->hasRoles(collect()));
788 |
789 | $user->assignRole($admin);
790 | $user->assignRole($member);
791 |
792 | $this->assertTrue($user->hasRoles(['administrator', 'member']));
793 | $this->assertTrue($user->hasRoles([$admin, $member]));
794 | $this->assertFalse($user->hasRoles(['non-existent', $admin]));
795 | $this->assertFalse($user->hasRoles([$admin, $member, $guest]));
796 | }
797 |
798 | public function test_user_has_any_roles()
799 | {
800 | $admin = $this->createRole([
801 | 'name' => 'administrator',
802 | 'label' => 'Admin',
803 | ]);
804 |
805 | $member = $this->createRole([
806 | 'name' => 'member',
807 | 'label' => 'Member',
808 | ]);
809 |
810 | $guest = $this->createRole([
811 | 'name' => 'guest',
812 | 'label' => 'Guest',
813 | ]);
814 |
815 | $user = $this->createUser([
816 | 'name' => 'John Doe',
817 | ]);
818 |
819 | $user->assignRole($admin);
820 | $user->assignRole($member);
821 |
822 | $this->assertTrue($user->hasAnyRoles(['administrator', 'member', 'non-existent']));
823 | $this->assertTrue($user->hasAnyRoles([$admin, $member, 'non-existent']));
824 | $this->assertTrue($user->hasAnyRoles([$admin, $member, $guest]));
825 | }
826 |
827 | public function test_user_specific_permissions()
828 | {
829 | $user = $this->createUser([
830 | 'name' => 'John Doe',
831 | ]);
832 |
833 | $editUser = $this->createPermission([
834 | 'name' => 'users.edit.1',
835 | 'label' => 'Edit Specific User',
836 | ]);
837 |
838 | $user->permissions()->save($editUser);
839 |
840 | $this->assertTrue($user->hasPermission('users.edit.1'));
841 | $this->assertTrue($user->hasPermission($editUser));
842 | }
843 |
844 | public function test_granting_same_permissions()
845 | {
846 | $admin = $this->createRole([
847 | 'name' => 'administrator',
848 | 'label' => 'Admin',
849 | ]);
850 |
851 | $editUser = $this->createPermission([
852 | 'name' => 'users.edit.1',
853 | 'label' => 'Edit Specific User',
854 | ]);
855 |
856 | $this->assertInstanceOf(Authorization::permissionModel(), $admin->grant($editUser));
857 | $this->assertInstanceOf(Authorization::permissionModel(), $admin->grant($editUser));
858 | }
859 |
860 | public function test_revoking_same_permissions()
861 | {
862 | $admin = $this->createRole([
863 | 'name' => 'administrator',
864 | 'label' => 'Admin',
865 | ]);
866 |
867 | $editUser = $this->createPermission([
868 | 'name' => 'users.edit.1',
869 | 'label' => 'Edit Specific User',
870 | ]);
871 |
872 | $admin->grant($editUser);
873 |
874 | $this->assertInstanceOf(Authorization::permissionModel(), $admin->revoke($editUser));
875 | $this->assertInstanceOf(Authorization::permissionModel(), $admin->revoke($editUser));
876 | }
877 |
878 | public function test_permissions_are_cached_in_registrar()
879 | {
880 | $permissions = collect([
881 | $this->createPermission([
882 | 'name' => 'create',
883 | 'label' => 'Create',
884 | ]),
885 | $this->createPermission([
886 | 'name' => 'edit',
887 | 'label' => 'Edit',
888 | ]),
889 | ]);
890 |
891 | $keys = $permissions->map->id;
892 |
893 | $this->assertEquals($keys, app(PermissionRegistrar::class)->getPermissions()->map->getKey());
894 | $this->assertEquals($keys, cache(Authorization::cacheKey())->map->getKey());
895 | }
896 |
897 | public function test_permission_cache_is_flushed_when_permissions_are_created()
898 | {
899 | $p = $this->createPermission([
900 | 'name' => 'create',
901 | 'label' => 'Create',
902 | ]);
903 |
904 | $this->assertEquals($p->getKey(), app(PermissionRegistrar::class)->getPermissions()->first()->getKey());
905 | $this->assertEquals($p->getKey(), cache(Authorization::cacheKey())->first()->getKey());
906 |
907 | $this->createPermission([
908 | 'name' => 'edit',
909 | 'label' => 'Edit',
910 | ]);
911 |
912 | $this->assertNull(cache(Authorization::cacheKey()));
913 | }
914 |
915 | public function test_permission_cache_is_flushed_when_permissions_are_updated()
916 | {
917 | $p = $this->createPermission([
918 | 'name' => 'create',
919 | 'label' => 'Create',
920 | ]);
921 |
922 | $this->assertEquals($p->getKey(), app(PermissionRegistrar::class)->getPermissions()->first()->getKey());
923 |
924 | $p->update(['name' => 'edit', 'label' => 'Edit']);
925 |
926 | $this->assertNull(cache(Authorization::cacheKey()));
927 | }
928 |
929 | public function test_permission_cache_is_flushed_when_permissions_are_deleted()
930 | {
931 | $p = $this->createPermission([
932 | 'name' => 'create',
933 | 'label' => 'Create',
934 | ]);
935 |
936 | $this->assertEquals($p->getKey(), app(PermissionRegistrar::class)->getPermissions()->first()->getKey());
937 |
938 | $p->delete();
939 |
940 | $this->assertNull(cache(Authorization::cacheKey()));
941 | }
942 |
943 | public function test_permission_cache_is_flushed_when_permissions_are_added_to_role()
944 | {
945 | $p = $this->createPermission(['name' => 'create', 'label' => 'Create']);
946 |
947 | $r = $this->createRole(['name' => 'admin', 'label' => 'Administrator']);
948 |
949 | $this->assertEquals($p->getKey(), app(PermissionRegistrar::class)->getPermissions()->first()->getKey());
950 | $this->assertEquals($p->getKey(), cache(Authorization::cacheKey())->first()->getKey());
951 |
952 | $r->permissions()->save($p);
953 |
954 | $this->assertNull(cache(Authorization::cacheKey()));
955 | }
956 |
957 | public function test_user_does_not_have_permission_with_cached_permissions()
958 | {
959 | $user = $this->createUser(['name' => 'John Doe']);
960 |
961 | $permission = $this->createPermission(['name' => 'create', 'label' => 'Create']);
962 |
963 | $role = $this->createRole(['name' => 'admin', 'label' => 'Administrator']);
964 |
965 | // Attach the permission to the role.
966 | $role->permissions()->attach($permission);
967 |
968 | // Attach the role to the user.
969 | $user->roles()->attach($role);
970 |
971 | // User has permission.
972 | $this->assertTrue($user->hasPermission($permission));
973 | $this->assertTrue($user->hasPermission('create'));
974 |
975 | $this->assertEquals($permission->getKey(), app(PermissionRegistrar::class)->getPermissions()->first()->getKey());
976 | $this->assertEquals($permission->getKey(), cache(Authorization::cacheKey())->first()->getKey());
977 |
978 | // Detach the permission from the role.
979 | $role->permissions()->detach($permission);
980 |
981 | // User no longer has permission.
982 | $this->assertFalse($user->hasPermission($permission));
983 | $this->assertFalse($user->hasPermission('create'));
984 | }
985 |
986 | public function test_permissions_are_not_cached_when_disabled()
987 | {
988 | Authorization::disablePermissionCache();
989 |
990 | $permission = $this->createPermission(['name' => 'create', 'label' => 'Create']);
991 |
992 | $this->assertEquals($permission->getKey(), app(PermissionRegistrar::class)->getPermissions()->first()->getKey());
993 | $this->assertNull(cache(Authorization::cacheKey()));
994 | }
995 | }
996 |
--------------------------------------------------------------------------------
/tests/Stubs/User.php:
--------------------------------------------------------------------------------
1 | increments('id');
23 | $table->string('name');
24 | $table->timestamps();
25 | });
26 | }
27 |
28 | /**
29 | * {@inheritdoc}
30 | */
31 | protected function getPackageProviders($app)
32 | {
33 | return [
34 | AuthorizationServiceProvider::class,
35 | ];
36 | }
37 |
38 | /**
39 | * Returns a new stub user instance.
40 | *
41 | * @param array $attributes
42 | *
43 | * @return User
44 | */
45 | protected function createUser($attributes = [])
46 | {
47 | return User::create($attributes);
48 | }
49 |
50 | /**
51 | * Returns a new role instance.
52 | *
53 | * @param array $attributes
54 | *
55 | * @return \DirectoryTree\Authorization\Role
56 | */
57 | protected function createRole($attributes = [])
58 | {
59 | $role = Authorization::role();
60 |
61 | return $role::create($attributes);
62 | }
63 |
64 | /**
65 | * Returns a new permission instance.
66 | *
67 | * @param array $attributes
68 | *
69 | * @return \DirectoryTree\Authorization\Permission
70 | */
71 | protected function createPermission($attributes = [])
72 | {
73 | $permission = Authorization::permission();
74 |
75 | return $permission::create($attributes);
76 | }
77 | }
78 |
--------------------------------------------------------------------------------