<?php
namespace App\Security\Voter;
use App\Entity\AppelAProjet;
use App\Entity\Project;
use App\Entity\QuestionnaireResponse;
use App\Entity\User;
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 QuestionnaireResponseVoter 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', 'EDIT_STATUS', 'VIEW_PRIVATE'])
&& ($subject instanceof QuestionnaireResponse || $subject == QuestionnaireResponse::class);
}
protected function voteOnAttribute(string $attribute, $subject, TokenInterface $token): bool
{
/** @var QuestionnaireResponse $subject */
/** @var User $user */
$user = $token->getUser();
// if the user is anonymous, do not grant access
if (!$user instanceof UserInterface) {
return false;
}
switch ($attribute) {
case 'EDIT_STATUS':
if ($this->security->isGranted('ROLE_ADMIN_GIRCI')) {
return true;
}
break;
case 'EDIT':
$project = $subject->getProject();
if ($this->security->isGranted('ROLE_ADMIN_GIRCI')) {
return true;
}
if ($subject->getStatus() == QuestionnaireResponse::S_STATUS_DRAFT) {
if ($subject->getAuthor() === $user) {
// si li, li doc et dc, vérifier les dates de l'appel à projet
if (in_array($subject->getQuestionnaireType(), [QuestionnaireResponse::QR_TYPE_LI_I, QuestionnaireResponse::QR_TYPE_LI_DOC])) {
if ($project->getAppelAProjet()->getStatus() == AppelAProjet::AAP_STATUS_LI) {
return true;
}
} elseif (in_array($subject->getQuestionnaireType(), [QuestionnaireResponse::QR_TYPE_LI_R, QuestionnaireResponse::QR_TYPE_DC])) {
if ($project->getAppelAProjet()->getStatus() == AppelAProjet::AAP_STATUS_DC) {
return true;
}
} else {
return true;
}
}
// pour LIR et DC, tous les membres de la drci doivent pouvoir intervenir
if ($this->security->isGranted('ROLE_DRCI')) {
if (in_array($subject->getQuestionnaireType(), [QuestionnaireResponse::QR_TYPE_LI_R, QuestionnaireResponse::QR_TYPE_DC])) {
if ($project->getDrci() === $user->getDrci()) {
if ($project->getAppelAProjet()->getStatus() == AppelAProjet::AAP_STATUS_DC) {
return true;
}
}
}
}
}
break;
case 'VIEW':
$project = $subject->getProject();
if ($this->security->isGranted('ROLE_ADMIN_GIRCI')) {
return true;
}
// si c'est l'auteur, oui)
if ($subject->getAuthor() === $user) {
return true;
}
if ($this->security->isGranted('ROLE_PRE_EVAL')
|| $this->security->isGranted('ROLE_RAPPORT')
|| $this->security->isGranted('ROLE_COORDONNATEUR')
|| $this->security->isGranted('ROLE_METHODO')
) {
if ($project->getAppelAProjet()->getOuvert() === true) {
// attention, lors de la deuxième phase d'ouverture, il semblerait qu'ils ne puissent plus voir les théma ? à confirmer
return true;
}
}
switch ($subject->getQuestionnaireType()) {
case QuestionnaireResponse::QR_TYPE_LI_I:
case QuestionnaireResponse::QR_TYPE_LI_R:
// si on peut voir le projet, on peut voir la LI
return ($this->security->isGranted('VIEW', $project));
case QuestionnaireResponse::QR_TYPE_LI_DOC:
// si on peut voir le projet, on peut voir la LI doc
return ($this->security->isGranted('VIEW', $project));
case QuestionnaireResponse::QR_TYPE_PREEVAL:
// le porteur et le drci ont le droit de voir passé un certain statut du projet
if ($this->security->isGranted('ROLE_PORTEUR') || $this->security->isGranted('ROLE_DRCI')) {
if ($this->security->isGranted('VIEW', $project)) {
if (!in_array($project->getStatus(), [
Project::PROJECT_STATUS_BROUILLON,
Project::PROJECT_STATUS_DEPOSE,
Project::PROJECT_STATUS_ELIGIBLE,
Project::PROJECT_STATUS_NON_ELIGIBLE,
Project::PROJECT_STATUS_PRE_EVALUE
])) {
return true;
}
}
}
// les coordonnateur après le dépot dc
if ($this->security->isGranted('ROLE_COORDONNATEUR') || $this->security->isGranted('ROLE_METHODO')) {
if ($project->getAppelAProjet()->getDateCloseDc() < new \DateTime()) {
return true;
}
}
// les rapporteurs
if ($this->security->isGranted('ROLE_RAPPORT')) {
// todo : est-ce qu'on tient compte de la date ?
$up = $this->userProjectRepository->findBy(['user' => $user, 'project' => $project, 'type' => QuestionnaireResponse::QR_TYPE_RAPPORT]);
if (count($up) > 0) {
return true;
}
}
break;
case QuestionnaireResponse::QR_TYPE_EVAL_COORDO:
// les coordonnateur après le dépot dc
if ($this->security->isGranted('ROLE_COORDONNATEUR') || $this->security->isGranted('ROLE_METHODO')) {
if ($project->getAppelAProjet()->getDateCloseDc() < new \DateTime()) {
return true;
}
}
// les rapporteurs
if ($this->security->isGranted('ROLE_RAPPORT')) {
// todo : est-ce qu'on tient compte de la date ?
$up = $this->userProjectRepository->findBy(['user' => $user, 'project' => $project, 'type' => QuestionnaireResponse::QR_TYPE_RAPPORT]);
if (count($up) > 0) {
return true;
}
}
break;
// case QuestionnaireResponse::QR_TYPE_EVAL_THEMA:
// // personne
// return false;
case QuestionnaireResponse::QR_TYPE_DC:
// le drci associé
if ($this->security->isGranted('ROLE_DRCI')) {
if ($project->getDrci() === $user->getDrci()) {
return true;
}
}
// les girci partenaires dès qu'ils sont associés
if ($this->security->isGranted('ROLE_GIRCI_PARTENAIRE')) {
return ($this->security->isGranted('VIEW', $project));
}
// les coordo après la phase de dépot
if ($this->security->isGranted('ROLE_COORDONNATEUR') || $this->security->isGranted('ROLE_METHODO')) {
if ($project->getAppelAProjet()->getDateCloseDc() < new DateTime()) {
return true;
}
}
// les experts associés à partir de la date de début d'expertise
if ($this->security->isGranted('ROLE_EXPERT')) {
if ($project->getAppelAProjet()->getDateOpenExpert() && $project->getAppelAProjet()->getDateOpenExpert() < new DateTime()) {
$up = $this->userProjectRepository->findOneBy(['user' => $user, 'project' => $project, 'type' => QuestionnaireResponse::QR_TYPE_EXPERT]);
if ($up) {
return true;
}
}
}
// les rapporteurs associés
if ($this->security->isGranted('ROLE_RAPPORT')) {
// todo : est-ce qu'on tient compte de la date ?
$up = $this->userProjectRepository->findBy(['user' => $user, 'project' => $project, 'type' => QuestionnaireResponse::QR_TYPE_RAPPORT]);
if (count($up) > 0) {
return true;
}
}
// l'expert 3
if ($this->security->isGranted('ROLE_EXPERT_3')) {
// todo : est-ce qu'on tient compte de la date ?
$up = $this->userProjectRepository->findBy(['user' => $user, 'project' => $project, 'type' => QuestionnaireResponse::QR_TYPE_EXPERT_3]);
if (count($up) > 0) {
return true;
}
}
break;
case QuestionnaireResponse::QR_TYPE_EXPERT:
// les girci partenaires associés
if ($this->security->isGranted('ROLE_GIRCI_PARTENAIRE')) {
$up = $this->userProjectRepository->findBy(['project' => $project, 'girci' => $user->getGirci(), 'questionnaireResponse' => $subject]);
if (count($up) > 0) {
return true;
}
}
// les coordo après la phase de dépot
if ($this->security->isGranted('ROLE_COORDONNATEUR') || $this->security->isGranted('ROLE_METHODO')) {
if ($subject->getStatus() == QuestionnaireResponse::S_STATUS_SUBMIT) {
return true;
}
}
// les rapporteurs associés
if ($this->security->isGranted('ROLE_RAPPORT')) {
// todo : est-ce qu'on tient compte de la date ?
$up = $this->userProjectRepository->findBy(['user' => $user, 'project' => $project, 'type' => QuestionnaireResponse::QR_TYPE_RAPPORT]);
if (count($up) > 0) {
return true;
}
}
// l'expert 3
if ($this->security->isGranted('ROLE_EXPERT_3')) {
// todo : est-ce qu'on tient compte de la date ?
$up = $this->userProjectRepository->findBy(['user' => $user, 'project' => $project, 'type' => QuestionnaireResponse::QR_TYPE_EXPERT_3]);
if (count($up) > 0) {
return true;
}
}
if ($this->security->isGranted('ROLE_PORTEUR')) {
if ($project->getAuthor() === $user && $project->getDrci() === $user->getDrci()) {
if (in_array($project->getStatus(), [Project::PROJECT_STATUS_SELECTIONNE, Project::PROJECT_STATUS_NON_SELECTIONNE])) {
return true;
}
}
}
if ($this->security->isGranted('ROLE_DRCI')) {
if ($project->getDrci() === $user->getDrci()) {
if (in_array($project->getStatus(), [Project::PROJECT_STATUS_SELECTIONNE, Project::PROJECT_STATUS_NON_SELECTIONNE])) {
return true;
}
}
}
if ($this->security->isGranted('ROLE_EXPERT')) {
// pour l'autre expert, si le projet à un statut sélectionné ou non sélectionné
if (in_array($project->getStatus(), [Project::PROJECT_STATUS_SELECTIONNE, Project::PROJECT_STATUS_NON_SELECTIONNE])) {
$up = $this->userProjectRepository->findBy(['user' => $user, 'project' => $project, 'type' => QuestionnaireResponse::QR_TYPE_EXPERT]);
if (count($up) > 0) {
return true;
}
}
}
break;
case QuestionnaireResponse::QR_TYPE_RAPPORT:
// l'expert 3
if ($this->security->isGranted('ROLE_EXPERT_3')) {
// todo : est-ce qu'on tient compte de la date ?
$up = $this->userProjectRepository->findBy(['user' => $user, 'project' => $project, 'type' => QuestionnaireResponse::QR_TYPE_EXPERT_3]);
if (count($up) > 0) {
return true;
}
}
if ($this->security->isGranted('ROLE_PORTEUR')) {
if ($project->getAuthor() === $user && $project->getDrci() === $user->getDrci()) {
if (in_array($project->getStatus(), [Project::PROJECT_STATUS_SELECTIONNE, Project::PROJECT_STATUS_NON_SELECTIONNE])) {
return true;
}
}
}
if ($this->security->isGranted('ROLE_DRCI')) {
if ($project->getDrci() === $user->getDrci()) {
if (in_array($project->getStatus(), [Project::PROJECT_STATUS_SELECTIONNE, Project::PROJECT_STATUS_NON_SELECTIONNE])) {
return true;
}
}
}
// les coordo après la phase de dépot
if ($this->security->isGranted('ROLE_COORDONNATEUR') || $this->security->isGranted('ROLE_METHODO')) {
if ($subject->getStatus() == QuestionnaireResponse::S_STATUS_SUBMIT) {
return true;
}
}
if ($this->security->isGranted('ROLE_EXPERT')) {
if (in_array($project->getStatus(), [Project::PROJECT_STATUS_SELECTIONNE, Project::PROJECT_STATUS_NON_SELECTIONNE])) {
$up = $this->userProjectRepository->findBy(['user' => $user, 'project' => $project, 'type' => QuestionnaireResponse::QR_TYPE_EXPERT]);
if (count($up) > 0) {
return true;
}
}
}
break;
case QuestionnaireResponse::QR_TYPE_EXPERT_3:
if ($this->security->isGranted('ROLE_PORTEUR')) {
if ($project->getAuthor() === $user && $project->getDrci() === $user->getDrci()) {
if (in_array($project->getStatus(), [Project::PROJECT_STATUS_SELECTIONNE, Project::PROJECT_STATUS_NON_SELECTIONNE])) {
return true;
}
}
}
if ($this->security->isGranted('ROLE_DRCI')) {
if ($project->getDrci() === $user->getDrci()) {
if (in_array($project->getStatus(), [Project::PROJECT_STATUS_SELECTIONNE, Project::PROJECT_STATUS_NON_SELECTIONNE])) {
return true;
}
}
}
// les coordo après la phase de dépot
if ($this->security->isGranted('ROLE_COORDONNATEUR') || $this->security->isGranted('ROLE_METHODO')) {
if ($subject->getStatus() == QuestionnaireResponse::S_STATUS_SUBMIT) {
return true;
}
}
if ($this->security->isGranted('ROLE_EXPERT')) {
if (in_array($project->getStatus(), [Project::PROJECT_STATUS_SELECTIONNE, Project::PROJECT_STATUS_NON_SELECTIONNE])) {
$up = $this->userProjectRepository->findBy(['user' => $user, 'project' => $project, 'type' => QuestionnaireResponse::QR_TYPE_EXPERT]);
if (count($up) > 0) {
return true;
}
}
}
break;
}
break;
case 'VIEW_PRIVATE':
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->getProject()->getAppelAProjet()->getOuvert() === true) {
return true;
}
$up = $this->userProjectRepository->findBy(['user' => $user, 'project' => $subject->getProject()]);
if (count($up) > 0) {
return true;
}
}
// a le droit de voir si évaluateur du projet
if ($this->security->isGranted('ROLE_EXPERT')
|| $this->security->isGranted('ROLE_EXPERT_3')
) {
$up = $this->userProjectRepository->findBy(['user' => $user, 'project' => $subject->getProject()]);
if (count($up) > 0) {
return true;
}
}
break;
}
return false;
}
}