PasswordRecoveryController.php 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. <?php
  2. namespace App\Controllers\Auth;
  3. use App\Controllers\Controller;
  4. use App\Web\Mail;
  5. use App\Web\ValidationChecker;
  6. use Psr\Http\Message\ResponseInterface as Response;
  7. use Psr\Http\Message\ServerRequestInterface as Request;
  8. use Slim\Exception\HttpNotFoundException;
  9. class PasswordRecoveryController extends Controller
  10. {
  11. /**
  12. * @param Request $request
  13. * @param Response $response
  14. * @return Response
  15. * @throws \Twig\Error\LoaderError
  16. * @throws \Twig\Error\RuntimeError
  17. * @throws \Twig\Error\SyntaxError
  18. */
  19. public function recover(Request $request, Response $response): Response
  20. {
  21. return view()->render($response, 'auth/recover_mail.twig');
  22. }
  23. /**
  24. * @param Request $request
  25. * @param Response $response
  26. * @return Response
  27. * @throws \Exception
  28. */
  29. public function recoverMail(Request $request, Response $response): Response
  30. {
  31. if ($this->session->get('logged', false)) {
  32. return redirect($response, route('home'));
  33. }
  34. $user = $this->database->query('SELECT `id`, `username` FROM `users` WHERE `email` = ? LIMIT 1', param($request, 'email'))->fetch();
  35. if (!isset($user->id)) {
  36. $this->session->alert(lang('recover_email_sent'), 'success');
  37. return redirect($response, route('recover'));
  38. }
  39. $resetToken = bin2hex(random_bytes(16));
  40. $this->database->query('UPDATE `users` SET `reset_token`=? WHERE `id` = ?', [
  41. $resetToken,
  42. $user->id,
  43. ]);
  44. Mail::make()
  45. ->from(platform_mail(), $this->config['app_name'])
  46. ->to(param($request, 'email'))
  47. ->subject(lang('mail.recover_password', [$this->config['app_name']]))
  48. ->message(lang('mail.recover_text', [
  49. $user->username,
  50. route('recover.password', ['resetToken' => $resetToken]),
  51. ]))
  52. ->send();
  53. $this->session->alert(lang('recover_email_sent'), 'success');
  54. return redirect($response, route('recover'));
  55. }
  56. /**
  57. * @param Request $request
  58. * @param Response $response
  59. * @param string $resetToken
  60. * @return Response
  61. * @throws \Twig\Error\LoaderError
  62. * @throws \Twig\Error\RuntimeError
  63. * @throws \Twig\Error\SyntaxError
  64. * @throws HttpNotFoundException
  65. */
  66. public function recoverPasswordForm(Request $request, Response $response, string $resetToken): Response
  67. {
  68. $user = $this->database->query('SELECT `id` FROM `users` WHERE `reset_token` = ? LIMIT 1', $resetToken)->fetch();
  69. if (!$user) {
  70. throw new HttpNotFoundException($request);
  71. }
  72. return view()->render($response, 'auth/recover_password.twig', [
  73. 'reset_token' => $resetToken
  74. ]);
  75. }
  76. /**
  77. * @param Request $request
  78. * @param Response $response
  79. * @param string $resetToken
  80. * @return Response
  81. * @throws HttpNotFoundException
  82. */
  83. public function recoverPassword(Request $request, Response $response, string $resetToken): Response
  84. {
  85. $user = $this->database->query('SELECT `id` FROM `users` WHERE `reset_token` = ? LIMIT 1', $resetToken)->fetch();
  86. if (!$user) {
  87. throw new HttpNotFoundException($request);
  88. }
  89. $validator = ValidationChecker::make()
  90. ->rules([
  91. 'password.required' => !empty(param($request, 'password')),
  92. 'password.match' => param($request, 'password') === param($request, 'password_repeat'),
  93. ])
  94. ->onFail(function ($rule) {
  95. $alerts = [
  96. 'password.required' => lang('password_required'),
  97. 'password.match' => lang('password_match'),
  98. ];
  99. $this->session->alert($alerts[$rule], 'danger');
  100. });
  101. if ($validator->fails()){
  102. return redirect($response, route('recover.password', ['resetToken' => $resetToken]));
  103. }
  104. $this->database->query('UPDATE `users` SET `password`=?, `reset_token`=? WHERE `id` = ?', [
  105. password_hash(param($request, 'password'), PASSWORD_DEFAULT),
  106. null,
  107. $user->id,
  108. ]);
  109. $this->session->alert(lang('password_restored'), 'success');
  110. return redirect($response, route('login.show'));
  111. }
  112. }