dbConn = $dbConn; $this->config = $config; $this->usersCtx = new UsersContext($this->dbConn); $this->perms = new Permissions($this->dbConn); $this->authInfo = new AuthInfo($this->perms); $this->auditLog = new AuditLog($this->dbConn); $this->changelog = new Changelog($this->dbConn); $this->comments = new Comments($this->dbConn); $this->counters = new Counters($this->dbConn); $this->emotes = new Emotes($this->dbConn); $this->forum = new Forum($this->dbConn); $this->loginAttempts = new LoginAttempts($this->dbConn); $this->news = new News($this->dbConn); $this->profileFields = new ProfileFields($this->dbConn); $this->recoveryTokens = new RecoveryTokens($this->dbConn); $this->sessions = new Sessions($this->dbConn); $this->tfaSessions = new TwoFactorAuthSessions($this->dbConn); } public function getDbConn(): IDbConnection { return $this->dbConn; } public function getDbQueryCount(): int { $result = $this->dbConn->query('SHOW SESSION STATUS LIKE "Questions"'); return $result->next() ? $result->getInteger(1) : 0; } public function createMigrationManager(): DbMigrationManager { return new DbMigrationManager($this->dbConn, 'msz_' . DbMigrationManager::DEFAULT_TABLE); } public function createMigrationRepo(): IDbMigrationRepo { return new FsDbMigrationRepo(MSZ_MIGRATIONS); } public function getConfig(): IConfig { return $this->config; } public function getRouter(): Router { return $this->router->getRouter(); } public function getEmotes(): Emotes { return $this->emotes; } public function getChangelog(): Changelog { return $this->changelog; } public function getNews(): News { return $this->news; } public function getComments(): Comments { return $this->comments; } public function getAuditLog(): AuditLog { return $this->auditLog; } public function getLoginAttempts(): LoginAttempts { return $this->loginAttempts; } public function getRecoveryTokens(): RecoveryTokens { return $this->recoveryTokens; } public function getTFASessions(): TwoFactorAuthSessions { return $this->tfaSessions; } public function getSessions(): Sessions { return $this->sessions; } public function getCounters(): Counters { return $this->counters; } public function getProfileFields(): ProfileFields { return $this->profileFields; } public function getForum(): Forum { return $this->forum; } public function getPerms(): Permissions { return $this->perms; } public function getUsersContext(): UsersContext { return $this->usersCtx; } public function createAuthTokenPacker(): AuthTokenPacker { return new AuthTokenPacker($this->config->getString('auth.secret', 'meow')); } public function getAuthInfo(): AuthInfo { return $this->authInfo; } public function createAuditLog(string $action, array $params = [], UserInfo|string|null $userInfo = null): void { if($userInfo === null && $this->authInfo->isLoggedIn()) $userInfo = $this->authInfo->getUserInfo(); $this->auditLog->createLog( $userInfo, $action, $params, $_SERVER['REMOTE_ADDR'] ?? '::1', $_SERVER['COUNTRY_CODE'] ?? 'XX' ); } private ?bool $hasManageAccess = null; public function hasManageAccess(): bool { $this->hasManageAccess ??= $this->authInfo->isLoggedIn() && !$this->usersCtx->hasActiveBan($this->authInfo->getUserInfo()) && $this->authInfo->getPerms('global')->check(Perm::G_IS_JANITOR); return $this->hasManageAccess; } public function getWebAssetInfo(): ?object { return json_decode(file_get_contents(MSZ_ASSETS . '/current.json')); } private ?string $chatUrl = null; public function getChatURL(): string { $this->chatUrl ??= $this->config->getString('sockChat.chatPath.normal'); return $this->chatUrl; } public function startTemplating(): void { $globals = $this->config->getValues([ ['site.name:s', 'Misuzu', 'site_name'], ['site.desc:s', '', 'site_description'], ['site.url:s', '', 'site_url'], ['eeprom.path:s', '', 'eeprom_path'], ['eeprom.app:s', '', 'eeprom_app'], ]); $globals['assets'] = $this->getWebAssetInfo(); $globals['auth_info'] = $this->authInfo; $globals['active_ban_info'] = $this->usersCtx->tryGetActiveBan($this->authInfo->getUserInfo()); $globals['display_timings_info'] = MSZ_DEBUG || $this->authInfo->getPerms('global')->check(Perm::G_TIMINGS_VIEW); $templating = new SasaeEnvironment( MSZ_TEMPLATES, cache: MSZ_DEBUG ? null : ['Misuzu', GitInfo::hash(true)], debug: MSZ_DEBUG ); $templating->addExtension(new MisuzuSasaeExtension($this)); $templating->addGlobal('globals', $globals); Template::init($templating); } public function startRouter(): void { $this->router = new HttpFx; $this->router->use('/', function($response) { $response->setPoweredBy('Misuzu'); }); $this->registerErrorPages(); $this->registerHttpRoutes(); } public function dispatchRouter(?HttpRequest $request = null): void { $this->router->dispatch($request); } private function registerErrorPages(): void { $this->router->addErrorHandler(400, function($response) { $response->setContent(Template::renderRaw('errors.400')); }); $this->router->addErrorHandler(403, function($response) { $response->setContent(Template::renderRaw('errors.403')); }); $this->router->addErrorHandler(404, function($response) { $response->setContent(Template::renderRaw('errors.404')); }); $this->router->addErrorHandler(500, function($response) { $response->setContent(file_get_contents(MSZ_TEMPLATES . '/500.html')); }); $this->router->addErrorHandler(503, function($response) { $response->setContent(file_get_contents(MSZ_TEMPLATES . '/503.html')); }); } private function registerHttpRoutes(): void { $this->router->register(new HomeRoutes( $this->config, $this->dbConn, $this->authInfo, $this->changelog, $this->comments, $this->counters, $this->news, $this->usersCtx )); $this->router->register(new AssetsRoutes( $this->authInfo, $this->usersCtx )); $this->router->register(new InfoRoutes); $this->router->register(new NewsRoutes( $this->config, $this->authInfo, $this->news, $this->usersCtx, $this->comments )); $this->router->register(new ChangelogRoutes( $this->config, $this->changelog, $this->usersCtx, $this->authInfo, $this->comments )); $this->router->register(new SharpChatRoutes( $this->config->scopeTo('sockChat'), $this->usersCtx, $this->emotes, $this->sessions, $this->perms, $this->authInfo, $this->createAuthTokenPacker(...) )); $this->router->register(new SatoriRoutes( $this->config->scopeTo('satori'), $this->usersCtx, $this->profileFields, $this->forum )); // below is still only otherwise available as stinky php files $this->router->get('/auth.php', function($response, $request) { $response->redirect(url([ 'logout' => 'auth-logout', 'reset' => 'auth-reset', 'forgot' => 'auth-forgot', 'register' => 'auth-register', ][$request->getParam('m')] ?? 'auth-login'), true); }); $this->router->get('/settings.php', function($response) { $response->redirect(url('settings-index'), true); }); } }