Added ability to scope RoutingContext.

This commit is contained in:
flash 2025-01-29 00:25:53 +00:00
parent 06d0413976
commit 33344541d6
10 changed files with 235 additions and 165 deletions

View file

@ -22,26 +22,26 @@ error_reporting(MSZ_DEBUG ? -1 : 0);
mb_internal_encoding('UTF-8');
date_default_timezone_set('GMT');
$cfg = FsConfig::fromFile(MSZ_CONFIG . '/config.cfg');
$env = FsConfig::fromFile(MSZ_CONFIG . '/config.cfg');
if($cfg->hasValues('sentry:dsn'))
(function($cfg) {
if($env->hasValues('sentry:dsn'))
(function($env) {
\Sentry\init([
'dsn' => $cfg->getString('dsn'),
'traces_sample_rate' => $cfg->getFloat('tracesRate', 0.2),
'profiles_sample_rate' => $cfg->getFloat('profilesRate', 0.2),
'dsn' => $env->getString('dsn'),
'traces_sample_rate' => $env->getFloat('tracesRate', 0.2),
'profiles_sample_rate' => $env->getFloat('profilesRate', 0.2),
]);
set_exception_handler(function(\Throwable $ex) {
\Sentry\captureException($ex);
});
})($cfg->scopeTo('sentry'));
})($env->scopeTo('sentry'));
$db = DbBackends::create($cfg->getString('database:dsn', 'null:'));
$db = DbBackends::create($env->getString('database:dsn', 'null:'));
$db->execute('SET SESSION time_zone = \'+00:00\', sql_mode = \'STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION\';');
$cfg = new DbConfig($db, 'msz_config');
Mailer::init($cfg->scopeTo('mail'));
$msz = new MisuzuContext($db, $cfg);
$msz = new MisuzuContext($db, $cfg, $env);

View file

@ -126,25 +126,27 @@ CSRF::init(
);
// order for these two currently matters i think: it shouldn't.
$router = $msz->createRouting();
$router = $msz->createRouting($request);
$msz->startTemplating();
$mszRequestPath = substr($request->getPath(), 1);
$mszLegacyPathPrefix = MSZ_PUBLIC . '-legacy/';
$mszLegacyPath = $mszLegacyPathPrefix . $mszRequestPath;
if(in_array('main', $env->getArray(sprintf('domain:%s', $request->getHeaderLine('Host'))))) {
$mszRequestPath = substr($request->getPath(), 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(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_dir($mszLegacyPath))
$mszLegacyPath .= '/index.php';
if(is_file($mszLegacyPath)) {
require_once $mszLegacyPath;
return;
if(is_file($mszLegacyPath)) {
require_once $mszLegacyPath;
return;
}
}
}
}

View file

@ -13,12 +13,14 @@ use Misuzu\Messages\MessagesContext;
use Misuzu\News\News;
use Misuzu\Perms\Permissions;
use Misuzu\Profile\ProfileFields;
use Misuzu\Routing\{BackedRoutingContext,RoutingContext};
use Misuzu\Users\{UsersContext,UserInfo};
use RPCii\HmacVerificationProvider;
use RPCii\Server\HttpRpcServer;
use Index\Config\Config;
use Index\Db\DbConnection;
use Index\Db\Migration\{DbMigrationManager,DbMigrationRepo,FsDbMigrationRepo};
use Index\Http\HttpRequest;
use Index\Templating\TplEnvironment;
use Index\Urls\UrlRegistry;
@ -55,7 +57,8 @@ class MisuzuContext {
public function __construct(
public private(set) DbConnection $dbConn,
public private(set) Config $config
public private(set) Config $config,
public private(set) Config $env
) {
$this->perms = new Permissions($dbConn);
$this->authInfo = new AuthInfo($this->perms);
@ -144,132 +147,144 @@ class MisuzuContext {
Template::init($this->templating);
}
public function createRouting(): RoutingContext {
$routingCtx = new RoutingContext;
public function createRouting(HttpRequest $request): RoutingContext {
$prefix = sprintf('domain:%s', $request->getHeaderLine('Host'));
$hostInfo = $this->env->scopeTo($prefix);
$purposes = $this->env->getArray($prefix);
$routingCtx = new BackedRoutingContext;
$this->urls = $routingCtx->urls;
$routingCtx->register(new \Misuzu\Home\HomeRoutes(
$this->config,
$this->dbConn,
$this->siteInfo,
$this->authInfo,
$this->changelog,
$this->comments,
$this->counters,
$this->news,
$this->usersCtx
));
if(in_array('main', $purposes)) {
$scopedInfo = $hostInfo->scopeTo('main');
$scopedCtx = $routingCtx->scopeTo(
$scopedInfo->getString('name'),
$scopedInfo->getString('path')
);
$routingCtx->register(new \Misuzu\Users\Assets\AssetsRoutes(
$this->authInfo,
$this->urls,
$this->usersCtx
));
$scopedCtx->register(new \Misuzu\Home\HomeRoutes(
$this->config,
$this->dbConn,
$this->siteInfo,
$this->authInfo,
$this->changelog,
$this->comments,
$this->counters,
$this->news,
$this->usersCtx
));
$routingCtx->register(new \Misuzu\Info\InfoRoutes);
$scopedCtx->register(new \Misuzu\Users\Assets\AssetsRoutes(
$this->authInfo,
$this->urls,
$this->usersCtx
));
$routingCtx->register(new \Misuzu\News\NewsRoutes(
$this->siteInfo,
$this->authInfo,
$this->urls,
$this->news,
$this->usersCtx,
$this->comments
));
$scopedCtx->register(new \Misuzu\Info\InfoRoutes);
$routingCtx->register(new \Misuzu\Messages\MessagesRoutes(
$this->config->scopeTo('messages'),
$this->urls,
$this->authInfo,
$this->messagesCtx,
$this->usersCtx,
$this->perms
));
$scopedCtx->register(new \Misuzu\News\NewsRoutes(
$this->siteInfo,
$this->authInfo,
$this->urls,
$this->news,
$this->usersCtx,
$this->comments
));
$routingCtx->register(new \Misuzu\Forum\ForumCategoriesRoutes(
$this->forumCtx,
$this->usersCtx,
$this->authInfo,
));
$routingCtx->register(new \Misuzu\Forum\ForumTopicsRoutes(
$this->urls,
$this->forumCtx,
$this->usersCtx,
$this->auditLog,
$this->authInfo,
));
$routingCtx->register(new \Misuzu\Forum\ForumPostsRoutes(
$this->urls,
$this->forumCtx,
$this->usersCtx,
$this->auditLog,
$this->authInfo,
));
$scopedCtx->register(new \Misuzu\Messages\MessagesRoutes(
$this->config->scopeTo('messages'),
$this->urls,
$this->authInfo,
$this->messagesCtx,
$this->usersCtx,
$this->perms
));
$routingCtx->register(new \Misuzu\Changelog\ChangelogRoutes(
$this->siteInfo,
$this->urls,
$this->changelog,
$this->usersCtx,
$this->authInfo,
$this->comments
));
$scopedCtx->register(new \Misuzu\Forum\ForumCategoriesRoutes(
$this->forumCtx,
$this->usersCtx,
$this->authInfo,
));
$scopedCtx->register(new \Misuzu\Forum\ForumTopicsRoutes(
$this->urls,
$this->forumCtx,
$this->usersCtx,
$this->auditLog,
$this->authInfo,
));
$scopedCtx->register(new \Misuzu\Forum\ForumPostsRoutes(
$this->urls,
$this->forumCtx,
$this->usersCtx,
$this->auditLog,
$this->authInfo,
));
$routingCtx->register(new \Misuzu\SharpChat\SharpChatRoutes(
$this->config->scopeTo('sockChat'),
$this->config->scopeTo('impersonate'),
$this->urls,
$this->usersCtx,
$this->authCtx,
$this->emotes,
$this->perms,
$this->authInfo,
$this->counters
));
$scopedCtx->register(new \Misuzu\Changelog\ChangelogRoutes(
$this->siteInfo,
$this->urls,
$this->changelog,
$this->usersCtx,
$this->authInfo,
$this->comments
));
$routingCtx->register(new \Misuzu\Satori\SatoriRoutes(
$this->config->scopeTo('satori'),
$this->usersCtx,
$this->forumCtx,
$this->profileFields
));
$scopedCtx->register(new \Misuzu\SharpChat\SharpChatRoutes(
$this->config->scopeTo('sockChat'),
$this->config->scopeTo('impersonate'),
$this->urls,
$this->usersCtx,
$this->authCtx,
$this->emotes,
$this->perms,
$this->authInfo,
$this->counters
));
$routingCtx->register(new LegacyRoutes($this->urls));
$scopedCtx->register(new \Misuzu\Satori\SatoriRoutes(
$this->config->scopeTo('satori'),
$this->usersCtx,
$this->forumCtx,
$this->profileFields
));
$rpcServer = new HttpRpcServer;
$routingCtx->router->register($rpcServer->createRouteHandler(
new HmacVerificationProvider(fn() => $this->config->getString('aleister.secret'))
));
$routingCtx->register(new LegacyRoutes($this->urls));
$rpcServer->register(new Auth\AuthRpcHandler(
$this->config->scopeTo('impersonate'),
$this->usersCtx,
$this->authCtx
));
$rpcServer = new HttpRpcServer;
$scopedCtx->register($rpcServer->createRouteHandler(
new HmacVerificationProvider(fn() => $this->config->getString('aleister.secret'))
));
$rpcServer->register(new Emoticons\EmotesRpcHandler(
$this->emotes
));
$rpcServer->register(new Auth\AuthRpcHandler(
$this->config->scopeTo('impersonate'),
$this->usersCtx,
$this->authCtx
));
$rpcServer->register(new Users\UsersRpcHandler(
$this->siteInfo,
$this->urls,
$this->usersCtx
));
$rpcServer->register(new Emoticons\EmotesRpcHandler(
$this->emotes
));
// This RPC server will eventually despawn when Hanyuu fully owns auth
$hanyuuRpcServer = new HttpRpcServer;
$routingCtx->router->scopeTo('/_hanyuu')->register($hanyuuRpcServer->createRouteHandler(
new HmacVerificationProvider(fn() => $this->config->getString('hanyuu.secret'))
));
$rpcServer->register(new Users\UsersRpcHandler(
$this->siteInfo,
$this->urls,
$this->usersCtx
));
$hanyuuRpcServer->register(new Hanyuu\HanyuuRpcHandler(
fn() => $this->config->getString('hanyuu.endpoint'),
$this->config->scopeTo('impersonate'),
$this->urls,
$this->usersCtx,
$this->authCtx
));
// This RPC server will eventually despawn when Hanyuu fully owns auth
$hanyuuRpcServer = new HttpRpcServer;
$scopedCtx->scopeTo('', '/_hanyuu')->register($hanyuuRpcServer->createRouteHandler(
new HmacVerificationProvider(fn() => $this->config->getString('hanyuu.secret'))
));
$hanyuuRpcServer->register(new Hanyuu\HanyuuRpcHandler(
fn() => $this->config->getString('hanyuu.endpoint'),
$this->config->scopeTo('impersonate'),
$this->urls,
$this->usersCtx,
$this->authCtx
));
}
return $routingCtx;
}

View file

@ -0,0 +1,39 @@
<?php
namespace Misuzu\Routing;
use Index\Http\HttpRequest;
use Index\Http\Routing\{HttpRouter,Router,RouteHandler};
use Index\Urls\{ArrayUrlRegistry,UrlRegistry,UrlSource};
class BackedRoutingContext implements RoutingContext {
public private(set) Router $router;
public private(set) UrlRegistry $urls;
public function __construct(
?Router $router = null,
?UrlRegistry $urls = null
) {
$this->urls = $urls ?? new ArrayUrlRegistry;
$this->router = $router ?? new HttpRouter(errorHandler: new RoutingErrorHandler);
$this->router->use('/', fn($resp) => $resp->setPoweredBy('Misuzu'));
}
public function register(RouteHandler|UrlSource $handler): void {
if($handler instanceof RouteHandler)
$this->router->register($handler);
if($handler instanceof UrlSource)
$this->urls->register($handler);
}
public function scopeTo(string $namePrefix, string $pathPrefix): RoutingContext {
return new ScopedRoutingContext(
$this->router->scopeTo($pathPrefix),
$this->urls->scopeTo($namePrefix, $pathPrefix)
);
}
/** @param mixed[] $args */
public function dispatch(?HttpRequest $request = null, array $args = []): void {
$this->router->dispatch($request, $args);
}
}

View file

@ -0,0 +1,12 @@
<?php
namespace Misuzu\Routing;
use Index\Http\HttpRequest;
use Index\Http\Routing\RouteHandler;
use Index\Urls\UrlSource;
interface RoutingContext {
public function register(RouteHandler|UrlSource $handler): void;
public function scopeTo(string $namePrefix, string $pathPrefix): RoutingContext;
public function dispatch(?HttpRequest $request = null, array $args = []): void;
}

View file

@ -1,7 +1,8 @@
<?php
namespace Misuzu;
namespace Misuzu\Routing;
use Index\Http\{HtmlHttpErrorHandler,HttpResponseBuilder,HttpRequest};
use Misuzu\Template;
class RoutingErrorHandler extends HtmlHttpErrorHandler {
public function handle(HttpResponseBuilder $response, HttpRequest $request, int $code, string $message): void {

View file

@ -0,0 +1,32 @@
<?php
namespace Misuzu\Routing;
use Index\Http\HttpRequest;
use Index\Http\Routing\{RouteHandler,Router};
use Index\Urls\{UrlRegistry,UrlSource};
class ScopedRoutingContext implements RoutingContext {
public function __construct(
private Router $router,
private UrlRegistry $urls
) {}
public function register(RouteHandler|UrlSource $handler): void {
if($handler instanceof RouteHandler)
$this->router->register($handler);
if($handler instanceof UrlSource)
$this->urls->register($handler);
}
public function scopeTo(string $namePrefix, string $pathPrefix): RoutingContext {
return new ScopedRoutingContext(
$this->router->scopeTo($pathPrefix),
$this->urls->scopeTo($namePrefix, $pathPrefix)
);
}
/** @param mixed[] $args */
public function dispatch(?HttpRequest $request = null, array $args = []): void {
$this->router->dispatch($request, $args);
}
}

View file

@ -1,29 +0,0 @@
<?php
namespace Misuzu;
use Index\Http\HttpRequest;
use Index\Http\Routing\{HttpRouter,Router,RouteHandler};
use Index\Urls\{ArrayUrlRegistry,UrlFormat,UrlRegistry,UrlSource};
class RoutingContext {
public private(set) UrlRegistry $urls;
public private(set) HttpRouter $router;
public function __construct() {
$this->urls = new ArrayUrlRegistry;
$this->router = new HttpRouter(errorHandler: new RoutingErrorHandler);
$this->router->use('/', fn($resp) => $resp->setPoweredBy('Misuzu'));
}
public function register(RouteHandler|UrlSource $handler): void {
if($handler instanceof RouteHandler)
$this->router->register($handler);
if($handler instanceof UrlSource)
$this->urls->register($handler);
}
/** @param mixed[] $args */
public function dispatch(?HttpRequest $request = null, array $args = []): void {
$this->router->dispatch($request, $args);
}
}

View file

@ -7,7 +7,6 @@ use Index\Config\Config;
use Index\Http\{HttpRequest,HttpResponseBuilder};
use Index\Http\Routing\{HttpGet,HttpMiddleware,RouteHandler,RouteHandlerTrait};
use Misuzu\Pagination;
use Misuzu\RoutingContext;
use Misuzu\Forum\ForumContext;
use Misuzu\Profile\ProfileFields;
use Misuzu\Users\UsersContext;

View file

@ -2,7 +2,6 @@
namespace Misuzu\SharpChat;
use RuntimeException;
use Misuzu\RoutingContext;
use Misuzu\Auth\{AuthContext,AuthInfo,Sessions};
use Misuzu\Counters\Counters;
use Misuzu\Emoticons\Emotes;