router); $form->addField('username', [ 'Username*', 'text', '', 'required', 'Username is required.', ]); $form->addField('password', [ 'Password*', 'password', '', 'required', 'Password is required.', ]); $form->addField('rememberMe', [ '', 'checkbox', ['1' => 'Remember me'], ]); $form->setSubmit('Sign in'); if ($form->validated()) { if (User::login($_POST['username'], $_POST['password'], $_POST['rememberMe'])) { $this->setAlert('success', 'Successfully signed in, redirecting...'); // Set delayed redirect URL $this->router->service()->redirectURL = Config::c('APP_URL') . '/admin'; } else { $user = User::getUser('', $_POST['username']); if ($user->exists() && $user->failed_login_attempt >= 5) { $this->setAlert('danger', 'User has been blocked.'); } else { $this->setAlert('danger', 'Invalid username and password combination.'); } } } else if ($_SERVER['REQUEST_METHOD'] == 'POST') { if(!_exists($_POST, 'username') || !_exists($_POST, 'password')) { $this->setAlert('danger', 'Please fill out both fields.'); } else { $this->setAlert('danger', 'Could not sign in.'); } } $this->router->service()->password = ""; parent::view($view, $title); } public function resetAction(string $view, string $title): void { // Send request if (!_exists($_GET, 'uid') || !_exists($_GET, 'reset-key')) { $this->requestResetForm(); } // Reset password else { $this->resetPasswordForm(); if ($_SERVER['REQUEST_METHOD'] != 'POST') { $this->router->service()->newPassword = true; $user = User::getUser($_GET['uid']); if (!$user->exists() || $_GET['reset-key'] != $user->reset_key) { $this->setAlert('danger', 'Link expired.'); } } } parent::view($view, $title); } public function logoutAction(): void { User::logout(); $this->router->response()->redirect('/'); } //-------------------------------------// private function requestResetForm(): void { // Only have required on 1 field $usernameRule = !_exists($_POST, 'reset-password-email') ? 'required' : ''; $emailRule = !_exists($_POST, 'reset-password-username') ? 'required|email' : ''; $form = new Form($this->router); $form->addField('reset-password-username', [ 'Username', 'text', '', "$usernameRule", 'Username is required.', ]); $form->addField('reset-password-email', [ 'Email', 'email', '', "$emailRule", 'Please enter a valid email address.', '[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$', 'Valid email address' ]); $form->setSubmit('Send request'); if ($form->validated()) { $this->requestResetSend(); } else if ($_SERVER['REQUEST_METHOD'] == 'POST') { if (!_exists($_POST, 'reset-password-username') && !_exists($_POST, 'reset-password-email')) { $this->setAlert('danger', 'Please fill out one of the fields.'); } else { $error = $form->errorMessage(); $this->setAlert('danger', $error ? $error : 'Could not send request.'); } } } private function requestResetSend(): void { $user = User::getUser('', $_POST['reset-password-username'], $_POST['reset-password-email']); if ($user->exists()) { // Generate new reset key $user->reset_key = _randomStr(25); $user->save(); // Send reset mail $subject = 'Password reset request - ' . Config::c('APP_NAME'); $resetUrl = Config::c('APP_URL') . "/reset-password?uid={$user->id}&reset-key={$user->reset_key}"; $message = " Click the link below to reset your password:
$resetUrl "; if (Mail::send($subject, $message, $user->email)) { $this->setAlert('success', 'Successfully requested password reset.'); } else { $this->setAlert('danger', 'Password reset failed.'); } } else { $this->setAlert('danger', 'User was not found.'); } } private function resetPasswordForm(): void { // Add _GETs to form post url $uid = $_GET['uid']; $resetKey = $_GET['reset-key']; $this->router->service()->url .= "?uid=$uid&reset-key=$resetKey"; $form = new Form($this->router); $form->addField('password', [ 'New password*', 'password', '', 'required', 'New password is required.', ]); $form->addField('password-again', [ 'New password again*', 'password', '', 'required', 'New password again is required.', ]); $form->setSubmit('Reset password'); if ($form->validated()) { $this->resetPasswordSend(); } else if ($_SERVER['REQUEST_METHOD'] == 'POST') { if (!_exists($_POST, 'password') || !_exists($_POST, 'password-again')) { $this->setAlert('danger', 'Please fill out all fields.'); } else { $error = $form->errorMessage(); $this->setAlert('danger', $error ? $error : 'Could not reset password.'); } } } private function resetPasswordSend(): void { $user = User::getUser($_GET['uid']); if ($user->exists()) { (bool)$notEmptyKey = $user->reset_key != ''; (bool)$correctKey = $user->reset_key == $_GET['reset-key']; (bool)$identicalPass = $_POST['password'] == $_POST['password-again']; } if ($notEmptyKey && $correctKey && $identicalPass) { $user->salt = _randomStr(15); $user->password = password_hash($user->salt . $_POST['password'], PASSWORD_BCRYPT, ['cost', 12]); $user->reset_key = ''; $user->save(); $this->setAlert('success', 'Successfully changed password.'); } // Display error message if (!$user || !$notEmptyKey || !$correctKey) { $this->setAlert('danger', 'Invalid password reset link.'); } else if (!$identicalPass) { $this->setAlert('danger', 'Fields did not match.'); } } }