<?php
namespace App\Controller\Website\Mybiz\Security;
use App\Data\RoleConstant;
use App\Entity\Member;
use App\Entity\User;
use App\Form\CRM\User\Authentication\ForgetPasswordType;
use App\Form\CRM\User\Authentication\ResetPasswordType;
use App\Repository\UserRepository;
use App\Security\Voter\CRM\CRMAccessVoter;
use App\Service\Api\Mobile\JwtAuthenticator;
use App\Service\Locale\LocaleProvider;
use App\Service\User\UserForgotPasswordHandler;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\PasswordHasher\Hasher\PasswordHasherFactoryInterface;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
use Symfony\Contracts\Translation\TranslatorInterface;
class SecurityController extends AbstractController
{
private string $locale;
public function __construct(LocaleProvider $localeProvider)
{
$this->locale = $localeProvider->provide();
}
/**
* @Route("/security/login", methods={"GET", "POST"}, name="mybiz_login")
*/
public function login(
Request $request,
AuthenticationUtils $authenticationUtils
): Response
{
/** @var User|null $user */
$user = $this->getUser();
if (null !== $user) {
return $this->redirectToRoute("mybiz_redirect");
}
$error = $authenticationUtils->getLastAuthenticationError();
$email = $request->get("email");
// last username entered by the user
$lastUsername = $email ?? $authenticationUtils->getLastUsername();
return $this->render('mybiz/security/login.html.twig', [
'last_username' => $lastUsername,
'email' => $email,
'error' => $error,
'locale' => $this->locale
]);
}
/**
* @Route("/security/redirect", methods={"GET", "POST"}, name="mybiz_redirect")
*/
public function redirectMember(
Request $request,
EntityManagerInterface $em,
RouterInterface $router
): Response
{
/** @var User|null $user */
$user = $this->getUser();
if (null === $user) {
return $this->redirectToRoute("mybiz_login");
}
$target = $request->getSession()->get("_security.futures_website.target_path");
try {
// Si l'utilisateur essaie d'aller quelque part, on le redirige vers cette route. Si aucune route ne match,
// On ne fait rien
$router->match(parse_url($target, PHP_URL_PATH));
$request->getSession()->set("_security.futures_website.target_path", null);
return $this->redirect($target);
} catch (\Throwable $e) {
}
$user->setLastLoginAt(new \DateTime());
$em->flush();
if ($this->isGranted(CRMAccessVoter::CRM_ACCESS, RoleConstant::ROLE_ADMIN)) {
return $this->redirectToRoute("crm_dashboard");
}
if ($this->isGranted(CRMAccessVoter::CRM_ACCESS, RoleConstant::ROLE_SUPPORT)) {
return $this->redirectToRoute("crm_member_list");
}
if ($this->isGranted(CRMAccessVoter::CRM_ACCESS, RoleConstant::ROLE_EDUCATEUR)) {
return $this->redirectToRoute("crm_replay_list");
}
/** @var Member|null $member */
$member = $user->getMember();
// Si le membre n'existe pas on le redirige sur /
if (null === $member) {
return $this->redirectToRoute("general_homepage");
}
if (false === $member->isAmbassador()) {
return $this->redirectToRoute("mybiz_become_ambasador");
}
return $this->redirect("/{$member->getPreferredLanguage()}");
}
/**
* @Route("/security/reset-password", methods={"GET", "POST"}, name="mybiz_account_reset_password")
*/
public function resetPassword(
Request $request,
PasswordHasherFactoryInterface $encoderFactory,
EntityManagerInterface $em,
TranslatorInterface $translator,
TokenStorageInterface $tokenStorage,
EventDispatcherInterface $eventDispatcher,
UserRepository $userRepository
): Response
{
$form = $this->createForm(ResetPasswordType::class, null, ["locale" => $this->locale]);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$datas = $form->getData();
$password = $datas["password"];
$confirmPassword = $datas["confirmPassword"];
if ($password !== $confirmPassword) {
$this->addFlash("warning", $translator->trans('validator.password.not_equal', [], 'validator', $this->locale));
return $this->render('mybiz/security/reset_password.html.twig', [
"form" => $form->createView(),
"locale" => $this->locale
]);
}
$token = $request->get("token");
if (empty($token)) {
$this->addFlash("warning", $translator->trans('validator.password.token_invalid', [], 'validator', $this->locale));
return $this->render('mybiz/security/reset_password.html.twig', [
"form" => $form->createView(),
"locale" => $this->locale
]);
}
/** @var User|null $user */
try {
$user = $userRepository->findUserByToken($token);
} catch (\Throwable $e) {
$this->addFlash("error", $translator->trans('validator.password.token_invalid', [], 'validator', $this->locale));
return $this->render('mybiz/security/reset_password.html.twig', [
"form" => $form->createView(),
"locale" => $this->locale
]);
}
if (null === $user) {
$this->addFlash("warning", $translator->trans('validator.password.token_invalid', [], 'validator', $this->locale));
return $this->render('mybiz/security/reset_password.html.twig', [
"form" => $form->createView(),
"locale" => $this->locale
]);
}
if (new \DateTime() > $user->getPasswordResetTokenExpiresAt()) {
$this->addFlash("warning", $translator->trans('validator.password.token_invalid', [], 'validator', $this->locale));
return $this->render('mybiz/security/reset_password.html.twig', [
"form" => $form->createView(),
"locale" => $this->locale
]);
}
$passwordEncoded = $encoderFactory->getPasswordHasher($user)->hash($password, $user->getSalt());
$user->setPassword($passwordEncoded);
$user->setPasswordResetToken(null);
$user->setPasswordResetTokenExpiresAt(null);
$user->setPasswordResetTokenEmailsSent(null);
$token = new UsernamePasswordToken($user, null, 'ofutures', $user->getRoles());
$tokenStorage->setToken($token); //now the user is logged in
//now dispatch the login event
$event = new InteractiveLoginEvent($request, $token);
$eventDispatcher->dispatch($event, 'security.interactive_login');
$em->persist($user);
$em->flush();
$this->addFlash("success", $translator->trans("security.forget_password.success", [], "security", $this->locale));
return $this->redirectToRoute("mybiz_redirect");
}
return $this->render('mybiz/security/reset_password.html.twig', [
"form" => $form->createView(),
"locale" => $this->locale
]);
}
/**
* @Route("/security/forget-password", methods={"GET", "POST"}, name="mybiz_forget_password")
*/
public function forgetPassword(
Request $request,
TranslatorInterface $translator,
UserForgotPasswordHandler $userForgotPasswordHandler,
UserRepository $userRepository
): Response
{
$form = $this->createForm(ForgetPasswordType::class, null, ["locale" => $this->locale]);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$datas = $form->getData();
if (!isset($datas["email"])) {
$this->addFlash("warning", $translator->trans("validator.user.email_invalid", [], "validator", $this->locale));
return $this->redirectToRoute("mybiz_forget_password");
}
$user = $userRepository->findOneBy([
"email" => $datas["email"]
]);
if (null === $user) {
$this->addFlash("warning", $translator->trans("validator.user.email_invalid", [], "validator", $this->locale));
return $this->redirectToRoute("mybiz_login");
}
try {
$userForgotPasswordHandler->handle($user);
} catch (\Throwable $e) {
return $this->render('mybiz/security/forget_password.html.twig', [
"form" => $form->createView(),
"locale" => $this->locale
]);
}
$this->addFlash("success", $translator->trans("security.forget_password.success", [], "security", $this->locale));
return $this->redirectToRoute("mybiz_login");
}
return $this->render('mybiz/security/forget_password.html.twig', [
"form" => $form->createView(),
"locale" => $this->locale
]);
}
/**
* @Route("/security/jwt/login", methods={"GET"}, name="mybiz_jwt_login")
*/
public function jwtLogin(
Request $request,
JwtAuthenticator $jwtAuthenticator
): Response
{
$jwt = $request->get("jwt");
if (null === $jwt) {
return $this->redirectToRoute("mybiz_login");
}
if (false === $jwtAuthenticator->authenticateByJwt($jwt)) {
return $this->redirectToRoute("mybiz_login");
}
return $this->redirectToRoute("futures_homepage");
}
}