<?php
namespace App\Security\Voter;
use App\Entity\Fine;
use App\Security\Role\FineRole;
use App\Security\Scope\FineScopeResolver;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
/**
* Decyduje o dostępie do zawiadomienia na podstawie jego statusu weryfikacji.
*
* Uwaga: Field::setPermission() dostaje FieldDto, a nie encję, więc pól nie da się
* autoryzować tą drogą - tam zostaje setDisabled().
*
* Cała logika ról siedzi w FineScopeResolver, żeby menu, filtrowanie listy i ten voter
* nie rozjechały się między sobą.
*/
final class FineVoter extends Voter
{
public const VIEW = 'FINE_VIEW';
public const EDIT = 'FINE_EDIT';
public const VERIFY = 'FINE_VERIFY';
public const ANON = 'FINE_ANON';
public const ATTRIBUTES = [self::VIEW, self::EDIT, self::VERIFY, self::ANON];
private const VERB_BY_ATTRIBUTE = [
self::VIEW => FineRole::VERB_VIEW,
self::EDIT => FineRole::VERB_EDIT,
self::VERIFY => FineRole::VERB_VERIFY,
self::ANON => FineRole::VERB_ANON,
];
public function __construct(private readonly FineScopeResolver $scopeResolver)
{
}
protected function supports(string $attribute, $subject): bool
{
return isset(self::VERB_BY_ATTRIBUTE[$attribute]);
}
protected function voteOnAttribute(string $attribute, $subject, TokenInterface $token): bool
{
$verb = self::VERB_BY_ATTRIBUTE[$attribute];
if ($subject instanceof Fine) {
$statusId = $subject->getVerificationStatus()?->getId();
return $statusId !== null && $this->scopeResolver->can($verb, $statusId);
}
return $this->scopeResolver->canAnywhere($verb);
}
}