<?php
namespace App\Permission\Voter;
use App\Entity\User;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;
use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
/**
* Doc: https://symfony.com/doc/5.4/security/voters.html
*
* @package App\Permission\Security\Voter
*/
class PermissionsVoter implements VoterInterface
{
public const SHOW = 'SHOW';
public const EDIT = 'EDIT';
public const DELETE = 'DELETE';
public function __construct(protected AccessDecisionManagerInterface $decisionManager)
{
}
protected function getSupportedAttributes()
{
return [self::SHOW, self::EDIT, self::DELETE];
}
/**
* Desc:
* $attribute => role's permission text. for example: EDIT,SHOW,DELETE
* $subject => the role that want to check. for example: ROLE_ADMIN,ROLE_SUPER_ADMIN
*
*
* @param $attribute
* @param $subject
* @return bool
*/
protected function supports($attribute, $subject)
{
return in_array($attribute, $this->getSupportedAttributes());
}
/**
* Desc:
* $attribute => role's permission text. for example: EDIT,SHOW,DELETE
* $subject => the role that want to check. for example: ROLE_ADMIN,ROLE_SUPER_ADMIN
*
* @param $attribute
* @param $subject
* @param TokenInterface $token
* @return bool
*/
protected function voteOnAttribute($permission, $role, TokenInterface $token)
{
// Super Admin Pass
if ($this->decisionManager->decide($token, [User::ROLE_SUPER_ADMIN])) {
return true;
}
/**
* @var $user User
*/
$user = $token->getUser();
if (!$user instanceof User) {
return false;
}
$hasPermission = false;
if (is_array($role)) {
foreach ($role as $roleValue) {
if (in_array($roleValue, $user->getRoles())) {
$hasPermission = true;
}
}
} else {
if (in_array($role, $user->getRoles())) {
$hasPermission = true;
}
}
return $hasPermission;
}
public function vote(TokenInterface $token, $subject, array $attributes)
{
$vote = self::ACCESS_ABSTAIN;
foreach ($attributes as $attribute) {
if (!$this->supports($attribute, $subject)) {
continue;
}
$vote = self::ACCESS_DENIED;
if ($this->voteOnAttribute($attribute, $subject, $token)) {
return self::ACCESS_GRANTED;
}
}
return $vote;
}
}