src/Controller/AuthentificationController.php line 102

Open in your IDE?
  1. <?php
  2. namespace App\Controller;
  3. use App\Entity\utilisateur\UtilisateurProfil;
  4. use App\Entity\utilisateur\Utilisateurs;
  5. use App\Form\administration\ResetMdpFormType;
  6. use App\Form\AuthentificationFormType;
  7. use App\Form\ForgetFormType;
  8. use App\Form\ResetFormType;
  9. use App\Form\CreatePasswordFormType;
  10. use App\Helpers\Helpers;
  11. use App\Repository\administration\UtilisateurSocieteRepository;
  12. use App\Repository\administration\UtilisateursRepository;
  13. use App\Repository\Utilisateur\UtilisateurSocieteAssociationRepository;
  14. use Doctrine\ORM\Mapping as ORM;
  15. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  16. use Symfony\Bundle\FrameworkBundle\Translation\Translator;
  17. use Symfony\Component\HttpFoundation\JsonResponse;
  18. use Symfony\Component\Mailer\Exception\TransportExceptionInterface;
  19. use Symfony\Component\Routing\Annotation\Route;
  20. use Symfony\Component\HttpFoundation\Request;
  21. use Symfony\Component\HttpFoundation\Response;
  22. use Doctrine\ORM\EntityManagerInterface;
  23. use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
  24. use Symfony\Component\Security\Core\Exception\AccessDeniedException;
  25. use Symfony\Contracts\Translation\TranslatorInterface;
  26. use Symfony\Component\Mailer\MailerInterface;
  27. use Symfony\Component\Mime\Email;
  28. use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
  29. use Symfony\Component\Security\Csrf\CsrfToken;
  30. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  31. class AuthentificationController extends AbstractController
  32. {
  33. /**
  34. * @ORM\Column(type="string")
  35. */
  36. private $objectManager;
  37. private const MAINTENANCE_FILE = __DIR__ . '/../../var/.maintenance';
  38. public function __construct(EntityManagerInterface $objectManager) {
  39. $this->objectManager = $objectManager;
  40. }
  41. public function setConnectionSessions($res, $utilisateur, $utilisateurSocieteAssociation, $repository)
  42. {
  43. $token = new UsernamePasswordToken($res, null, 'main', $utilisateur->getRoles());
  44. $this->get('security.token_storage')->setToken($token);
  45. $this->get('session')->set('_security_main', serialize($token));
  46. $utilisateurProfil = new UtilisateurProfil($res->getFkUtilisateurProfil()->getIdUtilisateurProfil(),$res->getFkUtilisateurProfil()->getLibelle());
  47. $this->get('session')->set('profil', $res->getFkUtilisateurProfil());
  48. $this->get('session')->set('societe', $res->getFkUtilisateurSociete());
  49. $arrayListeSocieteAssocie = [$res->getFkUtilisateurSociete()->getIdUtilisateurSociete()];
  50. $listeSocieteAssocie = $utilisateurSocieteAssociation->findByFkUtilisateurSocieteIdParent($res->getFkUtilisateurSociete()->getIdUtilisateurSociete());
  51. foreach($listeSocieteAssocie as $associe){
  52. $arrayListeSocieteAssocie[] = $associe->getFkUtilisateurSocieteId()->getIdUtilisateurSociete();
  53. }
  54. $this->get('session')->set('ListeDeSesSociete', $arrayListeSocieteAssocie);
  55. $menu = $repository->getUtilisateurMenu($res->getIdUtilisateur(),$utilisateurProfil->getIdUtilisateurProfil());
  56. $this->get('session')->set('menu',$menu);
  57. $this->get('session')->set('user',$res->getIdUtilisateur());
  58. $this->get('session')->set('accesMemo', $res->getAccesMemo());
  59. $this->get('session')->set('accesElium', $res->getAccesElium());
  60. }
  61. /**
  62. * @Route("/{_locale<%app.supported_locales%>}/login", name="login")
  63. * @param Request $request
  64. * @param UtilisateursRepository $repository
  65. * @param TranslatorInterface $translator
  66. * @param UtilisateurSocieteAssociationRepository $utilisateurSocieteAssociation
  67. * @return Response
  68. * @throws \Doctrine\DBAL\Driver\Exception
  69. * @throws \Doctrine\DBAL\Exception
  70. * @param MailerInterface $mailer
  71. */
  72. public function authentification(Request $request, UtilisateursRepository $repository,TranslatorInterface $translator,
  73. UtilisateurSocieteAssociationRepository $utilisateurSocieteAssociation,
  74. CsrfTokenManagerInterface $csrfTokenManager, MailerInterface $mailer) : Response
  75. {
  76. $session = $request->getSession();
  77. $em = $this->getDoctrine()->getManager();
  78. $remainingAttemps = 3;
  79. if ($session->has('societe')) {
  80. return $this->redirectToRoute('index');
  81. }
  82. $utilisateur = new Utilisateurs();
  83. $form = $this->createForm(AuthentificationFormType::class, $utilisateur);
  84. $form->handleRequest($request);
  85. if ($form->isSubmitted() && $form->isValid()) {
  86. $identifiant = $request->request->get('authentification_form')['identifiant'];
  87. $pwd = $request->request->get('authentification_form')['motdepasse'];
  88. $submittedToken = $request->request->get('authentification_form')['_token'] ?? null;
  89. $connectionIsAllowed = false;
  90. if (!$csrfTokenManager->isTokenValid(new CsrfToken('task_item', $submittedToken))) {
  91. throw $this->createAccessDeniedException('Invalid CSRF token.');
  92. }
  93. if($identifiant && $pwd) {
  94. $hashedPwd = $repository->getHashedPwd($identifiant);
  95. if(!$hashedPwd) {
  96. $this->getLog($request, 'Fail', 'Wrong credentials - Email does not exist');
  97. $this->addFlash('danger', $translator->trans('message.error_auth'));
  98. return $this->render('authentification/index.html.twig', [
  99. 'form' => $form->createView(),
  100. 'remainingAttempts' => null,
  101. 'accountActivated' => null,
  102. ]);
  103. }
  104. }
  105. if (password_verify($pwd, $hashedPwd['pwd'])) {
  106. $connectionIsAllowed = true;
  107. }
  108. if($connectionIsAllowed) {
  109. $resLogin = $repository->logInManagement($identifiant);
  110. if($resLogin) {
  111. $this->setConnectionSessions($resLogin[0], $utilisateur, $utilisateurSocieteAssociation, $repository);
  112. $this->getLog($request, 'Success', 'Correct credentials');
  113. return $this->redirectToRoute('index');
  114. }
  115. // SI USER NOT VERIFIED OU COMPTE DESACTIVE //
  116. else {
  117. $this->getLog($request, 'Fail', 'Account not verified / Account blocked');
  118. $this->addFlash('danger', $translator->trans('message.error_auth'));
  119. return $this->render('authentification/index.html.twig', [
  120. 'form' => $form->createView(),
  121. 'remainingAttempts' => null,
  122. 'accountActivated' => null,
  123. ]);
  124. }
  125. }
  126. else {
  127. $user = $repository->findOneByIdentifiant($identifiant);
  128. if($user) {
  129. $remainingAttemps = $user->getNbEssaiAvantBloquage();
  130. if ($remainingAttemps > 0 && $user->getIsVerified() != 0) {
  131. $user->setNbEssaiAvantBloquage($remainingAttemps - 1);
  132. if (($remainingAttemps - 1) == 0) {
  133. $user->setCompteDesactive(true);
  134. $messageToReseller = new Email();
  135. $messageToReseller->from($_ENV['MAILER_SENDER']);
  136. $messageToReseller->to($identifiant);
  137. $messageToReseller->subject($translator->trans('mail.objet.account-blocked-reseller',[],'mail+intl-icu'));
  138. $corps = $translator->trans('mail.account-blocked-reseller',[],'mail+intl-icu');
  139. $corps = utf8_decode($corps);
  140. $messageToReseller->html($corps,'text/html','UTF-8');
  141. $messageAdmin = new Email();
  142. $messageAdmin->from($_ENV['MAILER_SENDER']);
  143. $messageAdmin->to('administratif@planet-monetic.fr');
  144. $messageAdmin->subject($translator->trans('mail.objet.account-blocked',[],'mail+intl-icu'));
  145. $corps = $translator->trans('mail.account-blocked',['%$identifiant%' => $identifiant],'mail+intl-icu');
  146. $corps = utf8_decode(str_replace('%identifiant%',$identifiant,$corps));
  147. $messageAdmin->html($corps,'text/html','UTF-8');
  148. $messageToDev = new Email();
  149. $messageToDev->from($_ENV['MAILER_SENDER']);
  150. $messageToDev->to('developpement@planet-monetic.fr');
  151. $messageToDev->subject($translator->trans('mail.objet.account-blocked',[],'mail+intl-icu'));
  152. $corps = $translator->trans('mail.account-blocked',['%$identifiant%' => $identifiant],'mail+intl-icu');
  153. $corps = utf8_decode(str_replace('%identifiant%',$identifiant,$corps));
  154. $messageToDev->html($corps,'text/html','UTF-8');
  155. $mailer->send($messageToReseller);
  156. $mailer->send($messageAdmin);
  157. $mailer->send($messageToDev);
  158. }
  159. $em->persist($user);
  160. $em->flush();
  161. }
  162. }
  163. $this->getLog($request, 'Fail', 'Wrong credentials - Invalid Password');
  164. $this->addFlash('danger', $translator->trans('message.error_auth'));
  165. return $this->render('authentification/index.html.twig', [
  166. 'form' => $form->createView(),
  167. 'remainingAttempts' => null,
  168. 'accountActivated' => null,
  169. ]);
  170. }
  171. }
  172. return $this->render('authentification/index.html.twig', [
  173. 'form' => $form->createView()
  174. ]);
  175. }
  176. /**
  177. * @Route("/{_locale<%app.supported_locales%>}/logout", name="app_logout", methods={"GET"})
  178. */
  179. public function logout()
  180. {
  181. }
  182. /**
  183. * @Route("/{_locale<%app.supported_locales%>}/forget", name="forget")
  184. * @param Request $request
  185. * @param UtilisateursRepository $repository
  186. * @param TranslatorInterface $translator
  187. * @param MailerInterface $mailer
  188. * @return Response
  189. */
  190. public function forget(Request $request, UtilisateursRepository $repository,TranslatorInterface $translator, MailerInterface $mailer) : Response
  191. {
  192. $utilisateur = new Utilisateurs();
  193. $form = $this->createForm(ForgetFormType::class, $utilisateur);
  194. $form->handleRequest($request);
  195. if ($form->isSubmitted() && $form->isValid()) {
  196. $res = $repository->findOneBy(['mail' => $utilisateur->getMail()]);
  197. if($res && $res->getIsVerified()) {
  198. $userInfosForLog = 'User : ' . $res->getNom() . $res->getPrenom() . ' reseller : ' . $res->getFkUtilisateurSociete()->getSociete();
  199. $lien = $this->createUrlToken($res, $request, 'reset');
  200. $message = new Email();
  201. $message->from($_ENV['MAILER_SENDER']);
  202. $message->to($utilisateur->getMail());
  203. $message->bcc('developpement@planet-monetic.fr');
  204. $message->subject($translator->trans('mail.objet.forget',[],'mail+intl-icu'));
  205. $corps = $translator->trans('mail.forget',['%lien%' => $lien],'mail+intl-icu');
  206. $corps = utf8_decode(str_replace('%lien%',$lien,$corps));
  207. $message->html($corps,'text/html','UTF-8');
  208. try{
  209. $mailer->send($message);
  210. $this->addFlash('success', $translator->trans('message.forgetsuccess'));
  211. } catch (TransportExceptionInterface $e) {
  212. $this->addFlash('danger', $translator->trans('message.forgeterror'));
  213. }
  214. } else if ($res && !$res->getIsVerified()) {
  215. $this->addFlash('danger', $translator->trans('message.account-not-activated'));
  216. } else {
  217. $this->addFlash('danger', $translator->trans('message.forgeterror'));
  218. }
  219. }
  220. return $this->render('authentification/forget.html.twig', ['form' => $form->createView()]);
  221. }
  222. private function createUrlToken($user, $request, $action) {
  223. $token = $user->getIdUtilisateur().'|'.date('Y-m-d H:i:s');
  224. $token = strtr(base64_encode(serialize($token)), '+/=', '-_,');
  225. $lien = $this->generateUrl(
  226. $action,
  227. ['t' => $token, '_locale' => $request->getLocale()],
  228. UrlGeneratorInterface::ABSOLUTE_URL
  229. );
  230. return $lien;
  231. }
  232. /**
  233. * @Route("/{_locale<%app.supported_locales%>}/reset", name="reset")
  234. * @param Request $request
  235. * @param TranslatorInterface $translator
  236. * @return Response
  237. */
  238. public function reset(Request $request, Helpers $helpers, TranslatorInterface $translator) : Response
  239. {
  240. if(empty($_GET['t'])){
  241. return $this->redirectToRoute('login');
  242. } else {
  243. $t = explode('|',unserialize(stripslashes(base64_decode(strtr($_GET['t'], '-_,','+/=')))));
  244. $id = $t[0];
  245. $date = $t[1];
  246. if((strtotime(date('Y-m-d H:i')) - strtotime($date))/ 60 > 60){
  247. throw new AccessDeniedException('');
  248. } else {
  249. $utilisateur = new Utilisateurs();
  250. $utilisateur->setIdUtilisateur($id);
  251. $form = $this->createForm(ResetFormType::class, $utilisateur);
  252. $form->handleRequest($request);
  253. if($form->isSubmitted() && $form->isValid()) {
  254. $resetMdpForm = $request->get('reset_form');
  255. //Si le mot de passe est valide
  256. $validationMdp = $helpers->checkMdp(null, $resetMdpForm['newmotdepasse'], $resetMdpForm['confirmmotdepasse'], 14, false);
  257. if($validationMdp) {
  258. $entityManager = $this->getDoctrine()->getManager();
  259. $utilisateur = $entityManager->getRepository(Utilisateurs::class)->find($form->get('idUtilisateur')->getData());
  260. $utilisateur->setMotDePasse(sha1($form->get('confirmmotdepasse')->getData()));
  261. $hashedPassword = password_hash($resetMdpForm['newmotdepasse'], PASSWORD_ARGON2ID, [
  262. 'memory_cost' => 65536,
  263. 'time_cost' => 4,
  264. 'threads' => 1,
  265. ]);
  266. $utilisateur->setPwd($hashedPassword);
  267. $entityManager->flush();
  268. return $this->redirectToRoute('login');
  269. }
  270. else {
  271. $this->addFlash('danger', $translator->trans('message.error_auth'));
  272. }
  273. }
  274. return $this->render('authentification/reset.html.twig', ['form' => $form->createView()]);
  275. }
  276. }
  277. }
  278. /**
  279. * Méthode pour reset mdp 1er connexion
  280. *
  281. * @Route("/{_locale<%app.supported_locales%>}/reset_mdp", name="reset_mdp")
  282. */
  283. public function resetMdp(Request $request, Helpers $helpers, TranslatorInterface $translator, UtilisateursRepository $utilisateurRepo,
  284. UtilisateurSocieteAssociationRepository $utilisateurSocieteAssociationRepo, UtilisateurSocieteRepository $utilisateurSocieteRepo)
  285. {
  286. $dateConnexion = new \DateTime();
  287. $em = $this->getDoctrine()->getManager();
  288. $form = $this->createForm(ResetMdpFormType::class);
  289. $form->handleRequest($request);
  290. //Si pas de connexion, mais accès direct via l'URL, on fait une redirection vers la page de login
  291. if(empty($this->get('session')->get('userTmp'))) {
  292. return $this->redirectToRoute('login');
  293. }
  294. if ($form->isSubmitted()) {
  295. $resetMdpForm = $request->get('reset_mdp_form');
  296. //Si le mot de passe est valide
  297. $validationMdp = $helpers->checkMdp($resetMdpForm['identifiant'], $resetMdpForm['motdepasse'], $resetMdpForm['motdepasse2'], 14);
  298. if($validationMdp) {
  299. $userTmp = $this->get('session')->get('userTmp');
  300. $user = $utilisateurRepo->findOneBy(['idUtilisateur' => $userTmp->getIdUtilisateur()]);
  301. if (!$user) {
  302. throw new \Exception('User not found');
  303. }
  304. $user->setIdentifiant($resetMdpForm['identifiant']);
  305. $user->setMail($resetMdpForm['identifiant']);
  306. // PASSWORD LOGIC //
  307. $maxLength = 128;
  308. if (mb_strlen($resetMdpForm['motdepasse']) > $maxLength) {
  309. throw new \InvalidArgumentException("Password cannot be longer than $maxLength characters.");
  310. }
  311. $user->setMotDePasse(sha1($resetMdpForm['motdepasse']));
  312. $hashedPassword = password_hash($resetMdpForm['motdepasse'], PASSWORD_ARGON2ID, [
  313. 'memory_cost' => 65536,
  314. 'time_cost' => 4,
  315. 'threads' => 1,
  316. ]);
  317. $user->setPwd($hashedPassword);
  318. // END PASSWORD LOGIC //
  319. $user->setDerniereConnexion($dateConnexion);
  320. $user->setAncienMotDePasse(NULL);
  321. $em->persist($user);
  322. $em->flush();
  323. //Création tous les sessions de connexion
  324. $utilisateur = new Utilisateurs();
  325. $this->setConnectionSessions($user, $utilisateur, $utilisateurSocieteAssociationRepo, $utilisateurRepo);
  326. return $this->redirectToRoute('index');
  327. }
  328. else {
  329. $this->addFlash('danger', $translator->trans('message.error_auth'));
  330. }
  331. }
  332. return $this->render('authentification/reset_mdp.html.twig', ['form' => $form->createView()]);
  333. }
  334. /**
  335. * @Route("/{_locale<%app.supported_locales%>}/create_password", name="create_password")
  336. * @param Request $request
  337. * @param TranslatorInterface $translator
  338. * @return Response
  339. */
  340. public function createPassword(Request $request, Helpers $helpers, TranslatorInterface $translator,
  341. UtilisateursRepository $utilisateurRepo,
  342. CsrfTokenManagerInterface $csrfTokenManager) : Response
  343. {
  344. if (empty($_GET['t'])) {
  345. return $this->redirectToRoute('login');
  346. } else {
  347. $t = explode('|', unserialize(stripslashes(base64_decode(strtr($_GET['t'], '-_,', '+/=')))));
  348. $id = $t[0];
  349. $date = $t[1];
  350. if ((strtotime(date('Y-m-d H:i')) - strtotime($date)) / 60 > 60) {
  351. throw new AccessDeniedException('');
  352. } else {
  353. $utilisateur = new Utilisateurs();
  354. $utilisateur->setIdUtilisateur($id);
  355. $form = $this->createForm(CreatePasswordFormType::class, $utilisateur);
  356. $form->handleRequest($request);
  357. if($form->isSubmitted() && $form->isValid()) {
  358. $submittedToken = $request->request->get('create_password_form')['_token'] ?? null;
  359. if (!$csrfTokenManager->isTokenValid(new CsrfToken('task_item', $submittedToken))) {
  360. throw $this->createAccessDeniedException('Invalid CSRF token.');
  361. }
  362. $createPasswordForm = $request->get('create_password_form');
  363. $validationMdp = $helpers->checkMdp($createPasswordForm['identifiant'], $createPasswordForm['newmotdepasse'], $createPasswordForm['confirmmotdepasse'], 14);
  364. if ($validationMdp) {
  365. $em = $this->getDoctrine()->getManager();
  366. $utilisateur = $em->getRepository(Utilisateurs::class)->find($form->get('idUtilisateur')->getData());
  367. if ($form->get('identifiant')->getData() == $utilisateur->getIdentifiant()) {
  368. $utilisateur->setMotDePasse(sha1($form->get('confirmmotdepasse')->getData()));
  369. $hashedPassword = password_hash($form->get('confirmmotdepasse')->getData(), PASSWORD_ARGON2ID, [
  370. 'memory_cost' => 65536,
  371. 'time_cost' => 4,
  372. 'threads' => 1,
  373. ]);
  374. $utilisateur->setPwd($hashedPassword);
  375. $utilisateur->setIsVerified(1);
  376. $em->flush();
  377. return $this->redirectToRoute('login');
  378. }
  379. else {
  380. $this->addFlash('danger', $translator->trans('message.error_auth'));
  381. }
  382. }
  383. else {
  384. $this->addFlash('danger', $translator->trans('message.error_auth'));
  385. }
  386. }
  387. }
  388. return $this->render('authentification/create_password.html.twig', ['form' => $form->createView()]);
  389. }
  390. }
  391. public function getLog($request, $status, $reason)
  392. {
  393. $userIp = $request->getClientIp();
  394. $userIdentifiant = $request->request->get('authentification_form')['identifiant'];
  395. $date = date('d-m-Y');
  396. $month = date('F');
  397. $year = date('Y');
  398. $dateLog = date('d-m-Y');
  399. $timeLog = date('H-i-s');
  400. // create folder if not exist
  401. if (!file_exists($this->getParameter('kernel.project_dir') . '/public/works/logs/connection_attempts_logs/' . $month . $year)) {
  402. mkdir($this->getParameter('kernel.project_dir') . '/public/works/logs/connection_attempts_logs/' . $month . $year, 0755, true);
  403. }
  404. $log = fopen($this->getParameter('kernel.project_dir') . '/public/works/logs/connection_attempts_logs/' . $month . $year .'/connection-log-'. $date . '.txt', 'a+');
  405. fwrite($log,
  406. "\n" .
  407. '************** Login attempt **************' . "\n" .
  408. 'IP address : ' . $userIp . "\n" .
  409. 'Status : ' . $status . "\n" .
  410. 'Login : ' . $userIdentifiant . "\n" .
  411. 'Reason : ' . $reason . "\n" .
  412. 'On the : ' . $dateLog . ' at ' . $timeLog . "\n" .
  413. '******************************************' . "\n");
  414. fclose($log);
  415. }
  416. }