import Application from "wms-core/Application"; import {Type} from "wms-core/Utils"; import Migration from "wms-core/db/Migration"; import CreateMigrationsTable from "wms-core/migrations/CreateMigrationsTable"; import CreateLogsTable from "wms-core/migrations/CreateLogsTable"; import ExpressAppComponent from "wms-core/components/ExpressAppComponent"; import NunjucksComponent from "wms-core/components/NunjucksComponent"; import MysqlComponent from "wms-core/components/MysqlComponent"; import LogRequestsComponent from "wms-core/components/LogRequestsComponent"; import RedisComponent from "wms-core/components/RedisComponent"; import ServeStaticDirectoryComponent from "wms-core/components/ServeStaticDirectoryComponent"; import MaintenanceComponent from "wms-core/components/MaintenanceComponent"; import MailComponent from "wms-core/components/MailComponent"; import SessionComponent from "wms-core/components/SessionComponent"; import RedirectBackComponent from "wms-core/components/RedirectBackComponent"; import FormHelperComponent from "wms-core/components/FormHelperComponent"; import CsrfProtectionComponent from "wms-core/components/CsrfProtectionComponent"; import WebSocketServerComponent from "wms-core/components/WebSocketServerComponent"; import AboutController from "./controllers/AboutController"; import AutoUpdateComponent from "wms-core/components/AutoUpdateComponent"; import AuthController from "./controllers/AuthController"; import MagicLinkWebSocketListener from "wms-core/auth/magic_link/MagicLinkWebSocketListener"; import MagicLinkController from "./controllers/MagicLinkController"; import MailController from "wms-core/auth/MailController"; import FileController from "./controllers/FileController"; import CreateUsersAndUserEmailsTable from "wms-core/auth/migrations/CreateUsersAndUserEmailsTable"; import CreateMagicLinksTable from "wms-core/auth/migrations/CreateMagicLinksTable"; import CreateAuthTokensTable from "./migrations/CreateAuthTokensTable"; import AuthComponent from "wms-core/auth/AuthComponent"; import AuthGuard from "wms-core/auth/AuthGuard"; import MagicLink from "wms-core/auth/models/MagicLink"; import AuthToken from "./models/AuthToken"; import {MagicLinkActionType} from "./controllers/MagicLinkActionType"; import {Request} from "express"; import CreateFilesTable from "./migrations/CreateFilesTable"; import IncreaseFilesSizeField from "./migrations/IncreaseFilesSizeField"; import AddApprovedFieldToUsersTable from "wms-core/auth/migrations/AddApprovedFieldToUsersTable"; import BackendController from "./controllers/BackendController"; import CreateUrlRedirectsTable from "./migrations/CreateUrlRedirectsTable"; import AuthTokenController from "./controllers/AuthTokenController"; import URLRedirectController from "./controllers/URLRedirectController"; import LinkController from "./controllers/LinkController"; export default class App extends Application { private readonly port: number; private magicLinkWebSocketListener?: MagicLinkWebSocketListener; constructor(port: number) { super(require('../package.json').version); this.port = port; } protected getMigrations(): Type[] { return [ CreateMigrationsTable, CreateLogsTable, CreateUsersAndUserEmailsTable, CreateMagicLinksTable, CreateAuthTokensTable, CreateFilesTable, IncreaseFilesSizeField, AddApprovedFieldToUsersTable, CreateUrlRedirectsTable, ]; } protected async init(): Promise { this.registerComponents(); this.registerWebSocketListeners(); this.registerControllers(); } private registerComponents() { const redisComponent = new RedisComponent(); const mysqlComponent = new MysqlComponent(); const expressAppComponent = new ExpressAppComponent(this.port); this.use(expressAppComponent); this.use(new NunjucksComponent()); this.use(new LogRequestsComponent()); // Static files this.use(new ServeStaticDirectoryComponent('public')); this.use(new ServeStaticDirectoryComponent('node_modules/feather-icons/dist', '/icons')); // Maintenance this.use(new MaintenanceComponent(this, () => { return redisComponent.canServe() && mysqlComponent.canServe(); })); this.use(new AutoUpdateComponent()); // Services this.use(mysqlComponent); this.use(new MailComponent()); // Session this.use(redisComponent); this.use(new SessionComponent(redisComponent)); this.use(new AuthComponent(new class extends AuthGuard { public async getProofForSession(session: Express.Session): Promise { return await MagicLink.bySessionID(session.id, [MagicLinkActionType.LOGIN, MagicLinkActionType.REGISTER]); } public async getProofForRequest(req: Request): Promise { const authorization = req.header('Authorization'); if (authorization) { const token = await AuthToken.select().where('secret', authorization).first(); if (token) { token.use(); await token.save(); } return token; } return super.getProofForRequest(req); } })); // Utils this.use(new RedirectBackComponent()); this.use(new FormHelperComponent()); // Middlewares this.use(new CsrfProtectionComponent()); // WebSocket server this.use(new WebSocketServerComponent(this, expressAppComponent, redisComponent)); } private registerWebSocketListeners() { this.magicLinkWebSocketListener = new MagicLinkWebSocketListener(); this.use(this.magicLinkWebSocketListener); } private registerControllers() { // Multi-domain + vhost this.use(new LinkController()); // Priority this.use(new AuthController()); this.use(new MagicLinkController(this.magicLinkWebSocketListener!)); this.use(new BackendController()); // Core functionality this.use(new MailController()); // Other functionality this.use(new AuthTokenController()); // Semi-static this.use(new AboutController()); // Global slug this.use(new FileController()); this.use(new URLRedirectController()); } }