misuzu/public/auth/login.php

153 lines
5.3 KiB
PHP
Raw Normal View History

2022-09-13 13:14:49 +00:00
<?php
namespace Misuzu;
use Misuzu\AuthToken;
2023-01-01 20:23:53 +00:00
use Misuzu\Config\CfgType;
2022-09-13 13:14:49 +00:00
use Misuzu\Net\IPAddress;
use Misuzu\Users\User;
use Misuzu\Users\UserNotFoundException;
use Misuzu\Users\UserAuthSession;
use Misuzu\Users\UserLoginAttempt;
use Misuzu\Users\UserSession;
use Misuzu\Users\UserSessionCreationFailedException;
require_once '../../misuzu.php';
if(UserSession::hasCurrent()) {
url_redirect('index');
return;
}
if(!empty($_GET['resolve'])) {
header('Content-Type: application/json; charset=utf-8');
try {
// Only works for usernames, this is by design
$userInfo = User::byUsername((string)filter_input(INPUT_GET, 'name'));
} catch(UserNotFoundException $ex) {
echo json_encode([
'id' => 0,
'name' => '',
'avatar' => url('user-avatar', ['res' => 200, 'user' => 0]),
]);
return;
}
echo json_encode([
'id' => $userInfo->getId(),
'name' => $userInfo->getUsername(),
'avatar' => url('user-avatar', ['user' => $userInfo->getId(), 'res' => 200]),
]);
return;
}
$notices = [];
2023-01-01 20:23:53 +00:00
$siteIsPrivate = $cfg->getValue('private.enable', CfgType::T_BOOL);
$loginPermCat = $siteIsPrivate ? $cfg->getValue('private.perm.cat', CfgType::T_STR) : '';
$loginPermVal = $siteIsPrivate ? $cfg->getValue('private.perm.val', CfgType::T_INT) : 0;
2022-09-13 13:14:49 +00:00
$remainingAttempts = UserLoginAttempt::remaining();
while(!empty($_POST['login']) && is_array($_POST['login'])) {
if(!CSRF::validateRequest()) {
$notices[] = 'Was unable to verify the request, please try again!';
break;
}
$loginRedirect = empty($_POST['login']['redirect']) || !is_string($_POST['login']['redirect']) ? '' : $_POST['login']['redirect'];
if(empty($_POST['login']['username']) || empty($_POST['login']['password'])
|| !is_string($_POST['login']['username']) || !is_string($_POST['login']['password'])) {
$notices[] = "You didn't fill in a username and/or password.";
break;
}
if($remainingAttempts < 1) {
$notices[] = "There are too many failed login attempts from your IP address, please try again later.";
break;
}
$attemptsRemainingError = sprintf(
"%d attempt%s remaining",
$remainingAttempts - 1,
$remainingAttempts === 2 ? '' : 's'
);
$loginFailedError = "Invalid username or password, {$attemptsRemainingError}.";
try {
$userInfo = User::byUsernameOrEMailAddress($_POST['login']['username']);
} catch(UserNotFoundException $ex) {
UserLoginAttempt::create(false);
$notices[] = $loginFailedError;
break;
}
if(!$userInfo->hasPassword()) {
$notices[] = 'Your password has been invalidated, please reset it.';
break;
}
if($userInfo->isDeleted() || !$userInfo->checkPassword($_POST['login']['password'])) {
UserLoginAttempt::create(false, $userInfo);
$notices[] = $loginFailedError;
break;
}
if($userInfo->passwordNeedsRehash())
$userInfo->setPassword($_POST['login']['password'])->save();
if(!empty($loginPermCat) && $loginPermVal > 0 && !perms_check_user($loginPermCat, $userInfo->getId(), $loginPermVal)) {
$notices[] = "Login succeeded, but you're not allowed to browse the site right now.";
UserLoginAttempt::create(true, $userInfo);
break;
}
if($userInfo->hasTOTP()) {
url_redirect('auth-two-factor', [
'token' => UserAuthSession::create($userInfo)->getToken(),
]);
return;
}
UserLoginAttempt::create(true, $userInfo);
try {
$sessionInfo = UserSession::create($userInfo);
$sessionInfo->setCurrent();
} catch(UserSessionCreationFailedException $ex) {
$notices[] = "Something broke while creating a session for you, please tell an administrator or developer about this!";
break;
}
$authToken = AuthToken::create($userInfo, $sessionInfo);
setcookie('msz_auth', $authToken->pack(), $sessionInfo->getExpiresTime(), '/', msz_cookie_domain(), !empty($_SERVER['HTTPS']), true);
if(!is_local_url($loginRedirect))
$loginRedirect = url('index');
redirect($loginRedirect);
return;
}
$welcomeMode = !empty($_GET['welcome']);
$loginUsername = !empty($_POST['login']['username']) && is_string($_POST['login']['username']) ? $_POST['login']['username'] : (
!empty($_GET['username']) && is_string($_GET['username']) ? $_GET['username'] : ''
);
$loginRedirect = $welcomeMode ? url('index') : (!empty($_GET['redirect']) && is_string($_GET['redirect']) ? $_GET['redirect'] : null) ?? $_SERVER['HTTP_REFERER'] ?? url('index');
2023-01-01 20:23:53 +00:00
$sitePrivateMessage = $siteIsPrivate ? $cfg->getValue('private.msg', CfgType::T_STR) : '';
$canResetPassword = $siteIsPrivate ? $cfg->getValue('private.allow_password_reset', CfgType::T_BOOL, true) : true;
2022-09-13 13:14:49 +00:00
$canRegisterAccount = !$siteIsPrivate;
Template::render('auth.login', [
'login_notices' => $notices,
'login_username' => $loginUsername,
'login_redirect' => $loginRedirect,
'login_can_reset_password' => $canResetPassword,
'login_can_register' => $canRegisterAccount,
'login_attempts_remaining' => $remainingAttempts,
'login_welcome' => $welcomeMode,
'login_private' => [
'enabled' => $siteIsPrivate,
'message' => $sitePrivateMessage,
],
]);