<?php
namespace App\Security\Voter;
use App\Entity\PropietarioContenido;
use App\Entity\UsuarioHermes;
use App\Enum\RolEnum;
use App\Exception\Authorization\PropietarioContenidoAuthorizationException;
use App\Exception\Authorization\NoUserException;
use App\Security\PropietarioContenidoAuthorizationService;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
/**
* Voter para decidir acceso basado en roles de PropietarioContenido.
*/
class PropietarioContenidoVoter extends Voter
{
// Definir constantes para los atributos que manejará este voter
public const ROL_PROPIETARIO_CONTENIDO = 'ROL_PROPIETARIO_CONTENIDO';
private PropietarioContenidoAuthorizationService $authorizationService;
/**
* @var PropietarioContenidoAuthorizationException|null Última excepción que ocurrió al votar
*/
private ?PropietarioContenidoAuthorizationException $lastException = null;
public function __construct(PropietarioContenidoAuthorizationService $authorizationService)
{
$this->authorizationService = $authorizationService;
}
/**
* Determina si este voter soporta el atributo y subject dados.
*/
protected function supports(string $attribute, $subject): bool
{
// Solo soporta el atributo ROL_PROPIETARIO_CONTENIDO
if ($attribute !== self::ROL_PROPIETARIO_CONTENIDO) {
return false;
}
// El subject debe ser un array de roles de PropietarioContenido permitidos
if (!is_array($subject)) {
return false;
}
return true;
}
/**
* Determina si el acceso está concedido.
*
* @param string $attribute ROL_PROPIETARIO_CONTENIDO
* @param array $subject Array de roles de PropietarioContenido permitidos (RolEnum::PARTICIPANTE, etc.)
* @param TokenInterface $token Token de autenticación
* @return bool
*/
protected function voteOnAttribute(string $attribute, $subject, TokenInterface $token): bool
{
$user = $token->getUser();
// Si el usuario no es un objeto UsuarioHermes, denegar acceso
if (!$user instanceof UsuarioHermes) {
$this->lastException = new NoUserException(
'Debe iniciar sesión para acceder a este recurso.',
PropietarioContenidoAuthorizationException::SEVERITY_WARNING
);
return false;
}
// $subject es un array de roles permitidos según RolEnum
$rolesPermitidos = $subject;
try {
// Verificar acceso lanzando excepciones para capturar el motivo del fallo
$this->authorizationService->verificarAcceso(
$rolesPermitidos,
null,
false,
true // Lanzar excepciones
);
// Si no se lanzó excepción, el acceso está permitido
$this->lastException = null;
return true;
} catch (PropietarioContenidoAuthorizationException $e) {
// Guardar la excepción para que el controlador pueda consultarla posteriormente
$this->lastException = $e;
return false;
}
}
/**
* Obtiene la última excepción que ocurrió al votar.
* Esto permite a los controladores entender por qué se denegó el acceso.
*
* @return PropietarioContenidoAuthorizationException|null La última excepción o null si no hay
*/
public function getLastException(): ?PropietarioContenidoAuthorizationException
{
return $this->lastException;
}
}