src/Controller/SecurityController.php line 48

  1. <?php
  2. namespace App\Controller;
  3. use App\Balance\BalanceRefillAmountEnum;
  4. use App\Balance\BalanceService;
  5. use App\Donation\DonationLevelEnum;
  6. use App\Entity\User;
  7. use App\Form\RegistrationFormStepOneType;
  8. use App\Form\RegistrationFormStepTwoType;
  9. use App\Repository\UserRepository;
  10. use App\Security\LoginFormAuthenticator;
  11. use App\Util\Formatter;
  12. use App\Util\USA as USAUtil;
  13. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  14. use Symfony\Bundle\SecurityBundle\Security;
  15. use Symfony\Component\HttpFoundation\Request;
  16. use Symfony\Component\HttpFoundation\RequestStack;
  17. use Symfony\Component\HttpFoundation\Response;
  18. use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
  19. use Symfony\Component\Routing\Annotation\Route;
  20. use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
  21. class SecurityController extends AbstractController
  22. {
  23.     private const SESSION_KEY 'registration_user_id';
  24.     // todo make sure we don't start sessions for anon users
  25.     public function __construct(
  26.         private RequestStack   $requestStack,
  27.         private UserRepository $userRepository,
  28.     )
  29.     {
  30.     }
  31.     #[Route('/app'name'app_default'methods'GET')]
  32.     public function default(): Response
  33.     {
  34.         /**
  35.          * This is the entry point for requests without valid cup tag, e.g. direct URL type ins
  36.          */
  37.         return $this->render('home/default.html.twig', [
  38.         ]);
  39.     }
  40.     #[Route('/login'name'app_login'methods: ['GET''POST'])]
  41.     public function login(AuthenticationUtils $authenticationUtils): Response
  42.     {
  43.          if ($this->getUser()) {
  44.              return $this->redirectToRoute('app_home');
  45.          }
  46.         // get the login error if there is one
  47.         $error $authenticationUtils->getLastAuthenticationError();
  48.         // last username entered by the user
  49.         $lastUsername $authenticationUtils->getLastUsername();
  50.         return $this->render('security/login.html.twig', [
  51.             'last_username' => $lastUsername,
  52.             'error' => $error,
  53.             'states' => USAUtil::getUsStateDemocraticParties()
  54.         ]);
  55.     }
  56.     #[Route(path'/logout'name'app_logout')]
  57.     public function logout(): void
  58.     {
  59.         throw new \LogicException('This method can be blank - it will be intercepted by the logout key on your firewall.');
  60.     }
  61.     #[Route('/register'name'app_register_step_one'methods: ['GET''POST'])]
  62.     public function registerStepOne(
  63.         Request                     $request,
  64.         UserPasswordHasherInterface $userPasswordHasher,
  65.     ): Response
  66.     {
  67.         $user = new User();
  68.         $form $this->createForm(RegistrationFormStepOneType::class, $user);
  69.         $form->handleRequest($request);
  70.         if ($form->isSubmitted() && $form->isValid()) {
  71.             // encode the plain password
  72.             $user->setPassword(
  73.                 $userPasswordHasher->hashPassword(
  74.                     $user,
  75.                     $form->get('plainPassword')->getData()
  76.                 )
  77.             );
  78.             // keep uncompleted user in DB
  79.             $this->userRepository->save($usertrue);
  80.             // pass user to next step
  81.             $this->requestStack->getSession()->set(self::SESSION_KEY$user->getId());
  82.             return $this->redirectToRoute('app_register_step_two');
  83.         }
  84.         return $this->render('security/register_step_one.html.twig', [
  85.             'form' => $form,
  86.         ]);
  87.     }
  88.     #[Route('/register/fill'name'app_register_step_two'methods: ['GET''POST'])]
  89.     public function registerStepTwo(Request $requestBalanceService $balanceService): Response
  90.     {
  91.         $user $this->getUserFromPreviousStep();
  92.         if (empty($user)) {
  93.             return $this->redirectToRoute('app_register_step_one');
  94.         }
  95.         $form $this->createForm(RegistrationFormStepTwoType::class);
  96.         $form->handleRequest($request);
  97.         if ($form->isSubmitted() && $form->isValid()) {
  98.             $refillAmount BalanceRefillAmountEnum::tryFrom($form->get('refillAmount')->getData());
  99.             $level DonationLevelEnum::tryFrom($form->get('donationAmount')->getData());
  100.             // todo steps below should be in one transaction
  101.             // set default donation level, no flush needed yet since the user already in DB and has an ID
  102.             $user->setTransactionDefaultAmount($level);
  103.             // add points to balance
  104.             $balanceService->addToBalanceForUser($refillAmount$user);
  105.             // activate user
  106.             $user->activate();
  107.             $this->userRepository->save($user);
  108.             return $this->redirectToRoute('app_register_success');
  109.         }
  110.         return $this->render('security/register_step_two.html.twig', [
  111.             'form' => $form,
  112.         ]);
  113.     }
  114.     private function getUserFromPreviousStep(): ?User
  115.     {
  116.         // get user id passed from the previous step
  117.         $session $this->requestStack->getSession();
  118.         $userId $session->get(self::SESSION_KEY);
  119.         if (empty($userId) || !is_int($userId)) {
  120.             $session->invalidate();
  121.             return null;
  122.         }
  123.         // find previously saved user
  124.         $user $this->userRepository->find($userId);
  125.         if (empty($user)) {
  126.             $session->invalidate();
  127.             return null;
  128.         }
  129.         return $user;
  130.     }
  131.     #[Route('/register/success'name'app_register_success'methods'GET')]
  132.     public function registerSuccess(BalanceService $balanceServiceSecurity $security): Response
  133.     {
  134.         $user $this->getUserFromPreviousStep();
  135.         if (empty($user)) {
  136.             $this->redirectToRoute('app_register_step_one');
  137.         }
  138.         $security->login($userLoginFormAuthenticator::class);
  139.         $data = [
  140.             'name' => $user->getFullName(),
  141.             'email' => $user->getEmail(),
  142.             'employer' => $user->getEmployer(),
  143.             'occupation' => $user->getOccupation(),
  144.             'level' => Formatter::formatMoney($user->getTransactionDefaultAmount()),
  145.             'balance' => Formatter::formatMoney($balanceService->getBalanceForUser($user)),
  146.         ];
  147.         return $this->render('security/register_success.html.twig', [
  148.             'data' => $data,
  149.         ]);
  150.     }
  151. }