diff --git a/README.md b/README.md index acb8db7..edeea73 100644 --- a/README.md +++ b/README.md @@ -28,17 +28,24 @@ This is the contents of the published config file: declare(strict_types=1); return [ + /** + * You can add as many guards as you want with as many role names as you want, + * as long as super admin and admin are required. + * + * role_names.*.super_admin is required + * role_names.*.admin is required + */ 'role_names' => [ + // keyed by guard name 'web' => [ - 'super_admin' => 'super_admin', - 'admin' => 'admin', + // required this cannot rename or delete or modify permissions + 'super_admin' => 'super_admin', // no permission attached to this role, but it always skips gate checks + 'admin' => 'admin', // all permissions attached to this role + + // as many as you want, below it can edit permissions but cannot rename or delete role names + // sample 'user' => 'user', ], ], - 'extra_role_names' => [ - // 'web' => [ - // 'user' => 'user', - // ], - ], 'seeders' => [ 'roles' => \Lloricode\FilamentSpatieLaravelPermissionPlugin\Database\Seeders\DefaultRoleSeeder::class, @@ -47,6 +54,8 @@ return [ 'translated' => false, ]; + + ``` ## Usage diff --git a/config/filament-permission.php b/config/filament-permission.php index 136cfbc..5366bd3 100644 --- a/config/filament-permission.php +++ b/config/filament-permission.php @@ -3,17 +3,24 @@ declare(strict_types=1); return [ + /** + * You can add as many guards as you want with as many role names as you want, + * as long as super admin and admin are required. + * + * role_names.*.super_admin is required + * role_names.*.admin is required + */ 'role_names' => [ + // keyed by guard name 'web' => [ - 'super_admin' => 'super_admin', - 'admin' => 'admin', + // required this cannot rename or delete or modify permissions + 'super_admin' => 'super_admin', // no permission attached to this role, but it always skips gate checks + 'admin' => 'admin', // all permissions attached to this role + + // as many as you want, below it can edit permissions but cannot rename or delete role names + // sample 'user' => 'user', ], ], - 'extra_role_names' => [ - // 'web' => [ - // 'user' => 'user', - // ], - ], 'seeders' => [ 'roles' => \Lloricode\FilamentSpatieLaravelPermissionPlugin\Database\Seeders\DefaultRoleSeeder::class, diff --git a/src/Actions/EditRoleAction.php b/src/Actions/EditRoleAction.php index 625235c..2679bf6 100644 --- a/src/Actions/EditRoleAction.php +++ b/src/Actions/EditRoleAction.php @@ -19,7 +19,7 @@ public function execute(RoleContract & Model $role, RoleData $roleData): RoleCon abort(400, trans('Cannot update this role.')); } - $roleNames = PermissionConfig::extraRoleNamesByGuardName($roleData->guard_name); + $roleNames = PermissionConfig::roleNamesByGuardName($roleData->guard_name); $isExtraRole = in_array($role->name, $roleNames, true); diff --git a/src/Config/PermissionConfig.php b/src/Config/PermissionConfig.php index 6ae78f3..e7d7885 100644 --- a/src/Config/PermissionConfig.php +++ b/src/Config/PermissionConfig.php @@ -15,147 +15,43 @@ public static function defaultGuardName(): string public static function superAdmin(?string $guardName = null): string { - $guardName ??= self::defaultGuardName(); - - return ConfigFacade::string('filament-permission.role_names.' . $guardName . '.super_admin'); + return self::roleName('super_admin', $guardName); } public static function admin(?string $guardName = null): string { - $guardName ??= self::defaultGuardName(); - - return ConfigFacade::string('filament-permission.role_names.' . $guardName . '.admin'); + return self::roleName('admin', $guardName); } - public static function extraRole(string $roleName, ?string $guardName = null): string + public static function roleName(string $roleKey, ?string $guardName = null): string { - if (blank(self::extraRoleNames())) { - abort(500, 'No extra roles found in config/filament-permission.php'); - } - $guardName ??= self::defaultGuardName(); - return ConfigFacade::string('filament-permission.extra_role_names.' . $guardName . '.' . $roleName); + return ConfigFacade::string('filament-permission.role_names.' . $guardName . '.' . $roleKey); } /** * @return array> */ - public static function roleNames(): array + public static function roleNamesGroupByGuardName(): array { return ConfigFacade::array('filament-permission.role_names'); } - /** - * @return array> - */ - public static function extraRoleNames(): array - { - return ConfigFacade::array('filament-permission.extra_role_names', []); - } - - /** - * @return array> - */ - public static function allRoleNamesGroupByGuardName(): array - { - self::checkNoSameRoleNameOnExtra(); - - $roles = self::roleNames(); - $extraRoles = self::extraRoleNames(); - - return array_merge_recursive($roles, $extraRoles); - } - /** * @return array */ - public static function allRoleNames(?string $guardName = null): array - { - $data = collect(self::allRoleNamesGroupByGuardName()); - if ($guardName === null) { - return $data->flatten()->unique()->values()->toArray(); - } - - return collect($data->get($guardName))->flatten()->unique()->values()->toArray(); - } - - public static function allGuardNames(): array - { - $extraRoles = self::extraRoleNames(); - $roles = self::roleNames(); - - return collect($extraRoles)->keys() - ->merge(collect($roles)->keys()) - ->unique() - ->toArray(); - } - - /** - * @return array - */ public static function roleNamesByGuardName(?string $guardName = null): array { - $data = collect(self::roleNames()); - - if ($guardName === null) { - return $data->flatten()->unique()->values()->toArray(); - } - - return collect($data->get($guardName))->flatten()->unique()->values()->toArray(); - - } - - /** - * @return array - */ - public static function extraRoleNamesByGuardName(?string $guardName = null): array - { - $data = collect(self::extraRoleNames()); - - if ($guardName === null) { - return $data->flatten()->unique()->values()->toArray(); - } - - return collect($data->get($guardName))->flatten()->unique()->values()->toArray(); - } - - public static function checkNoSameRoleNameOnExtra(): void - { - self::checkDefaultGuardNameExist(); - $extraRoles = self::extraRoleNames(); - - if (blank($extraRoles)) { - return; - } - - foreach (self::roleNames() as $guardName => $guardRoles) { - - foreach ($guardRoles as $role) { - if (in_array($role, $extraRoles[$guardName], true)) { - abort(500, 'The extra_role name "' . $role . '" is already defined in role_names in guard "' . $guardName . '".'); - } - } - } - + return self::roleNamesGroupByGuardName()[$guardName ?? self::defaultGuardName()]; } - public static function checkDefaultGuardNameExist(): void - { - - $guardNames = self::allGuardNames(); - $authGuardNames = array_keys(config('auth.guards')); - - $invalidGuardNames = []; - foreach ($guardNames as $guardName) { - if (! in_array($guardName, $authGuardNames, true)) { - $invalidGuardNames[] = $guardName; - } - } - - if (filled($invalidGuardNames)) { - abort(500, 'Guard name "' . implode('", "', $invalidGuardNames) . '" is not defined in config/auth.php.'); - - } - } + // /** + // * @return array + // */ + // public static function guardNames(): array + // { + // return collect(self::roleNamesGroupByGuardName())->keys() + // ->toArray(); + // } } diff --git a/src/Database/Seeders/DefaultRoleSeeder.php b/src/Database/Seeders/DefaultRoleSeeder.php index 562d941..17eeefd 100644 --- a/src/Database/Seeders/DefaultRoleSeeder.php +++ b/src/Database/Seeders/DefaultRoleSeeder.php @@ -21,7 +21,7 @@ public function __construct( */ public function run(): void { - foreach (PermissionConfig::allRoleNamesGroupByGuardName() as $guardName => $roleNames) { + foreach (PermissionConfig::roleNamesGroupByGuardName() as $guardName => $roleNames) { foreach ($roleNames as $roleName) { $role = $this->roleContract->findOrCreate( diff --git a/src/Policies/RolePolicy.php b/src/Policies/RolePolicy.php index 4ed26d5..4b80a68 100644 --- a/src/Policies/RolePolicy.php +++ b/src/Policies/RolePolicy.php @@ -19,11 +19,10 @@ public function viewAny(User $user): bool public function view(User $user, RoleContract $role): bool { - if (in_array($role->name, PermissionConfig::extraRoleNamesByGuardName($role->guard_name), true)) { - return true; - } - - if (in_array($role->name, PermissionConfig::roleNamesByGuardName($role->guard_name), true)) { + if (in_array($role->name, [ + PermissionConfig::superAdmin($role->guard_name), + PermissionConfig::admin($role->guard_name), + ], true)) { return false; } @@ -37,7 +36,10 @@ public function create(User $user): bool public function update(User $user, RoleContract $role): bool { - if (in_array($role->name, PermissionConfig::roleNamesByGuardName($role->guard_name), true)) { + if (in_array($role->name, [ + PermissionConfig::superAdmin($role->guard_name), + PermissionConfig::admin($role->guard_name), + ], true)) { return false; } @@ -46,7 +48,11 @@ public function update(User $user, RoleContract $role): bool public function delete(User $user, RoleContract $role): bool { - if (in_array($role->name, PermissionConfig::allRoleNames($role->guard_name), true)) { + if (in_array( + $role->name, + PermissionConfig::roleNamesByGuardName($role->guard_name), + true + )) { return false; } diff --git a/src/Resources/RoleResource.php b/src/Resources/RoleResource.php index 2b40f0f..09e6fcb 100644 --- a/src/Resources/RoleResource.php +++ b/src/Resources/RoleResource.php @@ -51,7 +51,7 @@ public static function form(Form $form): Form return in_array( $record->name, - PermissionConfig::extraRoleNamesByGuardName($record->guard_name), + PermissionConfig::roleNamesByGuardName($record->guard_name), true ); }; @@ -79,7 +79,7 @@ public static function form(Form $form): Form $guards ->mapWithKeys(fn (string $guardName) => [$guardName => $guardName]) ) - ->default(config('auth.defaults.guard')) + ->default(PermissionConfig::defaultGuardName()) ->reactive(), ]), ]), diff --git a/src/Resources/RoleResource/Schema/PermissionSchema.php b/src/Resources/RoleResource/Schema/PermissionSchema.php index af63ec1..e21353c 100644 --- a/src/Resources/RoleResource/Schema/PermissionSchema.php +++ b/src/Resources/RoleResource/Schema/PermissionSchema.php @@ -21,7 +21,7 @@ final class PermissionSchema public static function schema(?string $guardName): array { - if ($guardName === null) { + if (blank($guardName)) { return [ Forms\Components\Placeholder::make(trans('Select guard name first before selecting permissions')), ]; diff --git a/tests/Actions/EditRoleActionTest.php b/tests/Actions/EditRoleActionTest.php index 491d1c6..011aff7 100644 --- a/tests/Actions/EditRoleActionTest.php +++ b/tests/Actions/EditRoleActionTest.php @@ -16,14 +16,14 @@ it('can not edit defaults', function () { /** @var array $roles */ - $roles = app(RoleContract::class)::whereIn('name', PermissionConfig::allRoleNames())->get(); + $roles = app(RoleContract::class)::whereIn('name', PermissionConfig::roleNamesByGuardName())->get(); $action = app(EditRoleAction::class); foreach ($roles as $role) { try { - $action->execute($role, new RoleData(name: fake()->word(), guard_name: null, permissions: [])); + $action->execute($role, new RoleData(name: fake()->word(), permissions: [], guard_name: null)); assertTrue(false); } catch (\Exception $e) { diff --git a/tests/Config/PermissionConfigTest.php b/tests/Config/PermissionConfigTest.php deleted file mode 100644 index 493472f..0000000 --- a/tests/Config/PermissionConfigTest.php +++ /dev/null @@ -1,197 +0,0 @@ - 'default_guard', - 'auth.guards' => [ - 'default_guard' => [ - 'driver' => 'session', - 'provider' => 'users', - ], - 'default_guard2' => [ - 'driver' => 'session', - 'provider' => 'users', - ], - ], - - 'filament-permission.role_names' => [ - 'default_guard' => [ - 'super_admin' => 'super_admin', - 'admin' => 'admin', - ], - 'default_guard2' => [ - 'super_admin' => 'super_admin', - 'admin' => 'admin', - 'super_admin2' => 'super_admin2', - 'admin2' => 'admin2', - ], - ], - 'filament-permission.extra_role_names' => [ - 'default_guard' => [ - 'extra_role' => 'extra_role', - ], - 'default_guard2' => [ - 'extra_role' => 'extra_role', - 'extra_role2' => 'extra_role2', - ], - ], - ]); -}); - -test('default guard', function () { - assertSame('default_guard', PermissionConfig::defaultGuardName()); -}); - -test('get super admin role name', function () { - assertSame('super_admin', PermissionConfig::superAdmin()); -}); - -test('get admin role name', function () { - assertSame('admin', PermissionConfig::admin()); -}); - -test('get extra role name', function () { - assertSame('extra_role', PermissionConfig::extraRole('extra_role')); -}); - -test('get all role names', function () { - assertSame([ - 'default_guard' => [ - 'super_admin' => 'super_admin', - 'admin' => 'admin', - ], - 'default_guard2' => [ - 'super_admin' => 'super_admin', - 'admin' => 'admin', - 'super_admin2' => 'super_admin2', - 'admin2' => 'admin2', - ], - ], PermissionConfig::roleNames()); -}); - -test('get all extra role names', function () { - assertSame([ - 'default_guard' => [ - 'extra_role' => 'extra_role', - ], - 'default_guard2' => [ - 'extra_role' => 'extra_role', - 'extra_role2' => 'extra_role2', - ], - ], PermissionConfig::extraRoleNames()); -}); - -test('get all role names group by guard name', function () { - assertSame([ - 'default_guard' => [ - 'super_admin' => 'super_admin', - 'admin' => 'admin', - 'extra_role' => 'extra_role', - ], - 'default_guard2' => [ - 'super_admin' => 'super_admin', - 'admin' => 'admin', - 'super_admin2' => 'super_admin2', - 'admin2' => 'admin2', - 'extra_role' => 'extra_role', - 'extra_role2' => 'extra_role2', - ], - ], PermissionConfig::allRoleNamesGroupByGuardName()); -}); - -test('get all role name by guard name', function () { - assertSame([ - 'super_admin', - 'admin', - 'extra_role', - 'super_admin2', - 'admin2', - 'extra_role2', - ], PermissionConfig::allRoleNames()); - - assertSame([ - 'super_admin', - 'admin', - 'super_admin2', - 'admin2', - 'extra_role', - 'extra_role2', - ], PermissionConfig::allRoleNames('default_guard2')); -}); - -test('role names by guard name', function () { - - assertSame([ - 'super_admin', - 'admin', - ], PermissionConfig::roleNamesByGuardName('default_guard')); - - assertSame([ - 'super_admin', - 'admin', - 'super_admin2', - 'admin2', - ], PermissionConfig::roleNamesByGuardName('default_guard2')); - -}); - -test('extra role names by guard name', function () { - - assertSame([ - 'extra_role', - ], PermissionConfig::extraRoleNamesByGuardName('default_guard')); - - assertSame([ - 'extra_role', - 'extra_role2', - ], PermissionConfig::extraRoleNamesByGuardName('default_guard2')); - -}); - -test('throw duplicate role names for guard name', function () { - - config([ - 'filament-permission.role_names' => [ - 'default_guard' => [ - 'super_admin' => 'super_admin', - 'admin' => 'admin', - ], - ], - 'filament-permission.extra_role_names' => [ - 'default_guard' => [ - 'super_admin' => 'super_admin', - ], - ], - ]); - - PermissionConfig::checkNoSameRoleNameOnExtra(); -}) - ->throws('The extra_role name "super_admin" is already defined in role_names in guard "default_guard".'); -test('throw guard name not exists', function () { - - config([ - 'filament-permission.role_names' => [ - 'xxxxx' => [ - 'super_admin' => 'super_admin', - 'admin' => 'admin', - ], - ], - 'filament-permission.extra_role_names' => [ - 'yyyyyyyyy' => [ - 'super_admin' => 'super_admin', - ], - ], - ]); - - PermissionConfig::checkDefaultGuardNameExist(); -}) - ->throws('Guard name "yyyyyyyyy", "xxxxx" is not defined in config/auth.php.');