<?php
namespace App\Security\Voter;
use App\Entity\AppelAProjet;
use App\Entity\Project;
use App\Entity\QuestionnaireResponse;
use App\Repository\UserProjectRepository;
use DateTime;
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 ProjectVoter extends Voter
{
private Security $security;
private UserProjectRepository|null $userProjectRepository;
public function __construct(Security $security)
{
$this->security = $security;
}
/**
* @required
*
* @param UserProjectRepository $userProjectRepository
*/
public function setUserProjectRepository(UserProjectRepository $userProjectRepository)
{
$this->userProjectRepository = $userProjectRepository;
}
protected function supports(string $attribute, $subject): bool
{
return in_array($attribute, ['EDIT', 'VIEW', 'ADD_FILES', 'SUBMIT', 'PRE_EVAL', 'COORDO', 'THEMA', 'CLONE_LI', 'ADD_DC', 'DC_SUBMIT', 'EXPERT', 'RAPPORT', 'EXPERT_3'])
&& $subject instanceof Project;
}
protected function voteOnAttribute(string $attribute, $subject, TokenInterface $token): bool
{
/** @var Project $subject */
$user = $token->getUser();
// if the user is anonymous, do not grant access
if (!$user instanceof UserInterface) {
return false;
}
// ... (check conditions and return true to grant permission) ...
switch ($attribute) {
case 'EDIT':
if ($this->security->isGranted('ROLE_ADMIN_GIRCI')) {
return true;
}
break;
case 'VIEW':
if ($this->security->isGranted('ROLE_PORTEUR')) {
// si il est l'auteur et si il appartient toujours à la même drci
if ($subject->getAuthor() === $user) {
if ($subject->getDrci() === $user->getDrci()) {
return true;
}
}
}
if ($this->security->isGranted('ROLE_DRCI')) {
if ($subject->getDrci() === $user->getDrci()) {
return true;
}
}
if ($this->security->isGranted('ROLE_ADMIN_GIRCI') || $this->security->isGranted('ROLE_COORDONNATEUR') || $this->security->isGranted('ROLE_METHODO')) {
return true;
}
if ($this->security->isGranted('ROLE_PRE_EVAL')
|| $this->security->isGranted('ROLE_RAPPORT'))
{
if ($subject->getAppelAProjet()->getOuvert() === true) {
return true;
} else {
$up = $this->userProjectRepository->findBy(['user' => $this->security->getUser(), 'project' => $subject]);
if (count($up) > 0) {
return true;
}
}
}
if ($this->security->isGranted('ROLE_THEMA')
|| $this->security->isGranted('ROLE_EXPERT')
|| $this->security->isGranted('ROLE_EXPERT_3'))
{
$up = $this->userProjectRepository->findBy(['user' => $this->security->getUser(), 'project' => $subject]);
if (count($up) > 0) {
return true;
}
}
if ($this->security->isGranted('ROLE_GIRCI_PARTENAIRE')) {
$up = $this->userProjectRepository->findBy(['project' => $subject, 'girci' => $this->security->getUser()->getGirci()]);
if (count($up) > 0) {
return true;
}
}
return false;
case 'ADD_FILES':
if ($this->security->isGranted('ROLE_PORTEUR')) {
// si il est l'auteur et si il appartient toujours à la même drci
if ($subject->getAuthor() !== $user) {
return false;
}
if ($subject->getDrci() !== $user->getDrci()) {
return false;
}
$aap = $subject->getAppelAProjet();
if ($aap->getStatus() !== AppelAProjet::AAP_STATUS_LI) {
return false;
}
if ($subject->getStatus() !== Project::PROJECT_STATUS_BROUILLON) {
return false;
}
return true;
}
break;
case 'SUBMIT':
if ($this->security->isGranted('ROLE_PORTEUR')) {
// si il est l'auteur et si il appartient toujours à la même drci
if ($subject->getAuthor() !== $user) {
return false;
}
if ($subject->getDrci() !== $user->getDrci()) {
return false;
}
$aap = $subject->getAppelAProjet();
if ($aap->getStatus() !== AppelAProjet::AAP_STATUS_LI) {
return false;
}
if ($subject->getStatus() !== Project::PROJECT_STATUS_BROUILLON) {
return false;
}
return true;
}
if ($this->security->isGranted('ROLE_DRCI')) {
if ($subject->getAuthor() !== $user && $subject->getDrci() !== $user->getDrci()) {
return false;
}
$aap = $subject->getAppelAProjet();
if ($aap->getQuestionnaireLi()) {
return false;
}
if ($aap->getStatus() !== AppelAProjet::AAP_STATUS_DC) {
return false;
}
if ($subject->getStatus() !== Project::PROJECT_STATUS_BROUILLON) {
return false;
}
return true;
}
break;
case 'PRE_EVAL':
if (!$this->security->isGranted('ROLE_PRE_EVAL')) {
return false;
}
if ($subject->getStatus() != Project::PROJECT_STATUS_ELIGIBLE) {
return false;
}
// est-ce que l'utilisateur est associé au projet en tant que pré-évaluateur ?
$up = $this->userProjectRepository->findOneBy(['user' => $this->security->getUser(), 'project' => $subject, 'type' => QuestionnaireResponse::QR_TYPE_PREEVAL]);
if (!$up) {
return false;
}
$aap = $subject->getAppelAProjet();
if ($aap->getDateOpenPreeval() && $aap->getDateOpenPreeval() < new DateTime()) {
// la date de fin n'est pas bloquante
return true;
}
break;
case 'THEMA':
if (!$this->security->isGranted('ROLE_THEMA')) {
return false;
}
if ($subject->getStatus() != Project::PROJECT_STATUS_ELIGIBLE) {
return false;
}
// est-ce que l'utilisateur est associé au projet en tant que évaluateur thématique ?
$up = $this->userProjectRepository->findOneBy(['user' => $this->security->getUser(), 'project' => $subject, 'type' => QuestionnaireResponse::QR_TYPE_EVAL_THEMA]);
if (!$up) {
return false;
}
$aap = $subject->getAppelAProjet();
if ($aap->getDateOpenPreeval() && $aap->getDateOpenPreeval() < new DateTime()) {
// la date de fin n'est pas bloquante
return true;
}
break;
case 'COORDO':
if (!$this->security->isGranted('ROLE_COORDONNATEUR')) {
return false;
}
if ($subject->getStatus() != Project::PROJECT_STATUS_ELIGIBLE) {
return false;
}
$aap = $subject->getAppelAProjet();
if ($aap->getDateOpenPreeval() && $aap->getDateOpenPreeval() < new DateTime()) {
// la date de fin n'est pas bloquante
// et il faut un questionnaire coordo (il n'y en a pas forcément)
if ($aap->getQuestionnaireEvalCoordo() !== null) {
return true;
}
}
break;
case 'CLONE_LI':
if (!$this->security->isGranted('ROLE_DRCI')) {
return false;
}
if ($subject->getDrci() !== $user->getDrci()) {
return false;
}
if ($subject->getStatus() != Project::PROJECT_STATUS_PRE_SELECTIONNE) {
return false;
}
$aap = $subject->getAppelAProjet();
if (!$aap->getQuestionnaireLi()) {
return false;
}
$now = new DateTime();
if ($aap->getDateOpenDc() < $now && $now < $aap->getDateCloseDc()) {
return true;
}
break;
case 'ADD_DC':
case 'DC_SUBMIT':
if (!$this->security->isGranted('ROLE_DRCI')) {
return false;
}
if ($subject->getDrci() !== $user->getDrci()) {
return false;
}
// comme ça, pas de problème pour les aap en 1 étape
if ($subject->getStatus() != Project::PROJECT_STATUS_PRE_SELECTIONNE) {
return false;
}
$now = new DateTime();
$aap = $subject->getAppelAProjet();
if ($aap->getDateOpenDc() < $now && $now < $aap->getDateCloseDc()) {
return true;
}
break;
case 'EXPERT':
if (!$this->security->isGranted('ROLE_EXPERT')) {
return false;
}
if ($subject->getStatus() != Project::PROJECT_STATUS_COMPLET) {
return false;
}
// est-ce que l'utilisateur est associé au projet en tant que expert ?
$up = $this->userProjectRepository->findOneBy(['user' => $this->security->getUser(), 'project' => $subject, 'type' => QuestionnaireResponse::QR_TYPE_EXPERT]);
if (!$up) {
return false;
}
$aap = $subject->getAppelAProjet();
if ($aap->getDateOpenExpert() && $aap->getDateOpenExpert() < new DateTime()) {
// la date de fin n'est pas bloquante
return true;
}
break;
case 'RAPPORT':
if (!$this->security->isGranted('ROLE_RAPPORT')) {
return false;
}
$aap = $subject->getAppelAProjet();
if ($aap->getQuestionnaireExpert()) {
if ($subject->getStatus() != Project::PROJECT_STATUS_EXPERTISE) {
return false;
}
} else {
if ($subject->getStatus() != Project::PROJECT_STATUS_COMPLET) {
return false;
}
}
// est-ce que l'utilisateur est associé au projet en tant que rapporteur ?
$up = $this->userProjectRepository->findOneBy(['user' => $this->security->getUser(), 'project' => $subject, 'type' => QuestionnaireResponse::QR_TYPE_RAPPORT]);
if (!$up) {
return false;
}
if ($aap->getDateOpenRapport() && $aap->getDateOpenRapport() < new DateTime()) {
// la date de fin n'est pas bloquante
return true;
}
break;
case 'EXPERT_3':
if (!$this->security->isGranted('ROLE_EXPERT_3')) {
return false;
}
if ($subject->getStatus() != Project::PROJECT_STATUS_RAPPORTE) {
return false;
}
// est-ce que l'utilisateur est associé au projet en tant que expert 3 ?
$up = $this->userProjectRepository->findOneBy(['user' => $this->security->getUser(), 'project' => $subject, 'type' => QuestionnaireResponse::QR_TYPE_EXPERT_3]);
if (!$up) {
return false;
}
$aap = $subject->getAppelAProjet();
if ($aap->getDateOpenExpert3() && $aap->getDateOpenExpert3() < new DateTime()) {
// la date de fin n'est pas bloquante
return true;
}
break;
}
return false;
}
}