misuzu/public/index.php

153 lines
5.5 KiB
PHP

<?php
namespace Misuzu;
use RuntimeException;
use Misuzu\Auth\{AuthTokenBuilder,AuthTokenCookie,AuthTokenInfo};
require_once __DIR__ . '/../misuzu.php';
if(!isset($msz) || !($msz instanceof \Misuzu\MisuzuContext))
die('Misuzu is not initialised.');
if(class_exists(\Whoops\Run::class))
(function($whoops) {
$whoops->pushHandler(new \Whoops\Handler\PrettyPageHandler);
$whoops->register();
})(new \Whoops\Run);
else
set_exception_handler(function(\Throwable $ex) {
\Sentry\captureException($ex);
http_response_code(500);
ob_clean();
header('Content-Type: text/html; charset=utf-8');
header('X-Accel-Redirect: /error-500.html');
exit;
});
// The whole wall of shit before the router setup and dispatch should be worked away
// Lockdown things should be middleware when there's no more legacy files
$request = \Index\Http\HttpRequest::fromRequest();
ob_start();
if(is_file(MSZ_ROOT . '/.migrating')) {
http_response_code(503);
header('Content-Type: text/html; charset=utf-8');
header('X-Accel-Redirect: /error-503.html');
exit;
}
$tokenPacker = $msz->authCtx->createAuthTokenPacker();
if(filter_has_var(INPUT_COOKIE, 'msz_auth'))
$tokenInfo = $tokenPacker->unpack(filter_input(INPUT_COOKIE, 'msz_auth'));
elseif(filter_has_var(INPUT_COOKIE, 'msz_uid') && filter_has_var(INPUT_COOKIE, 'msz_sid')) {
$tokenBuilder = new AuthTokenBuilder;
$tokenBuilder->setUserId((string)filter_input(INPUT_COOKIE, 'msz_uid', FILTER_SANITIZE_NUMBER_INT));
$tokenBuilder->setSessionToken((string)filter_input(INPUT_COOKIE, 'msz_sid'));
$tokenInfo = $tokenBuilder->toInfo();
$tokenBuilder = null;
} else
$tokenInfo = AuthTokenInfo::empty();
$userInfo = null;
$sessionInfo = null;
$userInfoReal = null;
$remoteAddr = (string)filter_input(INPUT_SERVER, 'REMOTE_ADDR');
if($tokenInfo->hasUserId && $tokenInfo->hasSessionToken) {
$tokenBuilder = new AuthTokenBuilder($tokenInfo);
try {
$sessionInfo = $msz->authCtx->sessions->getSession(sessionToken: $tokenInfo->sessionToken);
if($sessionInfo->expired) {
$tokenBuilder->removeUserId();
$tokenBuilder->removeSessionToken();
} elseif($sessionInfo->userId === $tokenInfo->userId) {
$userInfo = $msz->usersCtx->users->getUser($tokenInfo->userId, 'id');
if($userInfo->deleted) {
$tokenBuilder->removeUserId();
$tokenBuilder->removeSessionToken();
} else {
$msz->usersCtx->users->recordUserActivity($userInfo, remoteAddr: $remoteAddr);
$msz->authCtx->sessions->recordSessionActivity(sessionInfo: $sessionInfo, remoteAddr: $remoteAddr);
if($sessionInfo->shouldBumpExpires)
$tokenBuilder->setEdited();
if($tokenInfo->hasImpersonatedUserId) {
$allowToImpersonate = $userInfo->super;
$impersonatedUserId = $tokenInfo->impersonatedUserId;
if(!$allowToImpersonate) {
$allowImpersonateUsers = $msz->config->getArray(sprintf('impersonate.allow.u%s', $userInfo->id));
$allowToImpersonate = in_array((string)$impersonatedUserId, $allowImpersonateUsers, true);
}
if($allowToImpersonate) {
$userInfoReal = $userInfo;
try {
$userInfo = $msz->usersCtx->users->getUser($impersonatedUserId, 'id');
} catch(RuntimeException $ex) {
$userInfo = $userInfoReal;
$userInfoReal = null;
$tokenBuilder->removeImpersonatedUserId();
}
} else $tokenBuilder->removeImpersonatedUserId();
}
}
}
} catch(RuntimeException $ex) {
$tokenBuilder->removeUserId();
$tokenBuilder->removeSessionToken();
$tokenBuilder->removeImpersonatedUserId();
$userInfo = null;
$sessionInfo = null;
$userInfoReal = null;
}
if($tokenBuilder->isEdited()) {
$tokenInfo = $tokenBuilder->toInfo();
AuthTokenCookie::apply($tokenPacker->pack($tokenInfo));
}
}
$msz->authInfo->setInfo($tokenInfo, $userInfo, $sessionInfo, $userInfoReal);
CSRF::init(
$msz->config->getString('csrf.secret', 'soup'),
($msz->authInfo->isLoggedIn ? $sessionInfo->token : $remoteAddr)
);
// order for these two currently matters i think: it shouldn't.
$router = $msz->createRouting($request);
$msz->startTemplating();
if(in_array('main', $msz->env->getArray(sprintf('domain:%s', $request->getHeaderLine('Host'))))) {
$mszRequestPath = substr($request->path, 1);
$mszLegacyPathPrefix = MSZ_PUBLIC . '-legacy/';
$mszLegacyPath = $mszLegacyPathPrefix . $mszRequestPath;
if(str_starts_with($mszLegacyPath, $mszLegacyPathPrefix)) {
$mszLegacyPathReal = realpath($mszLegacyPath);
if($mszLegacyPath === $mszLegacyPathReal || $mszLegacyPath === $mszLegacyPathReal . '/') {
if(str_starts_with($mszRequestPath, '/manage') && !$msz->hasManageAccess())
Template::throwError(403);
if(is_dir($mszLegacyPath))
$mszLegacyPath .= '/index.php';
if(is_file($mszLegacyPath)) {
require_once $mszLegacyPath;
return;
}
}
}
}
$router->dispatch($request);