From 1f2362a33673582ffd9ad5b5211bc1ed25dea656 Mon Sep 17 00:00:00 2001 From: I Wayan Rupadana Date: Fri, 8 Sep 2023 16:12:10 +0800 Subject: [PATCH] add permission to access panel --- config/filament-shield.php | 4 ++ resources/lang/ar/filament-shield.php | 1 + resources/lang/de/filament-shield.php | 1 + resources/lang/en/filament-shield.php | 1 + resources/lang/es/filament-shield.php | 1 + resources/lang/fa/filament-shield.php | 1 + resources/lang/fr/filament-shield.php | 1 + resources/lang/hu/filament-shield.php | 1 + resources/lang/id/filament-shield.php | 1 + resources/lang/it/filament-shield.php | 1 + resources/lang/ja/filament-shield.php | 1 + src/FilamentShield.php | 45 +++++++++++++--- src/Middleware/PanelAccess.php | 45 ++++++++++++++++ src/Resources/RoleResource.php | 78 ++++++++++++++++++++++----- src/Support/Utils.php | 15 ++++++ src/Traits/HasPanelShield.php | 28 ++++++++++ 16 files changed, 206 insertions(+), 19 deletions(-) create mode 100644 src/Middleware/PanelAccess.php create mode 100644 src/Traits/HasPanelShield.php diff --git a/config/filament-shield.php b/config/filament-shield.php index e358e5b8..db208b9f 100644 --- a/config/filament-shield.php +++ b/config/filament-shield.php @@ -45,12 +45,14 @@ 'page' => 'page', 'widget' => 'widget', + 'panel' => 'panel' ], 'entities' => [ 'pages' => true, 'widgets' => true, 'resources' => true, + 'panels' => true, 'custom_permissions' => false, ], @@ -70,6 +72,8 @@ ], 'resources' => [], + + 'panels' => [] // Using Panel ID ], 'register_role_policy' => [ diff --git a/resources/lang/ar/filament-shield.php b/resources/lang/ar/filament-shield.php index 1329d6e7..2035b391 100644 --- a/resources/lang/ar/filament-shield.php +++ b/resources/lang/ar/filament-shield.php @@ -47,6 +47,7 @@ 'resources' => 'المصادر', 'widgets' => 'الملحقات', 'pages' => 'الصفحات', + 'panels' => 'لوحات', 'custom' => 'أذونات مخصصة', /* diff --git a/resources/lang/de/filament-shield.php b/resources/lang/de/filament-shield.php index 1562e2b0..29c8ae79 100644 --- a/resources/lang/de/filament-shield.php +++ b/resources/lang/de/filament-shield.php @@ -47,6 +47,7 @@ 'resources' => 'Ressourcen', 'widgets' => 'Widgets', 'pages' => 'Seiten', + 'panels' => 'Panels', 'custom' => 'benutzerdefinierte Berechtigungen', /* diff --git a/resources/lang/en/filament-shield.php b/resources/lang/en/filament-shield.php index 9ac503b8..396ac2ff 100644 --- a/resources/lang/en/filament-shield.php +++ b/resources/lang/en/filament-shield.php @@ -47,6 +47,7 @@ 'resources' => 'Resources', 'widgets' => 'Widgets', 'pages' => 'Pages', + 'panels' => 'Panels', 'custom' => 'Custom Permissions', /* diff --git a/resources/lang/es/filament-shield.php b/resources/lang/es/filament-shield.php index 5993e109..5765e974 100644 --- a/resources/lang/es/filament-shield.php +++ b/resources/lang/es/filament-shield.php @@ -47,6 +47,7 @@ 'resources' => 'Recursos', 'widgets' => 'Widgets', 'pages' => 'Páginas', + 'panels' => 'Paneles', 'custom' => 'Permisos personalizados', /* diff --git a/resources/lang/fa/filament-shield.php b/resources/lang/fa/filament-shield.php index b1b99272..8215988f 100644 --- a/resources/lang/fa/filament-shield.php +++ b/resources/lang/fa/filament-shield.php @@ -47,6 +47,7 @@ 'resources' => 'منابع', 'widgets' => 'ویجت‌ها', 'pages' => 'صفحات', + 'panels' => 'پانل ها', 'custom' => 'دسترسی‌های سفارشی', /* diff --git a/resources/lang/fr/filament-shield.php b/resources/lang/fr/filament-shield.php index f7aec8b4..03575675 100644 --- a/resources/lang/fr/filament-shield.php +++ b/resources/lang/fr/filament-shield.php @@ -47,6 +47,7 @@ 'resources' => 'Ressources', 'widgets' => 'Widgets', 'pages' => 'Pages', + 'panels' => 'Panneaux', 'custom' => 'Permissions personnalisées', /* diff --git a/resources/lang/hu/filament-shield.php b/resources/lang/hu/filament-shield.php index 2b4f8e5f..f2142f4b 100644 --- a/resources/lang/hu/filament-shield.php +++ b/resources/lang/hu/filament-shield.php @@ -47,6 +47,7 @@ 'resources' => 'Erőforrások', 'widgets' => 'Widgetek', 'pages' => 'Oldalak', + 'panels' => 'Panelek', 'custom' => 'Egyedi jogosultságok', /* diff --git a/resources/lang/id/filament-shield.php b/resources/lang/id/filament-shield.php index 83cf90f7..e3943d7b 100644 --- a/resources/lang/id/filament-shield.php +++ b/resources/lang/id/filament-shield.php @@ -47,6 +47,7 @@ 'resources' => 'Sumber Daya', 'widgets' => 'Widget', 'pages' => 'Halaman', + 'panels' => 'Panel', 'custom' => 'Izin Kustom', /* diff --git a/resources/lang/it/filament-shield.php b/resources/lang/it/filament-shield.php index ae5b7956..824adf9c 100644 --- a/resources/lang/it/filament-shield.php +++ b/resources/lang/it/filament-shield.php @@ -47,6 +47,7 @@ 'resources' => 'Resources', 'widgets' => 'Widgets', 'pages' => 'Pages', + 'panels' => 'Pannelli', 'custom' => 'Permessi Personalizzati', /* diff --git a/resources/lang/ja/filament-shield.php b/resources/lang/ja/filament-shield.php index 81b3111a..12de30e6 100644 --- a/resources/lang/ja/filament-shield.php +++ b/resources/lang/ja/filament-shield.php @@ -47,6 +47,7 @@ 'resources' => 'リソース', 'widgets' => 'ウィジェット', 'pages' => 'ページ', + 'panels' => 'パネル', 'custom' => 'カスタムパーミッション', /* diff --git a/src/FilamentShield.php b/src/FilamentShield.php index 46006421..bb397f0f 100755 --- a/src/FilamentShield.php +++ b/src/FilamentShield.php @@ -90,7 +90,7 @@ public static function generateForWidget(string $widget): void protected static function giveSuperAdminPermission(string | array | Collection $permissions): void { - if (! Utils::isSuperAdminDefinedViaGate()) { + if (!Utils::isSuperAdminDefinedViaGate()) { $superAdmin = static::createRole(); $superAdmin->givePermissionTo($permissions); @@ -118,7 +118,7 @@ public function getResources(): ?array ->unique() ->filter(function ($resource) { if (Utils::isGeneralExcludeEnabled()) { - return ! in_array( + return !in_array( Str::of($resource)->afterLast('\\'), Utils::getExcludedResouces() ); @@ -173,7 +173,7 @@ public static function getPages(): ?array return collect(Filament::getPages()) ->filter(function ($page) { if (Utils::isGeneralExcludeEnabled()) { - return ! in_array(Str::afterLast($page, '\\'), Utils::getExcludedPages()); + return !in_array(Str::afterLast($page, '\\'), Utils::getExcludedPages()); } return true; @@ -200,9 +200,9 @@ public static function getLocalizedPageLabel(string $page): string $pageObject = invade(new $object()); return $pageObject->getTitle() - ?? $pageObject->getHeading() - ?? $pageObject->getNavigationLabel() - ?? ''; + ?? $pageObject->getHeading() + ?? $pageObject->getNavigationLabel() + ?? ''; } /** @@ -215,7 +215,7 @@ public static function getWidgets(): ?array return collect(Filament::getWidgets()) ->filter(function ($widget) { if (Utils::isGeneralExcludeEnabled()) { - return ! in_array(Str::afterLast($widget, '\\'), Utils::getExcludedWidgets()); + return !in_array(Str::afterLast($widget, '\\'), Utils::getExcludedWidgets()); } return true; @@ -232,6 +232,7 @@ public static function getWidgets(): ?array ->toArray(); } + /** * Get localized widget label * @@ -261,6 +262,13 @@ public static function getLocalizedWidgetLabel(string $widget): string }; } + public static function getLocalizedPanelLabel(string $panel) + { + return Str::of($panel) + ->after(Utils::getPanelPermissionPrefix() . '_') + ->headline(); + } + protected static function transformClassString(string $string, bool $isPageClass = true): string { return (string) collect($isPageClass ? Filament::getPages() : Filament::getWidgets()) @@ -286,4 +294,27 @@ protected function getDefaultPermissionIdentifier(string $resource): string ->snake() ->replace('_', '::'); } + + + public static function getPanels(): ?array + { + return collect(Filament::getPanels()) + ->filter(function ($panel) { + if (Utils::isGeneralExcludeEnabled()) { + return !in_array($panel->getId(), Utils::getExcludedWidgets()); + } + + return true; + }) + ->reduce(function ($panels, $panel) { + $prepend = Str::of(Utils::getPanelPermissionPrefix())->append('_'); + $name = Str::of($panel->getId()) + ->prepend($prepend); + + $panels["{$name}"] = "{$name}"; + + return $panels; + }, collect()) + ->toArray(); + } } diff --git a/src/Middleware/PanelAccess.php b/src/Middleware/PanelAccess.php new file mode 100644 index 00000000..f8a626b8 --- /dev/null +++ b/src/Middleware/PanelAccess.php @@ -0,0 +1,45 @@ +getCurrentPanel(); + $panels = filament()->getPanels(); + + + if (count($panels) > 1) { + if (!$this->hasAccessTo($currentPanel)) { + foreach ($panels as $key => $panel) { + if ($this->hasAccessTo($panel)) { + return redirect($panel->getPath()); + } + } + } + } + + return $next($request); + } + + protected function hasAccessTo($panel) + { + $prepend = Str::of(Utils::getPanelPermissionPrefix())->append('_'); + $permissionName = Str::of($panel->getId()) + ->prepend($prepend); + + return auth()->user()->can($permissionName); + } +} diff --git a/src/Resources/RoleResource.php b/src/Resources/RoleResource.php index 5ae9c09c..65a3079f 100644 --- a/src/Resources/RoleResource.php +++ b/src/Resources/RoleResource.php @@ -113,6 +113,21 @@ public static function form(Form $form): Form ]), ]), + Forms\Components\Tabs\Tab::make(__('filament-shield::filament-shield.panels')) + ->visible(fn (): bool => (bool) Utils::isPanelEntityEnabled() && (count(FilamentShield::getPanels()) > 1 ? true : false) && filament()->getCurrentPanel()->getId() == "admin") + ->live() + ->schema([ + Forms\Components\Grid::make([ + 'sm' => 3, + 'lg' => 4, + ]) + ->schema(static::getPanelEntityPermissionSchema()) + ->columns([ + 'sm' => 3, + 'lg' => 4, + ]), + ]), + Forms\Components\Tabs\Tab::make(__('filament-shield::filament-shield.custom')) ->visible(fn (): bool => (bool) Utils::isCustomPermissionEntityEnabled()) ->live() @@ -245,7 +260,7 @@ public static function canGloballySearch(): bool /**--------------------------------* | Resource Related Logic Start | - *----------------------------------*/ + *----------------------------------*/ public static function getResourceEntitiesSchema(): ?array { @@ -268,7 +283,7 @@ public static function getResourceEntitiesSchema(): ?array $set($permission . '_' . $entity['resource'], $state); }); - if (! $state) { + if (!$state) { $set('select_all', false); } @@ -293,7 +308,12 @@ public static function getResourceEntitiesSchema(): ?array public static function getResourceEntityPermissionsSchema($entity): ?array { - return collect(Utils::getResourcePermissionPrefixes($entity['fqcn']))->reduce(function ($permissions /** @phpstan ignore-line */, $permission) use ($entity) { + return collect(Utils::getResourcePermissionPrefixes($entity['fqcn']))->reduce(function ( + $permissions + /** @phpstan ignore-line */ + , + $permission + ) use ($entity) { $permissions[] = Forms\Components\Checkbox::make($permission . '_' . $entity['resource']) ->label(FilamentShield::getLocalizedResourcePermissionLabel($permission)) ->extraAttributes(['class' => 'text-primary-600']) @@ -312,7 +332,7 @@ public static function getResourceEntityPermissionsSchema($entity): ?array ->afterStateUpdated(function (Forms\Set $set, Forms\Get $get, $state) use ($entity) { static::refreshResourceEntityStateAfterUpdate($set, $get, $entity); - if (! $state) { + if (!$state) { $set($entity['resource'], false); $set('select_all', false); } @@ -426,11 +446,11 @@ protected static function refreshResourceEntityStateAfterHydrated(Model $record, } /**--------------------------------* | Resource Related Logic End | - *----------------------------------*/ + *----------------------------------*/ /**--------------------------------* | Page Related Logic Start | - *----------------------------------*/ + *----------------------------------*/ protected static function getPageEntityPermissionsSchema(): ?array { @@ -451,7 +471,7 @@ protected static function getPageEntityPermissionsSchema(): ?array }) ->live() ->afterStateUpdated(function (Forms\Set $set, Forms\Get $get, $state) { - if (! $state) { + if (!$state) { $set('select_all', false); } @@ -467,11 +487,11 @@ protected static function getPageEntityPermissionsSchema(): ?array } /**--------------------------------* | Page Related Logic End | - *----------------------------------*/ + *----------------------------------*/ /**--------------------------------* | Widget Related Logic Start | - *----------------------------------*/ + *----------------------------------*/ protected static function getWidgetEntityPermissionSchema(): ?array { @@ -492,7 +512,7 @@ protected static function getWidgetEntityPermissionSchema(): ?array }) ->live() ->afterStateUpdated(function (Forms\Set $set, Forms\Get $get, $state) { - if (! $state) { + if (!$state) { $set('select_all', false); } @@ -506,9 +526,43 @@ protected static function getWidgetEntityPermissionSchema(): ?array return $widgets; }, []); } + + protected static function getPanelEntityPermissionSchema(): ?array + { + return collect(FilamentShield::getPanels())->reduce(function ($panels, $panel) { + $panels[] = Forms\Components\Grid::make() + ->schema([ + Forms\Components\Checkbox::make($panel) + ->label(FilamentShield::getLocalizedPanelLabel($panel)) + ->inline() + ->afterStateHydrated(function (Forms\Set $set, Forms\Get $get, $record) use ($panel) { + if (is_null($record)) { + return; + } + + $set($panel, $record->checkPermissionTo($panel)); + + static::refreshSelectAllStateViaEntities($set, $get); + }) + ->afterStateUpdated(function (Forms\Set $set, Forms\Get $get, $state) { + if (!$state) { + $set('select_all', false); + } + + static::refreshSelectAllStateViaEntities($set, $get); + }) + ->dehydrated(fn ($state): bool => $state) + ]) + ->columns(1) + ->columnSpan(1); + + return $panels; + }, []); + } + /**--------------------------------* | Widget Related Logic End | - *----------------------------------*/ + *----------------------------------*/ protected static function getCustomEntities(): ?Collection { @@ -546,7 +600,7 @@ protected static function getCustomEntitiesPermisssionSchema(): ?array }) ->live() ->afterStateUpdated(function (Forms\Set $set, Forms\Get $get, $state) { - if (! $state) { + if (!$state) { $set('select_all', false); } diff --git a/src/Support/Utils.php b/src/Support/Utils.php index eeb83181..22fa6245 100644 --- a/src/Support/Utils.php +++ b/src/Support/Utils.php @@ -109,6 +109,11 @@ public static function getWidgetPermissionPrefix(): string return (string) config('filament-shield.permission_prefixes.widget'); } + public static function getPanelPermissionPrefix(): string + { + return (string) config('filament-shield.permission_prefixes.panel'); + } + public static function isResourceEntityEnabled(): bool { return (bool) config('filament-shield.entities.resources', true); @@ -127,6 +132,11 @@ public static function isWidgetEntityEnabled(): bool return (bool) config('filament-shield.entities.widgets', true); } + public static function isPanelEntityEnabled(): bool + { + return (bool) config('filament-shield.entities.panels', true); + } + public static function isCustomPermissionEntityEnabled(): bool { return (bool) config('filament-shield.entities.custom_permissions', false); @@ -167,6 +177,11 @@ public static function getExcludedWidgets(): array return config('filament-shield.exclude.widgets'); } + public static function getExcludedPanels(): array + { + return config('filament-shield.exclude.panels'); + } + public static function isRolePolicyRegistered(): bool { return (bool) config('filament-shield.register_role_policy', true); diff --git a/src/Traits/HasPanelShield.php b/src/Traits/HasPanelShield.php new file mode 100644 index 00000000..eb04e331 --- /dev/null +++ b/src/Traits/HasPanelShield.php @@ -0,0 +1,28 @@ +getPanels()) + ->filter( + function (Panel $panel) { + $prepend = Str::of(Utils::getPanelPermissionPrefix())->append('_'); + $name = Str::of($panel->getId()) + ->prepend($prepend); + return $this->can($name); + } + ) + ->reduce(function($panels, Panel $panel) { + $panels[] = $panel->getId(); + + return $panels; + }); + } +} \ No newline at end of file