Tous les votants se sont abstenus. Il faut bien que quelque chose sorte de la question, et l’endroit où ce quelque chose se décide en dit long sur la façon dont un composant d’autorisation est assemblé.
Dans Access Control, le réglage s’appelle allow_if_all_abstain, il vaut false par défaut, et il appartient au gestionnaire.
access_control:
allow_if_all_abstain: false
Pourquoi il appartient au gestionnaire
Dans Symfony Security, cette valeur est portée par chaque stratégie. Cela fonctionne, et cela a un mode de défaillance : un réglage transmis par les appelants qui ont pensé à le transmettre. Changez l’algorithme de combinaison quelque part et la réponse au silence change avec lui, sans un mot.
Ici il siège sur le gestionnaire, si bien qu’un seul réglage est obéi par tous les points d’entrée : l’attribut de contrôleur, les règles d’URL, la fonction de gabarit, la garde de console, la garde de workflow, et n’importe quel appel que vous écrivez vous-même. Un algorithme de combinaison décide quoi faire des votes qu’il a reçus. Quoi faire d’aucun vote du tout n’est pas sa question.
Passer outre pour une question
Une requête isolée peut dire le contraire, et c’est le seul endroit où null signifie « s’en remettre au gestionnaire ».
new AccessRequest($requester, 'EDIT', $post, allowIfAllAbstain: true);
La même dérogation existe sur une politique d’accès, où elle reste visible à côté de la règle qu’elle assouplit :
#[AccessPolicy('EDIT', new Argument('post'), allowIfAllAbstain: true)]
Fermer par défaut, et savoir quand on ne le fait pas
Le défaut refuse, ce qui est la moitié sûre du choix : une question que personne n’a comprise n’est pas une question à laquelle on a répondu oui. Une application qui le bascule à true globalement a décidé que tout ce qui n’est pas explicitement gardé est public, et cette décision mérite d’être consignée ailleurs que dans une clé YAML.
La dérogation étroite est en général ce que les gens veulent vraiment : un point de terminaison, une politique, une ligne, visible dans le diff qui l’introduit.
Si votre application a Security, déclarez-le là
Une application dotée de SecurityBundle continue de déclarer cela sous security.access_decision_manager, et la passerelle l’y lit. Ne déclarez pas la même chose sur les deux clés.
Le dire deux fois ne fait pas silencieusement un choix : le bundle lève à la compilation sur deux valeurs contradictoires, exactement comme sur deux algorithmes de combinaison, deux hiérarchies de rôles ou deux jeux de règles d’URL. Une compilation qui s’arrête, c’est bien le but. Des règles d’accès qui se relâchent en silence sont ce que cette règle évite, et quatre des sept formes de security.access_decision_manager faisaient exactement cela avant qu’elle ne soit appliquée.
Le piège voisin, un étage plus bas
Le même raisonnement explique une décision plus modeste à l’intérieur du composant. L’environnement d’accès ne vous donne pas de valeur par défaut quand une clé manque, sauf si vous en demandez une : une règle qui s’abstient parce qu’une clé est absente tombe en position ouverte, et aucun point d’entrée ne devrait pouvoir désactiver une règle par omission.
Le silence est une vraie réponse, et il faut bien que quelque chose décide de son sens. La seule conception fautive est celle où ce quelque chose n’est personne en particulier.