<?php
namespace App\Controller\Auth;
use App\Entity\Auth\User;
use App\Event\UserCreatedEvent;
use App\Event\UserUpdatedEvent;
use App\Form\Auth\RegistrationFormType;
use App\Infrastructure\Social\SocialLoginService;
use App\Security\AppAuthenticator;
use App\Service\ProfileService;
use App\Service\TokenGeneratorService;
use DateTime;
use Doctrine\ORM\EntityManagerInterface;
use Exception;
use Psr\EventDispatcher\EventDispatcherInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\FormError;
use Symfony\Component\HttpFoundation\RedirectResponse;
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\Security\Core\Authorization\AuthorizationCheckerInterface;
use Symfony\Component\Security\Http\Authentication\UserAuthenticatorInterface;
class RegistrationController extends AbstractController
{
/**
* @Route("/register", name="app_register")
* @param Request $request
* @param AuthorizationCheckerInterface $checker
* @param UserPasswordHasherInterface $userPasswordHasher
* @param SocialLoginService $socialLoginService
* @param UserAuthenticatorInterface $authenticator
* @param AppAuthenticator $appAuthenticator
* @param EventDispatcherInterface $dispatcher
* @param TokenGeneratorService $tokenGeneratorService
* @param EntityManagerInterface $entityManager
* @param ProfileService $service
* @return Response
* @throws Exception
*/
public function register(Request $request, AuthorizationCheckerInterface $checker,
UserPasswordHasherInterface $userPasswordHasher,
SocialLoginService $socialLoginService,
UserAuthenticatorInterface $authenticator,
AppAuthenticator $appAuthenticator,
EventDispatcherInterface $dispatcher,
TokenGeneratorService $tokenGeneratorService,
EntityManagerInterface $entityManager, ProfileService $service): Response
{
if ($this->getUser()) {
if ($checker->isGranted('ROLE_ADMIN')) {
return $this->redirectToRoute('admin_dashboard');
}
return $this->redirectToRoute('homepage');
}
$user = new User();
$rootErrors = [];
// Si l'utilisateur provient de l'oauth, on préremplit ses données
$isOauthUser = $request->get('oauth') ? $socialLoginService->hydrate($user) : false;
$form = $this->createForm(RegistrationFormType::class, $user);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
// encode the plain password
$user->setPassword(
$form->has('plainPassword') ? $userPasswordHasher->hashPassword(
$user,
$form->get('plainPassword')->getData()
) : '');
$user->setConfirmationToken($isOauthUser ? null : $tokenGeneratorService->generate(60));
$user->setUsername($isOauthUser ? null : $user->getEmail());
$user->setRoles([$user->getProfile()->getToken()]);
$user->setIsParent($user->getProfile()->getSlug() === 'parent');
$entityManager->persist($user);
$entityManager->flush();
$dispatcher->dispatch(new UserCreatedEvent($user, $isOauthUser));
if (!$user->isIsParent() && !$user->isIsAdmin()) {
$dispatcher->dispatch(new UserUpdatedEvent($user));
}
if ($isOauthUser) {
$this->addFlash(
'success',
'Votre compte a été créé avec succès'
);
return $authenticator->authenticateUser($user, $appAuthenticator, $request) ?: $this->redirectToRoute('profile_edit');
}
$this->addFlash(
'success',
'Un message avec un lien de confirmation vous a été envoyé par mail. Veuillez suivre ce lien pour activer votre compte.'
);
return $this->redirectToRoute('app_login');
} elseif ($form->isSubmitted()) {
/** @var FormError $error */
foreach ($form->getErrors() as $error) {
if (null === $error->getCause()) {
$rootErrors[] = $error;
}
}
}
return $this->render('registration/register.html.twig', [
'form' => $form->createView(),
'link' => 'registration',
'errors' => $rootErrors,
'oauth_registration' => $request->get('oauth'),
'oauth_type' => $socialLoginService->getOauthType(),
]);
}
/**
* @Route("/inscription/confirmation/{id<\d+>}", name="register_confirm")
* @param User $user
* @param Request $request
* @param EventDispatcherInterface $dispatcher
* @param EntityManagerInterface $em
* @param AppAuthenticator $appAuthenticator
* @param UserAuthenticatorInterface $authenticator
* @return RedirectResponse
*/
public function confirmToken(User $user, Request $request, EventDispatcherInterface $dispatcher,
EntityManagerInterface $em, AppAuthenticator $appAuthenticator,
UserAuthenticatorInterface $authenticator): RedirectResponse
{
$token = $request->get('token');
if (empty($token) || $token !== $user->getConfirmationToken()) {
$this->addFlash('error', "Ce token n'est pas valide");
return $this->redirectToRoute('app_register');
}
if ($user->getCreatedAt() < new DateTime('-2 hours')) {
$this->addFlash('error', 'Ce token a expiré');
return $this->redirectToRoute('app_register');
}
$user->setIsVerified(true);
$user->setConfirmationToken(null);
$em->flush();
$dispatcher->dispatch(new UserUpdatedEvent($user));
$this->addFlash('success', 'Votre compte a été validé. Vous êtes maintenant connecté');
$authenticator->authenticateUser($user, $appAuthenticator, $request);
return $this->redirectToRoute('homepage');
}
}