Skip to content

Commit 877e2c7

Browse files
marklawntalkdrbyte
andauthored
Middleware: support enums in role/permission middleware (#2813)
* Allow middleware to handle enum based permission or role --------- Co-authored-by: Chris Brown <[email protected]>
1 parent 5e87096 commit 877e2c7

File tree

4 files changed

+158
-10
lines changed

4 files changed

+158
-10
lines changed

src/Middleware/PermissionMiddleware.php

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,7 @@ public function handle($request, Closure $next, $permission, $guard = null)
2828
throw UnauthorizedException::missingTraitHasRoles($user);
2929
}
3030

31-
$permissions = is_array($permission)
32-
? $permission
33-
: explode('|', $permission);
31+
$permissions = explode('|', self::parsePermissionsToString($permission));
3432

3533
if (! $user->canAny($permissions)) {
3634
throw UnauthorizedException::forPermissions($permissions);
@@ -42,15 +40,42 @@ public function handle($request, Closure $next, $permission, $guard = null)
4240
/**
4341
* Specify the permission and guard for the middleware.
4442
*
45-
* @param array|string $permission
43+
* @param array|string|\BackedEnum $permission
4644
* @param string|null $guard
4745
* @return string
4846
*/
4947
public static function using($permission, $guard = null)
5048
{
51-
$permissionString = is_string($permission) ? $permission : implode('|', $permission);
49+
// Convert Enum to its value if an Enum is passed
50+
if ($permission instanceof \BackedEnum) {
51+
$permission = $permission->value;
52+
}
53+
54+
$permissionString = self::parsePermissionsToString($permission);
55+
5256
$args = is_null($guard) ? $permissionString : "$permissionString,$guard";
5357

5458
return static::class.':'.$args;
5559
}
60+
61+
/**
62+
* Convert array or string of permissions to string representation.
63+
*
64+
* @return string
65+
*/
66+
protected static function parsePermissionsToString(array|string|\BackedEnum $permission)
67+
{
68+
// Convert Enum to its value if an Enum is passed
69+
if ($permission instanceof \BackedEnum) {
70+
$permission = $permission->value;
71+
}
72+
73+
if (is_array($permission)) {
74+
$permission = array_map(fn ($r) => $r instanceof \BackedEnum ? $r->value : $r, $permission);
75+
76+
return implode('|', $permission);
77+
}
78+
79+
return (string) $permission;
80+
}
5681
}

src/Middleware/RoleMiddleware.php

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,7 @@ public function handle($request, Closure $next, $role, $guard = null)
2828
throw UnauthorizedException::missingTraitHasRoles($user);
2929
}
3030

31-
$roles = is_array($role)
32-
? $role
33-
: explode('|', $role);
31+
$roles = explode('|', self::parseRolesToString($role));
3432

3533
if (! $user->hasAnyRole($roles)) {
3634
throw UnauthorizedException::forRoles($roles);
@@ -42,15 +40,37 @@ public function handle($request, Closure $next, $role, $guard = null)
4240
/**
4341
* Specify the role and guard for the middleware.
4442
*
45-
* @param array|string $role
43+
* @param array|string|\BackedEnum $role
4644
* @param string|null $guard
4745
* @return string
4846
*/
4947
public static function using($role, $guard = null)
5048
{
51-
$roleString = is_string($role) ? $role : implode('|', $role);
49+
$roleString = self::parseRolesToString($role);
50+
5251
$args = is_null($guard) ? $roleString : "$roleString,$guard";
5352

5453
return static::class.':'.$args;
5554
}
55+
56+
/**
57+
* Convert array or string of roles to string representation.
58+
*
59+
* @return string
60+
*/
61+
protected static function parseRolesToString(array|string|\BackedEnum $role)
62+
{
63+
// Convert Enum to its value if an Enum is passed
64+
if ($role instanceof \BackedEnum) {
65+
$role = $role->value;
66+
}
67+
68+
if (is_array($role)) {
69+
$role = array_map(fn ($r) => $r instanceof \BackedEnum ? $r->value : $r, $role);
70+
71+
return implode('|', $role);
72+
}
73+
74+
return (string) $role;
75+
}
5676
}

tests/PermissionMiddlewareTest.php

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,4 +434,55 @@ public function the_middleware_can_be_created_with_static_using_method()
434434
PermissionMiddleware::using(['edit-articles', 'edit-news'])
435435
);
436436
}
437+
438+
/**
439+
* @test
440+
*
441+
* @requires PHP >= 8.1
442+
*/
443+
#[RequiresPhp('>= 8.1')]
444+
#[Test]
445+
public function the_middleware_can_handle_enum_based_permissions_with_static_using_method()
446+
{
447+
$this->assertSame(
448+
'Spatie\Permission\Middleware\PermissionMiddleware:view articles',
449+
PermissionMiddleware::using(TestModels\TestRolePermissionsEnum::VIEWARTICLES)
450+
);
451+
$this->assertEquals(
452+
'Spatie\Permission\Middleware\PermissionMiddleware:view articles,my-guard',
453+
PermissionMiddleware::using(TestModels\TestRolePermissionsEnum::VIEWARTICLES, 'my-guard')
454+
);
455+
$this->assertEquals(
456+
'Spatie\Permission\Middleware\PermissionMiddleware:view articles|edit articles',
457+
PermissionMiddleware::using([TestModels\TestRolePermissionsEnum::VIEWARTICLES, TestModels\TestRolePermissionsEnum::EDITARTICLES])
458+
);
459+
}
460+
461+
/**
462+
* @test
463+
*
464+
* @requires PHP >= 8.1
465+
*/
466+
#[RequiresPhp('>= 8.1')]
467+
#[Test]
468+
public function the_middleware_can_handle_enum_based_permissions_with_handle_method()
469+
{
470+
app(Permission::class)->create(['name' => TestModels\TestRolePermissionsEnum::VIEWARTICLES->value]);
471+
app(Permission::class)->create(['name' => TestModels\TestRolePermissionsEnum::EDITARTICLES->value]);
472+
473+
Auth::login($this->testUser);
474+
$this->testUser->givePermissionTo(TestModels\TestRolePermissionsEnum::VIEWARTICLES);
475+
476+
$this->assertEquals(
477+
200,
478+
$this->runMiddleware($this->permissionMiddleware, TestModels\TestRolePermissionsEnum::VIEWARTICLES)
479+
);
480+
481+
$this->testUser->givePermissionTo(TestModels\TestRolePermissionsEnum::EDITARTICLES);
482+
483+
$this->assertEquals(
484+
200,
485+
$this->runMiddleware($this->permissionMiddleware, [TestModels\TestRolePermissionsEnum::VIEWARTICLES, TestModels\TestRolePermissionsEnum::EDITARTICLES])
486+
);
487+
}
437488
}

tests/RoleMiddlewareTest.php

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use InvalidArgumentException;
1010
use Laravel\Passport\Passport;
1111
use PHPUnit\Framework\Attributes\Test;
12+
use Spatie\Permission\Contracts\Role;
1213
use Spatie\Permission\Exceptions\UnauthorizedException;
1314
use Spatie\Permission\Middleware\RoleMiddleware;
1415
use Spatie\Permission\Tests\TestModels\UserWithoutHasRoles;
@@ -366,4 +367,55 @@ public function the_middleware_can_be_created_with_static_using_method()
366367
RoleMiddleware::using(['testAdminRole', 'anotherRole'])
367368
);
368369
}
370+
371+
/**
372+
* @test
373+
*
374+
* @requires PHP >= 8.1
375+
*/
376+
#[RequiresPhp('>= 8.1')]
377+
#[Test]
378+
public function the_middleware_can_handle_enum_based_roles_with_static_using_method()
379+
{
380+
$this->assertSame(
381+
'Spatie\Permission\Middleware\RoleMiddleware:writer',
382+
RoleMiddleware::using(TestModels\TestRolePermissionsEnum::WRITER)
383+
);
384+
$this->assertEquals(
385+
'Spatie\Permission\Middleware\RoleMiddleware:writer,my-guard',
386+
RoleMiddleware::using(TestModels\TestRolePermissionsEnum::WRITER, 'my-guard')
387+
);
388+
$this->assertEquals(
389+
'Spatie\Permission\Middleware\RoleMiddleware:writer|editor',
390+
RoleMiddleware::using([TestModels\TestRolePermissionsEnum::WRITER, TestModels\TestRolePermissionsEnum::EDITOR])
391+
);
392+
}
393+
394+
/**
395+
* @test
396+
*
397+
* @requires PHP >= 8.1
398+
*/
399+
#[RequiresPhp('>= 8.1')]
400+
#[Test]
401+
public function the_middleware_can_handle_enum_based_roles_with_handle_method()
402+
{
403+
app(Role::class)->create(['name' => TestModels\TestRolePermissionsEnum::WRITER->value]);
404+
app(Role::class)->create(['name' => TestModels\TestRolePermissionsEnum::EDITOR->value]);
405+
406+
Auth::login($this->testUser);
407+
$this->testUser->assignRole(TestModels\TestRolePermissionsEnum::WRITER);
408+
409+
$this->assertEquals(
410+
200,
411+
$this->runMiddleware($this->roleMiddleware, TestModels\TestRolePermissionsEnum::WRITER)
412+
);
413+
414+
$this->testUser->assignRole(TestModels\TestRolePermissionsEnum::EDITOR);
415+
416+
$this->assertEquals(
417+
200,
418+
$this->runMiddleware($this->roleMiddleware, [TestModels\TestRolePermissionsEnum::WRITER, TestModels\TestRolePermissionsEnum::EDITOR])
419+
);
420+
}
369421
}

0 commit comments

Comments
 (0)