<?php
declare(strict_types=1);
namespace App\Magazzino\Security;
use App\Magazzino\Service\ModuloConfigService;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
/**
* Voter granulare per il modulo magazzino.
*
* Attributi supportati:
* - magazzino.section.<key> es. magazzino.section.articoli
* - magazzino.entity.<name>.view|edit|delete|create
*
* Combina due controlli:
* 1) ModuloConfigService dice se la sezione รจ abilitata in config
* 2) Symfony role hierarchy controlla che l'utente abbia il ruolo richiesto
*/
class MagazzinoVoter extends Voter
{
public const SECTION_PREFIX = 'magazzino.section.';
public const ENTITY_PREFIX = 'magazzino.entity.';
public function __construct(
private readonly ModuloConfigService $config,
private readonly AuthorizationCheckerInterface $authChecker,
) {
}
protected function supports($attribute, $subject)
{
return is_string($attribute) && (
str_starts_with($attribute, self::SECTION_PREFIX)
|| str_starts_with($attribute, self::ENTITY_PREFIX)
);
}
protected function voteOnAttribute($attribute, $subject, TokenInterface $token)
{
if (!$token->getUser()) {
return false;
}
if (str_starts_with($attribute, self::SECTION_PREFIX)) {
$key = substr($attribute, strlen(self::SECTION_PREFIX));
$section = $this->config->getSection($key);
if ($section === null || empty($section['enabled'])) {
return false;
}
$role = $section['role'] ?? 'ROLE_MAGAZZINO_OPERATOR';
return $this->authChecker->isGranted($role);
}
if (str_starts_with($attribute, self::ENTITY_PREFIX)) {
$tail = substr($attribute, strlen(self::ENTITY_PREFIX));
[$entity, $op] = array_pad(explode('.', $tail, 2), 2, 'view');
$needed = match ($op) {
'view' => 'ROLE_MAGAZZINO_OPERATOR',
'create' => 'ROLE_MAGAZZINO_OPERATOR',
'edit' => 'ROLE_MAGAZZINO_OPERATOR',
'delete' => 'ROLE_MAGAZZINO_MANAGER',
default => 'ROLE_MAGAZZINO_MANAGER',
};
return $this->authChecker->isGranted($needed);
}
return false;
}
}