- Attribut :
AppoloDev\SFToolboxBundle\Security\Http\Attribute\IsNotGranted - Écouteur :
AppoloDev\SFToolboxBundle\Security\Http\EventListener\IsNotGrantedAttributeListener - Fichiers source :
src/Security/Http/Attribute/IsNotGranted.php,src/Security/Http/EventListener/IsNotGrantedAttributeListener.php
Attribut PHP au comportement inverse de #[IsGranted] (natif Symfony Security) : refuse l'accès quand la vérification réussit, plutôt que quand elle échoue. Utile pour restreindre une route aux utilisateurs qui n'ont pas un rôle/état donné — par exemple une page d'inscription réservée aux visiteurs non connectés, ou bloquer l'accès à des comptes bannis.
L'écouteur IsNotGrantedAttributeListener est enregistré automatiquement (autowiring + autoconfiguration, tag kernel.event_subscriber, priorité 20 sur KernelEvents::CONTROLLER_ARGUMENTS) — aucune configuration manuelle nécessaire, il suffit de poser l'attribut sur une classe/méthode/fonction contrôleur.
Signature identique à celle de #[IsGranted] natif :
public function __construct(
public string|Expression $attribute,
public array|string|Expression|null $subject = null,
public ?string $message = null,
public ?int $statusCode = null,
public ?int $exceptionCode = null,
)$attribute: rôle, nom de Voter, ou expressionExpressionLanguageà évaluer.$subject: sujet passé au Voter/à l'expression — peut référencer un argument nommé du contrôleur (string), une expression (Expression), ou un tableau des deux (avec clés optionnelles).$message: message d'erreur personnalisé (sinon un message générique est généré).$statusCode: si fourni, lève uneHttpExceptionavec ce code HTTP plutôt qu'uneAccessDeniedException(403 par défaut).$exceptionCode: code d'exception interne (distinct du code HTTP).
Répétable (#[Attribute::IS_REPEATABLE]), applicable sur classe, méthode ou fonction.
Écoute KernelEvents::CONTROLLER_ARGUMENTS. Pour chaque #[IsNotGranted] présent sur le contrôleur appelé :
- Résout le
$subject(argument nommé du contrôleur, ou expression évaluée avecrequest/argsdans le contexte). - Si
isGranted($attribute, $subject)retournetrue: lève une exception (HttpExceptionsistatusCodeest fourni, sinonAccessDeniedExceptionavec le message/attribut/sujet renseignés pour un débogage précis). - Ne fait rien si
isGranted()retournefalse(l'accès est autorisé — c'est bien la logique inversée par rapport à#[IsGranted]).
Vous n'appelez jamais cette méthode vous-même — elle est déclenchée automatiquement par le kernel HTTP.
use AppoloDev\SFToolboxBundle\Security\Http\Attribute\IsNotGranted;
use Symfony\Component\ExpressionLanguage\Expression;
// Page d'inscription réservée aux visiteurs non connectés :
#[Route('/register', name: 'app_register')]
#[IsNotGranted(new Expression('is_granted("IS_AUTHENTICATED_FULLY")'))]
class RegisterController extends AbstractController
{
// ...
}
// Bloquer l'accès à un compte banni :
#[Route('/profile', name: 'app_profile')]
#[IsNotGranted('ROLE_BANNED', message: 'Votre compte a été suspendu.', statusCode: 403)]
class ProfileController extends AbstractController
{
// ...
}
⚠️ Ne pas confondre avec#[IsGranted](natif Symfony) : ici, poser l'attribut bloque l'accès si la condition est vérifiée — c'est l'inverse du comportement habituel.