<?php
namespace App\Security\Voter;
use ApiPlatform\Core\Bridge\Doctrine\Orm\Paginator;
use App\Entity\Hei;
use App\Entity\User;
use App\HeiAdministration\StaffDirectory;
use App\Repository\HeiRepository;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Security\Core\User\UserInterface;
class HeiVoter extends Voter
{
public const VIEW = 'HEI_VIEW';
public const EDIT = 'HEI_EDIT';
public const CREATE = 'HEI_CREATE';
public const DELETE = 'HEI_DELETE';
public const VIEW_INCOMING_MOBILITIES = 'VIEW_INCOMING_MOBILITIES';
public const VIEW_OUTGOING_MOBILITIES = 'VIEW_INCOMING_MOBILITIES';
private Security $security;
private StaffDirectory $staffDirectory;
private HeiRepository $heiRepository;
public function __construct(
Security $security,
StaffDirectory $staffDirectory,
HeiRepository $heiRepository
) {
$this->security = $security;
$this->staffDirectory = $staffDirectory;
$this->heiRepository = $heiRepository;
}
protected function supports(string $attribute, mixed $subject): bool
{
return in_array($attribute, [
self::VIEW,
self::CREATE,
self::EDIT,
self::DELETE,
self::VIEW_INCOMING_MOBILITIES,
self::VIEW_OUTGOING_MOBILITIES,
])
&& (
$subject instanceof Paginator
|| null === $subject
|| $subject instanceof Hei
)
;
}
protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool
{
/**
* @var User $user
*/
$user = $token->getUser();
// if the user is anonymous, do not grant access
if (!$user instanceof UserInterface) {
return false;
}
if ($this->security->isGranted('ROLE_SUPER_ADMIN')) {
return true;
}
// TODO this should just be temporary until Api Platform allows security check on the owning side
if ($subject instanceof Paginator) {
$query = $subject
->getQuery()
;
$queryParameters = $query->getParameters();
$id = $queryParameters[0]
->getValue()
;
$hei = $this->heiRepository->findOneBy(['schacCode' => $id]);
} else {
$hei = $subject;
}
switch ($attribute) {
case self::VIEW:
$student = $user->getStudent();
return $this->staffDirectory->isStaffAtHei($user, $hei)
|| (null !== $student && $student->getHomeHei()->getId() === $hei->getId())
;
case self::EDIT:
case self::VIEW_INCOMING_MOBILITIES:
case self::VIEW_OUTGOING_MOBILITIES:
return $this->staffDirectory->isStaffAtHei($user, $hei);
case self::CREATE:
return $this->security->isGranted('ROLE_ADMIN');
case self::DELETE:
// This should never be reached as we already check for SUPER_ADMIN role higher up
return false;
}
return false;
}
}