<?php
namespace App\Controller;
use App\Entity\User;
use App\Entity\UserEnseignantDocument;
use App\Form\RegistrationFormType;
use App\Security\EmailVerifier;
use App\Security\LoginFormAuthenticator;
use App\Repository\UserRepository;
use Symfony\Bridge\Twig\Mime\TemplatedEmail;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Mime\Address;
use Symfony\Component\Routing\Annotation\Route;
#use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface as UserPasswordEncoderInterface;
#use Symfony\Component\Security\Guard\GuardAuthenticatorHandler;
use SymfonyCasts\Bundle\VerifyEmail\Exception\VerifyEmailExceptionInterface;
use Symfony\Component\Security\Core\Exception\UserNotFoundException;
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\CsrfTokenBadge;
use Symfony\Component\Security\Http\Authenticator\Passport\Credentials\PasswordCredentials;
use Symfony\Component\Security\Http\Authenticator\Passport\Passport;
use Symfony\Component\Security\Http\Authenticator\Passport\PassportInterface;
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\PasswordUpgradeBadge;
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
use App\Event\InscriptionFormateurEvent;
use App\Event\InscriptionEleveEvent;
use Symfony\Component\EventDispatcher\EventDispatcher;
//use App\EventListener\AdminUserEventListener;
use App\EventSubscriber\UserEventSubscriber;
use App\Exception\FlashableException;
use App\Service\FileUploader;
class RegistrationController extends AbstractController {
private $emailVerifier;
private $dispatcher;
public function __construct(\Doctrine\ORM\EntityManagerInterface $entityManager, EmailVerifier $emailVerifier, UserRepository $userRepository, UserEventSubscriber $userEventSubscriber) {
$this->emailVerifier = $emailVerifier;
// Émetteur des évènements Application Utilisateur
$this->dispatcher = new EventDispatcher();
$this->dispatcher->addSubscriber($userEventSubscriber);
$this->entityManager = $entityManager;
}
/**
* @Route("/register", name="app_register")
*/
public function register(Request $request, UserPasswordEncoderInterface $passwordEncoder, LoginFormAuthenticator $authenticator, FileUploader $fileUploader): Response {
$entityManager = $this->entityManager;
$entityManager->getConnection()->beginTransaction(); // Annuler l'auto-commit pour faire un rollback si le mailing se passe mal
$user = new User();
$form = $this->createForm(RegistrationFormType::class, $user);
$form->handleRequest($request);
$retour = array();
$retour['isNonVerified'] = false;
$retour['registrationForm'] = $form;
if ($form->isSubmitted()) {
try{
$client = new \Symfony\Component\HttpClient\CurlHttpClient();
if ($form->get('email2')->getData()) {
return $this->redirectToRoute('app_register');
}
$response = $client->request('POST', 'https://www.google.com/recaptcha/api/siteverify', ['body'=>['secret'=>$_ENV['RECAPTCHA_API_secret'], 'response'=>$request->request->get('g-recaptcha-response')]])->toArray();
$valid = $form->isValid();
if(!$valid)throw new FlashableException('Le formulaire n\'est pas valide.');
// if(!$response['success']){
// $this->addFlash(
// 'error',
// 'Échec recaptcha'
// );
// $valid = false;
// }
if($_ENV['APP_ENV'] == 'dev'){
// throw new \Exception('recaptcha failing : '.implode(', ', $response['error-codes']));
}
// encode the plain password
$user->setPassword(
$passwordEncoder->hashPassword(
$user,
$form->get('plainPassword')->getData()
)
);
// L'utilisateur a-t-il au minimum 16 ans ? Eg: conduite accompagnée ?
$user->setIsSuspend(0);
$statut = $form->get('statut')->getData();
$autorisation = $form->get('autorisation')->getData();
if ($autorisation) {
$fileUploader->setDuplicateModeReplace();
$fileUploader->setTargetDirectoryByUser($user);
$fileUploader->setUpload($autorisation);
$Document = new UserEnseignantDocument;
$Document->setDoc('autorisation');
$user->addUserEnseignantDocument($Document);
$fileUploader->setDocument($Document);
$fileUploader->setTargetDirectoryByDocument($Document);
$uploaded = $fileUploader->upload();
if(!$uploaded){
$this->addFlash(
'error',
$fileUploader->getError()
);
}
$entityManager->persist($Document);
}
$num_autorisation = $form->get('num_autorisation')->getData();
if($num_autorisation){
$Document = new UserEnseignantDocument;
$Document->setDoc('num_autorisation');
$Document->setType('text');
$Document->setContenu($num_autorisation);
$user->addUserEnseignantDocument($Document);
$entityManager->persist($Document);
}
$Event = false;
// Inscription d'un nouvel élève
if ($statut == '0')
{
$user->setRoles(array('ROLE_ELEVE'));
$Event = new InscriptionEleveEvent($user);
}
// Inscription d'un nouveau formateur
elseif ($statut == '1')
{
$user->setRoles(array('ROLE_PROF'));
$Event = new InscriptionFormateurEvent($user);
}
if(empty($user->getRoles())){
throw new FlashableException('Aucun rôle n\'a été attribué à l\'utilisateur.');
}
// Tentative de génération du lien de confirmation et mail à l'utilisateur
$entityManager->persist($user);
$entityManager->flush();
if ($Event) {// Dispatch de l'évènement de l'inscription => maj de app_user_event
$this->dispatcher->dispatch($Event, $Event::NAME);
}
try {
$response = $this->sendConfirmationEmail($user, $request);
$data = json_decode($response->getContent(), true);
if (!empty($data['success'])) {
$this->addFlash('success', $data['success']);
}
if (!empty($data['error'])) {
throw new \Exception($data['error']);
}
$entityManager->getConnection()->commit();
// On redirige l'utilisateur vers le formulaire de connexion
return $this->redirectToRoute('app_login');
}
catch(\Exception $e)
{
// On annule la transaction, l\'emailing n'a pas fonctionné
$entityManager->getConnection()->rollback();
throw new FlashableException($e->getMessage());
}
$userRepository = $entityManager->getRepository(User::class);
$qb = $userRepository->createQueryBuilder();
$qb = $userRepository->ByMail($qb, $form->get('email')->getData());
$qb = $userRepository->notVerified($qb);
$qb->select('count('.$userRepository::ALIAS.'.id)');
$retour['isNonVerified'] = $qb->getQuery()->getSingleScalarResult()>0;
}
catch(FlashableException $e) {
$this->addFlash('error', 'Une erreur est survenue durant le traitement du formulaire : '.$e->getMessage());
// On annule la transaction, quelque chose n'a pas fonctionné
// return $this->redirectToRoute('app_register');
}
}
foreach($form->getErrors()as$error){
echo$error->getMessage().'<br>'.PHP_EOL;
$this->addFlash('error', $error->getMessage());
}
if (!$form->isSubmitted()) {
$form->get('agreeTerms')->setData(false);
}
return $this->renderForm('registration/register.html.twig', $retour);
}
/**
* @Route("/register/send_confirm/{email}", name="app_send_confirm")
* Security("is_granted('ROLE_SUPER_ADMIN') or is_granted('ROLE_ADMIN') or is_granted('ROLE_ELEVE')", statusCode=404, message="Ressource non trouvée")
*/
public function sendConfirmationEmail(User $user, Request $request):Response
{
if($this->getUser() and $this->getUser()->isEleve() and $this->getUser()->getId() != $user->getId())
throw $this->createNotFoundException();
$data = array();
try {
$this->emailVerifier->sendEmailConfirmation(
'app_verify_email',
$user,
(new TemplatedEmail())
->to($user->getEmail())
->subject('Confirmation d\'adresse mail')
->htmlTemplate('registration/confirmation_email.html.twig')
);
$data['success'] = "Un mail vous a été envoyé à l'adresse \"".$user->getEmail()."\", merci de bien vouloir cliquer sur le lien pour valider votre compte.";
}
catch(\Exception $e)
{
$data['error'] = "L'email renseigné n'est pas valide.";
}
if($request->isXmlHttpRequest() || $request->getPreferredFormat()=='json') {
return $this->json($data);
}
if (!empty($data['error'])) {
$this->addFlash('error', $data['error']);
}
if (!empty($data['success'])) {
$this->addFlash('success', $data['success']);
}
return $this->redirectToRoute('app_login');
}
private function autologin(Passport $passport) {
return $passport;
}
/**
* @Route("/verify/email", name="app_verify_email")
*/
public function verifyUserEmail(Request $request, UserRepository $userRepository): Response {
$id = $request->get('id');
if (null === $id) {
return $this->redirectToRoute('app_register');
}
$user = $userRepository->find($id);
if (null === $user) {
return $this->redirectToRoute('app_register');
}
// validate email confirmation link, sets User::isVerified=true and persists
try {
$this->emailVerifier->handleEmailConfirmation($request, $user);
} catch (VerifyEmailExceptionInterface $exception) {
$this->addFlash('verify_email_error', $exception->getReason());
return $this->redirectToRoute('app_register');
}
// @TODO Change the redirect on success and handle or remove the flash message in your templates
$this->addFlash('success', 'Votre adresse mail a été vérifiée.');
if($user->isProf())
return $this->redirectToRoute('enseignant');
if($user->isEleve())
return $this->redirectToRoute('eleve');
return $this->redirectToRoute('login');
}
}