From d5e40f2ea3c01a67c727824161dc4b525f00a3ed Mon Sep 17 00:00:00 2001 From: Hasnayeen Date: Wed, 17 Jul 2024 21:21:04 +0600 Subject: [PATCH] Add authorization to page & panel --- src/Page.php | 33 ++++++++++++++++++++++++++++++++- src/Panel.php | 20 +++++++++++++++++--- 2 files changed, 49 insertions(+), 4 deletions(-) diff --git a/src/Page.php b/src/Page.php index 5190bcc..f89fcb8 100644 --- a/src/Page.php +++ b/src/Page.php @@ -4,6 +4,7 @@ use Hasnayeen\Xumina\Facades\Xumina; use Illuminate\Database\Eloquent\Model; +use Illuminate\Support\Facades\Gate; use Illuminate\Support\Str; use Inertia\Inertia; @@ -21,6 +22,8 @@ public function __construct( protected Content $content, protected Layout $layout, ) { + Gate::allowIf(call_user_func(Xumina::getCurrentPanel()->getAuthorizationCallback(), auth()->user())); + $this->authorize(); Inertia::share('title', static::getPageTitle()); Xumina::getCurrentPanel()->currentPage($this); } @@ -29,6 +32,34 @@ abstract public function outline(): array; abstract public static function routes(): array; + protected function authorize() + { + $action = request()->route()->getActionMethod(); + $model = static::$model; + $record = request()->route($model::getRouteKeyName()); + + $policyMethod = $this->mapMethodToPolicy($action); + + if ($record) { + Gate::authorize($policyMethod, $record); + } else { + Gate::authorize($policyMethod, $model); + } + } + + protected function mapMethodToPolicy($method) + { + $map = [ + 'index' => 'viewAny', + 'show' => 'view', + 'store' => 'create', + 'update' => 'update', + 'destroy' => 'delete', + ]; + + return $map[$method] ?? $method; + } + public static function getMiddlewares(): array { return []; @@ -102,7 +133,7 @@ public function breadcrumb(): array return [ [ 'text' => $title = Xumina::getCurrentPanel()->getRootPage()::getPageTitle(), - 'url' => route('xumina.'.Str::kebab(Xumina::getCurrentPanel()->getName()).'.'.Str::kebab($title)), + 'url' => route('xumina.' . Str::kebab(Xumina::getCurrentPanel()->getName()) . '.' . Str::kebab($title)), ], ]; } diff --git a/src/Panel.php b/src/Panel.php index d02a4ce..a11f782 100644 --- a/src/Panel.php +++ b/src/Panel.php @@ -2,6 +2,7 @@ namespace Hasnayeen\Xumina; +use Closure; use Hasnayeen\Xumina\Components\Icon; use Hasnayeen\Xumina\Contracts\Layout; use Hasnayeen\Xumina\Contracts\Theme; @@ -33,8 +34,21 @@ public function __construct( protected ?string $logoText = null, protected ?string $theme = DefaultTheme::class, protected array $navigations = [], + protected ?Closure $authorizationCallback = null, ) {} + public function authorize(Closure $callback): static + { + $this->authorizationCallback = $callback; + + return $this; + } + + public function getAuthorizationCallback() + { + return $this->authorizationCallback; + } + public function getName(): string { return $this->name; @@ -59,7 +73,7 @@ public function getPrefix(): ?string public function getPath(): string { - return $this->path ?? app_path('Xumina/'.Str::studly($this->getName())); + return $this->path ?? app_path('Xumina/' . Str::studly($this->getName())); } /** @@ -109,7 +123,7 @@ public function rootPage(string $rootPage): static public function getRootPage(): string { - return $this->rootPage ?? $this->getPages()->filter(fn ($page) => class_basename($page) === 'Dashboard')->first(); + return $this->rootPage ?? $this->getPages()->filter(fn($page) => class_basename($page) === 'Dashboard')->first(); } public function layout(string $layout): static @@ -198,7 +212,7 @@ public function getNavigations(): array ->items( Xumina::getCurrentPanel() ->getPages() - ->filter(fn ($page) => ! Str::contains($page, 'Auth')) + ->filter(fn($page) => ! Str::contains($page, 'Auth')) ->concat(Xumina::getCurrentPanel()->getResources()) ->map(function ($item) { if ($item::showInNavigation()) {