diff --git a/app/Controllers/Auth/PasswordRecoveryController.php b/app/Controllers/Auth/PasswordRecoveryController.php index bd2c60f..a9f4691 100644 --- a/app/Controllers/Auth/PasswordRecoveryController.php +++ b/app/Controllers/Auth/PasswordRecoveryController.php @@ -4,7 +4,91 @@ namespace App\Controllers\Auth; use App\Controllers\Controller; +use App\Web\Mail; +use Psr\Http\Message\ResponseInterface as Response; +use Psr\Http\Message\ServerRequestInterface as Request; class PasswordRecoveryController extends Controller { + + /** + * @param Request $request + * @param Response $response + * @return Response + * @throws \Twig\Error\LoaderError + * @throws \Twig\Error\RuntimeError + * @throws \Twig\Error\SyntaxError + */ + public function recover(Request $request, Response $response): Response + { + return view()->render($response, 'auth/recover_mail.twig'); + } + + + /** + * @param Request $request + * @param Response $response + * @return Response + * @throws \Exception + */ + public function recoverMail(Request $request, Response $response): Response + { + if ($this->session->get('logged', false)) { + return redirect($response, route('home')); + } + + $user = $this->database->query('SELECT `id`, `username` FROM `users` WHERE `email` = ? LIMIT 1', param($request, 'email'))->fetch(); + + if (!isset($user->id)) { + $this->session->alert(lang('recover_email_sent'), 'success'); + return redirect($response, route('recover')); + } + + $resetToken = bin2hex(random_bytes(16)); + + $this->database->query('UPDATE `users` SET `reset_token`=? WHERE `id` = ?', [ + $resetToken, + $user->id, + ]); + + Mail::make() + ->from('no-reply@'.str_ireplace('www.', '', parse_url($this->config['base_url'], PHP_URL_HOST)), $this->config['app_name']) + ->to(param($request, 'email')) + ->subject(lang('mail.recover_password', [$this->config['app_name']])) + ->message(lang('mail.recover_text', [ + $user->username, + route('recover.password', ['resetToken' => $resetToken]), + ])) + ->send(); + + $this->session->alert(lang('recover_email_sent'), 'success'); + return redirect($response, route('recover')); + } + + /** + * @param Request $request + * @param Response $response + * @param string $resetToken + * @return Response + * @throws \Twig\Error\LoaderError + * @throws \Twig\Error\RuntimeError + * @throws \Twig\Error\SyntaxError + */ + public function recoverPasswordForm(Request $request, Response $response, string $resetToken): Response + { + return view()->render($response, 'auth/recover_password.twig', [ + 'reset_token' => $resetToken + ]); + } + + /** + * @param Request $request + * @param Response $response + * @param string $resetToken + * @return Response + */ + public function recoverPassword(Request $request, Response $response, string $resetToken): Response + { + + } } diff --git a/app/routes.php b/app/routes.php index 92bf70e..a995e15 100644 --- a/app/routes.php +++ b/app/routes.php @@ -2,6 +2,7 @@ // Auth routes use App\Controllers\AdminController; +use App\Controllers\Auth\PasswordRecoveryController; use App\Controllers\Auth\RegisterController; use App\Controllers\ClientController; use App\Controllers\DashboardController; @@ -66,6 +67,10 @@ $app->get('/', [DashboardController::class, 'redirects'])->setName('root'); $app->get('/register', [RegisterController::class, 'registerForm'])->setName('register.show'); $app->post('/register', [RegisterController::class, 'register'])->setName('register'); $app->get('/activate/{activateToken}', [RegisterController::class, 'activateUser'])->setName('activate'); +$app->get('/recover', [PasswordRecoveryController::class, 'recover'])->setName('recover'); +$app->post('/recover/mail', [PasswordRecoveryController::class, 'recoverMail'])->setName('recover.mail'); +$app->get('/recover/password/{resetToken}', [PasswordRecoveryController::class, 'recoverPasswordForm'])->setName('recover.password.view'); +$app->post('/recover/password/{resetToken}', [PasswordRecoveryController::class, 'recoverPassword'])->setName('recover.password'); $app->get('/login', [LoginController::class, 'show'])->setName('login.show'); $app->post('/login', [LoginController::class, 'login'])->setName('login'); $app->map(['GET', 'POST'], '/logout', [LoginController::class, 'logout'])->setName('logout'); diff --git a/resources/lang/en.lang.php b/resources/lang/en.lang.php index d38cf30..5daf586 100644 --- a/resources/lang/en.lang.php +++ b/resources/lang/en.lang.php @@ -118,7 +118,15 @@ return [ 'password_recovery' => 'Recover password', 'no_account' => 'Don\'t have an account?', 'register' => 'Register', + 'register_success' => 'The account has been created, a confirmation email has been sent.', 'default_user_quota' => 'Default User Quota', 'invalid_quota' => 'Invalid values as default user quota.', - 'mail.activate_text' => "Hi %s!\nthank you for creating your account on %s (%s), click on the following link to activate it:\n\n%s" + 'mail.activate_text' => "Hi %s!\nthank you for creating your account on %s (%s), click on the following link to activate it:\n\n%s", + 'mail.activate_account' => '%s - Account Activation', + 'mail.recover_text' => "Hi %s,\na password reset has been requested for your account. To complete the procedure click on the following link:\n\n%s\n\nIf it wasn't you who requested the password reset, simply ignore this email.", + 'mail.recover_password' => '%s - Password Recovery', + 'recover_email_sent' => 'If present, a recovery email was sent to the specified account.', + 'account_activated' => 'Account activated, now you can login!', + 'quota_enabled' => 'Enable user quota', + 'password_repeat' => 'Repeat Password', ]; diff --git a/resources/templates/auth/login.twig b/resources/templates/auth/login.twig index e21419f..c2832a9 100644 --- a/resources/templates/auth/login.twig +++ b/resources/templates/auth/login.twig @@ -36,17 +36,16 @@
- + - + -
diff --git a/resources/templates/auth/recover_mail.twig b/resources/templates/auth/recover_mail.twig new file mode 100644 index 0000000..26474f4 --- /dev/null +++ b/resources/templates/auth/recover_mail.twig @@ -0,0 +1,52 @@ +{% extends 'base.twig' %} + +{% block title %}{{ lang('password_recovery') }}{% endblock %} + +{% block head %} + +{% endblock %} + +{% block content %} +
+ +
+{% endblock %} \ No newline at end of file diff --git a/resources/templates/auth/recover_password.twig b/resources/templates/auth/recover_password.twig new file mode 100644 index 0000000..8561a9d --- /dev/null +++ b/resources/templates/auth/recover_password.twig @@ -0,0 +1,52 @@ +{% extends 'base.twig' %} + +{% block title %}{{ lang('password_recovery') }}{% endblock %} + +{% block head %} + +{% endblock %} + +{% block content %} +
+ +
+{% endblock %} \ No newline at end of file diff --git a/resources/templates/auth/register.twig b/resources/templates/auth/register.twig index 0ac3990..9887630 100644 --- a/resources/templates/auth/register.twig +++ b/resources/templates/auth/register.twig @@ -1,6 +1,6 @@ {% extends 'base.twig' %} -{% block title %}{{ lang('login') }}{% endblock %} +{% block title %}{{ lang('register') }}{% endblock %} {% block head %}