You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
233 lines
5.9 KiB
233 lines
5.9 KiB
4 years ago
|
<?php
|
||
|
|
||
|
namespace App\Controllers;
|
||
|
|
||
|
use App\Classes\Config;
|
||
|
use App\Classes\Db;
|
||
|
use App\Classes\Form;
|
||
|
use App\Classes\User;
|
||
|
use App\Classes\Mail;
|
||
|
|
||
|
class LoginController extends PageController {
|
||
|
|
||
|
public function loginAction(string $view, string $title): void {
|
||
|
$form = new Form($this->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:<br>
|
||
|
<a href='$resetUrl'>$resetUrl</a>
|
||
|
";
|
||
|
|
||
|
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.');
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|