<?php
namespace App\Domain\User\Voter;
use App\Domain\Application\Voter\AbstractVoter;
use App\Domain\User\Entity\User;
use App\Domain\User\Security\RoleChecker;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Security;
class UserVoter extends AbstractVoter
{
public const VIEW = 'view';
public const EDIT = 'edit';
public const DELETE = 'delete';
public function __construct(
Security $security,
private readonly RoleChecker $roleChecker,
) {
parent::__construct($security);
}
public function supportsType(string $subjectType): bool
{
return is_a($subjectType, User::class, true);
}
public function supportsAttribute(string $attribute): bool
{
return \in_array($attribute, [
self::VIEW,
self::EDIT,
self::DELETE,
]);
}
/**
* @param User $subject
*/
protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool
{
$user = $token->getUser();
if (!$user instanceof User) {
return false;
}
return match ($attribute) {
self::VIEW => $this->canView($user, $subject),
self::EDIT => $this->canEdit($user, $subject),
self::DELETE => $this->canDelete($user, $subject),
default => false,
};
}
private function canView(User $user, User $subject): bool
{
return true;
}
private function canEdit(User $user, User $subject): bool
{
if ($this->security->isGranted(User::ROLE_SUPER_ADMIN)) {
return true;
}
if ($this->roleChecker->isGranted($subject, User::ROLE_SUPER_ADMIN) && $user !== $subject) {
return false;
}
return true;
}
private function canDelete(User $user, User $subject): bool
{
return $this->security->isGranted(User::ROLE_SUPER_ADMIN)
&& !$this->roleChecker->isGranted($subject, User::ROLE_SUPER_ADMIN);
}
}