Skip to content

Commit

Permalink
readable and flexible seeder for permissions
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 11, 2024
1 parent 35e5218 commit 6e4e7b4
Show file tree
Hide file tree
Showing 4 changed files with 163 additions and 38 deletions.
89 changes: 75 additions & 14 deletions src/Database/Seeders/BasePermissionSeeder.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,45 +5,57 @@
namespace Lloricode\FilamentSpatieLaravelPermissionPlugin\Database\Seeders;

use Illuminate\Database\Seeder;
use Illuminate\Support\Collection;
use Illuminate\Support\Str;
use Lloricode\FilamentSpatieLaravelPermissionPlugin\Database\Seeders\Support\PermissionSeeder;
use Lloricode\FilamentSpatieLaravelPermissionPlugin\Database\Seeders\Support\ResourceSeeder;
use Spatie\Permission\Contracts\Permission as PermissionContract;

abstract class BasePermissionSeeder extends Seeder
{
/**
* @return array<string, PermissionSeeder>
*/
abstract protected function permissionsByGuard(): array;

public function run(): void
{
$permissionClass = app(PermissionContract::class);

collect($this->permissionsByGuard())
->map(fn (array $permissions) => collect($permissions))
->each(
function (Collection $permissions, string $guardName) use ($permissionClass) {
function (PermissionSeeder $permissionSeeder, string $guardName) use ($permissionClass) {
$output = $this->command->getOutput();

$output->info('Seeding permissions for guard: ' . $guardName . ' ...');
$output->title(sprintf('Seeding permissions for guard: [%s] ...', $guardName));

$output->progressStart($permissions->count());
$output->text('panels');
$this->seedPanelsPagesWidgets($permissionSeeder->panels, $guardName);

$permissions->sort()->each(
function (string $permission) use ($permissionClass, $guardName, $output) {
$permissionClass->findOrCreate(name: $permission, guardName: $guardName);
$output->progressAdvance();
}
);
$output->text('pages');
$this->seedPanelsPagesWidgets($permissionSeeder->pages, $guardName);

$output->progressFinish();
$output->text('widgets');
$this->seedPanelsPagesWidgets($permissionSeeder->widgets, $guardName);

$output->text('resources');
$this->seedResource($permissionSeeder->resources, $guardName);

$allPermissionNames = $permissionSeeder->allPermissionNames();

$output->info(sprintf(
'Done Seeding permissions for guard: [%s] with total of [%d] permissions.!',
$guardName,
count($allPermissionNames)
));

$output->info('Done Seeding permissions for guard: ' . $guardName . '!');
$output->newLine();

$permissionClass::whereGuardName($guardName)
->whereNotIn('name', $permissions)
->whereNotIn('name', $allPermissionNames)
->delete();
}
);

}

/** @param class-string $modelPolicy */
Expand Down Expand Up @@ -73,6 +85,55 @@ protected static function generatePermissionGroup(string $resourceName, array $p
return collect($permissions)
->map(fn (string $permission) => "{$resourceName}.{$permission}")
->prepend($resourceName)
->sort()
->toArray();
}

/**
* @param array<int, string> $permissionNames
*/
public function seedPanelsPagesWidgets(array $permissionNames, string $guardName): void
{
$permissionClass = app(PermissionContract::class);

$permissionNames = collect($permissionNames);

$output = $this->command->getOutput();
$output->progressStart($permissionNames->count());

$permissionNames->sort()->each(
function (string $permission) use ($permissionClass, $guardName, $output) {
$permissionClass->findOrCreate(name: $permission, guardName: $guardName);
$output->progressAdvance();
}
);

$output->progressFinish();
}

/**
* @param array<int, ResourceSeeder> $resourcePermissionNames
*/
public function seedResource(array $resourcePermissionNames, string $guardName): void
{
$permissionClass = app(PermissionContract::class);

$permissionNames = collect();

foreach ($resourcePermissionNames as $resourcePermissionName) {
$permissionNames = $permissionNames->merge($resourcePermissionName->permissionNames);
}

$output = $this->command->getOutput();
$output->progressStart($permissionNames->count());

$permissionNames->sort()->each(
function (string $permission) use ($permissionClass, $guardName, $output) {
$permissionClass->findOrCreate(name: $permission, guardName: $guardName);
$output->progressAdvance();
}
);

$output->progressFinish();
}
}
60 changes: 36 additions & 24 deletions src/Database/Seeders/DefaultPermissionSeeder.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,56 +7,68 @@
use Exception;
use Filament\Facades\Filament;
use Filament\Panel;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Gate;
use Lloricode\FilamentSpatieLaravelPermissionPlugin\Contracts\HasPermissionPage;
use Lloricode\FilamentSpatieLaravelPermissionPlugin\Contracts\HasPermissionWidgets;
use Lloricode\FilamentSpatieLaravelPermissionPlugin\Database\Seeders\Support\PermissionSeeder;
use Lloricode\FilamentSpatieLaravelPermissionPlugin\Database\Seeders\Support\ResourceSeeder;
use Lloricode\FilamentSpatieLaravelPermissionPlugin\FilamentPermissionGenerateName;

class DefaultPermissionSeeder extends BasePermissionSeeder
{
/** @throws Exception */
/**
* {@inheritdoc}
*
* @throws Exception
*/
#[\Override]
protected function permissionsByGuard(): array
{
return [
Config::string('filament-permission.guard') => self::getPermissionsFromPanels()
->merge(self::getPermissionsFromResourceModelPolicies())
->merge(self::getPermissionsFromWidgets())
->merge(self::getPermissionsFromPages())
->toArray(),
Config::string('filament-permission.guard') => new PermissionSeeder(
panels: self::getPermissionsFromPanels(),
pages: self::getPermissionsFromPages(),
widgets: self::getPermissionsFromWidgets(),
resources: self::getPermissionsFromResourceModelPolicies()
),
];
}

/** @return \Illuminate\Support\Collection<int, string> */
private static function getPermissionsFromPanels(): Collection
/** @return array<int, string> */
private static function getPermissionsFromPanels(): array
{
return collect(Filament::getPanels())
->map(fn (Panel $panel) => FilamentPermissionGenerateName::getPanelPermissionName($panel))
->prepend(FilamentPermissionGenerateName::PANELS)
->values();
->values()
->sort()
->toArray();
}

/** @return \Illuminate\Support\Collection<int, string> */
private static function getPermissionsFromResourceModelPolicies(): Collection
/** @return array<int, ResourceSeeder> */
private static function getPermissionsFromResourceModelPolicies(): array
{
$permissionsByPolicy = collect();

foreach (Filament::getResources() as $filamentResource) {

$modelPolicy = Gate::getPolicyFor($filamentResource::getModel());

$permissionsByPolicy = $permissionsByPolicy->merge(
self::generateFilamentResourcePermissions($modelPolicy::class)
);
$permissionsByPolicy->push(new ResourceSeeder(
resource: $filamentResource,
model: $filamentResource::getModel(),
modelPolicy: $modelPolicy::class,
permissionNames: self::generateFilamentResourcePermissions($modelPolicy::class)
));

}

return $permissionsByPolicy;
return $permissionsByPolicy->sort()->toArray();
}

/** @return \Illuminate\Support\Collection<int, string> */
private static function getPermissionsFromWidgets(): Collection
/** @return array<int, string> */
private static function getPermissionsFromWidgets(): array
{
$permissionNames = collect();

Expand All @@ -67,16 +79,16 @@ private static function getPermissionsFromWidgets(): Collection
}

if ($permissionNames->isEmpty()) {
return $permissionNames;
return [];
}

$permissionNames->prepend(FilamentPermissionGenerateName::WIDGETS);

return $permissionNames;
return $permissionNames->sort()->toArray();
}

/** @return \Illuminate\Support\Collection<int, string> */
private static function getPermissionsFromPages(): Collection
/** @return array<int, string> */
private static function getPermissionsFromPages(): array
{
$permissionNames = collect();

Expand All @@ -87,11 +99,11 @@ private static function getPermissionsFromPages(): Collection
}

if ($permissionNames->isEmpty()) {
return $permissionNames;
return [];
}

$permissionNames->prepend(FilamentPermissionGenerateName::PAGES);

return $permissionNames;
return $permissionNames->sort()->toArray();
}
}
34 changes: 34 additions & 0 deletions src/Database/Seeders/Support/PermissionSeeder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

declare(strict_types=1);

namespace Lloricode\FilamentSpatieLaravelPermissionPlugin\Database\Seeders\Support;

readonly class PermissionSeeder
{
/**
* @param array<int, ResourceSeeder> $resources
*/
public function __construct(
public array $panels,
public array $pages,
public array $widgets,
public array $resources,
) {}

/**
* @return array<int, string>
*/
public function allPermissionNames(): array
{
$collect = collect($this->panels)
->merge($this->pages)
->merge($this->widgets);

foreach ($this->resources as $resource) {
$collect = $collect->merge($resource->permissionNames);
}

return $collect->toArray();
}
}
18 changes: 18 additions & 0 deletions src/Database/Seeders/Support/ResourceSeeder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

declare(strict_types=1);

namespace Lloricode\FilamentSpatieLaravelPermissionPlugin\Database\Seeders\Support;

readonly class ResourceSeeder
{
/**
* @param array<int, string> $permissionNames
*/
public function __construct(
public string $resource,
public string $model,
public string $modelPolicy,
public array $permissionNames
) {}
}

0 comments on commit 6e4e7b4

Please sign in to comment.