src/PaaBundle/Security/PaaVoter.php line 18

Open in your IDE?
  1. <?php
  2. // Classe prenant la décision d'accorder l'accès aux ressources de PAA
  3. // Via <ControllerObject>->get('security.authorization_checker')->isGranted('modiUsager', <idUsager>)
  4. // https://symfony.com/doc/3.4/components/security/authorization.html
  5. // https://symfony.com/doc/3.4/security/voters.html#security-voters-change-strategy
  6. namespace App\PaaBundle\Security;
  7. use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;
  8. use Doctrine\ORM\EntityManagerInterface;
  9. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  10. use Symfony\Component\Security\Core\Authorization\Voter\Voter;
  11. use App\PaaBundle\Entity\users;
  12. // use App\PaaBundle\Component\Paa\Paa_Constantes;     // LG 20211222
  13. use App\PaaBundle\Component\Paa\Paa_Constantes_Sécurité;
  14. class PaaVoter extends Voter {
  15.     // these strings are just invented: you can use anything
  16.     const MENU 'menu';
  17.     const VOIR 'voir';
  18.     const MODIFIER 'modi';
  19.     const AJOUTER 'ajou';
  20.     const MENU_DONNEESDEBASE "DonnéesDeBase";
  21.     const MENU_AUTRESLISTES "AutresListes";
  22.     const MENU_SEMAINEREELLE "SemaineRéelle";
  23.     const MENU_SEMAINETYPE "SemaineType";
  24.     const MENU_EDITIONS "Editions";
  25.     const MENU_OUTILS "Outils";
  26.     const MENU_USERS "Users";
  27.     const MENU_SEMAINEREELLE_NONPLANNING "SemaineRéelle_NonPlanning";
  28.     const MENU_USERS_NONDECONNEXION "User_NonDeconnexion";
  29.     const MENU_BACKOFFICE "BackOffice";
  30.     // TRINH ajouter 20220418
  31.     const MENU_TRINH "TRINH";
  32.     /**
  33.      * @var AccessDecisionManagerInterface
  34.      */
  35.     private $decisionManager;
  36.     private $entityManager;
  37.     /**
  38.      * PaaVoter constructor.
  39.      *
  40.      * @param AccessDecisionManagerInterface $decisionManager
  41.      */
  42.     public function __construct(AccessDecisionManagerInterface $decisionManagerEntityManagerInterface $em) {
  43.         $this->decisionManager $decisionManager;
  44.         $this->entityManager $em;
  45.     }
  46.     protected function supports($attribute$item 0) {
  47.         // if the attribute isn't one we support, return false
  48.         if (!in_array(substr($attribute04), array(self::MENUself::VOIRself::MODIFIERself::AJOUTER)) 
  49.                         /*&& !in_array($attribute, array("IS_AUTHENTICATED_FULLY", "IS_AUTHENTICATED_REMEMBERED"))*/) {
  50.             return false;
  51.         }
  52.         return true;
  53.     }
  54.     protected function voteOnAttribute($attribute$item 0TokenInterface $token) {
  55.         $user $token->getUser();
  56.         if (!$user instanceof users) {
  57.             // the user must be logged in; if not, deny access
  58.             return false;
  59.         }
  60.         $lsTypeAccès substr($attribute04);  // self::VOIR ou self::MODIFIER
  61.         $lsTypeRessource substr($attribute4);  // "Usager", "Intervenant", ...
  62.         if ($lsTypeAccès == self::MENU) {
  63.             return $this->voteOnMenu($item$user$token);
  64.         } else {
  65.             return $this->voteOnDataAccess($lsTypeAccès$lsTypeRessource$item$user$token);
  66.         }
  67.         throw new \LogicException('This code should not be reached!');
  68.     }
  69.     // Déterminer si l'user en cours a droit au menu demandé
  70.     private function voteOnMenu($psMenu$poUserTokenInterface $token) {
  71.         switch ($psMenu) {
  72.             case self::MENU_USERS:
  73.                 return $this->decisionManager->decide($token, array('ROLE_ADMIN'));
  74.             case self::MENU_DONNEESDEBASE:
  75.                 return $this->decisionManager->decide($token, array('ROLE_ADMIN'));
  76.                             
  77.             case self::MENU_AUTRESLISTES:
  78.                 return $this->decisionManager->decide($token, array('ROLE_ADMIN'));
  79.             case self::MENU_TRINH:
  80.                 return $this->decisionManager->decide($token, array('ROLE_ADMIN'));        
  81.             case self::MENU_EDITIONS:
  82.                 return $this->decisionManager->decide($token, array('ROLE_ADMIN'));
  83.                             
  84.             case self::MENU_OUTILS:
  85.                 return $this->decisionManager->decide($token, array('ROLE_ADMIN'));
  86.             case self::MENU_SEMAINETYPE:
  87.                 return $this->decisionManager->decide($token, array('ROLE_CONCEPTEUR'));
  88.             case self::MENU_SEMAINEREELLE:
  89.                 return $this->decisionManager->decide($token, array('ROLE_ENSEIGNANT')) || $this->decisionManager->decide($token, array('ROLE_ETUDIANT'));
  90.              case self::MENU_SEMAINEREELLE_NONPLANNING:
  91.                 return $this->decisionManager->decide($token, array('ROLE_ADMIN')) || $this->decisionManager->decide($token, array('ROLE_CONCEPTEUR'));
  92.                             
  93.             case self::MENU_USERS_NONDECONNEXION:
  94.                 return $this->decisionManager->decide($token, array('ROLE_ADMIN'));
  95.             case self::MENU_BACKOFFICE:
  96.                 return $this->decisionManager->decide($token, array('ROLE_ADMIN'));
  97.             default:
  98.                 throw new \LogicException('Cas de menu non prévu : psMenu = $psMenu');
  99.         }
  100.     }
  101.     private function getDroitsCurrentUser($poUser) {
  102.                 if ($poUser->getctype_res() == 'I') {
  103.             // Intervenant : voir s'il a les droits
  104.             $liIntervenant $poUser->getiid_res();
  105. // $liIntervenant = 923456789 ;
  106. // $loIntervenant = $this->entityManager->getRepository("PaaBundle:intervenants")->find($liIntervenant)
  107.             if ($liIntervenant == null) {
  108.                 // Cet user n'a pas d'intervenant
  109. //                    echo $Err1 ;
  110.             } else if (($loIntervenant $this->entityManager->getRepository("PaaBundle:intervenants")->find($liIntervenant)) == null) {
  111.                 
  112.             } else if ($loIntervenant == null) {
  113.                 // Cet intervenant n'a pas été retrouvé
  114. //                    echo $Err2 ;
  115.             } else {
  116.                 return $loIntervenant->getIdroitsw();
  117.             }
  118.         }
  119.         return 0;
  120.     }
  121.     // Vérifie si l'un au moins des rôles demandés est possédé par l'user décrit dans le token
  122.     // Astuce car je ne sais pas changer le mode de décision de $this->decisionManager
  123.     // LG 20211223
  124.     private function décideAffirmative(TokenInterface $token$paRolesAutorisés) {
  125.         $lbDécision false ;
  126.         foreach ($paRolesAutorisés as $role) {
  127.             if ($this->decisionManager->decide($token, array($role))) {
  128.                 // Le décitionManager accepte ce rôle : c'est bon
  129.                 $lbDécision true ;
  130.             }
  131.         }
  132.         return $lbDécision ;
  133.     }
  134.     private function voteOnDataAccess($psTypeAccès$psTypeRessource$item$poUserTokenInterface $token) {
  135.         // ---------------------------------------------------------------------------------------
  136.         // Récursivité sur une liste d'items
  137.         if (Vartype($item) == "C") {
  138.             // On a fourni une liste d'items
  139.             // Rappeller cette fonction pour chaque item
  140.             $laItems explode(","$item);
  141.             foreach ($laItems as $lsItem) {
  142.                 $liItem intval($lsItem);
  143.                 if (!$lsItem) {
  144.                     // Item vide : RAS
  145.                 } else
  146.                 if (!$this->voteOnDataAccess($psTypeAccès$psTypeRessource$liItem$poUser$token)) {
  147.                     // Pas les droits sur cet item, pas la peine d'examiner les autres
  148.                     return false;
  149.                 }
  150.             }
  151.             // Si on arrive là, c'est que les droits sont OK
  152.             return true;
  153.         }
  154.         // Fin de récursivité sur une liste d'items
  155.         // ---------------------------------------------------------------------------------------
  156.         if (in_array($psTypeRessource, ['seances''seancesTrad''ModiHorairesSéance''EnlèveSéance']) && $item) {
  157.             // On cherche à voir, modifier ou déplacer une séance
  158. // // LG 20240328 début
  159. // Annulé car seule les séances créés par l'utilisateur en cours devraient être accessibles pour les AB du SG "divers" (en plus des séances qui le concernent lui) 
  160. //             if ($poUser->hasRole('ROLE_CONCEPTEUR')) {
  161. //                 // Concepteur de planning : droits sur toutes les séances
  162. //                 return true ;
  163. //             }
  164. // // LG 20240328 fin
  165.             $loSéancesRepository $this->entityManager->getRepository("PaaBundle:seances");
  166.             $loSéance $loSéancesRepository->find($item) ;
  167.             if ($loSéance && $loSéance->estSGABDivers()) {
  168.                 // Cette séance est du sous-groupe d'actibases "Divers"
  169.                 // Seul le participant lui-même peut voir ou modifier cette séance
  170.                 $loUser $token->getUser();
  171.                 if ($loUser->getiIdRes() && $loUser->getcTypeRes() == "I") {
  172.                     // L'utilisateur en cours est un intervanant
  173.                     // Il a le droit s'il est l'intervenant de cette séance
  174.                     return $loSéancesRepository->SéanceUtiliseRessource($item$loUser->getcTypeRes(), $loUser->getiIdRes()) ;
  175.                 } else {
  176.                     // L'utilisateur en cours n'est pas un intervanant
  177.                     return false ;
  178.                 }
  179.             }
  180.         }
  181.         // Simplification abusive à corriger par la suite
  182.         switch ($psTypeAccès) {
  183.             case self::VOIR:
  184.                 $lbDecision $this->décideAffirmative($token, array('ROLE_ADMIN''ROLE_ENSEIGNANT''ROLE_ETUDIANT')) ;
  185.                 return $lbDecision ;
  186.             case self::MODIFIER:
  187.             //return true;
  188.             case self::AJOUTER:
  189.             //return true;
  190.         }
  191. // LG 20210921 déac début : cause une récursivité infinie
  192. //// LG 20190830 début
  193. //        if (!$this->voteOnDataAccess(self::VOIR, $psTypeRessource, $item, $poUser, $token)) {
  194. //            // L'utilisateur en cours n'a même pas le droit de voir
  195. //            return false;
  196. //        }
  197. //// LG 20190830 fin
  198. // LG 20210921 déac fin
  199.         $lbAutorise $poUser->hasRole('ROLE_ADMIN');
  200.         if ($lbAutorise) return true;
  201. // LG 20221014 déplacé + haut début
  202. //         // ---------------------------------------------------------------------------------------
  203. //         // Récursivité sur une liste d'items
  204. //         if (Vartype($item) == "C") {
  205. //             // On a fourni une liste d'items
  206. //             // Rappeller cette fonction pour chaque item
  207. //             $laItems = explode(",", $item);
  208. //             foreach ($laItems as $lsItem) {
  209. //                 $liItem = intval($lsItem);
  210. //                 if (!$lsItem) {
  211. //                     // Item vide : RAS
  212. //                 } else
  213. //                 if (!$this->voteOnDataAccess($psTypeAccès, $psTypeRessource, $liItem, $poUser, $token)) {
  214. //                     // Pas les droits sur cet item, pas la peine d'examiner les autres
  215. //                     return false;
  216. //                 }
  217. //             }
  218. //             // Si on arrive là, c'est que les droits sont OK
  219. //             return true;
  220. //         }
  221. //         // Fin de récursivité sur une liste d'items
  222. //         // ---------------------------------------------------------------------------------------
  223. // LG 20221014 déplacé + haut fin
  224.         $lbAutorise false;
  225.         if (!$lbAutorise && $psTypeRessource == 'users') {
  226.             // L'utilisateur actuel n'a pas les droits, mais peut-être s'agit-il de sa propre fiche ?
  227.             $loUser $token->getUser();
  228.             if ($loUser) {
  229.                 $lbAutorise = (strval($loUser->getid()) === strval($item));
  230.                 if ($lbAutorise) {
  231.                     $peutchangerprofil $loUser->isLPeutChangerProfil();
  232.                     $lbAutorise false;
  233.                 }
  234.             }
  235.         } else if (false) {
  236.             // Pas d'accès en écriture pour les étudiants
  237.         } else {
  238.             // On doit se baser sur les droits de l'user courant
  239.             $loUser $token->getUser();
  240.             $liId_User $loUser->getid();
  241.             $liDroits $this->getDroitsCurrentUser($loUser);
  242.             if ($liDroits == Paa_Constantes_Sécurité::eiDroitsW_PredefAdministrateur) {
  243.                 return true;
  244.             }
  245.             if ($liDroits == Paa_Constantes_Sécurité::eiDroitsW_PredefAucun) {
  246.             }
  247.                 if ($poUser->hasRole('ROLE_ENSEIGNANT_POSEDIVERS')
  248.                         && !$poUser->hasRole('ROLE_CONCEPTEUR')
  249.                         ) {
  250.                     // L'utilisateur en cours n'est pas concepteur, as a le droit de poser des séances "Divers" pour lui-même
  251.                     if (in_array($psTypeRessource, ['PoseSéance'])) {
  252.                         // L'utilisateur en cours cherche à poser une séance
  253.                         $loActisRepository $this->entityManager->getRepository("PaaBundle:activites");
  254.                         $loActi $loActisRepository->find($item) ;
  255.                         // CB 20221010 old if ($loActi && $loActi->estABDivers()) {
  256.                         if ($loActi && $loActi->estSGABDivers()) {
  257.                             // La séance que souhaite poser cet intervenant est une séance de l'AB "Divers"
  258.                             return true ;
  259.                         } else {
  260.                             // La séance que souhaite poser cet intervenant n'est pas une séance de l'AB "Divers"
  261.                             return false ;
  262.                         }
  263.                     }
  264.                     if (in_array($psTypeRessource, ['seances''seancesTrad''ModiHorairesSéance''EnlèveSéance'])) {
  265.                         // L'enseignant cherche à déplacer une séance
  266.                         $loSéancesRepository $this->entityManager->getRepository("PaaBundle:seances");
  267.                         $loSéance $loSéancesRepository->find($item) ;
  268. // LG 20221012 old                        if ($loSéance && $loSéance->estABDivers()) {
  269.                         if ($loSéance && $loSéance->estSGABDivers()) {
  270.                             // S'assurer que les droits pris en compte contiennent le bit "SéancesQuiConcernentIntervenant"
  271.                             $liDroits |= Paa_Constantes_Sécurité::eiDroits_SéancesQuiConcernentIntervenant ;
  272.                         } else {
  273.                             // La séance que souhaite poser cet intervenant n'est pas une séance de l'AB "Divers"
  274.                             return false ;
  275.                         }
  276.                     }
  277.                 }
  278.             // Cas de figure traités selon le modèle de sécurité.prg, fonction "Autorise"
  279.             // Transformation de certains cas
  280.             if (in_array($psTypeRessource, ['PoseSéance''EnlèveSéance''ModifieSéance''ModiHorairesSéance''SesPropresParticipations''seancesTrad'])) {
  281.                 // Il faut tester si c'est une séance d'absence ou non
  282.                 $loSéancesRepository $this->entityManager->getRepository("PaaBundle:seances");
  283.                 $liActiBase null;
  284.                 If (Upper($psTypeRessource) === Upper("PoseSéance")) {
  285. // echo $err1 ;
  286.                     // On passe l'Id d'activité
  287.                     // Déterminer si c'est une absence et en profiter pour récupérer l'activité de base
  288.                     $liActi $item;
  289.                     $liSeance null;
  290.                     $lbEstAbsence $loSéancesRepository->EstAbsence($liSeance$liActi$liActiBase);
  291.                 } else {
  292.                     // On passe l'Id de séance
  293.                     // Déterminer si c'est une absence et en profiter pour récupérer l'activité de base
  294.                     $liActi null;
  295.                     $liSeance $item;
  296.                     $lbEstAbsence $loSéancesRepository->EstAbsence($liSeance$liActi$liActiBase);
  297.                 }
  298.                 if ($lbEstAbsence) { // C'est une absence
  299.                     $psTypeRessource .= "Absence";
  300.                 } else {
  301.                     $lbEstPrésence $loSéancesRepository->EstPrésence(nullnull$liActiBase);
  302.                     If ($lbEstPrésence) { // C'est une présence
  303.                         $psTypeRessource .= "Présence";
  304.                     }
  305.                 }
  306.             }
  307.             // Modifier une séance
  308.             if (in_array($psTypeRessource, ['EnlèveSéance''ModiHorairesSéance''ChangeActivitéDeSéance''SesPropresParticipations''seances''seancesTrad'])) {
  309.                 // désactivé car absent de Sécurité.PRG if ($liDroits & Paa_Constantes_Sécurité::eiDroits_Séances > 0) return true ;
  310. // echo $err2 ;
  311. // LG 20220926 début
  312.                 if ($poUser->hasRole('ROLE_CONCEPTEUR')) {
  313.                     return true;
  314.                 }
  315. // LG 20220926 fin
  316.                 if ($liDroits Paa_Constantes_Sécurité::eiDroits_ModifSéanceActiCrééeParAutre 0)
  317.                     return true;
  318.                 $loSéancesRepository $this->entityManager->getRepository("PaaBundle:seances");
  319. // LG 20220110 old                if ($loSéancesRepository->RtvUserCréateur($item) == $liId_User) {
  320.                 if ($loSéancesRepository->RtvUserCréateur($item) == $loUser->getiIdRes()) {
  321.                     // L'utilisateur en cours est le créateur de la séance
  322.                     // Il peut la modifier
  323.                     return true;
  324.                 }
  325.                 If ($liDroits Paa_Constantes_Sécurité::eiDroits_SéancesQuiConcernentIntervenant
  326.                         And $item
  327.                         And $loSéancesRepository->SéanceUtiliseRessource($item$loUser->getcTypeRes(), $loUser->getiIdRes())
  328.                         And !$loSéancesRepository->EstAbsence($item)) {
  329.                     // Droits sur ses propres séances et cette séance le concerne
  330.                     return true;
  331.                 }
  332. // LG : Obsolète ? En tout cas, je n'ai pas fini de traduire ce code depuis VFP
  333. //                If ($liDroits & Paa_Constantes_Sécurité::eiDroits_SesPropresParticipations > 0
  334. //                                        And $item
  335. //                                        And Evl($pvVar2, "") = "I"
  336. //                                        And Evl($pvVar3, 0) = $liId_User
  337. //                                        And $loSéancesRepository->SéanceUtiliseRessource($item, "I", $liId_User)
  338. //                                        And ($pvVar4    //&&  pvVar4 : .T. si c'est pour l'ajustement d'une participation à l'intérieur d'une séance 
  339. //                                            Or $loSéancesRepository->EstAbsence($item) or $loSéancesRepository->EstPrésence($item)
  340. //                                            Or $loSéancesRepository->RtvUserCréateur("tSeances", $item) = $liId_User)) {
  341. //                    return true ;
  342. //                }
  343.             } else if (in_array($psTypeRessource, ['GetId_Activité''PoseSéance'])) {
  344. // LG 20220926 début
  345.                 if ($poUser->hasRole('ROLE_CONCEPTEUR')) {
  346.                     return true;
  347.                 } else
  348. // LG 20220926 fin
  349.                 If ($liDroits Paa_Constantes_Sécurité::eiDroits_Séances 0) {
  350.                     return true;
  351.                 } Else If ($liDroits Paa_Constantes_Sécurité::eiDroits_SesPropresParticipations 0
  352.                         And $item
  353. // LG 20220110 old                        And $loSéancesRepository->SéanceUtiliseRessource($item, "I", $liId_User)) {
  354.                         And $loSéancesRepository->SéanceUtiliseRessource($item$loUser->getcTypeRes(), $loUser->getiIdRes())) {
  355.                     // Droits sur ses propres participations et cette séance le concerne
  356.                     return true;
  357.                 }
  358.             } else {
  359.                 // Cas non prévu
  360.             }
  361.         }
  362.         return $lbAutorise;
  363.     }
  364. }