<?php
namespace App\Controller;
use App\Entity\User;
use App\Form\RegisterType;
use App\Form\ResetPasswordType;
use App\Service\UserService;
use Bluesquare\ValidatorBundle\Validator;
use Doctrine\ORM\EntityManagerInterface;
use EWZ\Bundle\RecaptchaBundle\Form\Type\EWZRecaptchaV3Type;
use EWZ\Bundle\RecaptchaBundle\Validator\Constraints\IsTrueV3;
use KnpU\OAuth2ClientBundle\Client\ClientRegistry;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Config\Definition\Exception\Exception;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\Mailer\MailerInterface;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\Exception\CustomUserMessageAuthenticationException;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
use Symfony\Component\Validator\Constraints\Email;
use Symfony\Component\Validator\Constraints\NotBlank;
class AuthController extends AbstractController
{
protected function loginAs(User $user)
{
$token = new UsernamePasswordToken($user, null, 'main', $user->getRoles());
$this->get('security.token_storage')->setToken($token);
$this->get('session')->set('_security_main', serialize($token));
}
/**
* @Route("/auth/redirect", name="auth.redirect")
*/
public function redirectUser(Request $request): RedirectResponse
{
// TODO: redirect by role (if you want)
$user = $this->getUser();
if ($user instanceof User) {
$session = $request->getSession();
$price_id = $session->get('price_id');
if ($request->getSession()->get('article_id') && $request->getSession()->get('article_slug')) {
$article_id = $request->getSession()->get('article_id');
$article_slug = $request->getSession()->get('article_slug');
return $this->redirectToRoute('article.view', ['id' => $article_id, 'slug' => $article_slug]);
}
if ($price_id) {
return $this->redirectToRoute('products.details', ['price_id' => $price_id]);
}
return $this->redirectToRoute('account');
}
return $this->redirectToRoute('auth.login');
}
/**
* @Route("/auth/login", name="auth.login")
*/
public function login(Request $request, AuthenticationUtils $authenticationUtils, Validator $validator): Response
{
$builder = $this->createFormBuilder()
->add('email', EmailType::class, [
'constraints' => [
new NotBlank(),
new Email(),
],
'attr' => [
'class' => 'auth-form-input',
],
])
->add('password', PasswordType::class, [
'constraints' => [
new NotBlank(),
],
'attr' => [
'class' => 'auth-form-input',
],
])
->add('recaptcha', EWZRecaptchaV3Type::class, [
'action_name' => 'auth_register',
'mapped' => false,
'constraints' => [
new IsTrueV3(),
],
])
;
$loginForm = $builder->getForm();
$loginForm->handleRequest($request);
$error = $authenticationUtils->getLastAuthenticationError();
$lastEmail = $authenticationUtils->getLastUsername();
if ($request->get('article_id') && $request->get('article_slug')) {
$session = $request->getSession();
$article_id = $request->get('article_id');
$article_slug = $request->get('article_slug');
$session->set('article_id', $article_id);
$session->set('article_slug', $article_slug);
}
return $this->render('auth/login.html.twig', [
'last_email' => $lastEmail,
'error' => $error,
'login_form' => $loginForm->createView(),
'validator' => $validator,
]);
}
/**
* @Route("/auth/register", name="auth.register")
*/
public function register(Request $request, EntityManagerInterface $manager, UserService $userService, Validator $validator,MailerInterface $symfonyMailer)
{
$validator->context('auth.register');
$sender = $this->getParameter('mailer_from_address');
$user = new User();
$form = $this->createForm(RegisterType::class, $user);
$builder = $this->createFormBuilder($user)
->add('email', EmailType::class, [
'constraints' => [
new NotBlank(),
new Email(),
],
])
->add('password', PasswordType::class, [
'constraints' => [
new NotBlank(),
],
])
->add('recaptcha', EWZRecaptchaV3Type::class, [
'action_name' => 'auth_register',
'mapped' => false,
'constraints' => [
new IsTrueV3(),
],
])
;
$registerForm = $builder->getForm();
$registerForm->handleRequest($request);
if ($registerForm->isSubmitted() && $registerForm->isValid()) {
$email = $user->getEmail();
$password = $user->getPassword();
$user = $userService->createUser($email, $password);
$userService->sendActivationEmail($user, $sender, $symfonyMailer);
$session = $request->getSession();
$price_id = $session->get('price_id');
if ($price_id && $user->getActivatedAt()) {
return $this->redirectToRoute('products.details', ['price_id' => $price_id]);
}
$article_id = $session->get('article_id');
$article_slug = $session->get('article_slug');
if ($article_id && $article_slug && $user->getActivatedAt()) {
return $this->redirectToRoute('article.view', ['id' => $article_id, 'slug' => $article_slug]);
}
return $this->redirectToRoute('auth.login');
}
// form A&C
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$email = $user->getEmail();
if ($this->hasNumbers($form->getData()->getFirstname()) && $this->hasNumbers($form->getData()->getLastname())) {
$this->addFlash('error', 'les données ne sont pas valides');
return $this->render('auth/register.html.twig', [
'validator' => $validator,
'register_form' => $registerForm->createView(), 'form' => $form->createView(),
]);
} else {
$user = $userService->createUser_new($form->getData());
$userService->sendActivationEmail($user, $sender, $symfonyMailer);
return $this->render('_partials/register/register-confirm.html.twig', [
'form' => $form->createView(), 'email' => $email, 'lastName' => $user->getLastname() , 'firstName' =>$user->getFirstname()
]);
}
}
return $this->render('auth/register.html.twig', [
'validator' => $validator,
'register_form' => $registerForm->createView(), 'form' => $form->createView(),
]);
}
/**
* @Route("/auth/activate/{hash}", name="auth.activate_account")
*/
public function activateAccount(Request $request, UserService $userService, $hash, Session $session)
{
$user = $userService->checkValidationToken($hash);
if (!$user) {
return $this->redirectUser($request);
}
$this->loginAs($user);
return $this->render('auth/activation.html.twig');
}
/**
* @Route("/auth/activate_account/{hash}", name="auth.activate_account_new")
*/
public function activateAccount_refonte(Request $request, UserService $userService, $hash, Session $session): RedirectResponse
{
$user = $userService->checkValidationToken($hash);
if ($user instanceof User) {
$this->loginAs($user);
$session->set('firstLogin', 'true');
return $this->redirectToRoute('homepage');
}
return $this->redirectUser($request);
}
/**
* @Route("/auth/forgot-password", name="auth.forgot_password")
*/
public function forgotPassword(Request $request, EntityManagerInterface $manager, UserService $userService, Validator $validator , MailerInterface $symfonyMailer)
{
$sender = $this->getParameter('mailer_from_address');
$validator->context('auth.forgot_password');
$builder = $this->createFormBuilder()
->add('email', EmailType::class, [
'constraints' => [
new NotBlank(),
new Email(),
],
])
->add('recaptcha', EWZRecaptchaV3Type::class, [
'action_name' => 'forgot_password',
'mapped' => false,
'constraints' => [
new IsTrueV3(),
],
]);
$form = $builder->getForm();
$builder2 = $this->createFormBuilder()
->add('email', EmailType::class, [
'constraints' => [
new NotBlank(),
new Email(),
],
]);
$form2 = $builder2->getForm();
if ($request->isXmlHttpRequest()) {
$data = json_decode($request->getContent());
$email = $data->email;
$user = $manager->getRepository(User::class)->findOneBy(['email' => $email]);
if (!$user) {
return $this->json(['errors' => 'error'], 500);
}
$userService->sendResetPasswordEMail($user, $sender, $symfonyMailer);;
return $this->json(['success' => 'ok'], 200);
}
$form->handleRequest($request);
$form2->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$email = $form->get('email')->getData();
$user = $manager->getRepository(User::class)->findOneBy(['email' => $email]);
if (!$user) {
$this->addFlash('error', 'Cet email n\'est pas connu.');
} else {
$userService->sendResetPasswordEMail($user, $sender, $symfonyMailer);;
return $this->redirectToRoute('home');
}
}
if ($form2->isSubmitted() && $form2->isValid()) {
$email = $form2->get('email')->getData();
$user = $manager->getRepository(User::class)->findOneBy(['email' => $email]);
if (!$user) {
$this->addFlash('error', 'Cet email n\'est pas connu.');
} else {
$userService->sendResetPasswordEMail($user, $sender, $symfonyMailer);;
$this->addFlash('success', 'Le lien de réinitialisation a été envoyé à votre email.');
return $this->redirectToRoute('auth.forgot_password');
}
}
return $this->render('auth/forgot_password.html.twig', [
'validator' => $validator,
'reset_password_form' => $form->createView(), 'form' => $form2->createView(),
]);
}
/**
* @Route("/auth/legacy", name="auth.legacy")
*/
public function legacy(Request $request, EntityManagerInterface $manager, UserService $userService, Validator $validator)
{
$username = $request->getSession()->get(Security::LAST_USERNAME);
if (null === $username) {
return $this->redirectToRoute('auth.login');
}
$user = $manager->getRepository(User::class)->findOneBy(['email' => $username]);
if (!$user) {
return $this->redirectToRoute('auth.login');
}
$userService->sendResetPasswordMail($user);
return $this->render('auth/legacy.html.twig', [
'username' => $username,
]);
}
/**
* @Route("/auth/reset-password/{hash}", name="auth.reset_password")
*/
public function resetPassword(Request $request, UserService $userService, Validator $validator, $hash)
{
$validator->context('auth.reset_password');
$user = $userService->checkResetPasswordToken($hash);
if (!$user) {
return $this->redirectToRoute('auth.login');
}
$form = $this->createForm(ResetPasswordType::class);
$form->handleRequest($request);
if ($validator->post()) {
$validator
->required('password', 'password_confirm')
->minLength('password', 6)
->identical('password', 'password_confirm')
;
if ($validator->check()) {
$password = $validator->get('password');
$userService->updatePassword($user, $password);
$validator->keep();
$this->loginAs($user);
return $this->redirectToRoute('auth.redirect');
}
}
if ($form->isSubmitted() && $form->isValid()) {
$password = $form->getData()['password'];
$userService->updatePassword($user, $password);
$this->loginAs($user);
return $this->redirectToRoute('homepage');
}
return $this->render('auth/reset_password.html.twig', [
'user' => $user, 'form' => $form->createView(), 'hash' => $hash, 'email' => $user->getEmail(),
]);
}
/**
* @Route("/connect/google", name="connect_google")
*/
public function connectGoogle(ClientRegistry $clientRegistry): RedirectResponse
{
return $clientRegistry
->getClient('google')
->redirect(['email'])
;
}
/**
* @Route("/oauth/check/google", name="oauth_check_google")
*/
public function oauthCheckGoogle(Request $request)
{
return $this->extracted($request);
}
/**
* @Route("/connect/linkedIn", name="connect_linkedIn")
*/
public function connectLinkedIn(ClientRegistry $clientRegistry): RedirectResponse
{
return $clientRegistry
->getClient('linkedin')
->redirect(['r_emailaddress', 'r_liteprofile'])
;
}
/**
* @Route("/oauth/check/linkedIn", name="oauth_check_linkedIn")
*/
public function oauthCheckLinkedIn(Request $request)
{
return $this->extracted($request);
}
/**
* @Route("/connect/facebook", name="connect_facebook")
*/
public function connectFacebook(ClientRegistry $clientRegistry): RedirectResponse
{
return $clientRegistry
->getClient('facebook')
->redirect(['email', 'public_profile'])
;
}
/**
* @Route("/oauth/check/facebook", name="oauth_check_facebook")
*/
public function oauthCheckFacebook(Request $request)
{
return $this->extracted($request);
}
/**
* @return RedirectResponse|Response
*/
public function extracted(Request $request)
{
$session = $request->getSession();
$price_id = $session->get('price_id');
if ($price_id) {
return $this->redirectToRoute('products.details', ['price_id' => $price_id]);
}
if ($request->getSession()->get('article_id') && $request->getSession()->get('article_slug')) {
$article_id = $request->getSession()->get('article_id');
$article_slug = $request->getSession()->get('article_slug');
return $this->redirectToRoute('article.view', ['id' => $article_id, 'slug' => $article_slug]);
}
return $this->redirectToRoute('homepage');
}
private function hasNumbers($str) {
return preg_match('/\d/', $str) === 1;
}
}