mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-09-25 08:05:00 +00:00
Add RoleDumper
and DumpListPermissionsCommand
to generate a markdown list of permissions
This commit is contained in:
86
src/Bundle/ChillMainBundle/Security/RoleDumper.php
Normal file
86
src/Bundle/ChillMainBundle/Security/RoleDumper.php
Normal file
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Chill\MainBundle\Security;
|
||||
|
||||
use Symfony\Component\Security\Core\Role\RoleHierarchyInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
final readonly class RoleDumper
|
||||
{
|
||||
public function __construct(
|
||||
private RoleProvider $roleProvider,
|
||||
private RoleHierarchyInterface $roleHierarchy,
|
||||
private TranslatorInterface $translator,
|
||||
) {}
|
||||
|
||||
public function dumpAsMarkdown(): string
|
||||
{
|
||||
$roles = $this->roleProvider->getRoles();
|
||||
$rolesWithoutScopes = $this->roleProvider->getRolesWithoutScopes();
|
||||
|
||||
// Group roles by title
|
||||
$groups = [];
|
||||
foreach ($roles as $role) {
|
||||
$title = $this->roleProvider->getRoleTitle($role);
|
||||
$title ??= 'Other';
|
||||
$groups[$title][] = $role;
|
||||
}
|
||||
|
||||
// Sort groups by title
|
||||
ksort($groups, SORT_NATURAL | SORT_FLAG_CASE);
|
||||
|
||||
$lines = [];
|
||||
foreach ($groups as $title => $roleList) {
|
||||
// Sort roles by translated label for deterministic output
|
||||
usort($roleList, function (string $a, string $b): int {
|
||||
$ta = $this->translator->trans($a);
|
||||
$tb = $this->translator->trans($b);
|
||||
|
||||
return strcasecmp($ta, $tb);
|
||||
});
|
||||
|
||||
$translatedTitle = $this->translator->trans($title);
|
||||
$lines[] = '## '.$translatedTitle;
|
||||
|
||||
foreach ($roleList as $role) {
|
||||
// Translate primary role
|
||||
$translatedRole = $this->translator->trans($role);
|
||||
|
||||
// Scope marker: (S) if needs scope, (~~S~~) if no scope required
|
||||
$needsScope = !in_array($role, $rolesWithoutScopes, true);
|
||||
$scopeMarker = $needsScope ? '(S)' : '(~~S~~)';
|
||||
|
||||
// Compute dependent roles from hierarchy (exclude itself)
|
||||
$reachable = $this->roleHierarchy->getReachableRoleNames([$role]);
|
||||
$dependents = array_values(array_filter($reachable, static fn (string $r): bool => $r !== $role));
|
||||
|
||||
// Translate dependents and sort deterministically
|
||||
$translatedDependents = array_map(fn (string $r) => $this->translator->trans($r), $dependents);
|
||||
sort($translatedDependents, SORT_NATURAL | SORT_FLAG_CASE);
|
||||
|
||||
if (count($translatedDependents) > 0) {
|
||||
$lines[] = sprintf('- **%s** %s: %s', $translatedRole, $scopeMarker, implode(', ', $translatedDependents));
|
||||
} else {
|
||||
$lines[] = sprintf('- **%s** %s', $translatedRole, $scopeMarker);
|
||||
}
|
||||
}
|
||||
|
||||
// Add a blank line between groups
|
||||
$lines[] = '';
|
||||
}
|
||||
|
||||
// Trim possible trailing blank line
|
||||
$markdown = rtrim(implode("\n", $lines));
|
||||
|
||||
return $markdown."\n"; // End with newline for POSIX friendliness
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user