import constants from "constants"; import cors from "cors"; import { CronJob } from "cron"; import express, { type NextFunction, type Request, type Response, } from "express"; import fs from "fs"; import https from "https"; import { RegisterRoutes } from "./generated/routes.js"; import { inject } from "./infrastructure/di/injector.js"; import { sessionHandler } from "./infrastructure/sessionHandler.js"; import { EnvironmentService } from "./services/environmentService.js"; import { FoundEventsService } from "./services/foundEvents/foundEventsService.js"; import { KeycloakUser } from "./services/keycloak/user/keycloak-user.js"; import { PushService } from "./services/push/pushService.js"; // import helmet from "helmet"; // TODO import http2 from 'http2'; async function run() { const app = express(); const keycloakUser = inject(KeycloakUser); //TODO app.use(helmet.hsts()); this and other helmets app.use( cors({ origin: [ "https://taekwondo-chemnitz.toni714.de", "https://tcc-1-ev-intern.web.app", "http://localhost:4200", "https://localhost:4200", "http://localhost:8080", ], methods: ["GET", "POST", "PUT", "DELETE", "OPTIONS"], //TODO reevaluate }), ); app.use(sessionHandler); app.use(await keycloakUser.middleware()); app.use(express.urlencoded({ extended: true })); app.use(express.json()); RegisterRoutes(app); const environment = inject(EnvironmentService); // wants to be last app.use( (err: unknown, _req: Request, res: Response, _next: NextFunction) => { console.dir(err); const ex = JSON.stringify(err); res.header("Content-Length", `${ex.length}`); res.status(500).send(ex); throw err; }, ); const isDev = environment.isDev(); let cert: https.ServerOptions["cert"]; let key: https.ServerOptions["key"]; let SSL_KEY_PASSWORD: string | undefined; let port: number; if (isDev) { //TODO start with HTTPS in dev // cert = fs.readFileSync("src/cert.pem"); // key = fs.readFileSync("src/key.pem"); port = 3000; const server = app.listen(port, error => { if (error) { console.error("Startup crashed:", error); } console.log(`Server is running at http://localhost:${port}`); }); server.on("close", () => stopCron()); } else { port = 5443; const SSL_CERT_PATH = process.env["SSL_CERT_PATH"]; const SSL_KEY_PATH = process.env["SSL_KEY_PATH"]; SSL_KEY_PASSWORD = process.env["SSL_KEY_PASSWORD"]; if (!SSL_CERT_PATH || !SSL_KEY_PATH || !SSL_KEY_PASSWORD) { throw new Error("Missing SSL configuration"); } cert = fs.readFileSync(SSL_CERT_PATH); key = fs.readFileSync(SSL_KEY_PATH); const sslOptions: https.ServerOptions = { cert: cert, key: key, passphrase: SSL_KEY_PASSWORD, minVersion: "TLSv1.3", maxVersion: "TLSv1.3", ecdhCurve: "X25519:prime256v1:secp384r1", honorCipherOrder: false, secureOptions: constants.SSL_OP_NO_TLSv1 | constants.SSL_OP_NO_TLSv1_1 | constants.SSL_OP_NO_TLSv1_2 | constants.SSL_OP_NO_SSLv2 | constants.SSL_OP_NO_SSLv3, }; const server = https.createServer(sslOptions, app).listen(port, () => { console.log(`Server is running on port ${port}`); }); server.on("close", () => stopCron()); } // const h2SslOptions={}; // http2.createServer(h2SslOptions, app).listen(port, ()=>{ // console.log(`HTTP/2 server is running on port ${port}`); // }) initJobs(); startCron(); console.log("setup done"); } const jobs: CronJob[] = []; function initJobs() { const eventsService = inject(FoundEventsService); const crawlJob = CronJob.from({ cronTime: "35 4 * * *", onTick: async () => { await eventsService.crawl(); }, }); jobs.push(crawlJob); const pushService = inject(PushService); const notifyJob = CronJob.from({ cronTime: "10 12 * * *", onTick: async () => { await pushService.sendEventNotifications(); }, }); jobs.push(notifyJob); } function startCron() { console.log("starting jobs"); for (const job of jobs) { job.start(); } } async function stopCron() { console.log("stopping jobs"); for (const job of jobs) { job.stop(); } } run();