Skip to content

Commit

Permalink
simple config handling
Browse files Browse the repository at this point in the history
Signed-off-by: Lloric Mayuga Garcia <[email protected]>
  • Loading branch information
lloricode committed Aug 24, 2024
1 parent c23611c commit cb66ddd
Show file tree
Hide file tree
Showing 10 changed files with 64 additions and 343 deletions.
23 changes: 16 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -47,6 +54,8 @@ return [

'translated' => false,
];


```

## Usage
Expand Down
21 changes: 14 additions & 7 deletions config/filament-permission.php
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion src/Actions/EditRoleAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
132 changes: 14 additions & 118 deletions src/Config/PermissionConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -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<string, array<string, string>>
*/
public static function roleNames(): array
public static function roleNamesGroupByGuardName(): array
{
return ConfigFacade::array('filament-permission.role_names');
}

/**
* @return array<string, array<string, string>>
*/
public static function extraRoleNames(): array
{
return ConfigFacade::array('filament-permission.extra_role_names', []);
}

/**
* @return array<string, array<string, string>>
*/
public static function allRoleNamesGroupByGuardName(): array
{
self::checkNoSameRoleNameOnExtra();

$roles = self::roleNames();
$extraRoles = self::extraRoleNames();

return array_merge_recursive($roles, $extraRoles);
}

/**
* @return array<string, string>
*/
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<int, string>
*/
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<int, string>
*/
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<int, string>
// */
// public static function guardNames(): array
// {
// return collect(self::roleNamesGroupByGuardName())->keys()
// ->toArray();
// }
}
2 changes: 1 addition & 1 deletion src/Database/Seeders/DefaultRoleSeeder.php
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
20 changes: 13 additions & 7 deletions src/Policies/RolePolicy.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand All @@ -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;
}

Expand All @@ -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;
}

Expand Down
4 changes: 2 additions & 2 deletions src/Resources/RoleResource.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
);
};
Expand Down Expand Up @@ -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(),
]),
]),
Expand Down
2 changes: 1 addition & 1 deletion src/Resources/RoleResource/Schema/PermissionSchema.php
Original file line number Diff line number Diff line change
Expand Up @@ -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')),
];
Expand Down
4 changes: 2 additions & 2 deletions tests/Actions/EditRoleActionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@
it('can not edit defaults', function () {

/** @var array<int, Role&Model> $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) {
Expand Down
Loading

0 comments on commit cb66ddd

Please sign in to comment.