<?php
namespace App\Controller;
use App\Entity\User;
use App\Notification\ContactNotification;
use App\Utils\FormValidator;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Csrf\TokenGenerator\TokenGeneratorInterface;
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
class SecurityController extends AbstractController
{
#[Route(path: '/', name: 'homepage')]
public function home()
{
return $this->render('security/homepage.html.twig', []);
}
#[Route(path: '/login/{message}/{sendTokenActiveAccount}', name: 'app_login')]
public function login(AuthenticationUtils $authenticationUtils, string $message = null, bool $sendTokenActiveAccount = false): Response
{
// if ($this->getUser()) {
// return $this->redirectToRoute('target_path');
// }
if ($message) {
$this->addFlash('info', $message);
}
// get the login error if there is one
$error = $authenticationUtils->getLastAuthenticationError();
// last username entered by the user
$lastUsername = $authenticationUtils->getLastUsername();
return $this->render('security/login.html.twig', ['last_username' => $lastUsername, 'error' => $error, 'sendTokenActiveAccount' => $sendTokenActiveAccount]);
}
#[Route(path: '/logout/{message}/{sendTokenActiveAccount}', name: 'app_logout')]
public function logout(string $message = null, bool $sendTokenActiveAccount = false): Response
{
return $this->redirectToRoute('app_login', ['message' => $message, 'sendTokenActiveAccount' => $sendTokenActiveAccount]);
}
#[Route(path: '/register/{accountUrl}', name: 'app_register')]
public function register(
Request $request,
UserPasswordHasherInterface $passwordHasher,
TokenGeneratorInterface $tokenGenerator,
ContactNotification $contactNotification,
FormValidator $formValidator,
EntityManagerInterface $entityManager,
string $accountUrl
): Response
{
if ($request->isMethod('POST')) {
if ($this->isCsrfTokenValid('register', $request->get('_token'))) {
$email = $request->request->get('email');
$password = $request->request->get('password');
$account = $request->request->get('account');
$emailIsUnique = $formValidator->isEmailUnique($email);
$passwordIsSecure = $formValidator->isSecurePassword($password);
if (!$emailIsUnique) {
$this->addFlash('danger', "Cette adresse email est déjà utilisée.");
}
if (!$passwordIsSecure) {
$this->addFlash('danger', "Le mot de passe n'est pas suffisamment fort.");
}
//si l'email fournit est bien unique et si le mot de passe est sécurisé
if ($emailIsUnique && $passwordIsSecure) {
$token = $tokenGenerator->generateToken(); //création du token pour activer le compte
$user = new User();
//si l'utilisateur s'inscrit en tant que facturier
if ($account === 'facturier') {
$user->setRoles([User::ROLE_FACTURIER]);
} else {
$user->setRoles([User::ROLE_PROFESSIONAL]);
}
$user->setPassword($passwordHasher->hashPassword($user, $password));
$user->setEmail($email);
$user->setIsProfessional(1);
$user->setActive(0);
$user->setNameUser($request->request->get('email'));
$user->setResetToken($token);
$entityManager->persist($user);
$entityManager->flush();
$url = $this->generateUrl('app_active_account', array('token' => $token), UrlGeneratorInterface::ABSOLUTE_URL);
$contactNotification->sendTokenActiveAccountByEmail($url, $email);
$this->addFlash('info', 'Enregistrement réalisé avec succès ! Vous devez activer votre compte via le lien que vous allez recevoir par mail avant de pouvoir vous connectez.');
return $this->redirectToRoute('app_login');
}
}
}
return $this->render('security/register.html.twig', ['accountUrl' => $accountUrl]);
}
#[Route(path: '/forgotten_password', name: 'app_forgotten_password')]
public function forgottenPassword(
Request $request,
TokenGeneratorInterface $tokenGenerator,
ContactNotification $contactNotification,
EntityManagerInterface $entityManager
): Response
{
if ($request->isMethod('POST')) {
$email = $request->request->get('email');
$user = $entityManager->getRepository(User::class)->findOneByEmail($email);
/* @var $user User */
if ($user === null) {
$this->addFlash('danger', 'Email Inconnu');
return $this->redirectToRoute('app_forgotten_password');
}
$token = $tokenGenerator->generateToken();
try {
$user->setResetToken($token);
$user->setUpdatedAt(new \DateTime('now'));
$entityManager->flush();
} catch (\Exception $e) {
$this->addFlash('warning', $e->getMessage());
return $this->redirectToRoute('app_forgotten_password');
}
$url = $this->generateUrl('app_reset_password', array('token' => $token), UrlGeneratorInterface::ABSOLUTE_URL);
$contactNotification->sendTokenPasswordByEmail($url, $user->getEmail());
$this->addFlash('info', 'Mail envoyé.');
return $this->redirectToRoute('app_login');
}
return $this->render('security/forgotten_password.html.twig');
}
#[Route(path: '/reset_password/{token}', name: 'app_reset_password')]
public function resetPassword(Request $request, string $token, UserPasswordHasherInterface $passwordHasher, FormValidator $formValidator, EntityManagerInterface $entityManager)
{
if ($request->isMethod('POST')) {
$user = $entityManager->getRepository(User::class)->findOneByResetToken($token);
/* @var $user User */
if ($user === null) {
$this->addFlash('danger', 'Token Inconnu');
return $this->redirectToRoute('app_forgotten_password');
}
$passwordIsSecure = $formValidator->isSecurePassword($request->request->get('password'));
if (!$passwordIsSecure) {
$this->addFlash('danger', "Le mot de passe n'est pas suffisamment fort.");
return $this->render('security/reset_password.html.twig', ['token' => $token]);
}
$user->setResetToken('');
$user->setPassword($passwordHasher->hashPassword($user, $request->request->get('password')));
$user->setUpdatedAt(new \DateTime('now'));
$entityManager->flush();
$this->addFlash('info', 'Mot de passe mis à jour');
return $this->redirectToRoute('app_login');
} else {
return $this->render('security/reset_password.html.twig', ['token' => $token]);
}
}
#[Route(path: '/changePassword', name: 'app_change_password')]
public function changePassword(Request $request, UserPasswordHasherInterface $passwordHasher, ?UserInterface $user, FormValidator $formValidator, EntityManagerInterface $entityManager)
{
if (!$user) {
return $this->redirectToRoute('app_login');
}
if ($user->getIsFirstConnexion() && $user->getIsProfessional() == 0) { //si c'est la première connexion d'un patient
$this->addFlash('info', "Bonjour, pour une question de sécurité, nous vous invitons à choisir et modifier votre mot de passe.");
}
if ($request->isMethod('POST') && $this->isCsrfTokenValid('change_password', $request->request->get('_token'))) {
$oldPassword = $request->request->get('_old_password');
$password = $request->request->get('_password');
$confirmPassword = $request->request->get('_confirm_password');
// Si l'ancien mot de passe est bon
if ($passwordHasher->isPasswordValid($user, $oldPassword)) {
if ($password === $confirmPassword) {
$passwordIsSecure = $formValidator->isSecurePassword($password);
if (!$passwordIsSecure) {
$this->addFlash('danger', "Le mot de passe n'est pas suffisamment fort.");
return $this->render('security/change_password.html.twig');
}
if ($user->getIsFirstConnexion()) { //si c'est la première connexion de l'utilisater
$user->setIsFirstConnexion(0);
}
$user->setPassword($passwordHasher->hashPassword($user, $password));
$user->setUpdatedAt(new \DateTime('now'));
$entityManager->persist($user);
$entityManager->flush();
$this->addFlash('info', 'Votre mot de passe a bien été changé !');
return $this->redirectToRoute('profil');
} else {
$this->addFlash('danger', "Les mots de passes ne sont pas identiques.");
return $this->render('security/change_password.html.twig');
}
} else {
$this->addFlash('danger', "Ce n'est pas le bon mot de passe.");
return $this->render('security/change_password.html.twig');
}
}
return $this->render('security/change_password.html.twig', array());
}
#[Route(path: '/active-account/{token}', name: 'app_active_account')]
public function activeAccount(string $token, EntityManagerInterface $entityManager)
{
$user = $entityManager->getRepository(User::class)->findOneByResetToken($token);
if ($user === null) {
$this->addFlash('danger', 'Token Inconnu');
return $this->redirectToRoute('app_logout');
}
$user->setResetToken('');
$user->setUpdatedAt(new \DateTime('now'));
$user->setActive(1);
$entityManager->flush();
$this->addFlash('info', 'Votre compte est maintenant actif ! Il ne vous reste plus qu\'à vous connecter.');
return $this->redirectToRoute('app_login');
}
#[Route(path: '/send/active-account', name: 'app_send_active_account')]
public function sendActiveAccount(Request $request, TokenGeneratorInterface $tokenGenerator, ContactNotification $contactNotification, EntityManagerInterface $entityManager)
{
if ($request->isMethod('POST')) {
$email = $request->request->get('email');
$user = $entityManager->getRepository(User::class)->findOneByEmail($email);
if ($user === null) {
$this->addFlash('danger', 'Email Inconnu');
return $this->redirectToRoute('app_send_active_account');
}
$token = $tokenGenerator->generateToken();
try {
$user->setResetToken($token);
$user->setUpdatedAt(new \DateTime('now'));
$entityManager->flush();
} catch (\Exception $e) {
$this->addFlash('warning', $e->getMessage());
return $this->redirectToRoute('app_send_active_account');
}
$url = $this->generateUrl('app_active_account', array('token' => $token), UrlGeneratorInterface::ABSOLUTE_URL);
$contactNotification->sendTokenActiveAccountByEmail($url, $email);
return $this->redirectToRoute('app_login', ['message' => 'Mail pour activer votre compte envoyé.', 'sendTokenActiveAccount' => true]);
}
return $this->render('security/send_active_account.html.twig');
}
}