<?php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\FormError;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
use Symfony\Component\Validator\Constraints\Email as EmailConstraint;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Validator\Validator\ValidatorInterface;
use App\Entity\Aide;
use App\Entity\ParametrageTexte;
use App\Entity\RefRole;
use App\Entity\UtilisateurInformation;
use App\Form\Type\FirstConnectionType;
use App\Form\Type\LoginType;
use App\Form\Type\ReinitializeType;
use App\Form\Type\UpdatePasswordType;
use Doctrine\Persistence\ManagerRegistry;
use Symfony\Component\Mailer\MailerInterface;
use Symfony\Component\Mime\Email;
use Twig\Environment;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Validator\Validation;
/**
* Description of SecurityController
* @author Maxime Dequant
*/
class SecurityController extends AbstractController
{
private ManagerRegistry $doctrine;
private $twig;
private MailerInterface $mailer;
private ValidatorInterface $validator;
public function __construct(ManagerRegistry $doctrine, Environment $twig, MailerInterface $mailer, ValidatorInterface $validator)
{
$this->doctrine = $doctrine;
$this->twig = $twig;
$this->mailer = $mailer;
$this->validator = $validator;
}
#[Route(path: '/login', name: 'ctsweb_front_login')]
public function login(Request $request, AuthenticationUtils $authenticationUtils): \Symfony\Component\HttpFoundation\Response
{
$session = $request->getSession();
$user = $authenticationUtils->getLastUsername();
$error = '';
$dateNow = new \DateTime();
$em = $this->doctrine->getManager();
$uiRep = $em->getRepository(UtilisateurInformation::class);
$userInfo = $uiRep->getUserInfoByLogin($user);
if ($session->has('expired')) {
// $error = "Votre compte a expiré";
$error = "La date de fin de droit d’accès à votre compte est dépassée. Veuillez contacter l’administrateur";
$session->remove('expired');
} elseif (!empty($userInfo) && $userInfo['utilisateurActif'] == true && $dateNow <= $userInfo['dateBlocage']) {
$error = "Votre compte est bloqué pendant 30 minutes, suite à un trop grand nombre de tentatives de connexion.";
} elseif ($session->has('disabled_user') || (!empty($userInfo) && $userInfo['utilisateurActif'] == false)) {
$error = "Votre compte a été désactivé, Veuillez contacter l'administrateur national";
$session->remove('disabled_user');
} elseif ($session->has('disabled_fede')) {
$error = "Votre fédération a été désactivée, Veuillez contacter l'administrateur national";
$session->remove('disabled_fede');
} else {
if ($request->attributes->has(Security::AUTHENTICATION_ERROR)) {
$error = $request->attributes->get(Security::AUTHENTICATION_ERROR);
} else {
if ($session->get(Security::AUTHENTICATION_ERROR)) {
$uiRep->addTentative($user);
$error = "Authentification échouée";
$session->remove(Security::AUTHENTICATION_ERROR);
}
}
}
$form = $this->createForm(LoginType::class);
$form->handleRequest($request);
$mail_contact = null;
$mail_contact_info = $em->getRepository(ParametrageTexte::class)->getByCode('COURRIEL_CONTACT_INFO');
if ((is_countable($mail_contact_info) ? count($mail_contact_info) : 0) > 0)
$mail_contact = $mail_contact_info[0]->getTexte();
$texte_login = null;
$texte_login_info = $em->getRepository(ParametrageTexte::class)->getByCode('LOGIN_INFO');
if ((is_countable($texte_login_info) ? count($texte_login_info) : 0) > 0)
$texte_login = $texte_login_info[0]->getTexte();
$urlAide = null;
$aide = $em->getRepository(Aide::class)->findOneBy(['type' => 'login']);
if (isset($aide)) {
$urlAide = $this->getParameter('dir_file_aide') . $aide->getPath();
}
return $this->render(
'Security/login.html.twig',
['form' => $form->createView(), 'request' => $request, 'error' => $error, 'texte_login' => $texte_login, 'mail_contact' => $mail_contact, 'url_aide' => $urlAide, 'version' => $this->getParameter('version')]
);
}
#[Route(path: '/first_connection', name: 'ctsweb_front_first_connection')]
public function firstConnection(Request $request)
{
$form = $this->createForm(FirstConnectionType::class);
$form->handleRequest($request);
$error = "";
$requestForm = $request->request->get('first_connection');
$user = $this->getUser();
$em = $this->doctrine->getManager();
$repository = $em->getRepository(UtilisateurInformation::class);
if ($form->isSubmitted() && $form->isValid()) {
if (
preg_match(
'/^(?=(.*[a-z]){1,})(?=(.*[A-Z]){1,})(?=(.*[\d]){1,})(?=(.*[\W]){1,})(?!.*\s).{12,}$/',
(string) $requestForm['password']['first']
)
) {
$result = $repository->changePassword($requestForm, $user->getIdUtilisateur());
if (isset($result['error']) && $result['error'] == 0) {
$dateConnexion = new \DateTime();
$dateConnexion->setTimezone(new \DateTimeZone('Europe/Paris'));
$dateConnexion->format('Y-m-d H:i:s');
$user->getUtilisateur()->setCourriel($requestForm['email']);
$user->getUtilisateur()->setDateConnexion($dateConnexion->format('Y-m-d H:i:s'));
$user->setJetonMdp(null);
$em->flush();
return match ($user->getUtilisateur()->getIdRole()) {
RefRole::ROLE_DS_ADMIN, RefRole::ROLE_DS_INVITE, RefRole::ROLE_DR, RefRole::ROLE_FEDE, RefRole::ROLE_FEDE_INVITE, RefRole::ROLE_DS_SIGNATAIRE, RefRole::ROLE_DR_SIGNATAIRE, RefRole::ROLE_LECTEUR => new RedirectResponse('/v2/gerer-cts/actualites/liste-actualites'),
RefRole::ROLE_CTS => new RedirectResponse('/v2/mon-activite/actualites'),
RefRole::ROLE_GCR, RefRole::ROLE_GCS => new RedirectResponse('/v2/gerer-cts/gerer-conges/en-attente'),
default => new RedirectResponse('/v2/mon-activite/actualites'),
};
} else {
$error = $result['retour'];
}
} else {
$error = "Votre mot de passe doit avoir une longueur de 12 caractères minimum, contenant au moins un chiffre, une lettre minuscule, une lettre majuscule et un caractère spécial";
}
} else {
if ($repository->findFirstConnection($user->getIdUtilisateur()) != "") {
} else {
return $this->render(
'Security/first_connection.html.twig',
['form' => $form->createView(), 'error' => $error, 'version' => $this->getParameter('version')]
);
}
}
return $this->render(
'Security/first_connection.html.twig',
['form' => $form->createView(), 'error' => $error, 'version' => $this->getParameter('version')]
);
}
#[Route(path: '/reinitialize', name: 'ctsweb_front_reinitialize_pwd')]
public function reinitialize(Request $request): \Symfony\Component\HttpFoundation\Response
{
$error = "";
$info = "";
$errorList = [];
$requestForm = $request->request->get('reinitialize');
$repository = $this->doctrine->getManager()->getRepository(UtilisateurInformation::class);
$session = $request->getSession();
$hasPasswordExpired = $session->get('has_password_expired', false);
$form = $this->createForm(ReinitializeType::class);
$form->handleRequest($request);
if ((is_countable($errorList) ? count($errorList) : 0) != 0) {
$errorMessage = new FormError($errorList[0]->getMessage());
$form->addError($errorMessage);
}
if ($form->isSubmitted() && $form->isValid()) {
$result = $repository->findUserReinitialize($requestForm);
if (isset($result['error']) && $result['error'] == 0) {
$host = $this->getParameter('host');
$token = $result['user']['tokenUpdatePwd'];
$linkUpdatePwd = sprintf('update_password/%s', $token);
$mail_contact = null;
$mail_ass_info = $this->doctrine->getManager()->getRepository(ParametrageTexte::class)->getByCode('COURRIEL_ASSISTANCE_INFO');
if ((is_countable($mail_ass_info) ? count($mail_ass_info) : 0) > 0)
$mail_contact = $mail_ass_info[0]->getTexte();
try {
$email = (new Email())
->from($mail_contact)
->to($result['user']['email'])
->subject('CTS-WEB : Réinitialisation de votre mot de passe')
->html($this->twig->render(
'Security/email_reinitialize.html.twig',
[
'host' => $host,
'username' => $result['user']['username'],
'password' => $result['user']['password'],
'nom' => $result['user']['nom'],
'prenom' => $result['user']['prenom'],
'date' => $result['user']['date'],
'linkUpdatePwd' => $linkUpdatePwd,
'from' => $mail_contact,
'hasPasswordExpired' => $hasPasswordExpired
]
));
$this->mailer->send($email);
$info = "Un courriel vous a été envoyé pour réinitialiser votre mot de passe. En cas de difficulté, veuillez contacter la direction des sports, centre de gestion opérationnelle des CTS.";
} catch (\Exception) {
$error = "Erreur lors de l'envoi du mail";
}
} else {
$error = $result['message'];
}
}
return $this->render(
'Security/reinitialize.html.twig',
['form' => $form->createView(), 'request' => $request, 'error' => $error, 'info' => $info,'hasPasswordExpired' => $hasPasswordExpired, 'version' => $this->getParameter('version')]
);
}
#[Route(path: '/update_password/{token}', name: 'ctsweb_front_update_password')]
public function updatePassword(Request $request, $token)
{
$form = $this->createForm(UpdatePasswordType::class);
$form->handleRequest($request);
$result = null;
$requestForm = $request->request->get('update_password');
$uiRep = $this->doctrine->getManager()->getRepository(UtilisateurInformation::class);
if ($form->isSubmitted() && $form->isValid()) {
if (
preg_match(
'/^(?=(.*[a-z]){1,})(?=(.*[A-Z]){1,})(?=(.*[\d]){1,})(?=(.*[\W]){1,})(?!.*\s).{12,}$/',
(string) $requestForm['password']['first']
)
) {
//Mettre à jour le mot de passe
$result = $uiRep->updatePassword($requestForm, $token);
} else {
$message = "Votre mot de passe doit avoir une longueur de 12 caractères minimum, contenant au moins un chiffre, une lettre minuscule, une lettre majuscule et un caractère spécial";
$errorMessage = new FormError($message);
$form->addError($errorMessage);
}
} else if (empty($token) || !$uiRep->isValidToken($token)) {
//Rédirection vers la page login
return new RedirectResponse('/login');
}
return $this->render(
'Security/update_password.html.twig',
['form' => $form->createView(), 'error' => (isset($result['error']) && $result['error']) ? $result['message'] : '', 'info' => (isset($result['error']) && !$result['error']) ? $result['message'] : '', 'version' => $this->getParameter('version')]
);
}
#[Route(path: '/retrieve_login', name: 'ctsweb_front_retrieve_login')]
public function retrieveLogin(Request $request): Response
{
$error = "";
$info = "";
$requestForm = $request->request->get('reinitialize');
$repository = $this->doctrine->getManager()->getRepository(UtilisateurInformation::class);
$form = $this->createForm(ReinitializeType::class);
$form->handleRequest($request);
$data = $form->getData();
$email = $data['courriel'] ?? '';
$emailConstraint = new EmailConstraint();
$emailConstraint->message = 'Adresse e-mail incorrecte';
$errorList = $this->validator->validate($email, $emailConstraint);
if ((is_countable($errorList) ? count($errorList) : 0) != 0) {
$errorMessage = new FormError($errorList[0]->getMessage());
$form->addError($errorMessage);
}
$mail_contact = null;
$mail_ass_info = $this->doctrine->getManager()->getRepository(ParametrageTexte::class)->getByCode('COURRIEL_ASSISTANCE_INFO');
if ((is_countable($mail_ass_info) ? count($mail_ass_info) : 0) > 0) {
$mail_contact = $mail_ass_info[0]->getTexte();
}
if ($form->isSubmitted() && $form->isValid()) {
$result = $repository->retrieveUserLogin($requestForm);
if (isset($result['error']) && $result['error'] == 0) {
try {
$host = $this->getParameter('host');
$mail_contact = null;
$mail_ass_info = $this->doctrine->getManager()->getRepository(ParametrageTexte::class)->getByCode('COURRIEL_ASSISTANCE_INFO');
if ((is_countable($mail_ass_info) ? count($mail_ass_info) : 0) > 0)
$mail_contact = $mail_ass_info[0]->getTexte();
$linkUpdatePwd = 'reinitialize';
$email = (new Email())
->from('cts-web.assistance@sports.gouv.fr')
->to($email)
->subject('CTS-WEB : Identifiant perdu')
->html($this->twig->render(
'Security/email_retreive_login.html.twig',
['host' => $host, 'from' => $mail_contact, 'linkUpdatePwd' => $linkUpdatePwd, 'username' => $result['message']]
));
$this->mailer->send($email);
$info = "Un courriel vous a été envoyé pour réinitialiser votre mot de passe. En cas de difficulté, veuillez contacter la direction des sports, centre de gestion opérationnelle des CTS.";
} catch (\Exception) {
$error = "Erreur lors de l'envoi du mail";
}
} else {
$error = $result['message'];
}
}
$content = $this->twig->render(
'Security/retrieve_login.html.twig',
['form' => $form->createView(), 'error' => $error, 'info' => $info, 'version' => $this->getParameter('version')]
);
return new Response($content);
}
#[Route(path: '/login_check', name: 'login_check')]
public function check(): never
{
throw new \RuntimeException('You must configure the check path to be handled by the firewall using form_login in your security firewall configuration.');
}
#[Route(path: '/logout', name: 'logout', methods: ['GET'])]
public function logout(): never
{
throw new \RuntimeException('You must activate the logout in your security firewall configuration.');
}
#[Route(path: '/api/isConnected', name: 'ctsweb_is_connected')]
public function isConnected()
{
try {
$user = $this->getUser();
if (is_null($user) || is_null($user->getIdUtilisateur())) {
return new JsonResponse(
['success' => true, 'isConnected' => false]
);
}
return new JsonResponse(
['success' => true, 'isConnected' => true]
);
} catch (\Exception $e) {
return new JsonResponse(
['success' => false, 'data' => $e->getMessage()]
);
}
}
}