feat(sidebar) : add role gate to sidebar provider and global nav config
This commit is contained in:
@@ -7,19 +7,31 @@ namespace App\Shared\Domain\Sidebar;
|
||||
final class SidebarFilter
|
||||
{
|
||||
/**
|
||||
* @param list<array{label:string, icon:string, items: list<array{label:string, to:string, icon:string, module?:string}>}> $sections
|
||||
* @param list<string> $activeModuleIds
|
||||
* @param list<array{label:string, icon:string, roles?:list<string>, items: list<array{label:string, to:string, icon:string, module?:string, roles?:list<string>}>}> $sections
|
||||
* @param list<string> $activeModuleIds
|
||||
* @param list<string> $activeRoles
|
||||
*
|
||||
* @return array{sections: list<array{label:string, icon:string, items: list<array{label:string, to:string, icon:string}>}>, disabledRoutes: list<string>}
|
||||
*/
|
||||
public static function filter(array $sections, array $activeModuleIds): array
|
||||
public static function filter(array $sections, array $activeModuleIds, array $activeRoles = []): array
|
||||
{
|
||||
$outSections = [];
|
||||
$disabledRoutes = [];
|
||||
|
||||
foreach ($sections as $section) {
|
||||
// Gate de rôle au niveau section (ne pollue pas disabledRoutes : réservé au filtrage module).
|
||||
if (!self::rolesSatisfied($section['roles'] ?? null, $activeRoles)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$items = [];
|
||||
foreach ($section['items'] as $item) {
|
||||
// Gate de rôle au niveau item.
|
||||
if (!self::rolesSatisfied($item['roles'] ?? null, $activeRoles)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Filtrage par module actif (pilote la redirection front via disabledRoutes).
|
||||
$module = $item['module'] ?? null;
|
||||
if (null !== $module && !in_array($module, $activeModuleIds, true)) {
|
||||
$disabledRoutes[] = $item['to'];
|
||||
@@ -37,4 +49,23 @@ final class SidebarFilter
|
||||
|
||||
return ['sections' => $outSections, 'disabledRoutes' => $disabledRoutes];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param null|list<string> $required
|
||||
* @param list<string> $activeRoles
|
||||
*/
|
||||
private static function rolesSatisfied(?array $required, array $activeRoles): bool
|
||||
{
|
||||
if (null === $required || [] === $required) {
|
||||
return true;
|
||||
}
|
||||
|
||||
foreach ($required as $role) {
|
||||
if (in_array($role, $activeRoles, true)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ use ApiPlatform\State\ProviderInterface;
|
||||
use App\Shared\Domain\Module\ModuleRegistry;
|
||||
use App\Shared\Domain\Sidebar\SidebarFilter;
|
||||
use App\Shared\Infrastructure\ApiPlatform\Resource\SidebarResource;
|
||||
use Symfony\Bundle\SecurityBundle\Security;
|
||||
use Symfony\Component\DependencyInjection\Attribute\Autowire;
|
||||
|
||||
final readonly class SidebarProvider implements ProviderInterface
|
||||
@@ -16,6 +17,7 @@ final readonly class SidebarProvider implements ProviderInterface
|
||||
public function __construct(
|
||||
#[Autowire('%kernel.project_dir%')]
|
||||
private string $projectDir,
|
||||
private Security $security,
|
||||
) {}
|
||||
|
||||
public function provide(Operation $operation, array $uriVariables = [], array $context = []): SidebarResource
|
||||
@@ -23,10 +25,13 @@ final readonly class SidebarProvider implements ProviderInterface
|
||||
/** @var list<class-string> $moduleClasses */
|
||||
$moduleClasses = require $this->projectDir.'/config/modules.php';
|
||||
|
||||
/** @var list<array{label:string, icon:string, items: list<array{label:string, to:string, icon:string, module?:string}>}> $sidebar */
|
||||
/** @var list<array{label:string, icon:string, roles?:list<string>, items: list<array{label:string, to:string, icon:string, module?:string, roles?:list<string>}>}> $sidebar */
|
||||
$sidebar = require $this->projectDir.'/config/sidebar.php';
|
||||
|
||||
$filtered = SidebarFilter::filter($sidebar, ModuleRegistry::ids($moduleClasses));
|
||||
$user = $this->security->getUser();
|
||||
$roles = null !== $user ? $user->getRoles() : [];
|
||||
|
||||
$filtered = SidebarFilter::filter($sidebar, ModuleRegistry::ids($moduleClasses), array_values($roles));
|
||||
|
||||
$dto = new SidebarResource();
|
||||
$dto->sections = $filtered['sections'];
|
||||
|
||||
Reference in New Issue
Block a user