<?php
declare(strict_types=1);
namespace App\Security;
use App\Entity\System\Customer;
use App\Entity\System\Employee;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
class ImpersonateUserVoter extends Voter
{
public const CAN_SWITCH_USER = 'CAN_SWITCH_USER';
protected function supports($attribute, $subject): bool
{
return $attribute === self::CAN_SWITCH_USER && $subject instanceof Customer;
}
protected function voteOnAttribute($attribute, $subject, TokenInterface $token): bool
{
$user = $token->getUser();
if (!$user instanceof Employee || !$subject instanceof Customer) {
return false;
}
if ($this->loggedUserIsAdmin($user)) {
return true;
}
$subjectRolesIndex = \array_flip($subject->getRoles());
if ($this->requestedUserHasManagementRoles($subjectRolesIndex)) {
return false;
}
$userRolesIndex = \array_flip($user->getRoles());
return $this->loggedUserHasAnyImpersonatorRole($userRolesIndex);
}
/**
* @param array $subjectRolesIndex
*
* @return bool
*/
protected function requestedUserHasManagementRoles(array $subjectRolesIndex): bool
{
return \array_key_exists('ROLE_EMPLOYEE', $subjectRolesIndex);
}
protected function loggedUserIsAdmin(Employee $user): bool
{
$userRolesIndex = \array_flip($user->getRoles());
return \array_key_exists('ROLE_SUPER_ADMIN', $userRolesIndex);
}
/**
* @param array<string, array-key> $userRolesIndex
*/
public function loggedUserHasAnyImpersonatorRole(array $userRolesIndex): bool
{
return \array_key_exists('ROLE_SUPER_ADMIN', $userRolesIndex)
|| \array_key_exists('ROLE_TECH_SUPPORT', $userRolesIndex)
|| \array_key_exists('ROLE_SALES_ADMIN', $userRolesIndex)
|| \array_key_exists('ROLE_FINANCE', $userRolesIndex)
|| \array_key_exists('ROLE_SALES', $userRolesIndex);
}
}