Skip to content

Commit

Permalink
Use object on config, optimise guard name 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 18, 2024
1 parent b7ebea9 commit 9aea027
Show file tree
Hide file tree
Showing 11 changed files with 178 additions and 62 deletions.
16 changes: 9 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,16 @@ This is the contents of the published config file:
declare(strict_types=1);

return [
'guard' => 'web',
'roles' => [
'super_admin' => 'super_admin',
'admin' => 'admin',
'role_names' => [
'web' => [
'super_admin' => 'super_admin',
'admin' => 'admin',
],
],
'extra_roles' => [

'extra_role_names' => [
// 'web' => [
// 'user' => 'user',
// ],
],

'seeders' => [
Expand All @@ -44,7 +47,6 @@ return [

'translated' => false,
];

```

## Usage
Expand Down
15 changes: 9 additions & 6 deletions config/filament-permission.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,16 @@
declare(strict_types=1);

return [
'guard' => 'web',
'roles' => [
'super_admin' => 'super_admin',
'admin' => 'admin',
'role_names' => [
'web' => [
'super_admin' => 'super_admin',
'admin' => 'admin',
],
],
'extra_roles' => [

'extra_role_names' => [
// 'web' => [
// 'user' => 'user',
// ],
],

'seeders' => [
Expand Down
9 changes: 3 additions & 6 deletions src/Actions/EditRoleAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,17 @@
namespace Lloricode\FilamentSpatieLaravelPermissionPlugin\Actions;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Config;
use Lloricode\FilamentSpatieLaravelPermissionPlugin\Config\PermissionConfig;
use Lloricode\FilamentSpatieLaravelPermissionPlugin\Data\RoleData;
use Spatie\Permission\Contracts\Role as RoleContract;

readonly class EditRoleAction
{
public function execute(RoleContract & Model $role, RoleData $roleData): RoleContract & Model
{
$roles = array_merge(
Config::array('filament-permission.roles'),
Config::array('filament-permission.extra_roles')
);
$roleNames = PermissionConfig::allRoleNames($roleData->guard_name);

if (in_array($role->name, $roles, true)) {
if (in_array($role->name, $roleNames, true)) {
abort(400, trans('Cannot update this role.'));
}

Expand Down
12 changes: 7 additions & 5 deletions src/Concern/PermissionUser.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,20 @@

namespace Lloricode\FilamentSpatieLaravelPermissionPlugin\Concern;

use Lloricode\FilamentSpatieLaravelPermissionPlugin\Config\PermissionConfig;

trait PermissionUser
{
public function isAdminOrSuperAdmin(): bool
public function isAdminOrSuperAdmin(?string $guardName = null): bool
{
return $this->hasAnyRole(
config('filament-permission.roles.super_admin'),
config('filament-permission.roles.admin')
PermissionConfig::superAdmin($guardName),
PermissionConfig::admin($guardName),
);
}

public function isSuperAdmin(): bool
public function isSuperAdmin(?string $guardName = null): bool
{
return $this->hasRole(config('filament-permission.roles.super_admin'));
return $this->hasRole(PermissionConfig::superAdmin($guardName));
}
}
127 changes: 127 additions & 0 deletions src/Config/PermissionConfig.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
<?php

declare(strict_types=1);

namespace Lloricode\FilamentSpatieLaravelPermissionPlugin\Config;

use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Config as ConfigFacade;

final class PermissionConfig
{
public static function getDefaultGuardName(): string
{
return ConfigFacade::string('auth.defaults.guard');
}

public static function superAdmin(?string $guardName = null): string
{
$guardName ??= self::getDefaultGuardName();

return ConfigFacade::string('filament-permission.role_names.' . $guardName . '.super_admin');
}

public static function admin(?string $guardName = null): string
{
$guardName ??= self::getDefaultGuardName();

return ConfigFacade::string('filament-permission.role_names.' . $guardName . '.admin');
}

public static function extraRole(string $roleName, ?string $guardName = null): string
{
if (blank(self::extraRoleNames())) {
abort(500, 'No extra roles found in config/filament-permission.php');
}

$guardName ??= self::getDefaultGuardName();

return ConfigFacade::string('filament-permission.extra_roles.' . $guardName . '.' . $roleName);
}

/**
* @return array<string, array<string, string>>
*/
public static function allRoleNamesByGuardName(): 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
{
if ($guardName === null) {
return Arr::flatten(self::allRoleNamesByGuardName());
}

return Arr::get(self::allRoleNamesByGuardName(), $guardName);
}

public static function allGuardNames(): array
{
$extraRoles = self::extraRoleNames();
$roles = self::roleNames();

return collect($extraRoles)->keys()
->merge(collect($roles)->keys())
->unique()
->toArray();
}

/**
* @return array<string, array<string, string>>
*/
private static function roleNames(): array
{
return ConfigFacade::array('filament-permission.role_names');
}

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

private static function checkDefaultGuardNameExist(): void
{

$guardNames = self::allGuardNames();
$authGuardNames = array_keys(config('auth.guards'));

foreach ($guardNames as $guardName) {
if (! in_array($guardName, $authGuardNames, true)) {
abort(500, 'Guard name "' . $guardName . '" is not defined in config/auth.php');
}
}

}

private 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, 'extra_role name "' . $role . '" is already defined in role_names in guard "' . $guardName . '"');
}
}
}

}
}
2 changes: 1 addition & 1 deletion src/Data/RoleData.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
/** @param array<int, string> $permissions */
public function __construct(
public string $name,
public string $guard_name,
public ?string $guard_name,
public array $permissions,
) {}
}
4 changes: 2 additions & 2 deletions src/Database/Seeders/DefaultPermissionSeeder.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
use Exception;
use Filament\Facades\Filament;
use Filament\Panel;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Gate;
use Lloricode\FilamentSpatieLaravelPermissionPlugin\Config\PermissionConfig;
use Lloricode\FilamentSpatieLaravelPermissionPlugin\Contracts\HasPermissionPage;
use Lloricode\FilamentSpatieLaravelPermissionPlugin\Contracts\HasPermissionWidgets;
use Lloricode\FilamentSpatieLaravelPermissionPlugin\Database\Seeders\Support\PermissionSeeder;
Expand All @@ -26,7 +26,7 @@ class DefaultPermissionSeeder extends BasePermissionSeeder
protected function permissionsByGuard(): array
{
return [
Config::string('filament-permission.guard') => new PermissionSeeder(
PermissionConfig::getDefaultGuardName() => new PermissionSeeder(
panels: $this->getPermissionsFromPanels(),
pages: $this->getPermissionsFromPages(),
widgets: $this->getPermissionsFromWidgets(),
Expand Down
34 changes: 13 additions & 21 deletions src/Database/Seeders/DefaultRoleSeeder.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
namespace Lloricode\FilamentSpatieLaravelPermissionPlugin\Database\Seeders;

use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\Config;
use Lloricode\FilamentSpatieLaravelPermissionPlugin\Config\PermissionConfig;
use Spatie\Permission\Contracts\Permission as PermissionContract;
use Spatie\Permission\Contracts\Role as RoleContract;

Expand All @@ -21,30 +21,22 @@ public function __construct(
*/
public function run(): void
{
$guard = Config::string('filament-permission.guard');
foreach (PermissionConfig::allRoleNamesByGuardName() as $guardName => $roleNames) {

foreach (Config::array('filament-permission.roles') as $roleName) {

$role = $this->roleContract->findOrCreate(
name: $roleName,
guardName: $guard,
);

if (config('filament-permission.roles.admin') === $roleName) {
$role->givePermissionTo(
$this->permissionContract
->where('guard_name', $guard)
->pluck('name')
foreach ($roleNames as $roleName) {
$role = $this->roleContract->findOrCreate(
name: $roleName,
guardName: $guardName,
);
if (PermissionConfig::admin($guardName) === $roleName) {
$role->givePermissionTo(
$this->permissionContract
->where('guard_name', $guardName)
->pluck('name')
);
}
}
}

foreach (Config::array('filament-permission.extra_roles') as $roleName) {
$this->roleContract->findOrCreate(
name: $roleName,
guardName: $guard,
);
}

}
}
8 changes: 2 additions & 6 deletions src/Policies/RolePolicy.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
namespace Lloricode\FilamentSpatieLaravelPermissionPlugin\Policies;

use Illuminate\Foundation\Auth\User;
use Illuminate\Support\Facades\Config;
use Lloricode\FilamentSpatieLaravelPermissionPlugin\Config\PermissionConfig;
use Spatie\Permission\Contracts\Role as RoleContract;

class RolePolicy
Expand All @@ -16,11 +16,7 @@ public function before(?User $user, string $ability, mixed $role = null): ?bool
{
if ($role instanceof RoleContract) {

if (in_array($role->name, Config::array('filament-permission.roles'), true)) {
return false;
}

if (in_array($role->name, Config::array('filament-permission.extra_roles'), true)) {
if (in_array($role->name, PermissionConfig::allRoleNames($role->guard_name), true)) {
return false;
}
}
Expand Down
10 changes: 3 additions & 7 deletions tests/Actions/EditRoleActionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,25 @@
namespace Lloricode\FilamentSpatieLaravelPermissionPlugin\Tests\Actions;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Config;
use Lloricode\FilamentSpatieLaravelPermissionPlugin\Actions\EditRoleAction;
use Lloricode\FilamentSpatieLaravelPermissionPlugin\Config\PermissionConfig;
use Lloricode\FilamentSpatieLaravelPermissionPlugin\Data\RoleData;
use Spatie\Permission\Contracts\Role;
use Spatie\Permission\Contracts\Role as RoleContract;

use function PHPUnit\Framework\assertTrue;

it('can not edit defaults', function () {
$roleNames = array_values(array_merge(
Config::array('filament-permission.roles'),
Config::array('filament-permission.extra_roles')
));

/** @var array<int, Role&Model> $roles */
$roles = app(RoleContract::class)::whereIn('name', $roleNames)->get();
$roles = app(RoleContract::class)::whereIn('name', PermissionConfig::allRoleNames())->get();

$action = app(EditRoleAction::class);

foreach ($roles as $role) {

try {
$action->execute($role, new RoleData(name: fake()->word(), guard_name: '', permissions: []));
$action->execute($role, new RoleData(name: fake()->word(), guard_name: null, permissions: []));

assertTrue(false);
} catch (\Exception $e) {
Expand Down
3 changes: 2 additions & 1 deletion tests/Helpers.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
declare(strict_types=1);

use Illuminate\Database\Eloquent\Model;
use Lloricode\FilamentSpatieLaravelPermissionPlugin\Config\PermissionConfig;
use Lloricode\FilamentSpatieLaravelPermissionPlugin\Tests\Fixture\UserFactory;
use Spatie\Permission\Contracts\Role as RoleContract;

Expand All @@ -22,7 +23,7 @@ function getSuperAdminRole(): RoleContract & Model
{
/** @var RoleContract&Model $role */
$role = app(RoleContract::class)->findByName(
name: config('filament-permission.roles.super_admin'),
name: PermissionConfig::superAdmin(),
);

return $role;
Expand Down

0 comments on commit 9aea027

Please sign in to comment.