Dans un gabarit, is_granted() continue de répondre comme il l’a toujours fait. Ce qui est nouveau, c’est la fonction d’à côté, qui remet la décision entière à Twig au lieu d’un booléen.
{% if is_granted('EDIT', post) %}
<a href="{{ path('post_edit', {id: post.id}) }}">Edit</a>
{% endif %}
Rien ne change dans vos gabarits. is_granted_for_user(otherUser, 'EDIT', post) pose la même question au sujet de quelqu’un d’autre, comme avant.
Dire pourquoi, pas seulement si
{% set decision = access_control_decision('EDIT', post) %}
{% if not decision.isGranted %}
<p class="notice">{{ decision.reason }}</p>
{% endif %}
Une page qui cache un bouton est une page au sujet de laquelle un utilisateur écrira un ticket. Une page qui dit que le document est verrouillé pendant qu’un autre rédacteur le tient, ou que le compte attend sa vérification, répond au ticket avant qu’il ne soit écrit. access_control_decision_for_user() pose la même question au sujet d’un autre compte, et c’est de cela qu’est fait un écran d’administration qui liste les permissions effectives.
Une mise en garde, puisque la raison est un diagnostic : elle est écrite pour des développeurs, pas pour des visiteurs. Affichez-la sur un écran interne, ou choisissez règle par règle ce qu’un visiteur doit lire.
Pourquoi elle ne s’appelle pas access_decision
Security publie une fonction de ce nom, et les deux formes divergent : decision est ici une énumération là où celle de Security est un booléen, et reason est une propriété là où Security a getMessage().
Une fonction dont le type de retour dépendrait des bundles installés serait un piège, donc les deux vivent côte à côte. access_decision() continue d’être publiée par Security et de rendre l’objet de Security, et vous avancez à votre rythme.
Une extension, pas deux
Laisser les deux extensions publier is_granted() ne lèverait rien du tout. Twig garde en silence celle qui a été initialisée en dernier, donc la réponse dépendrait de l’ordre de config/bundles.php, qui n’est pas un endroit où l’on cherche un bogue d’autorisation.
Le bundle remplace donc l’extension Twig de Security par une extension qui publie tout le reste et pas ces deux fonctions. Les aides d’usurpation d’identité et les fonctions de décision de Security sont déléguées nommément, relevant de l’authentification plutôt que de l’autorisation.
Les nommer a un coût, accepté en connaissance de sa conséquence : une fonction que Symfony ajouterait dans une version ultérieure serait laissée de côté. La liste est donc comparée à l’extension de Security, et une inconnue lève à la compilation plutôt que de disparaître discrètement de vos gabarits.
Le contrôle d’accès au niveau du champ est refusé, bruyamment
L’is_granted() de Security accepte un troisième argument, un champ, qui passe par symfony/acl. Aucun votant ici ne comprend un vote sur un champ, et plutôt que de répondre false, la fonction lève avec un message qui le dit exactement.
Une application qui emploie l’ACL au niveau du champ dans ses gabarits ne peut pas installer ce bundle. C’est délibéré : un refus qu’un gabarit ne peut pas distinguer d’un vrai relève de la même famille de faute qu’une garde qui laisse passer.
Et sans Twig, rien n’est publié et rien n’échoue : les fonctions viennent d’un paquet facultatif, et le vérificateur répond aux mêmes questions depuis PHP.