<?php
declare(strict_types=1);
namespace App\Security;
use App\Entity\System\Customer;
use App\Entity\System\Employee;
use App\Entity\System\Role;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
class ImpersonateUserVoter extends Voter
{
private ParameterBagInterface $parameterBag;
public function __construct(
ParameterBagInterface $parameterBag
) {
$this->parameterBag = $parameterBag;
}
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;
}
if ($this->requestedUserIsEmployee($subject->getEmail())) {
return $user->getEmail() === $subject->getEmail();
}
$userRolesIndex = \array_flip($user->getRoles());
return $this->loggedUserHasAnyImpersonatorRole($userRolesIndex);
}
protected function requestedUserIsEmployee(string $email): bool
{
return str_contains($email, $this->parameterBag->get('microsoft_tenant_email_postfix'));
}
protected function loggedUserIsAdmin(Employee $user): bool
{
$userRolesIndex = \array_flip($user->getRoles());
return \array_key_exists(Role::ROLE_EMPLOYEE_DEVELOPER, $userRolesIndex);
}
/**
* @param array<string, array-key> $userRolesIndex
*/
public function loggedUserHasAnyImpersonatorRole(array $userRolesIndex): bool
{
return \array_key_exists(Role::ROLE_EMPLOYEE_SUPER_ADMIN, $userRolesIndex)
|| \array_key_exists(Role::ROLE_EMPLOYEE_TECH_SUPPORT, $userRolesIndex)
|| \array_key_exists(Role::ROLE_EMPLOYEE_SALES_ADMIN, $userRolesIndex)
|| \array_key_exists('ROLE_FINANCE', $userRolesIndex);
}
}