misuzu/public/auth/password.php

138 lines
4.7 KiB
PHP
Raw Normal View History

2019-03-08 00:35:53 +00:00
<?php
namespace Misuzu;
2019-10-02 19:02:22 +00:00
use UnexpectedValueException;
2019-12-12 00:42:28 +00:00
use Misuzu\Net\IPAddress;
2019-10-02 19:02:22 +00:00
2019-03-08 00:35:53 +00:00
require_once '../../misuzu.php';
2019-06-10 17:04:53 +00:00
if(user_session_active()) {
url_redirect('settings-account');
2019-03-08 00:35:53 +00:00
return;
}
2019-03-18 21:30:19 +00:00
$reset = !empty($_POST['reset']) && is_array($_POST['reset']) ? $_POST['reset'] : [];
$forgot = !empty($_POST['forgot']) && is_array($_POST['forgot']) ? $_POST['forgot'] : [];
$userId = !empty($reset['user']) ? (int)$reset['user'] : (
!empty($_GET['user']) ? (int)$_GET['user'] : 0
);
2019-03-08 00:35:53 +00:00
$username = $userId > 0 ? user_username_from_id($userId) : '';
2019-06-10 17:04:53 +00:00
if($userId > 0 && empty($username)) {
url_redirect('auth-forgot');
2019-03-08 00:35:53 +00:00
return;
}
$notices = [];
$siteIsPrivate = Config::get('private.enable', Config::TYPE_BOOL);
$canResetPassword = $siteIsPrivate ? Config::get('private.allow_password_reset', Config::TYPE_BOOL, true) : true;
2019-12-12 00:42:28 +00:00
$ipAddress = IPAddress::remote();
2019-03-08 00:35:53 +00:00
$remainingAttempts = user_login_attempts_remaining($ipAddress);
2019-06-10 17:04:53 +00:00
while($canResetPassword) {
if(!empty($reset) && $userId > 0) {
2019-12-11 18:10:54 +00:00
if(!CSRF::validateRequest()) {
2019-03-08 00:35:53 +00:00
$notices[] = 'Was unable to verify the request, please try again!';
break;
}
2019-03-18 21:30:19 +00:00
$verificationCode = !empty($reset['verification']) && is_string($reset['verification']) ? $reset['verification'] : '';
2019-03-08 00:35:53 +00:00
2019-06-10 17:04:53 +00:00
if(!user_recovery_token_validate($userId, $verificationCode)) {
2019-03-08 00:35:53 +00:00
$notices[] = 'Invalid verification code!';
break;
}
2019-03-18 21:30:19 +00:00
$password = !empty($reset['password']) && is_array($reset['password']) ? $reset['password'] : [];
$passwordNew = !empty($password['new']) && is_string($password['new']) ? $password['new'] : '';
$passwordConfirm = !empty($password['confirm']) && is_string($password['confirm']) ? $password['confirm'] : '';
2019-03-08 00:35:53 +00:00
2019-06-10 17:04:53 +00:00
if(empty($passwordNew) || empty($passwordConfirm)
2019-03-08 00:35:53 +00:00
|| $passwordNew !== $passwordConfirm) {
$notices[] = "Password confirmation failed!";
break;
}
2019-06-10 17:04:53 +00:00
if(user_validate_password($passwordNew) !== '') {
2019-03-08 00:35:53 +00:00
$notices[] = 'Your password is too weak!';
break;
}
2019-06-10 17:04:53 +00:00
if(user_password_set($userId, $passwordNew)) {
2019-03-08 00:35:53 +00:00
audit_log(MSZ_AUDIT_PASSWORD_RESET, $userId);
} else {
throw new UnexpectedValueException('Password reset failed.');
}
// disable two factor auth to prevent getting locked out of account entirely
user_totp_update($userId, null);
2019-03-08 00:35:53 +00:00
user_recovery_token_invalidate($userId, $verificationCode);
url_redirect('auth-login', ['redirect' => '/']);
2019-03-08 00:35:53 +00:00
return;
}
2019-06-10 17:04:53 +00:00
if(!empty($forgot)) {
2019-12-11 18:10:54 +00:00
if(!CSRF::validateRequest()) {
2019-03-08 00:35:53 +00:00
$notices[] = 'Was unable to verify the request, please try again!';
break;
}
2019-06-10 17:04:53 +00:00
if(empty($forgot['email']) || !is_string($forgot['email'])) {
2019-03-08 00:35:53 +00:00
$notices[] = "You didn't supply an e-mail address.";
break;
}
2019-06-10 17:04:53 +00:00
if($remainingAttempts < 1) {
2019-03-08 00:35:53 +00:00
$notices[] = "There are too many failed login attempts from your IP address, please try again later.";
break;
}
2019-03-18 21:30:19 +00:00
$forgotUser = user_find_for_reset($forgot['email']);
2019-03-08 00:35:53 +00:00
2019-06-10 17:04:53 +00:00
if(empty($forgotUser)) {
2019-03-08 00:35:53 +00:00
$notices[] = "This e-mail address is not registered with us.";
break;
}
2019-06-10 17:04:53 +00:00
if(!user_recovery_token_sent($forgotUser['user_id'], $ipAddress)) {
2019-03-08 00:35:53 +00:00
$verificationCode = user_recovery_token_create($forgotUser['user_id'], $ipAddress);
2019-06-10 17:04:53 +00:00
if(empty($verificationCode)) {
2019-03-08 00:35:53 +00:00
throw new UnexpectedValueException('A verification code failed to insert.');
}
2019-12-03 19:09:18 +00:00
$recoveryMessage = Mailer::template('password-recovery', [
'username' => $forgotUser['username'],
'token' => $verificationCode,
]);
2019-03-08 00:35:53 +00:00
2019-12-03 19:09:18 +00:00
$recoveryMail = Mailer::sendMessage(
2019-03-08 00:35:53 +00:00
[$forgotUser['email'] => $forgotUser['username']],
2019-12-03 19:09:18 +00:00
$recoveryMessage['subject'], $recoveryMessage['message']
2019-03-08 00:35:53 +00:00
);
2019-12-03 19:09:18 +00:00
if(!$recoveryMail) {
2019-03-08 00:35:53 +00:00
$notices[] = "Failed to send reset email, please contact the administrator.";
user_recovery_token_invalidate($forgotUser['user_id'], $verificationCode);
break;
}
}
url_redirect('auth-reset', ['user' => $forgotUser['user_id']]);
2019-03-08 00:35:53 +00:00
return;
}
break;
}
Template::render($userId > 0 ? 'auth.password_reset' : 'auth.password_forgot', [
2019-03-08 00:35:53 +00:00
'password_notices' => $notices,
2019-03-18 21:30:19 +00:00
'password_email' => !empty($forget['email']) && is_string($forget['email']) ? $forget['email'] : '',
2019-03-08 00:35:53 +00:00
'password_attempts_remaining' => $remainingAttempts,
'password_user_id' => $userId,
'password_username' => $username,
'password_verification' => $verificationCode ?? '',
]);