src/Listener/CheckCguListener.php line 54

Open in your IDE?
  1. <?php
  2. namespace App\Listener;
  3. use App\Entity\User;
  4. use App\Services\DTV\YamlConfig\YamlReader;
  5. use DateTime;
  6. use Doctrine\ORM\EntityManagerInterface;
  7. use Psr\Log\LoggerInterface;
  8. use Symfony\Component\HttpFoundation\RedirectResponse;
  9. use Symfony\Component\HttpFoundation\RequestStack;
  10. use Symfony\Component\HttpKernel\Event\ResponseEvent;
  11. use Symfony\Component\Routing\RouterInterface;
  12. use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
  13. use Doctrine\Persistence\ManagerRegistry;
  14. class CheckCguListener
  15. {
  16. private TokenStorageInterface $token;
  17. private RouterInterface $router;
  18. private EntityManagerInterface $em;
  19. private YamlReader $yamlReader;
  20. private RequestStack $requestStack;
  21. private LoggerInterface $logger;
  22. private ManagerRegistry $managerRegistry;
  23. public function __construct(
  24. EntityManagerInterface $em,
  25. TokenStorageInterface $token,
  26. RouterInterface $router,
  27. YamlReader $yamlReader,
  28. RequestStack $requestStack,
  29. LoggerInterface $logger,
  30. ManagerRegistry $managerRegistry
  31. ) {
  32. $this->token = $token;
  33. $this->router = $router;
  34. $this->em = $em;
  35. $this->yamlReader = $yamlReader;
  36. $this->requestStack = $requestStack;
  37. $this->logger = $logger;
  38. $this->managerRegistry = $managerRegistry;
  39. }
  40. /**
  41. * @param ResponseEvent $event
  42. *
  43. * @return void
  44. */
  45. public function onKernelResponse(ResponseEvent $event)
  46. {
  47. $request = $event->getRequest();
  48. $global = $this->yamlReader->getGlobal();
  49. // Dans Symfony, le type de requête "1" signifie généralement une requête principale
  50. if ($event->getRequestType() !== 1) {
  51. return;
  52. }
  53. if ($request->isXmlHttpRequest()) {
  54. return;
  55. }
  56. if ($request->isXmlHttpRequest()) {
  57. return;
  58. }
  59. // si on est sur une page statique, on ne check pas les CGU
  60. if (in_array(
  61. $request->get('_route'),
  62. [
  63. 'static_file_folder',
  64. 'static_project_file',
  65. 'front_common_css_custom',
  66. 'front_user_accept_cgu_first',
  67. 'front_user_accept_cgu_only',
  68. 'front_user_welcome_register',
  69. 'front_user_password',
  70. ],
  71. )) {
  72. return;
  73. }
  74. if (NULL !== $this->token->getToken()) {
  75. $token = $this->token->getToken();
  76. // L'utilisateur est en train d'impersonner un autre utilisateur, donc on ne fait rien
  77. if ($token && in_array('ROLE_PREVIOUS_ADMIN', $token->getRoleNames())) {
  78. return;
  79. }
  80. /** @var User $user */
  81. $user = $this->token->getToken()->getUser();
  82. $user = $this->em->getRepository(User::class)->findOneBy([
  83. 'id' => $user->getId()
  84. ]);
  85. if ($user instanceof User) {
  86. $this->updateUserLastActivity($user);
  87. $cguToValidate = true;
  88. if(isset($global['cgu_to_validate']) && $global['cgu_to_validate'] === FALSE) {
  89. $cguToValidate = false;
  90. }
  91. if($cguToValidate){
  92. // L'utilisateur est de type developer ou super-admin, on passe directement en actif
  93. if ($user->isDeveloper() || $user->isSuperAdmin()) {
  94. if ($user->getStatus() == 'cgu_pending' || $user->getCguAt() === NULL) {
  95. $user->setStatus('enabled')
  96. ->setCguAt(new DateTime())
  97. ;
  98. $this->em->flush();
  99. }
  100. return;
  101. } // Sinon, on passe par la validation des CGU
  102. elseif (NULL === $user->getCguAt() || $user->getStatus() === 'cgu_pending') {
  103. $event->setResponse(
  104. new RedirectResponse(
  105. $this->router->generate('front_user_accept_cgu_only'),
  106. ),
  107. );
  108. }
  109. }
  110. // L'utilisateur est en train d'impersonner un autre utilisateur, donc on ne fait rien
  111. if ($token && in_array('ROLE_PREVIOUS_ADMIN', $token->getRoleNames())) {
  112. return;
  113. }
  114. // TODO: Si on est sur un enfant d'un portail il faut gérer le fait de rediriger sur le portail avec un message clair
  115. // Si le password de l'utilisateur est expiré, on le redirige vers la page de changement de mot de passe, sauf si on est déjà sur cette page
  116. if (!$user->isDeveloper() && $request->get('_route') !== 'front_user_password')
  117. {
  118. $now = new DateTime();
  119. $passwordUpdatedAt = $user->getPasswordUpdatedAt() ?? (new DateTime())->modify('-370 days');
  120. $date = $now->diff($passwordUpdatedAt);
  121. $global = $this->yamlReader->getGlobal();
  122. $remainingPasswordValidityDays = $global[ 'login_security' ][ 'password_validation_days' ] ?? 365;
  123. $rest = $remainingPasswordValidityDays - $date->days;
  124. if ($rest < 0) {
  125. $session = $this->requestStack->getSession();
  126. $session->getFlashBag()->add(
  127. 'danger',
  128. 'Votre mot de passe a expiré ! Veuillez le mettre à jour.',
  129. );
  130. $event->setResponse(
  131. new RedirectResponse(
  132. $this->router->generate('saml_logout'),
  133. ),
  134. );
  135. }
  136. }
  137. }
  138. }
  139. }
  140. /**
  141. * Met à jour la date de dernière activité de l'utilisateur
  142. *
  143. * @param User $user Utilisateur
  144. *
  145. * @return void
  146. */
  147. private function updateUserLastActivity(User $user): void
  148. {
  149. if(!$this->em->isOpen()){
  150. $this->managerRegistry->resetManager();
  151. $user = $this->em->getRepository(User::class)->findOneBy([
  152. 'id' => $user->getId()
  153. ]);
  154. }else{
  155. $this->em->refresh($user);
  156. }
  157. // Si la dernière activité de l'utilisateur date de moins de 1H, on ne fait rien
  158. $now = new DateTime();
  159. $timestampDebut = $user->getLastActivity() ? $user->getLastActivity()->getTimestamp() : 0;
  160. $timestampFin = $now->getTimestamp();
  161. $diff = $timestampFin - $timestampDebut;
  162. if ($diff >= 3600) {
  163. try {
  164. $user->setLastActivity(new DateTime());
  165. $this->em->flush();
  166. } catch (\Exception $e) {
  167. $this->logger->error('Impossible de mettre à jour la date de dernière activité de l\'utilisateur.', [
  168. 'user' => $user->getId(),
  169. 'error' => $e->getMessage(),
  170. ]);
  171. }
  172. }
  173. }
  174. }