
16 Lis Symfony Voter i role
W ostatnim wpisie przybliżyłam temat Votera. Jeśli jeszcze go nie czytałeś, to sprawdź. Bez poprzedniego wpisu ciężej będzie Ci zrozumieć ten. Dlatego zapraszam Cię do przeczytania podstawowych informacji o Symfony Voter, a potem powrót tutaj. Jeśli jednak znasz Votery lub przeczytałeś poprzedni tekst, to zapraszam Cię po poznania użycia voterów, które jest mniej popularne. Chciałabym Ci pokazać jak Symfony Voter i role mogą ze sobą współpracować i uzupełniać się wzajemnie.
Symfony Voter i role
Działanie Votera na podstawie roli nie różni się niczym od zwykłego Votera. Również sprawdzany jest metodą is_granted() zarówno w adnotacji, jak i kodzie php czy plikach twig. Różnica jest taka, że w pierwszym przykładzie $attribute był definiowany w Voterze jako akcja, do której jest dopuszczany user. W poniższym przykładzie nie opieramy się już na tego typu constach a na zbiorze ról i Voter również traktujemy jako odrębną rolę z bardziej skomplikowaną logiką niż standarowe role.
Zdecydowałam się na opisanie tego przypadku mimo tak małych różnic, ponieważ nigdzie nie zdnalazłam podobnych przykładów wykorzystania Votera a uważam, że ma ono duzo zalet. Jest łatwiejsze w utrzymaniu oraz bardziej czytelne.
Przykład
<?php namespace Backend\UserBundle; /** * Class Roles */ final class Roles { const CAN_EDIT_POST = 'CAN_EDIT_POST'; }
Powyżej jest przykładowa klasa zawierająca zestaw constów odpowiadających rolom. Poniżej to kod samego Votera, który weryfikuje $attribute będący identyfikatorem roli.
<?php use Backend\UserBundle\Entity\User; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Authorization\PostManagerInterface; use Symfony\Component\Security\Core\Authorization\Voter\Voter; /** * Class CanEditPostVoter */ class CanEditPostVoter extends Voter { /** * {@inheritdoc} */ protected function supports($attribute, $subject) { return Roles::CAN_EDIT_POST === $attribute && $subject instanceof Post; } /** * {@inheritdoc} */ protected function voteOnAttribute($attribute, $subject, TokenInterface $token) { $user = $token->getUser(); if (!$subject instanceof Post) { return false; } if ($user->getId() === $subject->getAuthorId()) { return true; } } }
Oto przykład wywołania Votera w formie adnotacji do akcji. Wygląda on bardzo podobnie do weryfikacji klasy, różni się jedynie metodą is_granted. W przypadku weryfikacji roli sprawdzilibyśmy ja metodą has_role().
<?php class PostController extends Controller { /** * @Security("is_granted('CAN_EDIT_POST', post)") * * @param Post $post * @param Request $request * @return Response */ public function editAction(Post $post, Request $request) { ... } }
Mam nadzieję, że ten przykład był przydatny. Co sądzisz o takim użyciu Votera? Lepsze od standardowego, a może gorsze? Napisz w komentarzu, co o tym sądzisz!