src/Security/Voter/CrudVoter.php line 19
<?phpnamespace App\Security\Voter;use App\Entity\Action;use App\Entity\UserRole;use App\Entity\EntityName;use App\Entity\Permission;use Doctrine\ORM\EntityManagerInterface;use Symfony\Bundle\SecurityBundle\Security;use Symfony\Component\Security\Core\User\UserInterface;use Symfony\Component\Security\Core\Authorization\Voter\Voter;use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;/*** Voter for the operations on CRUD entities*/class CrudVoter extends Voter{private $security, $actions, $em;/*** Constructor. Sets the global variables and creates a list with the names of the actions** @param Security $security Required by Symfony* @param EntityManagerInterface $em Used to get the list of the actions and the user's permissions from the database* @return void*/public function __construct(Security $security, EntityManagerInterface $em){$actionObjectList = $em->getRepository(Action::class)->findAll();$this->actions = array(); // [NEW, EDIT, ...]. It was CRUD_*action* but this is better$this->security = $security;$this->em = $em;foreach ($actionObjectList as $action){array_push($this->actions, $action->getName());}}/*** Checks whether the voter has to vote on the required permission** @param string $attribute The required action (NEW/LIST/VIEW/EDIT/DELETE). The first parameter of denyAccessUnlessGranted* @param mixed $subject The entity's object which the voter may have to vote on, the second parameter of denyAccessUnlessGranted. Does not play a role in whether or not the voter is going to vote* @return bool True if the voter is going to vote, false otherwise*/protected function supports(string $attribute, $subject): bool{// First, $attribute is the authentication role, then it changes to the first parameter of denyAccessUnlessGrantedreturn in_array($attribute, $this->actions);}/*** Determines whether the user has the permission to perform the required action to a certain entity** @param string $attribute The required action (NEW/LIST/VIEW/EDIT/DELETE). The first parameter of denyAccessUnlessGranted* @param mixed $subject The entity on which to perform the requested action, the second parameter of denyAccessUnlessGranted. Used only to get the entity's name* @param TokenInterface $token Used to get the User object of the user who is requesting the permission* @return bool True if the permission is granted, false otherwise*/protected function voteOnAttribute(string $attribute, $subject, TokenInterface $token): bool{$user = $token->getUser();// if the user is anonymous, do not grant accessif (!$user instanceof UserInterface)return false;// I want the list of permissions for the entity on which I'm doing the CRUD// Then I check if there's at least a role the user also has$totalPermissions = array();foreach ($user->getRoles() as $role){$roleID = $this->em->getRepository(UserRole::class) ->findOneBy(['name' => $role]);$entityID = $this->em->getRepository(EntityName::class)->findOneBy(['name' => $subject->getEntityName()]);$actionID = $this->em->getRepository(Action::class) ->findOneBy(['name' => $attribute]);// Check in the database if the permission exists (if a user with a role $roleID can perform the action $actionID on the $entityName entities$permission = $this->em->getRepository(Permission::class)->findOneByAllFields($roleID, $entityID, $actionID);if ($permission) // Without this check it would put a null object in the arrayarray_push($totalPermissions, $permission);}if (!empty($totalPermissions))return true; // I just need the user to have one permissionreturn false;}}