isLoggedIn()) { url_redirect('index'); return; } $users = $msz->getUsersContext()->getUsers(); $sessions = $msz->getSessions(); $loginAttempts = $msz->getLoginAttempts(); if(!empty($_GET['resolve'])) { header('Content-Type: application/json; charset=utf-8'); try { // Only works for usernames, this is by design $userInfo = $users->getUser((string)filter_input(INPUT_GET, 'name'), 'name'); } catch(Exception $ex) { echo json_encode([ 'id' => 0, 'name' => '', 'avatar' => url('user-avatar', ['res' => 200, 'user' => 0]), ]); return; } echo json_encode([ 'id' => (int)$userInfo->getId(), 'name' => $userInfo->getName(), 'avatar' => url('user-avatar', ['user' => $userInfo->getId(), 'res' => 200]), ]); return; } $notices = []; $ipAddress = $_SERVER['REMOTE_ADDR']; $countryCode = $_SERVER['COUNTRY_CODE'] ?? 'XX'; $userAgent = $_SERVER['HTTP_USER_AGENT'] ?? ''; $remainingAttempts = $loginAttempts->countRemainingAttempts($ipAddress); $siteIsPrivate = $cfg->getBoolean('private.enable'); if($siteIsPrivate) { [ 'private.perm.cat' => $loginPermCat, 'private.perm.val' => $loginPermVal, 'private.msg' => $sitePrivateMessage, 'private.allow_password_reset' => $canResetPassword, ] = $cfg->getValues([ 'private.perm.cat:s', 'private.perm.val:i', 'private.msg:s', ['private.allow_password_reset:b', true], ]); } else { $loginPermCat = ''; $loginPermVal = 0; $sitePrivateMessage = ''; $canResetPassword = true; } 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; } $clientInfo = ClientInfo::fromRequest(); $attemptsRemainingError = sprintf( "%d attempt%s remaining", $remainingAttempts - 1, $remainingAttempts === 2 ? '' : 's' ); $loginFailedError = "Invalid username or password, {$attemptsRemainingError}."; try { $userInfo = $users->getUser($_POST['login']['username'], 'login'); } catch(Exception $ex) { $loginAttempts->recordAttempt(false, $ipAddress, $countryCode, $userAgent, $clientInfo); $notices[] = $loginFailedError; break; } if(!$userInfo->hasPasswordHash()) { $notices[] = 'Your password has been invalidated, please reset it.'; break; } if($userInfo->isDeleted() || !$userInfo->verifyPassword($_POST['login']['password'])) { $loginAttempts->recordAttempt(false, $ipAddress, $countryCode, $userAgent, $clientInfo, $userInfo); $notices[] = $loginFailedError; break; } if($userInfo->passwordNeedsRehash()) $users->updateUser($userInfo, password: $_POST['login']['password']); if(!empty($loginPermCat) && $loginPermVal > 0 && !$msz->getPerms()->checkPermissions($loginPermCat, $loginPermVal, $userInfo)) { $notices[] = "Login succeeded, but you're not allowed to browse the site right now."; $loginAttempts->recordAttempt(true, $ipAddress, $countryCode, $userAgent, $clientInfo, $userInfo); break; } if($userInfo->hasTOTPKey()) { $tfaToken = $msz->getTFASessions()->createToken($userInfo); url_redirect('auth-two-factor', [ 'token' => $tfaToken, ]); return; } $loginAttempts->recordAttempt(true, $ipAddress, $countryCode, $userAgent, $clientInfo, $userInfo); try { $sessionInfo = $sessions->createSession($userInfo, $ipAddress, $countryCode, $userAgent, $clientInfo); } catch(Exception $ex) { $notices[] = "Something broke while creating a session for you, please tell an administrator or developer about this!"; break; } $tokenBuilder = $msz->getAuthInfo()->getTokenInfo()->toBuilder(); $tokenBuilder->setUserId($userInfo); $tokenBuilder->setSessionToken($sessionInfo); $tokenBuilder->removeImpersonatedUserId(); $tokenInfo = $tokenBuilder->toInfo(); AuthTokenCookie::apply($tokenPacker->pack($tokenInfo)); 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'); $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, ], ]);