From 0b7c70f3489796250f23e91dfe5083f3cc902d26 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Rapha=C3=ABl=20Gertz?= Date: Mon, 11 Dec 2023 02:42:05 +0100 Subject: [PATCH 1/1] Add index function Remove field, hash and mail from register context Use checker isGranted member function Use security getUser member function Cleanup Set edit form field from admin or user set Add disabled and sent query parameter to login context Cleanup recover function Cleanup register function Fix user constructor arguments Set register form field from admin or user set Fix translation of context --- Controller/DefaultController.php | 643 +++++++++++++------------------ 1 file changed, 264 insertions(+), 379 deletions(-) diff --git a/Controller/DefaultController.php b/Controller/DefaultController.php index de4ff4e..6fc4111 100644 --- a/Controller/DefaultController.php +++ b/Controller/DefaultController.php @@ -22,10 +22,46 @@ use Symfony\Component\Mime\Address; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; use Symfony\Component\Security\Http\Authentication\AuthenticationUtils; +use Rapsys\UserBundle\RapsysUserBundle; + /** * {@inheritdoc} */ class DefaultController extends AbstractController { + /** + * User index + * + * @param Request $request The request + * @return Response The response + */ + public function index(Request $request): Response { + //Without admin + if (!$this->checker->isGranted($this->config['default']['admin'])) { + //Throw 403 + throw $this->createAccessDeniedException($this->translator->trans('Unable to list users')); + } + + //Get count + $this->context['count'] = $this->doctrine->getRepository($this->config['class']['user'])->findCountAsInt(); + + //With not enough users + if ($this->context['count'] - $this->page * $this->limit < 0) { + //Throw 404 + throw $this->createNotFoundException($this->translator->trans('Unable to find users')); + } + + //Get users + $this->context['users'] = $this->doctrine->getRepository($this->config['class']['user'])->findAllAsArray($this->page, $this->limit); + + //Render view + return $this->render( + //Template + $this->config['index']['view']['name'], + //Context + $this->context+$this->config['index']['view']['context'] + ); + } + /** * Confirm account from mail link * @@ -58,7 +94,7 @@ class DefaultController extends AbstractController { $this->addFlash('error', $this->translator->trans('Account %mail% do not exists', ['%mail%' => $smail])); //Redirect to register view - return $this->redirectToRoute($this->config['route']['register']['name'], ['mail' => $smail, 'field' => $sfield = $this->slugger->serialize([]), 'hash' => $this->slugger->hash($smail.$sfield)]+$this->config['route']['register']['context']); + return $this->redirectToRoute($this->config['route']['register']['name'], $this->config['route']['register']['context']); } //Set active @@ -103,36 +139,30 @@ class DefaultController extends AbstractController { } //Prevent access when not admin, user is not guest and not currently logged user - if (!$this->isGranted('ROLE_ADMIN') && $user != $this->getUser() || !$this->isGranted('IS_AUTHENTICATED_FULLY')) { + if (!$this->checker->isGranted($this->config['default']['admin']) && $user != $this->security->getUser() || !$this->checker->isGranted('IS_AUTHENTICATED_FULLY')) { //Throw access denied //XXX: prevent slugger reverse engineering by not displaying decoded mail throw $this->createAccessDeniedException($this->translator->trans('Unable to access user: %mail%', ['%mail%' => $smail])); } - - //Create the RegisterType form and give the proper parameters + + //Create the EditType form and give the proper parameters $edit = $this->createForm($this->config['edit']['view']['edit'], $user, [ - //Set action to register route name and context + //Set action to edit route name and context 'action' => $this->generateUrl($this->config['route']['edit']['name'], ['mail' => $smail, 'hash' => $this->slugger->hash($smail)]+$this->config['route']['edit']['context']), //Set civility class 'civility_class' => $this->config['class']['civility'], //Set civility default 'civility_default' => $this->doctrine->getRepository($this->config['class']['civility'])->findOneByTitle($this->config['default']['civility']), - //Disable mail - 'mail' => $this->isGranted('ROLE_ADMIN'), - //Disable password - 'password' => false, //Set method 'method' => 'POST' - ]+$this->config['edit']['field']); + ]+($this->checker->isGranted($this->config['default']['admin'])?$this->config['edit']['admin']:$this->config['edit']['field'])); //With admin role - if ($this->isGranted('ROLE_ADMIN')) { - //Create the LoginType form and give the proper parameters + if ($this->checker->isGranted($this->config['default']['admin'])) { + //Create the EditType form and give the proper parameters $reset = $this->createForm($this->config['edit']['view']['reset'], $user, [ - //Set action to register route name and context + //Set action to edit route name and context 'action' => $this->generateUrl($this->config['route']['edit']['name'], ['mail' => $smail, 'hash' => $this->slugger->hash($smail)]+$this->config['route']['edit']['context']), - //Disable mail - 'mail' => false, //Set method 'method' => 'POST' ]); @@ -199,7 +229,7 @@ class DefaultController extends AbstractController { } //Without admin role //XXX: prefer a reset on login to force user unspam action - } elseif (!$this->isGranted('ROLE_ADMIN')) { + } elseif (!$this->checker->isGranted($this->config['default']['admin'])) { //Add notice $this->addFlash('notice', $this->translator->trans('To change your password login with your mail and any password then follow the procedure')); } @@ -227,8 +257,6 @@ class DefaultController extends AbstractController { $login = $this->createForm($this->config['login']['view']['form'], null, [ //Set action to login route name and context 'action' => $this->generateUrl($this->config['route']['login']['name'], $this->config['route']['login']['context']), - //Disable repeated password - 'password_repeated' => false, //Set method 'method' => 'POST' ]); @@ -268,7 +296,7 @@ class DefaultController extends AbstractController { //Add error message to mail field $login->get('mail')->addError(new FormError($error)); - //Create the LoginType form and give the proper parameters + //Create the RecoverType form and give the proper parameters $recover = $this->createForm($this->config['recover']['view']['form'], null, [ //Set action to recover route name and context 'action' => $this->generateUrl($this->config['route']['recover']['name'], $this->config['route']['recover']['context']), @@ -297,7 +325,7 @@ class DefaultController extends AbstractController { //Template $this->config['login']['view']['name'], //Context - ['login' => $login->createView()]+$context+$this->config['login']['view']['context'] + ['login' => $login->createView(), 'disabled' => $request->query->get('disabled', 0), 'sent' => $request->query->get('sent', 0)]+$context+$this->config['login']['view']['context'] ); } @@ -311,157 +339,56 @@ class DefaultController extends AbstractController { * @return Response The response */ public function recover(Request $request, ?string $hash, ?string $pass, ?string $mail): Response { - //Without mail, pass and hash - if (empty($mail) && empty($pass) && empty($hash)) { - //Create the LoginType form and give the proper parameters - $form = $this->createForm($this->config['recover']['view']['form'], null, [ - //Set action to recover route name and context - 'action' => $this->generateUrl($this->config['route']['recover']['name'], $this->config['route']['recover']['context']), - //Without password - 'password' => false, - //Set method - 'method' => 'POST' - ]); - - //With post method - if ($request->isMethod('POST')) { - //Refill the fields in case the form is not valid. - $form->handleRequest($request); + //Set user + $user = null; - //With form submitted and valid - if ($form->isSubmitted() && $form->isValid()) { - //Set data - $data = $form->getData(); - - //Find user by data mail - if ($user = $this->doctrine->getRepository($this->config['class']['user'])->findOneByMail($data['mail'])) { - //Set mail shortcut - $recoverMail =& $this->config['recover']['mail']; - - //Set mail - $mail = $this->slugger->short($user->getMail()); - - //Set pass - $pass = $this->slugger->hash($user->getPassword()); - - //Generate each route route - foreach($this->config['recover']['route'] as $route => $tag) { - //Only process defined routes - if (!empty($this->config['route'][$route])) { - //Process for recover mail url - if ($route == 'recover') { - //Set the url in context - $recoverMail['context'][$tag] = $this->router->generate( - $this->config['route'][$route]['name'], - //Prepend recover context with tag - [ - 'mail' => $mail, - 'pass' => $pass, - 'hash' => $this->slugger->hash($mail.$pass) - ]+$this->config['route'][$route]['context'], - UrlGeneratorInterface::ABSOLUTE_URL - ); - } - } - } + //Set context + $context = []; - //Set recipient_name - $recoverMail['context']['recipient_mail'] = $user->getMail(); - - //Set recipient_name - $recoverMail['context']['recipient_name'] = $user->getRecipientName(); - - //Init subject context - $subjectContext = $this->slugger->flatten(array_replace_recursive($this->config['recover']['view']['context'], $recoverMail['context']), null, '.', '%', '%'); - - //Translate subject - $recoverMail['subject'] = ucfirst($this->translator->trans($recoverMail['subject'], $subjectContext)); - - //Create message - $message = (new TemplatedEmail()) - //Set sender - ->from(new Address($this->config['contact']['mail'], $this->config['contact']['title'])) - //Set recipient - //XXX: remove the debug set in vendor/symfony/mime/Address.php +46 - ->to(new Address($recoverMail['context']['recipient_mail'], $recoverMail['context']['recipient_name'])) - //Set subject - ->subject($recoverMail['subject']) - - //Set path to twig templates - ->htmlTemplate($recoverMail['html']) - ->textTemplate($recoverMail['text']) - - //Set context - //XXX: require recursive merge to avoid loosing subkeys - //['subject' => $recoverMail['subject']]+$recoverMail['context']+$this->config['recover']['view']['context'] - ->context(array_replace_recursive($this->config['recover']['view']['context'], $recoverMail['context'], ['subject' => $recoverMail['subject']])); - - //Try sending message - //XXX: mail delivery may silently fail - try { - //Send message - $this->mailer->send($message); - - //Redirect on the same route with sent=1 to cleanup form - return $this->redirectToRoute($request->get('_route'), ['sent' => 1]+$request->get('_route_params')); - //Catch obvious transport exception - } catch(TransportExceptionInterface $e) { - //Add error message mail unreachable - $form->get('mail')->addError(new FormError($this->translator->trans('Account found but unable to contact: %mail%', array('%mail%' => $data['mail'])))); - } - //Accout not found - } else { - //Add error message to mail field - $form->get('mail')->addError(new FormError($this->translator->trans('Unable to find account %mail%', ['%mail%' => $data['mail']]))); - } - } + //With mail, pass and hash + if (!empty($mail) && !empty($pass) && !empty($hash)) { + //With invalid hash + if ($hash != $this->slugger->hash($mail.$pass)) { + //Throw bad request + throw new BadRequestHttpException($this->translator->trans('Invalid %field% field: %value%', ['%field%' => 'hash', '%value%' => $hash])); } - //Render view - return $this->render( - //Template - $this->config['recover']['view']['name'], - //Context - ['form' => $form->createView(), 'sent' => $request->query->get('sent', 0)]+$this->config['recover']['view']['context'] - ); - } - - //With invalid hash - if ($hash != $this->slugger->hash($mail.$pass)) { - //Throw bad request - throw new BadRequestHttpException($this->translator->trans('Invalid %field% field: %value%', ['%field%' => 'hash', '%value%' => $hash])); - } + //Get mail + $mail = $this->slugger->unshort($smail = $mail); - //Get mail - $mail = $this->slugger->unshort($smail = $mail); + //Without valid mail + if (filter_var($mail, FILTER_VALIDATE_EMAIL) === false) { + //Throw bad request + //XXX: prevent slugger reverse engineering by not displaying decoded mail + throw new BadRequestHttpException($this->translator->trans('Invalid %field% field: %value%', ['%field%' => 'mail', '%value%' => $smail])); + } - //Without valid mail - if (filter_var($mail, FILTER_VALIDATE_EMAIL) === false) { - //Throw bad request - //XXX: prevent slugger reverse engineering by not displaying decoded mail - throw new BadRequestHttpException($this->translator->trans('Invalid %field% field: %value%', ['%field%' => 'mail', '%value%' => $smail])); - } + //With existing subscriber + if (empty($user = $this->doctrine->getRepository($this->config['class']['user'])->findOneByMail($mail))) { + //Throw not found + //XXX: prevent slugger reverse engineering by not displaying decoded mail + throw $this->createNotFoundException($this->translator->trans('Unable to find account %mail%', ['%mail%' => $smail])); + } - //With existing subscriber - if (empty($user = $this->doctrine->getRepository($this->config['class']['user'])->findOneByMail($mail))) { - //Throw not found - //XXX: prevent slugger reverse engineering by not displaying decoded mail - throw $this->createNotFoundException($this->translator->trans('Unable to find account %mail%', ['%mail%' => $smail])); - } + //With unmatched pass + if ($pass != $this->slugger->hash($user->getPassword())) { + //Throw not found + //XXX: prevent use of outdated recover link + throw $this->createNotFoundException($this->translator->trans('Outdated recover link')); + } - //With unmatched pass - if ($pass != $this->slugger->hash($user->getPassword())) { - //Throw not found - //XXX: prevent use of outdated recover link - throw $this->createNotFoundException($this->translator->trans('Outdated recover link')); + //Set context + $context = ['mail' => $smail, 'pass' => $pass, 'hash' => $hash]; } //Create the LoginType form and give the proper parameters $form = $this->createForm($this->config['recover']['view']['form'], $user, [ //Set action to recover route name and context - 'action' => $this->generateUrl($this->config['route']['recover']['name'], ['mail' => $smail, 'pass' => $pass, 'hash' => $hash]+$this->config['route']['recover']['context']), - //Without mail - 'mail' => false, + 'action' => $this->generateUrl($this->config['route']['recover']['name'], $context+$this->config['route']['recover']['context']), + //With user disable mail + 'mail' => ($user === null), + //With user enable password + 'password' => ($user !== null), //Set method 'method' => 'POST' ]); @@ -476,26 +403,132 @@ class DefaultController extends AbstractController { //Set data $data = $form->getData(); - //Set hashed password - $hashed = $this->hasher->hashPassword($user, $user->getPassword()); + //With user + if ($user !== null) { + //Set hashed password + $hashed = $this->hasher->hashPassword($user, $user->getPassword()); - //Update pass - $pass = $this->slugger->hash($hashed); + //Update pass + $pass = $this->slugger->hash($hashed); - //Set user password - $user->setPassword($hashed); + //Set user password + $user->setPassword($hashed); - //Persist user - $this->manager->persist($user); + //Persist user + $this->manager->persist($user); + + //Send to database + $this->manager->flush(); - //Send to database - $this->manager->flush(); + //Add notice + $this->addFlash('notice', $this->translator->trans('Account password updated')); + + //Redirect to user login + return $this->redirectToRoute($this->config['route']['login']['name'], ['mail' => $smail, 'hash' => $this->slugger->hash($smail)]+$this->config['route']['login']['context']); + //Find user by data mail + } elseif ($user = $this->doctrine->getRepository($this->config['class']['user'])->findOneByMail($data['mail'])) { + //Set context + $context = [ + 'recipient_mail' => $user->getMail(), + 'recipient_name' => $user->getRecipientName() + ] + array_replace_recursive( + $this->config['context'], + $this->config['recover']['view']['context'], + $this->config['recover']['mail']['context'] + ); + + //Generate each route route + foreach($this->config['recover']['route'] as $route => $tag) { + //Only process defined routes + if (!empty($this->config['route'][$route])) { + //Process for recover mail url + if ($route == 'recover') { + //Set the url in context + $context[$tag] = $this->router->generate( + $this->config['route'][$route]['name'], + //Prepend recover context with tag + [ + 'mail' => $smail = $this->slugger->short($context['recipient_mail']), + 'pass' => $spass = $this->slugger->hash($pass = $user->getPassword()), + 'hash' => $this->slugger->hash($smail.$spass) + ]+$this->config['route'][$route]['context'], + UrlGeneratorInterface::ABSOLUTE_URL + ); + } + } + } + + //Iterate on keys to translate + foreach($this->config['translate'] as $translate) { + //Extract keys + $keys = explode('.', $translate); + + //Set current + $current =& $context; + + //Iterate on each subkey + do { + //Skip unset translation keys + if (!isset($current[current($keys)])) { + continue(2); + } + + //Set current to subkey + $current =& $current[current($keys)]; + } while(next($keys)); + + //Set translation + $current = $this->translator->trans($current); + + //Remove reference + unset($current); + } + + //Translate subject + $context['subject'] = $subject = ucfirst( + $this->translator->trans( + $this->config['recover']['mail']['subject'], + $this->slugger->flatten($context, null, '.', '%', '%') + ) + ); + + //Create message + $message = (new TemplatedEmail()) + //Set sender + ->from(new Address($this->config['contact']['address'], $this->config['contact']['name'])) + //Set recipient + //XXX: remove the debug set in vendor/symfony/mime/Address.php +46 + ->to(new Address($context['recipient_mail'], $context['recipient_name'])) + //Set subject + ->subject($context['subject']) - //Add notice - $this->addFlash('notice', $this->translator->trans('Account %mail% password updated', ['%mail%' => $mail])); + //Set path to twig templates + ->htmlTemplate($this->config['recover']['mail']['html']) + ->textTemplate($this->config['recover']['mail']['text']) - //Redirect to user login - return $this->redirectToRoute($this->config['route']['login']['name'], ['mail' => $smail, 'hash' => $this->slugger->hash($smail)]+$this->config['route']['login']['context']); + //Set context + ->context($context); + + //Try sending message + //XXX: mail delivery may silently fail + try { + //Send message + $this->mailer->send($message); + + //Add notice + $this->addFlash('notice', $this->translator->trans('Your recovery mail has been sent, to retrieve your account you must follow the recuperate link inside')); + + //Add junk warning + $this->addFlash('warning', $this->translator->trans('If you did not receive a recovery mail, check your Spam or Junk mail folders')); + + //Redirect on the same route with sent=1 to cleanup form + return $this->redirectToRoute($request->get('_route'), ['sent' => 1]+$request->get('_route_params'), 302); + //Catch obvious transport exception + } catch(TransportExceptionInterface $e) { + //Add error message mail unreachable + $form->get('mail')->addError(new FormError($this->translator->trans('Unable to reach account'))); + } + } } } @@ -504,7 +537,7 @@ class DefaultController extends AbstractController { //Template $this->config['recover']['view']['name'], //Context - ['form' => $form->createView(), 'sent' => $request->query->get('sent', 0)]+$this->config['recover']['view']['context'] + ['recover' => $form->createView(), 'sent' => $request->query->get('sent', 0)]+$this->config['recover']['view']['context'] ); } @@ -512,12 +545,9 @@ class DefaultController extends AbstractController { * Register an account * * @param Request $request The request - * @param ?string $hash The hashed serialized field array - * @param ?string $field The serialized then shorted form field array - * @param ?string $mail The shorted mail address * @return Response The response */ - public function register(Request $request, ?string $hash, ?string $field, ?string $mail): Response { + public function register(Request $request): Response { //With mail if (!empty($_POST['register']['mail'])) { //Log new user infos @@ -541,182 +571,23 @@ class DefaultController extends AbstractController { ); } - //With mail and field - if (!empty($field) && !empty($hash)) { - //With invalid hash - if ($hash != $this->slugger->hash($mail.$field)) { - //Throw bad request - throw new BadRequestHttpException($this->translator->trans('Invalid %field% field: %value%', ['%field%' => 'hash', '%value%' => $hash])); - } - - //With mail - if (!empty($mail)) { - //Get mail - $mail = $this->slugger->unshort($smail = $mail); - - //Without valid mail - if (filter_var($mail, FILTER_VALIDATE_EMAIL) === false) { - //Throw bad request - //XXX: prevent slugger reverse engineering by not displaying decoded mail - throw new BadRequestHttpException($this->translator->trans('Invalid %field% field: %value%', ['%field%' => 'mail', '%value%' => $smail])); - } - - //With existing registrant - if ($existing = $this->doctrine->getRepository($this->config['class']['user'])->findOneByMail($mail)) { - //With disabled existing - if ($existing->isDisabled()) { - //Render view - $response = $this->render( - //Template - $this->config['register']['view']['name'], - //Context - ['title' => $this->translator->trans('Access denied'), 'disabled' => 1]+$this->config['register']['view']['context'] - ); - - //Set 403 - $response->setStatusCode(403); - - //Return response - return $response; - //With unactivated existing - } elseif (!$existing->isActivated()) { - //Set mail shortcut - $activateMail =& $this->config['register']['mail']; - - //Generate each route route - foreach($this->config['register']['route'] as $route => $tag) { - //Only process defined routes - if (!empty($this->config['route'][$route])) { - //Process for confirm url - if ($route == 'confirm') { - //Set the url in context - $activateMail['context'][$tag] = $this->router->generate( - $this->config['route'][$route]['name'], - //Prepend subscribe context with tag - [ - 'mail' => $smail = $this->slugger->short($existing->getMail()), - 'hash' => $this->slugger->hash($smail) - ]+$this->config['route'][$route]['context'], - UrlGeneratorInterface::ABSOLUTE_URL - ); - } - } - } - - //Set recipient_name - $activateMail['context']['recipient_mail'] = $existing->getMail(); - - //Set recipient name - $activateMail['context']['recipient_name'] = $existing->getRecipientName(); - - //Init subject context - $subjectContext = $this->slugger->flatten(array_replace_recursive($this->config['register']['view']['context'], $activateMail['context']), null, '.', '%', '%'); - - //Translate subject - $activateMail['subject'] = ucfirst($this->translator->trans($activateMail['subject'], $subjectContext)); - - //Create message - $message = (new TemplatedEmail()) - //Set sender - ->from(new Address($this->config['contact']['mail'], $this->config['contact']['title'])) - //Set recipient - //XXX: remove the debug set in vendor/symfony/mime/Address.php +46 - ->to(new Address($activateMail['context']['recipient_mail'], $activateMail['context']['recipient_name'])) - //Set subject - ->subject($activateMail['subject']) - - //Set path to twig templates - ->htmlTemplate($activateMail['html']) - ->textTemplate($activateMail['text']) - - //Set context - ->context(['subject' => $activateMail['subject']]+$activateMail['context']); - - //Try sending message - //XXX: mail delivery may silently fail - try { - //Send message - $this->mailer->send($message); - //Catch obvious transport exception - } catch(TransportExceptionInterface $e) { - //Add error message mail unreachable - $this->addFlash('error', $this->translator->trans('Account %mail% tried activate but unable to contact', ['%mail%' => $existing->getMail()])); - } - - //Get route params - $routeParams = $request->get('_route_params'); - - //Remove mail, field and hash from route params - unset($routeParams['mail'], $routeParams['field'], $routeParams['hash']); - - //Redirect on the same route with sent=1 to cleanup form - return $this->redirectToRoute($request->get('_route'), ['sent' => 1]+$routeParams); - } - - //Add error message mail already exists - $this->addFlash('warning', $this->translator->trans('Account %mail% already exists', ['%mail%' => $existing->getMail()])); - - //Redirect to user view - return $this->redirectToRoute( - $this->config['route']['edit']['name'], - [ - 'mail' => $smail = $this->slugger->short($existing->getMail()), - 'hash' => $this->slugger->hash($smail) - ]+$this->config['route']['edit']['context'] - ); - } - //Without mail - } else { - //Set smail - $smail = $mail; - } - - //Try - try { - //Unshort then unserialize field - $field = $this->slugger->unserialize($sfield = $field); - //Catch type error - } catch (\Error|\Exception $e) { - //Throw bad request - throw new BadRequestHttpException($this->translator->trans('Invalid %field% field: %value%', ['%field%' => 'field', '%value%' => $field]), $e); - } - - //With non array field - if (!is_array($field)) { - //Throw bad request - throw new BadRequestHttpException($this->translator->trans('Invalid %field% field: %value%', ['%field%' => 'field', '%value%' => $field])); - } - //Without field and hash - } else { - //Set smail - $smail = $mail; - - //Set smail - $sfield = $field; - - //Reset field - $field = []; - } - //Init reflection $reflection = new \ReflectionClass($this->config['class']['user']); //Create new user - $user = $reflection->newInstance(strval($mail)); + $user = $reflection->newInstance('', ''); //Create the RegisterType form and give the proper parameters - $form = $this->createForm($this->config['register']['view']['form'], $user, $field+[ + $form = $this->createForm($this->config['register']['view']['form'], $user, [ //Set action to register route name and context - 'action' => $this->generateUrl($this->config['route']['register']['name'], ['mail' => $smail, 'field' => $sfield, 'hash' => $hash]+$this->config['route']['register']['context']), + 'action' => $this->generateUrl($this->config['route']['register']['name'], $this->config['route']['register']['context']), //Set civility class 'civility_class' => $this->config['class']['civility'], //Set civility default 'civility_default' => $this->doctrine->getRepository($this->config['class']['civility'])->findOneByTitle($this->config['default']['civility']), - //With mail - 'mail' => true, //Set method 'method' => 'POST' - ]+$this->config['register']['field']); + ]+($this->checker->isGranted($this->config['default']['admin'])?$this->config['register']['admin']:$this->config['register']['field'])); //With post method if ($request->isMethod('POST')) { @@ -728,24 +599,6 @@ class DefaultController extends AbstractController { //Set data $data = $form->getData(); - //With existing registrant - if ($this->doctrine->getRepository($this->config['class']['user'])->findOneByMail($mail = $data->getMail())) { - //Add error message mail already exists - $this->addFlash('warning', $this->translator->trans('Account %mail% already exists', ['%mail%' => $mail])); - - //Redirect to user view - return $this->redirectToRoute( - $this->config['route']['edit']['name'], - [ - 'mail' => $smail = $this->slugger->short($mail), - 'hash' => $this->slugger->hash($smail) - ]+$this->config['route']['edit']['context'] - ); - } - - //Set mail shortcut - $registerMail =& $this->config['register']['mail']; - //Set password $user->setPassword($this->hasher->hashPassword($user, $user->getPassword())); @@ -763,22 +616,32 @@ class DefaultController extends AbstractController { } else { //Throw exception //XXX: consider missing group as fatal - throw new \Exception(sprintf('Group from rapsys_user.default.group[%d] not found by title: %s', $i, $groupTitle)); + throw new \Exception(sprintf('Group %s listed in %s.default.group[%d] not found by title', $groupTitle, RapsysUserBundle::getAlias(), $i)); } } + //Set context + $context = [ + 'recipient_mail' => $user->getMail(), + 'recipient_name' => $user->getRecipientName() + ] + array_replace_recursive( + $this->config['context'], + $this->config['register']['view']['context'], + $this->config['register']['mail']['context'] + ); + //Generate each route route foreach($this->config['register']['route'] as $route => $tag) { //Only process defined routes if (!empty($this->config['route'][$route])) { - //Process for confirm url + //Process for confirm mail url if ($route == 'confirm') { //Set the url in context - $registerMail['context'][$tag] = $this->router->generate( + $context[$tag] = $this->router->generate( $this->config['route'][$route]['name'], - //Prepend subscribe context with tag + //Prepend register context with tag [ - 'mail' => $smail = $this->slugger->short($data->getMail()), + 'mail' => $smail = $this->slugger->short($context['recipient_mail']), 'hash' => $this->slugger->hash($smail) ]+$this->config['route'][$route]['context'], UrlGeneratorInterface::ABSOLUTE_URL @@ -787,34 +650,56 @@ class DefaultController extends AbstractController { } } - //Set recipient_name - $registerMail['context']['recipient_mail'] = $data->getMail(); + //Iterate on keys to translate + foreach($this->config['translate'] as $translate) { + //Extract keys + $keys = explode('.', $translate); - //Set recipient name - $registerMail['context']['recipient_name'] = $data->getRecipientName(); + //Set current + $current =& $context; - //Init subject context - $subjectContext = $this->slugger->flatten(array_replace_recursive($this->config['register']['view']['context'], $registerMail['context']), null, '.', '%', '%'); + //Iterate on each subkey + do { + //Skip unset translation keys + if (!isset($current[current($keys)])) { + continue(2); + } + + //Set current to subkey + $current =& $current[current($keys)]; + } while(next($keys)); + + //Set translation + $current = $this->translator->trans($current); + + //Remove reference + unset($current); + } //Translate subject - $registerMail['subject'] = ucfirst($this->translator->trans($registerMail['subject'], $subjectContext)); + $context['subject'] = $subject = ucfirst( + $this->translator->trans( + $this->config['register']['mail']['subject'], + $this->slugger->flatten($context, null, '.', '%', '%') + ) + ); //Create message $message = (new TemplatedEmail()) //Set sender - ->from(new Address($this->config['contact']['mail'], $this->config['contact']['title'])) + ->from(new Address($this->config['contact']['address'], $this->config['contact']['name'])) //Set recipient //XXX: remove the debug set in vendor/symfony/mime/Address.php +46 - ->to(new Address($registerMail['context']['recipient_mail'], $registerMail['context']['recipient_name'])) + ->to(new Address($context['recipient_mail'], $context['recipient_name'])) //Set subject - ->subject($registerMail['subject']) + ->subject($context['subject']) //Set path to twig templates - ->htmlTemplate($registerMail['html']) - ->textTemplate($registerMail['text']) + ->htmlTemplate($this->config['register']['mail']['html']) + ->textTemplate($this->config['register']['mail']['text']) //Set context - ->context(['subject' => $registerMail['subject']]+$registerMail['context']); + ->context($context); //Try saving in database try { @@ -835,12 +720,12 @@ class DefaultController extends AbstractController { //Catch obvious transport exception } catch(TransportExceptionInterface $e) { //Add error message mail unreachable - $form->get('mail')->addError(new FormError($this->translator->trans('Account %mail% tried subscribe but unable to contact', ['%mail%' => $data->getMail()]))); + $form->get('mail')->addError(new FormError($this->translator->trans('Unable to reach account'))); } //Catch double subscription } catch (UniqueConstraintViolationException $e) { //Add error message mail already exists - $this->addFlash('error', $this->translator->trans('Account %mail% already exists', ['%mail%' => $mail])); + $this->addFlash('error', $this->translator->trans('Account already exists')); } } } @@ -850,7 +735,7 @@ class DefaultController extends AbstractController { //Template $this->config['register']['view']['name'], //Context - ['form' => $form->createView(), 'sent' => $request->query->get('sent', 0)]+$this->config['register']['view']['context'] + ['register' => $form->createView(), 'sent' => $request->query->get('sent', 0)]+$this->config['register']['view']['context'] ); } } -- 2.41.1