<?php
namespace App\Controller;
use App\Entity\Speaker;
use App\Entity\User;
use App\Form\Cabinet\AvatarType;
use App\Form\RegisterSpeakerType;
use App\Form\RegisterType;
use App\Repository\UserRepository;
use App\Service\ImageUploader;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
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\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
use App\Security\EmailVerifier;
use Symfony\Bridge\Twig\Mime\TemplatedEmail;
use Symfony\Component\Mime\Address;
class SecurityController extends AbstractController
{
/**
* @Route("/login", name="app_login")
*/
public function login(Request $request, AuthenticationUtils $authenticationUtils): Response
{
// if ($this->getUser()) {
// return $this->redirectToRoute('target_path');
// }
// get the login error if there is one
$error = $authenticationUtils->getLastAuthenticationError();
// last username entered by the user
$lastUsername = $authenticationUtils->getLastUsername();
return $this->render('security/login.html.twig', ['last_username' => $lastUsername, 'error' => $error]);
}
/**
* @Route("/logout", name="app_logout")
*/
public function logout()
{
throw new \LogicException('This method can be blank - it will be intercepted by the logout key on your firewall.');
}
/**
* @Route("/check-login", name="app_check_login")
*/
public function checkEmail(Request $request, UserRepository $userRepository): RedirectResponse
{
if ($this->getUser()) {
return $this->redirectToRoute('home');
}
$session = $request->getSession();
if ($session->has('oauth_user_info')) {
$session->remove('oauth_user_info');
}
$email = $request->get('email');
$type = $request->get('user_type');
// If exist go to login page
if ($userRepository->findOneBy(['email' => $email])) {
return $this->redirectToRoute('app_login', [
'email' => $email,
'user_type' => $type,
]);
}
// Registration page
return $this->redirectToRoute('app_registration', [
'email' => $email,
'user_type' => $type,
]);
}
/**
* @Route("/registration", name="app_registration")
*/
public function registration(
Request $request,
UserPasswordHasherInterface $passwordHasher,
EmailVerifier $emailVerifier,
AuthenticationManagerInterface $authenticationManager,
TokenStorageInterface $tokenStorage,
ImageUploader $imageUploader
)
{
/**
* @todo temporary dummy
*/
//return $this->render('security/registration_dummy.html.twig');
if ($this->getUser()) {
return $this->redirectToRoute('home');
}
$session = $request->getSession();
$cookies = $request->cookies;
$request->get('user_type') && $request->get('user_type') !== "" ? $userType = $request->get('user_type') : $userType = (int)$cookies->get('user_type');
if ($userType != 2) $userType = 1;
$form = ($userType == 2) ? $this->createForm(RegisterSpeakerType::class) : $this->createForm(RegisterType::class);
$form->handleRequest($request);
if ($form->isSubmitted()) {
if ($form->isValid()) {
/* @var User $user */
$user = $form->getData();
$user
->setPassword($passwordHasher->hashPassword($user, $form->get('password')->getData()))
->setNotificationEmail($user->getEmail())
->setTimezone('Europe/Moscow');
if ($userType == 2) {
$user->addRole('ROLE_SPEAKER');
// $speaker = (new Speaker())->setUser($user);
// $this->getDoctrine()->getManager()->persist($speaker);
$avatar = $form->get('speaker')->get('photo')->getData();
if ($avatar) {
if ($user->getAvatar()) {
$imageUploader->delete($user->getAvatar());
}
$user->setAvatar($imageUploader->upload($avatar));
}
}
$this->getDoctrine()->getManager()->persist($user);
$this->getDoctrine()->getManager()->flush();
// generate a signed url and email it to the user
$emailVerifier->sendEmailConfirmation('app_registration_verify', $user,
(new TemplatedEmail())
->from(new Address($_ENV['MAILER_FROM_EMAIL'], $_ENV['MAILER_FROM_NAME']))
->to($user->getEmail())
->subject('Please Confirm your Email')
->htmlTemplate('security/confirmation_email.html.twig')
);
$request->getSession()->set('unconfirmed_user_id', $user->getId());
if ($session->has('oauth_user_info')) {
$session->remove('oauth_user_info');
}
$token = new UsernamePasswordToken($user, 'main', $user->getRoles());
$authenticatedToken = $authenticationManager->authenticate($token);
$tokenStorage->setToken($authenticatedToken);
return $this->redirectToRoute($this->getRedirectRoute($user->getRoles()));
}
} else {
if ($session->has('oauth_user_info')) {
$authUserInfo = $session->get('oauth_user_info');
$form->get('email')->setData($authUserInfo['email']);
$form->get('firstName')->setData($authUserInfo['first_name']);
$form->get('lastName')->setData($authUserInfo['last_name']);
} else {
$form->get('email')->setData($request->get('email', ''));
}
}
return $this->render('security/registration.html.twig', [
'form' => $form->createView(),
'userType' => $userType
]);
}
/**
* @Route("/registration/verify", name="app_registration_verify")
*/
public function verifyUserEmail(
Request $request,
UserRepository $userRepository,
EmailVerifier $emailVerifier,
AuthenticationManagerInterface $authenticationManager,
TokenStorageInterface $tokenStorage
)
{
$id = $request->query->get('id'); // retrieve the user id from the url
// Verify the user id exists and is not null
if (null === $id) {
return $this->redirectToRoute('home');
}
$user = $userRepository->find($id);
// Ensure the user exists in persistence
if (null === $user) {
return $this->redirectToRoute('home');
}
if ($request->getSession()->has('unconfirmed_user_id') === false) {
$request->getSession()->remove('unconfirmed_user_id');
}
// validate email confirmation link, sets User::isVerified=true and persists
try {
$emailVerifier->handleEmailConfirmation($request, $user);
} catch (\Exception $e) {
return $this->redirectToRoute($this->getRedirectRoute($user->getRoles()));
}
$token = new UsernamePasswordToken($user, 'main', $user->getRoles());
$authenticatedToken = $authenticationManager->authenticate($token);
$tokenStorage->setToken($authenticatedToken);
return $this->redirectToRoute($this->getRedirectRoute($user->getRoles()));
}
/**
* @Route("/registration/confirm", name="app_registration_confirm")
*/
public function registrationConfirm(Request $request)
{
if ($this->getUser() && $this->getUser()->getEmailConfirmed() === true) {
return $this->redirectToRoute('home');
}
if ($request->getSession()->has('unconfirmed_user_id') === false) {
return $this->redirectToRoute('app_login');
}
return $this->render('security/registration_confirm.html.twig');
}
/**
* @Route("/registration/resend", name="app_registration_resend")
*/
public function registrationResend(
Request $request,
UserRepository $userRepository,
EmailVerifier $emailVerifier
)
{
// if ($this->getUser()) {
// return $this->redirectToRoute('cabinet.speaker_office.index');
// }
if ($request->getSession()->has('unconfirmed_user_id') === false) {
return $this->redirectToRoute('app_login');
}
$id = $request->getSession()->get('unconfirmed_user_id');
$user = $userRepository->find($id);
if (null === $user) {
return $this->redirectToRoute('home');
}
// generate a signed url and email it to the user
$emailVerifier->sendEmailConfirmation('app_registration_verify', $user,
(new TemplatedEmail())
->from(new Address($_ENV['MAILER_FROM_EMAIL'], $_ENV['MAILER_FROM_NAME']))
->to($user->getEmail())
->subject('Please Confirm your Email')
->htmlTemplate('security/confirmation_email.html.twig')
);
return $this->redirectToRoute($this->getRedirectRoute($user->getRoles()));
}
/**
* @Route("/registration/resent", name="app_registration_resent")
*/
public function registrationResent(Request $request)
{
if ($this->getUser()) {
return $this->redirectToRoute($this->getRedirectRoute($this->getUser()->getRoles()));
}
if ($request->getSession()->has('unconfirmed_user_id') === false) {
return $this->redirectToRoute('app_login');
}
return $this->render('security/registration_resent.html.twig');
}
private function getRedirectRoute(array $roles): string
{
if (in_array('ROLE_SPEAKER', $roles)){
return 'cabinet.speaker_office.index';
}
return 'app_registration_confirm';
}
}