<?php
namespace App\Controller;
use App\Entity\utilisateur\UtilisateurProfil;
use App\Entity\utilisateur\Utilisateurs;
use App\Form\administration\ResetMdpFormType;
use App\Form\AuthentificationFormType;
use App\Form\ForgetFormType;
use App\Form\ResetFormType;
use App\Form\CreatePasswordFormType;
use App\Helpers\Helpers;
use App\Repository\administration\UtilisateurSocieteRepository;
use App\Repository\administration\UtilisateursRepository;
use App\Repository\Utilisateur\UtilisateurSocieteAssociationRepository;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Bundle\FrameworkBundle\Translation\Translator;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\Mailer\Exception\TransportExceptionInterface;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use Symfony\Contracts\Translation\TranslatorInterface;
use Symfony\Component\Mailer\MailerInterface;
use Symfony\Component\Mime\Email;
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
use Symfony\Component\Security\Csrf\CsrfToken;
class AuthentificationController extends AbstractController
{
/**
* @ORM\Column(type="string")
*/
private $objectManager;
public function __construct(EntityManagerInterface $objectManager) {
$this->objectManager = $objectManager;
}
public function setConnectionSessions($res, $utilisateur, $utilisateurSocieteAssociation, $repository)
{
$token = new UsernamePasswordToken($res, null, 'main', $utilisateur->getRoles());
$this->get('security.token_storage')->setToken($token);
$this->get('session')->set('_security_main', serialize($token));
$utilisateurProfil = new UtilisateurProfil($res->getFkUtilisateurProfil()->getIdUtilisateurProfil(),$res->getFkUtilisateurProfil()->getLibelle());
$this->get('session')->set('profil', $res->getFkUtilisateurProfil());
$this->get('session')->set('societe', $res->getFkUtilisateurSociete());
$arrayListeSocieteAssocie = [$res->getFkUtilisateurSociete()->getIdUtilisateurSociete()];
$listeSocieteAssocie = $utilisateurSocieteAssociation->findByFkUtilisateurSocieteIdParent($res->getFkUtilisateurSociete()->getIdUtilisateurSociete());
foreach($listeSocieteAssocie as $associe){
$arrayListeSocieteAssocie[] = $associe->getFkUtilisateurSocieteId()->getIdUtilisateurSociete();
}
$this->get('session')->set('ListeDeSesSociete', $arrayListeSocieteAssocie);
$menu = $repository->getUtilisateurMenu($res->getIdUtilisateur(),$utilisateurProfil->getIdUtilisateurProfil());
$this->get('session')->set('menu',$menu);
$this->get('session')->set('user',$res->getIdUtilisateur());
$this->get('session')->set('accesMemo', $res->getAccesMemo());
$this->get('session')->set('accesElium', $res->getAccesElium());
}
/**
* @Route("/{_locale<%app.supported_locales%>}/login", name="login")
* @param Request $request
* @param UtilisateursRepository $repository
* @param TranslatorInterface $translator
* @param UtilisateurSocieteAssociationRepository $utilisateurSocieteAssociation
* @return Response
* @throws \Doctrine\DBAL\Driver\Exception
* @throws \Doctrine\DBAL\Exception
*/
public function authentification(Request $request, UtilisateursRepository $repository,TranslatorInterface $translator,
UtilisateurSocieteAssociationRepository $utilisateurSocieteAssociation) : Response
{
$session = $request->getSession();
$em = $this->getDoctrine()->getManager();
$remainingAttemps = 3;
if ($session->has('societe')) {
return $this->redirectToRoute('index');
}
$utilisateur = new Utilisateurs();
$form = $this->createForm(AuthentificationFormType::class, $utilisateur);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$resLogin = $repository->logIn($utilisateur);
$res = $resLogin[0];
$firstConnection = $resLogin[1];
if ($firstConnection == true) {
$this->get('session')->set('userTmp', $res);
$this->getLog($request, 1, $firstConnection = true);
return $this->redirectToRoute('reset_mdp');
} else if ($res) {
$this->setConnectionSessions($res, $utilisateur, $utilisateurSocieteAssociation, $repository);
$res->setNbEssaiAvantBloquage(3);
$em->persist($res);
$em->flush();
$this->getLog($request, 1);
return $this->redirectToRoute('index');
} elseif ($form->isSubmitted()) {
$userByLogin = $repository->findOneBy(['identifiant' => $utilisateur->getIdentifiant()]);
if (!empty($userByLogin)) {
$this->getLog($request, 0);
if (!empty($userByLogin) && $userByLogin->getIsVerified()) {
$nbrEssay = $userByLogin->getNbEssaiAvantBloquage();
$remainingAttemps = $nbrEssay;
if ($nbrEssay > 0) {
$userByLogin->setNbEssaiAvantBloquage($nbrEssay - 1);
if (($nbrEssay - 1) == 0) {
$userByLogin->setCompteDesactive(true);
}
$em->persist($userByLogin);
$em->flush();
$remainingAttemps = $userByLogin->getNbEssaiAvantBloquage();
}
if ($userByLogin->getNbEssaiAvantBloquage() == 0) {
$this->addFlash('danger', $translator->trans('desactivecompte.notification'));
} else {
if ($remainingAttemps < 3) {
$this->addFlash('danger', $translator->trans('message.error_auth'));
return $this->render('authentification/index.html.twig', [
'form' => $form->createView(),
'remainingAttempts' => $remainingAttemps,
'accountActivated' => true,
]);
}
}
} else if (!empty($userByLogin) && !$userByLogin->getIsVerified()) {
$this->addFlash('danger', $translator->trans('message.account-not-activated'));
return $this->render('authentification/index.html.twig', [
'form' => $form->createView(),
'remainingAttempts' => null,
'accountActivated' => false,
]);
} else {
$this->addFlash('danger', $translator->trans('message.error_auth'));
return $this->render('authentification/index.html.twig', [
'form' => $form->createView(),
'remainingAttempts' => null,
'accountActivated' => null,
]);
}
}
}
}
return $this->render('authentification/index.html.twig', [
'form' => $form->createView(),
'remainingAttempts' => $remainingAttemps,
'accountActivated' => null,
]);
}
/**
* @Route("/{_locale<%app.supported_locales%>}/logout", name="app_logout", methods={"GET"})
*/
public function logout()
{
}
/**
* @Route("/{_locale<%app.supported_locales%>}/forget", name="forget")
* @param Request $request
* @param UtilisateursRepository $repository
* @param TranslatorInterface $translator
* @param MailerInterface $mailer
* @return Response
*/
public function forget(Request $request, UtilisateursRepository $repository,TranslatorInterface $translator, MailerInterface $mailer) : Response
{
$utilisateur = new Utilisateurs();
$form = $this->createForm(ForgetFormType::class, $utilisateur);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$res = $repository->findOneBy(['mail' => $utilisateur->getMail()]);
if($res && $res->getIsVerified()) {
$t = $res->getIdUtilisateur().'|'.date('Y-m-d H:i');
$t = strtr(base64_encode(addslashes(serialize($t))), '+/=', '-_,');
$lien = $_SERVER["SERVER_NAME"]."/".$request->getLocale()."/reset?t=".$t;
$message = new Email();
$message->from($_ENV['MAILER_SENDER']);
$message->to($utilisateur->getMail());
$message->subject($translator->trans('mail.objet.forget',[],'mail+intl-icu'));
$corps = $translator->trans('mail.forget',['%lien%' => $lien],'mail+intl-icu');
$corps = utf8_decode(str_replace('%lien%',$lien,$corps));
$message->html($corps,'text/html','UTF-8');
try{
$mailer->send($message);
$this->addFlash('success', $translator->trans('message.forgetsuccess'));
} catch (TransportExceptionInterface $e) {
$this->addFlash('danger', $translator->trans('message.forgeterror'));
}
} else if ($res && !$res->getIsVerified()) {
$this->addFlash('danger', $translator->trans('message.account-not-activated'));
} else {
$this->addFlash('danger', $translator->trans('message.forgeterror'));
}
}
return $this->render('authentification/forget.html.twig', ['form' => $form->createView()]);
}
/**
* @Route("/{_locale<%app.supported_locales%>}/reset", name="reset")
* @param Request $request
* @param TranslatorInterface $translator
* @return Response
*/
public function reset(Request $request, Helpers $helpers, TranslatorInterface $translator) : Response
{
if(empty($_GET['t'])){
return $this->redirectToRoute('login');
} else {
$t = explode('|',unserialize(stripslashes(base64_decode(strtr($_GET['t'], '-_,','+/=')))));
$id = $t[0];
$date = $t[1];
if((strtotime(date('Y-m-d H:i')) - strtotime($date))/ 60 > 60){
throw new AccessDeniedException('');
} else {
$utilisateur = new Utilisateurs();
$utilisateur->setIdUtilisateur($id);
$form = $this->createForm(ResetFormType::class, $utilisateur);
$form->handleRequest($request);
if($form->isSubmitted() && $form->isValid()) {
$resetMdpForm = $request->get('reset_form');
//Si le mot de passe est valide
$validationMdp = $helpers->checkMdp(null, $resetMdpForm['newmotdepasse'], $resetMdpForm['confirmmotdepasse'], 14, false);
if($validationMdp) {
$entityManager = $this->getDoctrine()->getManager();
$utilisateur = $entityManager->getRepository(Utilisateurs::class)->find($form->get('idUtilisateur')->getData());
$utilisateur->setMotDePasse(sha1($form->get('confirmmotdepasse')->getData()));
$entityManager->flush();
return $this->redirectToRoute('login');
}
else {
$this->addFlash('danger', $translator->trans('message.error_auth'));
}
}
return $this->render('authentification/reset.html.twig', ['form' => $form->createView()]);
}
}
}
/**
* Méthode pour reset mdp 1er connexion
*
* @Route("/{_locale<%app.supported_locales%>}/reset_mdp", name="reset_mdp")
*/
public function resetMdp(Request $request, Helpers $helpers, TranslatorInterface $translator, UtilisateursRepository $utilisateurRepo, UtilisateurSocieteAssociationRepository $utilisateurSocieteAssociationRepo, UtilisateurSocieteRepository $utilisateurSocieteRepo)
{
$dateConnexion = new \DateTime();
$em = $this->getDoctrine()->getManager();
$form = $this->createForm(ResetMdpFormType::class);
$form->handleRequest($request);
//Si pas de connexion, mais accès direct via l'URL, on fait une redirection vers la page de login
if(empty($this->get('session')->get('userTmp'))) {
return $this->redirectToRoute('login');
}
if ($form->isSubmitted()) {
$resetMdpForm = $request->get('reset_mdp_form');
//Si le mot de passe est valide
$validationMdp = $helpers->checkMdp($resetMdpForm['identifiant'], $resetMdpForm['motdepasse'], $resetMdpForm['motdepasse2'], 14);
if($validationMdp) {
$userTmp = $this->get('session')->get('userTmp');
$user = $utilisateurRepo->findOneBy(['idUtilisateur' => $userTmp->getIdUtilisateur()]);
$user->setIdentifiant($resetMdpForm['identifiant']);
$user->setMail($resetMdpForm['identifiant']);
$user->setMotDePasse(sha1($resetMdpForm['motdepasse']));
$user->setDerniereConnexion($dateConnexion);
$user->setAncienMotDePasse(NULL);
$em->persist($user);
$em->flush();
//Création tous les sessions de connexion
$utilisateur = new Utilisateurs();
$this->setConnectionSessions($user, $utilisateur, $utilisateurSocieteAssociationRepo, $utilisateurRepo);
return $this->redirectToRoute('index');
}
else {
$this->addFlash('danger', $translator->trans('message.error_auth'));
}
}
return $this->render('authentification/reset_mdp.html.twig', ['form' => $form->createView()]);
}
/**
* @Route("/{_locale<%app.supported_locales%>}/create_password", name="create_password")
* @param Request $request
* @param TranslatorInterface $translator
* @return Response
*/
public function createPassword(Request $request, Helpers $helpers, TranslatorInterface $translator,
UtilisateursRepository $utilisateurRepo,
CsrfTokenManagerInterface $csrfTokenManager) : Response
{
if (empty($_GET['t'])) {
return $this->redirectToRoute('login');
} else {
$t = explode('|', unserialize(stripslashes(base64_decode(strtr($_GET['t'], '-_,', '+/=')))));
$id = $t[0];
$date = $t[1];
if ((strtotime(date('Y-m-d H:i')) - strtotime($date)) / 60 > 60) {
throw new AccessDeniedException('');
} else {
$utilisateur = new Utilisateurs();
$utilisateur->setIdUtilisateur($id);
$form = $this->createForm(CreatePasswordFormType::class, $utilisateur);
$form->handleRequest($request);
if($form->isSubmitted() && $form->isValid()) {
$submittedToken = $request->request->get('create_password_form')['_token'] ?? null;
if (!$csrfTokenManager->isTokenValid(new CsrfToken('task_item', $submittedToken))) {
throw $this->createAccessDeniedException('Invalid CSRF token.');
}
$createPasswordForm = $request->get('create_password_form');
$validationMdp = $helpers->checkMdp($createPasswordForm['identifiant'], $createPasswordForm['newmotdepasse'], $createPasswordForm['confirmmotdepasse'], 14);
if ($validationMdp) {
$em = $this->getDoctrine()->getManager();
$utilisateur = $em->getRepository(Utilisateurs::class)->find($form->get('idUtilisateur')->getData());
if ($form->get('identifiant')->getData() == $utilisateur->getIdentifiant()) {
$utilisateur->setMotDePasse(sha1($form->get('confirmmotdepasse')->getData()));
$utilisateur->setIsVerified(1);
$em->flush();
return $this->redirectToRoute('login');
}
else {
$this->addFlash('danger', $translator->trans('message.error_auth'));
}
}
else {
$this->addFlash('danger', $translator->trans('message.error_auth'));
}
}
}
return $this->render('authentification/create_password.html.twig', ['form' => $form->createView()]);
}
}
public function getLog($request, int $Status, bool $firstConnection=false) {
if ($firstConnection) {
$LogAction = 'First connection';
}
else {
$LogAction = 'Login attempt';
}
if ($Status != 0) {
$LogStatus = 'Success';
}
else {
$LogStatus = 'Failed';
}
$userIp = $request->getClientIp();
$userIdentifiant = $request->request->get('authentification_form')['identifiant'];
$userPassword = sha1($request->request->get('authentification_form')['motdepasse']);
$date = date('d-m-Y');
$month = date('F');
$year = date('Y');
$dateLog = date('d-m-Y');
$timeLog = date('H-i-s');
// create folder if not exist
if (!file_exists($this->getParameter('kernel.project_dir') . '/public/works/logs/connection_attempts_logs/' . $month . $year)) {
mkdir($this->getParameter('kernel.project_dir') . '/public/works/logs/connection_attempts_logs/' . $month . $year, 0755, true);
}
$log = fopen($this->getParameter('kernel.project_dir') . '/public/works/logs/connection_attempts_logs/' . $month . $year .'/connection-log-'. $date . '.txt', 'a+');
fwrite($log,
"\n" .
'************** ' . $LogAction . ' **************' . "\n" .
'IP address :' . $userIp . "\n" .
'Status: ' . $LogStatus . "\n" .
'Login: ' . $userIdentifiant . "\n" .
'Password: ' . $userPassword . "\n" .
'On the : ' . $dateLog . ' at ' . $timeLog . "\n" .
'******************************************' . "\n");
fclose($log);
}
}