Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[V6] Full uuid/guid/ulid support #2089

Merged
merged 2 commits into from
Feb 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/Models/Permission.php
Original file line number Diff line number Diff line change
Expand Up @@ -104,13 +104,13 @@ public static function findByName(string $name, $guardName = null): PermissionCo
/**
* Find a permission by its id (and optionally guardName).
*
* @param int $id
* @param int|string $id
* @param string|null $guardName
* @return \Spatie\Permission\Contracts\Permission
*
* @throws \Spatie\Permission\Exceptions\PermissionDoesNotExist
*/
public static function findById(int $id, $guardName = null): PermissionContract
public static function findById($id, $guardName = null): PermissionContract
{
$guardName = $guardName ?? Guard::getDefaultName(static::class);
$permission = static::getPermission([(new static())->getKeyName() => $id, 'guard_name' => $guardName]);
Expand Down
4 changes: 2 additions & 2 deletions src/Models/Role.php
Original file line number Diff line number Diff line change
Expand Up @@ -108,11 +108,11 @@ public static function findByName(string $name, $guardName = null): RoleContract
/**
* Find a role by its id (and optionally guardName).
*
* @param int $id
* @param int|string $id
* @param string|null $guardName
* @return \Spatie\Permission\Contracts\Role|\Spatie\Permission\Models\Role
*/
public static function findById(int $id, $guardName = null): RoleContract
public static function findById($id, $guardName = null): RoleContract
{
$guardName = $guardName ?? Guard::getDefaultName(static::class);

Expand Down
21 changes: 21 additions & 0 deletions src/PermissionRegistrar.php
Original file line number Diff line number Diff line change
Expand Up @@ -384,4 +384,25 @@ private function hydrateRolesCache()

$this->permissions['roles'] = [];
}

public static function isUid($value)
{
if (! is_string($value) || empty(trim($value))) {
return false;
}

// check if is UUID/GUID
$uid = preg_match('/^[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}$/iD', $value) > 0;
if ($uid) {
return true;
}

// check if is ULID
$ulid = 26 == strlen($value) && 26 == strspn($value, '0123456789ABCDEFGHJKMNPQRSTVWXYZabcdefghjkmnpqrstvwxyz') && $value[0] <= '7';
if ($ulid) {
return true;
}

return false;
}
}
10 changes: 5 additions & 5 deletions src/Traits/HasPermissions.php
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ protected function convertToPermissionModels($permissions): array
if ($permission instanceof Permission) {
return $permission;
}
$method = is_string($permission) ? 'findByName' : 'findById';
$method = is_string($permission) && ! PermissionRegistrar::isUid($permission) ? 'findByName' : 'findById';

return $this->getPermissionClass()->{$method}($permission, $this->getDefaultGuardName());
}, Arr::wrap($permissions));
Expand All @@ -152,14 +152,14 @@ public function filterPermission($permission, $guardName = null)
{
$permissionClass = $this->getPermissionClass();

if (is_string($permission)) {
if (is_string($permission) && ! PermissionRegistrar::isUid($permission)) {
$permission = $permissionClass->findByName(
$permission,
$guardName ?? $this->getDefaultGuardName()
);
}

if (is_int($permission)) {
if (is_int($permission) || is_string($permission)) {
drbyte marked this conversation as resolved.
Show resolved Hide resolved
$permission = $permissionClass->findById(
$permission,
$guardName ?? $this->getDefaultGuardName()
Expand Down Expand Up @@ -204,7 +204,7 @@ protected function hasWildcardPermission($permission, $guardName = null): bool
{
$guardName = $guardName ?? $this->getDefaultGuardName();

if (is_int($permission)) {
if (is_int($permission) || PermissionRegistrar::isUid($permission)) {
$permission = $this->getPermissionClass()->findById($permission, $guardName);
}

Expand Down Expand Up @@ -449,7 +449,7 @@ protected function getStoredPermission($permissions)
{
$permissionClass = $this->getPermissionClass();

if (is_numeric($permissions)) {
if (is_numeric($permissions) || PermissionRegistrar::isUid($permissions)) {
return $permissionClass->findById($permissions, $this->getDefaultGuardName());
}

Expand Down
8 changes: 4 additions & 4 deletions src/Traits/HasRoles.php
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ public function scopeRole(Builder $query, $roles, $guard = null): Builder
return $role;
}

$method = is_numeric($role) ? 'findById' : 'findByName';
$method = is_numeric($role) || PermissionRegistrar::isUid($role) ? 'findById' : 'findByName';

return $this->getRoleClass()->{$method}($role, $guard ?: $this->getDefaultGuardName());
}, Arr::wrap($roles));
Expand Down Expand Up @@ -195,13 +195,13 @@ public function hasRole($roles, string $guard = null): bool
$roles = $this->convertPipeToArray($roles);
}

if (is_string($roles)) {
if (is_string($roles) && ! PermissionRegistrar::isUid($roles)) {
return $guard
? $this->roles->where('guard_name', $guard)->contains('name', $roles)
: $this->roles->contains('name', $roles);
}

if (is_int($roles)) {
if (is_int($roles) || is_string($roles)) {
$roleClass = $this->getRoleClass();
$key = (new $roleClass())->getKeyName();

Expand Down Expand Up @@ -325,7 +325,7 @@ protected function getStoredRole($role): Role
{
$roleClass = $this->getRoleClass();

if (is_numeric($role)) {
if (is_numeric($role) || PermissionRegistrar::isUid($role)) {
return $roleClass->findById($role, $this->getDefaultGuardName());
}

Expand Down
27 changes: 27 additions & 0 deletions tests/HasPermissionsWithCustomModelsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,31 @@ public function it_can_use_custom_fields_from_cache()

$this->assertSame(0, count(DB::getQueryLog()));
}

/** @test */
public function it_can_scope_users_using_a_int()
{
// Skipped because custom model uses uuid,
// replacement "it_can_scope_users_using_a_uuid"
$this->assertTrue(true);
}

/** @test */
public function it_can_scope_users_using_a_uuid()
{
$uuid1 = $this->testUserPermission->getKey();
$uuid2 = app(Permission::class)::where('name', 'edit-news')->first()->getKey();

$user1 = User::create(['email' => '[email protected]']);
$user2 = User::create(['email' => '[email protected]']);
$user1->givePermissionTo([$uuid1, $uuid2]);
$this->testUserRole->givePermissionTo($uuid1);
$user2->assignRole('testRole');

$scopedUsers1 = User::permission($uuid1)->get();
$scopedUsers2 = User::permission([$uuid2])->get();

$this->assertEquals(2, $scopedUsers1->count());
$this->assertEquals(1, $scopedUsers2->count());
}
}
20 changes: 20 additions & 0 deletions tests/Permission.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,24 @@ class Permission extends \Spatie\Permission\Models\Permission
'permission_test_id',
'name',
];

protected static function boot()
{
parent::boot();
static::creating(function ($model) {
if (empty($model->{$model->getKeyName()})) {
$model->{$model->getKeyName()} = \Str::uuid()->toString();
}
});
}

public function getIncrementing()
{
return false;
}

public function getKeyType()
{
return 'string';
}
}
51 changes: 51 additions & 0 deletions tests/PermissionRegistarTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php

namespace Spatie\Permission\Test;

use Spatie\Permission\PermissionRegistrar;

class PermissionRegistarTest extends TestCase
{
/** @test */
public function it_can_check_uids()
{
$uids = [
// UUIDs
'00000000-0000-0000-0000-000000000000',
'9be37b52-e1fa-4e86-b65f-cbfcbedde838',
'fc458041-fb21-4eea-a04b-b55c87a7224a',
'78144b52-a889-11ed-afa1-0242ac120002',
'78144f4e-a889-11ed-afa1-0242ac120002',
// GUIDs
'4b8590bb-90a2-4f38-8dc9-70e663a5b0e5',
'A98C5A1E-A742-4808-96FA-6F409E799937',
'1f01164a-98e9-4246-93ec-7941aefb1da6',
'91b73d20-89e6-46b0-b39b-632706cc3ed7',
'0df4a5b8-7c2e-484f-ad1d-787d1b83aacc',
// ULIDs
'01GRVB3DREB63KNN4G2QVV99DF',
'01GRVB3DRECY317SJCJ6DMTFCA',
'01GRVB3DREGGPBXNH1M24GX1DS',
'01GRVB3DRESRM2K9AVQSW1JCKA',
'01GRVB3DRES5CQ31PB24MP4CSV',
];

$not_uids = [
'9be37b52-e1fa',
'9be37b52-e1fa-4e86',
'9be37b52-e1fa-4e86-b65f',
'01GRVB3DREB63KNN4G2',
'TEST STRING',
'00-00-00-00-00-00',
'91GRVB3DRES5CQ31PB24MP4CSV',
];

foreach ($uids as $uid) {
$this->assertTrue(PermissionRegistrar::isUid($uid));
}

foreach ($not_uids as $not_uid) {
$this->assertFalse(PermissionRegistrar::isUid($not_uid));
}
}
}
20 changes: 20 additions & 0 deletions tests/Role.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,24 @@ class Role extends \Spatie\Permission\Models\Role
'role_test_id',
'name',
];

protected static function boot()
{
parent::boot();
static::creating(function ($model) {
if (empty($model->{$model->getKeyName()})) {
$model->{$model->getKeyName()} = \Str::uuid()->toString();
}
});
}

public function getIncrementing()
{
return false;
}

public function getKeyType()
{
return 'string';
}
}
6 changes: 6 additions & 0 deletions tests/TestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -159,13 +159,19 @@ private function prepareMigration()
'(\'id\'); // role id',
'references(\'id\') // permission id',
'references(\'id\') // role id',
'bigIncrements',
'unsignedBigInteger(PermissionRegistrar::$pivotRole)',
'unsignedBigInteger(PermissionRegistrar::$pivotPermission)',
],
[
'CreatePermissionCustomTables',
'(\'permission_test_id\');',
'(\'role_test_id\');',
'references(\'permission_test_id\')',
'references(\'role_test_id\')',
'uuid',
'uuid(PermissionRegistrar::$pivotRole)->nullable(false)',
'uuid(PermissionRegistrar::$pivotPermission)->nullable(false)',
],
file_get_contents(__DIR__.'/../database/migrations/create_permission_tables.php.stub')
);
Expand Down