From 117ff4484d01ffe1122d5c9a32b58bd71293b87a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hmer?= Date: Sat, 6 Sep 2025 00:10:50 +0200 Subject: [PATCH] Allow to show what permissions a user is lacking in case of access denied message Should help with errors like 1026 --- src/Security/Voter/PermissionVoter.php | 10 ++++++-- src/Services/UserSystem/VoterHelper.php | 24 +++++++++++++++++-- .../TwigBundle/Exception/error403.html.twig | 7 ++++-- 3 files changed, 35 insertions(+), 6 deletions(-) diff --git a/src/Security/Voter/PermissionVoter.php b/src/Security/Voter/PermissionVoter.php index c6ec1b3d..8c304d86 100644 --- a/src/Security/Voter/PermissionVoter.php +++ b/src/Security/Voter/PermissionVoter.php @@ -24,6 +24,7 @@ namespace App\Security\Voter; use App\Services\UserSystem\VoterHelper; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; +use Symfony\Component\Security\Core\Authorization\Voter\Vote; use Symfony\Component\Security\Core\Authorization\Voter\Voter; /** @@ -39,12 +40,17 @@ final class PermissionVoter extends Voter } - protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool + protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token, ?Vote $vote = null): bool { $attribute = ltrim($attribute, '@'); [$perm, $op] = explode('.', $attribute); - return $this->helper->isGranted($token, $perm, $op); + $result = $this->helper->isGranted($token, $perm, $op); + if ($result === false) { + $this->helper->addReason($vote, $perm, $op); + } + + return $result; } public function supportsAttribute(string $attribute): bool diff --git a/src/Services/UserSystem/VoterHelper.php b/src/Services/UserSystem/VoterHelper.php index 644351f4..dda00de7 100644 --- a/src/Services/UserSystem/VoterHelper.php +++ b/src/Services/UserSystem/VoterHelper.php @@ -28,6 +28,9 @@ use App\Repository\UserRepository; use App\Security\ApiTokenAuthenticatedToken; use Doctrine\ORM\EntityManagerInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; +use Symfony\Component\Security\Core\Authorization\Voter\Vote; +use Symfony\Component\Security\Core\Authorization\Voter\Voter; +use Symfony\Contracts\Translation\TranslatorInterface; /** * @see \App\Tests\Services\UserSystem\VoterHelperTest @@ -35,10 +38,14 @@ use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; final class VoterHelper { private readonly UserRepository $userRepository; + private readonly array $permissionStructure; - public function __construct(private readonly PermissionManager $permissionManager, private readonly EntityManagerInterface $entityManager) + public function __construct(private readonly PermissionManager $permissionManager, + private readonly TranslatorInterface $translator, + private readonly EntityManagerInterface $entityManager) { $this->userRepository = $this->entityManager->getRepository(User::class); + $this->permissionStructure = $this->permissionManager->getPermissionStructure(); } /** @@ -124,4 +131,17 @@ final class VoterHelper { return $this->permissionManager->isValidOperation($permission, $operation); } -} \ No newline at end of file + + public function addReason(?Vote $voter, string $permission, $operation): void + { + if ($voter !== null) { + $voter->addReason(sprintf("User does not have permission %s -> %s -> %s (%s.%s).", + $this->translator->trans('perm.group.'.$this->permissionStructure['perms'][$permission]['group'] ?? 'default' ), + $this->translator->trans($this->permissionStructure['perms'][$permission]['label'] ?? $permission), + $this->translator->trans($this->permissionStructure['perms'][$permission]['operations'][$operation]['label'] ?? $operation), + $permission, + $operation + )); + } + } +} diff --git a/templates/bundles/TwigBundle/Exception/error403.html.twig b/templates/bundles/TwigBundle/Exception/error403.html.twig index f5987179..334670fc 100644 --- a/templates/bundles/TwigBundle/Exception/error403.html.twig +++ b/templates/bundles/TwigBundle/Exception/error403.html.twig @@ -1,6 +1,9 @@ {% extends "bundles/TwigBundle/Exception/error.html.twig" %} {% block status_comment %} - Nice try! But you are not allowed to do this! + Nice try! But you are not allowed to do this!
+ {{ exception.message }}
If you think you should have access to this ressource, contact the adminstrator. -{% endblock %} \ No newline at end of file + + +{% endblock %}