<?php
/**
* Created by PhpStorm.
* User: Ronald
* Date: 12/23/2019
* Time: 4:31 PM
*/
namespace App\Controller;
use App\Entity\CustomerAccount;
use App\Entity\RequestAccess;
use App\Entity\User;
use App\Form\Login\ForgotPasswordType;
use App\Form\Login\ResetPasswordType;
use App\Form\Login\RequestAccessType;
use App\GoogleAPI\GoogleApi;
use App\Mailer\AccountMailer;
use App\Mailer\Mailer;
use App\Model\Login\ForgotPassword;
use App\Model\Login\ResetPassword;
use App\Repository\UserRepository;
use App\Security\LoginFormAuthenticator;
use ReCaptcha\ReCaptcha;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
use Symfony\Component\Security\Guard\GuardAuthenticatorHandler;
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
use Symfony\Component\Mailer\MailerInterface;
use Symfony\Component\Mime\Email;
/**
* Class LoginController
* @package App\Controller
*/
class LoginController extends BaseController
{
/**
* @Route("/requestAccess", name="request_access", methods={"POST"})
* @param Request $request
* @param AccountMailer $mailer
* @param GoogleApi $googleApi
* @param UserRepository $userRepository
* @return Response
*/
public function requestAccess(Request $request, AccountMailer $mailer,GoogleApi $googleApi, UserRepository $userRepo): Response
{
$arrayResponse = array();
try {
$requestAccess = new RequestAccess();
$form = $this->createForm(RequestAccessType::class, $requestAccess);
$form->submit($request->request->get('request_access'));
$recaptcha = new ReCaptcha($_ENV['GOOGLE_RECAPTCHA_SECRET']);
$token = $request->request->get('recaptcha_response')??"";
$resp = $recaptcha->verify($token, $request->getClientIp());
if ($form->isValid()) {
if (!$resp->isSuccess()){
throw new \Exception("Recaptcha Error", "400");
}
if ($user = $userRepo->findOneBy(array('email' => $requestAccess->getEmail()))) {
$this->addFlash('warning', $requestAccess->getEmail().' is already in our system. Try resetting your password with \'Forgot Password\'.');
$mailer->forgotPasswordEmail($user);
$arrayResponse = array('requestAccessTab' => false);
} else {
$this->setAddressFromGoogle($googleApi,$requestAccess);
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($requestAccess);
$entityManager->flush();
$isCustomerAccountDomain=$this->getCustomerAccountDomain();
$mailer->requestAccessEmail($requestAccess, $userRepo, $isCustomerAccountDomain);
$site="OverseasXpress";
if($isCustomerAccountDomain){
$site="GTN Xpress";
}
throw new \Exception("Thank you for your interest in ".$site.". One of our agents has received your request to access the platform. We will get back to you after reviewing your information.", "200");
}
}else{
throw new \Exception("Validation Error", "400");
}
} catch (\Exception $e) {
if ($e->getCode() == 200) {
$this->addFlash('success', $e->getMessage());
} else {
$this->addFlash('error', $e->getMessage());
$arrayResponse = array('requestAccessTab' => true);
}
}
return $this->redirectToRoute("login", $arrayResponse);
}
/**
* @Route("/status", name="status")
*/
public function statusAction(): JsonResponse
{
return JsonResponse::fromJsonString('{"status": "ok"}');
}
/**
* @Route("/{userToken}",name="login", methods={"GET","POST"},defaults={"userToken"=false})
* @param AuthenticationUtils $authenticationUtils
* @return Response
*/
public function login(AuthenticationUtils $authenticationUtils, Request $request,GuardAuthenticatorHandler $guard, LoginFormAuthenticator $loginAuthenticator,$userToken=null): Response
{
//Try to login with token
if($userToken){
$em = $this->getDoctrine()->getManager();;
if ($user = $em->getRepository(User::class)->findOneBy(['sessionToken' => $userToken])) {
$user->resetSessionToken();
$em->persist($user);
$em->flush();
// Authenticate user
$guard->authenticateUserAndHandleSuccess(
$user,
$request,
$loginAuthenticator,
'main'
);
return $this->redirectToRoute("search");
}
}
$openGetStarted=false;
$this->initSessionVar();
$requestAccess = new RequestAccess();
if($requestQuery=$request->query->all()){
if(key_exists('ref',$requestQuery)){
if ($userDB = $this->getDoctrine()->getRepository(User::class)->findOneBy(["ownershipLink" => trim($requestQuery['ref'])])) {
$requestAccess->setOwnershipLink($userDB->getName());
$openGetStarted=true;
}else{
$requestAccess->setOwnershipLink($requestQuery['ref']);
}
}
}
$form = $this->createForm(RequestAccessType::class, $requestAccess,['doFilterByCustomerAccount'=>$this->getCustomerAccountDomain(true)]);
$requestAccessTab = $request->query->get('requestAccessTab');
// get the login error if there is one
$error = $authenticationUtils->getLastAuthenticationError();
// last username entered by the user
$lastUsername = $authenticationUtils->getLastUsername();
return $this->render('login/login.html.twig', [
'last_username' => $lastUsername,
'error' => $error,
'requestAccessForm' => $form->createView(),
'requestAccessTab' => $requestAccessTab,
'openGetStarted' => $openGetStarted
]);
}
/**
* @Route(path="/login/forgotPassword", name="forgotPassword", methods={"GET","POST"})
* @param Request $request
* @param AccountMailer $mailer
* @return Response
*/
public function forgotPassword(Request $request, AccountMailer $mailer): Response
{
$this->initSessionVar();
if ($request->isMethod('post')) {
$forgotPassword = new ForgotPassword();
$form = $this->createForm(ForgotPasswordType::class, $forgotPassword);
$form->submit($request->request->all());
if ($form->isValid()) {
try {
$userRepo = $this->getDoctrine()->getRepository(User::class);
if (!$user = $userRepo->findOneBy(array('email' => $forgotPassword->getEmail()))) {
//As per the PEN test folks, we should always send the same message whether we found the email or not.
//throw new \Exception("Email not found", "400");
throw new \Exception("You'll receive an email with the instructions to reset your password if the specified email is associated with an account.", "200");
}
$user->createNewResetToken();
$this->getDoctrine()->getManager()->flush();
$mailer->forgotPasswordEmail($user);
throw new \Exception("You'll receive an email with the instructions to reset your password if the specified email is associated with an account.", "200");
} catch (\Exception $e) {
if ($e->getCode() == 200) {
$this->addFlash('success', $e->getMessage());
} else {
$this->addFlash('error', $e->getMessage());
}
}
}
}
return $this->render('login/forgotPassword.html.twig');
}
/**
* @Route(path="/resetPassword/{userToken}/{setReset}/{createPassword}" , name="resetPassword", methods={"GET","POST"})
* @param Request $request
* @param UserPasswordEncoderInterface $encoder
* @param $userToken
* @param $setReset
* @param $createPassword
* @return Response
*/
public function resetPassword(Request $request,UserPasswordEncoderInterface $encoder, $userToken, $setReset=false, $createPassword=false): Response
{
$this->initSessionVar();
if ($request->isMethod('post')) {
$resetPassword = new ResetPassword();
$form = $this->createForm(ResetPasswordType::class, $resetPassword);
$form->submit($request->request->all());
if ($form->isValid()) {
try {
$em = $this->getDoctrine()->getManager();
$userRepo = $em->getRepository(User::class);
if (!$user = $userRepo->findOneBy(array('resetPasswordToken' => $resetPassword->getUserToken()))) {
throw new \Exception("Token not valid", "400");
}
$user->setPassword($encoder->encodePassword($user, $resetPassword->getPassword()));
$user->setResetPasswordToken(null);
$user->resetPasswordRules();
$em->persist($user);
$em->flush();
$resetText = $setReset == '1'?'set':'reset';
$resetText =$createPassword?'created':$resetText;
throw new \Exception("Your password has been $resetText successfully", "200");
} catch (\Exception $e) {
if ($e->getCode() == 200) {
$this->addFlash('success', $e->getMessage());
return $this->redirectToRoute('login');
} else {
$this->addFlash('error', $e->getMessage());
}
}
} else {
$this->addFlash('error','form error');
}
}
return $this->render('login/resetPassword.html.twig',
array(
'userToken' => $userToken,
'setReset' => $setReset,
'createPassword'=>$createPassword
));
}
}