src/Controller/Security/SecurityController.php line 39

Open in your IDE?
  1. <?php
  2. namespace App\Controller\Security;
  3. use App\Entity\Users\LoginAttempt;
  4. use App\Entity\Users\User;
  5. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  6. use Symfony\Component\HttpFoundation\Request;
  7. use Doctrine\ORM\EntityManagerInterface;
  8. use Symfony\Component\EventDispatcher\EventDispatcherInterface;
  9. use Symfony\Component\HttpFoundation\Session\SessionInterface;
  10. use Symfony\Component\Routing\Annotation\Route;
  11. use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
  12. use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
  13. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  14. use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
  15. use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
  16. use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
  17. class SecurityController extends AbstractController
  18. {
  19. protected $em;
  20. protected $encoder;
  21. protected $tokenStorage;
  22. protected $session;
  23. protected $eventDispatcher;
  24. public function __construct(EntityManagerInterface $entityManager, UserPasswordEncoderInterface $encoder, TokenStorageInterface $tokenStorage, SessionInterface $session, EventDispatcherInterface $eventDispatcher)
  25. {
  26. $this->em = $entityManager;
  27. $this->encoder = $encoder;
  28. $this->tokenStorage = $tokenStorage;
  29. $this->session = $session;
  30. $this->eventDispatcher = $eventDispatcher;
  31. }
  32. /**
  33. * @Route("/", name="index")
  34. */
  35. public function index(AuthenticationUtils $authUtils)
  36. {
  37. // Redirect
  38. return $this->redirect($this->generateUrl("security_login"));
  39. }
  40. /**
  41. * @Route("/login", name="security_login")
  42. */
  43. public function login(AuthenticationUtils $authUtils, Request $request)
  44. {
  45. // Logged in?
  46. if($this->container->get('security.authorization_checker')->isGranted('IS_AUTHENTICATED_REMEMBERED') )
  47. {
  48. // Redirect
  49. return $this->redirect($this->generateUrl("dashboard_index"));
  50. }
  51. // Grab login method
  52. $loginMethod = in_array($request->query->get('method'), ["pin", "email"]) ? $request->query->get('method') : "pin";
  53. // Get the login error
  54. $authenticationError = $authUtils->getLastAuthenticationError();
  55. if($authenticationError)
  56. {
  57. // Flash message
  58. $this->get('session')->getFlashBag()->add('error', $authenticationError->getMessage());
  59. }
  60. return $this->render('Security/login.html.twig', [
  61. 'loginMethod' => $loginMethod
  62. ]);
  63. }
  64. /**
  65. * @Route("/login_pin", name="security_loginpin")
  66. */
  67. public function pinLogin(AuthenticationUtils $authUtils, Request $request)
  68. {
  69. $ipAddress = $request->getClientIp();
  70. // Too many attempts
  71. $loginAttempts = $this->em->getRepository(LoginAttempt::class)->findFiltered([
  72. "ipAddress" => $ipAddress,
  73. "created" => ["gte", new \DateTime("-15 minutes")]
  74. ]);
  75. if(count($loginAttempts) >= 5)
  76. die("Too many failed login attempts!");
  77. // Logging in via PIN?
  78. if($request->request->has('pin') && strlen($request->request->get('pin')) == 6)
  79. {
  80. // Grab stuff
  81. $pin = $request->request->get('pin');
  82. // Find a user with this PIN
  83. $user = $this->em->getRepository(User::class)->findOneFiltered([
  84. "pin" => $pin
  85. ]);
  86. // No user?
  87. if(!$user)
  88. {
  89. // Record it
  90. $loginAttempt = new LoginAttempt([
  91. "ipAddress" => $ipAddress
  92. ]);
  93. // Persist & flush
  94. $this->em->persist($loginAttempt);
  95. $this->em->flush();
  96. // Flash message
  97. $this->get('session')->getFlashBag()->add('error', "Invalid login details");
  98. // Redirect
  99. return $this->redirectToRoute('security_login');
  100. }
  101. else
  102. {
  103. // Grab a token
  104. $token = new UsernamePasswordToken($user, $user->getPassword(), "app", $user->getRoles());
  105. // Set the token
  106. $this->tokenStorage->setToken($token);
  107. $this->session->set('_security_common', serialize($token));
  108. // Fire the login event
  109. $event = new InteractiveLoginEvent($request, $token);
  110. $this->eventDispatcher->dispatch($event, "security.interactive_login");
  111. // Redirect
  112. return $this->redirectToRoute('dashboard_index');
  113. }
  114. }
  115. else
  116. {
  117. // Record it
  118. $loginAttempt = new LoginAttempt([
  119. "ipAddress" => $ipAddress
  120. ]);
  121. // Persist & flush
  122. $this->em->persist($loginAttempt);
  123. $this->em->flush();
  124. // Redirect
  125. return $this->redirectToRoute('security_login');
  126. }
  127. }
  128. /**
  129. * @Route("/login_check", name="security_logincheck")
  130. */
  131. public function loginCheck()
  132. {
  133. }
  134. /**
  135. * @Route("/logout", name="security_logout")
  136. */
  137. public function logout()
  138. {
  139. }
  140. /**
  141. * @Route("/forgot_password/{reset_token}", name="security_forgotpassword")
  142. */
  143. public function forgotPassword(Request $request, AuthenticationUtils $authUtils, $reset_token = '')
  144. {
  145. // Is it sent?
  146. if($request->query->get('sent'))
  147. {
  148. return $this->render('Security/forgotPassword.html.twig', array(
  149. 'sent' => true
  150. ));
  151. }
  152. // Resetting?
  153. elseif(strlen($reset_token))
  154. {
  155. // Find the member
  156. $member = $this->em->getRepository('App:Members\Member')->findOneFiltered(array(
  157. "resetToken" => $reset_token
  158. ));
  159. // Found it?
  160. if(!$member)
  161. {
  162. // Flash message
  163. $this->get('session')->getFlashBag()->add('error', "The reset link was invalid");
  164. // Redirect
  165. return $this->redirect($this->generateUrl("security_login"));
  166. }
  167. // Submitted the form?
  168. if($request->isMethod('post') && $request->request->get('action') == "do_reset")
  169. {
  170. // Grab the data
  171. $password = $request->request->get('password');
  172. $confirmPassword = $request->request->get('confirm');
  173. // Not long enough
  174. if(strlen($password) < 6)
  175. {
  176. // Flash message
  177. $this->get('session')->getFlashBag()->add('error', "Your new password must be at least 6 characters");
  178. }
  179. elseif($password != $confirmPassword)
  180. {
  181. // Flash message
  182. $this->get('session')->getFlashBag()->add('error', "Your passwords do not match");
  183. }
  184. else
  185. {
  186. // Encode password
  187. $encodedPassword = $this->encoder->encodePassword($member, $password);
  188. $member->setPassword($encodedPassword);
  189. $member->setResetToken(md5(uniqid()));
  190. // Persist & flush
  191. $this->em->persist($member);
  192. $this->em->flush($member);
  193. // Flash message
  194. $this->get('session')->getFlashBag()->add('success', "Your password has been changed. Please login below.");
  195. // Redirect
  196. return $this->redirect($this->generateUrl("security_login"));
  197. }
  198. }
  199. return $this->render('Frontend/Account/forgotPassword.html.twig', array(
  200. 'sent' => false,
  201. 'reset_token' => $reset_token
  202. ));
  203. }
  204. else
  205. {
  206. // Are we posting?
  207. if($request->isMethod('post') && $request->request->get('action') == "do_reset")
  208. {
  209. // Grab email
  210. $email = trim($request->request->get('email', ''));
  211. // If it's valid
  212. if(filter_var($email, FILTER_VALIDATE_EMAIL))
  213. {
  214. // Find the member
  215. $member = $this->em->getRepository('App:Members\Member')->findOneFiltered(array(
  216. "email" => $email
  217. ));
  218. // Found it?
  219. if($member)
  220. {
  221. // Get the email template
  222. $emailTemplate = $this->em->getRepository('App:Settings\EmailTemplate')->findOneFiltered(array(
  223. "identifier" => "reset_password"
  224. ));
  225. // Not found?
  226. if(!$emailTemplate)
  227. throw new \Exception("Cannot find the email template!");
  228. // Generate a new reset token
  229. $member->setResetToken(md5(uniqid()));
  230. // Persist & flush
  231. $this->em->persist($member);
  232. $this->em->flush($member);
  233. // Send the email
  234. $this->utilHelper->sendEmail(array(
  235. "recipients" => array($member->getEmail()),
  236. "subject" => $emailTemplate->getSubject(),
  237. "template" => $emailTemplate
  238. ), array(
  239. 'RESETLINK' => $this->generateUrl("security_forgotpassword", array(
  240. 'reset_token' => $member->getResetToken()
  241. ), UrlGeneratorInterface::ABSOLUTE_URL)
  242. ));
  243. }
  244. // Redirect
  245. return $this->redirect($this->generateUrl("security_forgotpassword") . '?sent=1');
  246. }
  247. else
  248. {
  249. // Flash message
  250. $this->get('session')->getFlashBag()->add('error', "The specified email address is invalid");
  251. // Redirect
  252. return $this->redirect($this->generateUrl("security_login"));
  253. }
  254. }
  255. else
  256. {
  257. // Redirect
  258. return $this->redirect($this->generateUrl("security_login"));
  259. }
  260. }
  261. }
  262. }