Added ability to scope RoutingContext.
This commit is contained in:
parent
06d0413976
commit
33344541d6
10 changed files with 235 additions and 165 deletions
18
misuzu.php
18
misuzu.php
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
39
src/Routing/BackedRoutingContext.php
Normal file
39
src/Routing/BackedRoutingContext.php
Normal 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);
|
||||
}
|
||||
}
|
12
src/Routing/RoutingContext.php
Normal file
12
src/Routing/RoutingContext.php
Normal 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;
|
||||
}
|
|
@ -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 {
|
32
src/Routing/ScopedRoutingContext.php
Normal file
32
src/Routing/ScopedRoutingContext.php
Normal 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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue