import bodyParser from "body-parser"; import { initModules, apiMiddleware } from "./auth.js"; import { loadPep } from "../modules/pep/index.js"; import swaggerUi from "swagger-ui-express"; import swaggerDocument from "./api/v1/swagger.json" with { type: "json" }; import { getConfig } from "../common/config.js"; import { core } from "../modules/core/index.js" import { getAgreements } from "../http/agreements.js" import express from "express"; import session from "express-session"; import { PgSessionStore } from "./sessionStore.js"; import passport from "passport"; import { refresh } from "./refresh.js"; import { logout } from "./logout.js"; import { logRequest } from "./logging.js"; import { routeAgreements } from "./agreements.js"; import { dashboardHandlers } from "./dashboard.js"; import { makePassthrough } from "./dashboardPassthrough.js"; import { apiKeyHandlers } from "./apiKeys.js"; import { getUsage } from "../modules/core/usage.js"; import path from "path"; async function render(view, res, config) { try { res.render(view, { config, }); } catch (e) { console.error(e); } } async function renderPrivate(view, req, res, config) { try { if (!req.user) { return res.redirect('/'); } const now = new Date(); const begin = new Date(now.getFullYear(), now.getMonth(), 1); const end = new Date(now.getFullYear(), now.getMonth() + 1, 0); const usage = await getUsage(req.user, begin, end); const agreements = await getAgreements(req?.user?.id); res.render(view, { config, agreements, user: req.user, usage, }); } catch (e) { console.error(e); } } async function renderPrivateUI(req, res, config) { try { if (!req.user) { return res.redirect('/'); } const uiPath = path.join(process.cwd(), "ui", "index.html"); res.sendFile(uiPath); } catch (e) { console.error(e); } } export async function initHTTP(app) { const config = getConfig(); passport.serializeUser(function (user, done) { done(null, user); }); passport.deserializeUser(function (user, done) { done(null, user); }); const sess = { secret: config.secureSecret, resave: false, saveUninitialized: false, store: new PgSessionStore(), cookie: { httpOnly: true, sameSite: 'lax' }, // sameSite=lax: CSRF defense } if (app.get('env') === 'production') { app.set('trust proxy', 1) // trust first proxy sess.cookie.secure = true // serve secure cookies over HTTPS } app.use(session(sess)); app.use(passport.initialize()); app.use(passport.session()); app.use(express.static("./http/public")); app.set('views', './http/views'); app.set('view engine', 'ejs'); await initModules(app, passport); logRequest(app); routeAgreements(app); await loadPep(app); app.get("/", (req, res) => render('login', res, config)); app.get("/dashboard", (req, res) => renderPrivate('dashboard', req, res, config)); app.get("/refresh", refresh); app.post('/logout', logout); // UI app.get("/home", (req, res) => renderPrivateUI(req, res, config)); const dashboard = dashboardHandlers({ service: makePassthrough() }); app.get("/api/dashboard/summary", dashboard.summary); app.get("/api/dashboard/transactions", dashboard.transactions); app.get("/api/dashboard/series", dashboard.series); app.get("/api/dashboard/verify", dashboard.verify); app.get("/api/dashboard/transactions/:eventUuid", dashboard.event); app.get("/api/dashboard/agreement/:agreementUuid", dashboard.agreement); app.get("/api/dashboard/details/:eventUuid", dashboard.details); const apiKeys = apiKeyHandlers(); app.get("/api/dashboard/auth/whoami", apiKeys.whoami); app.get("/api/dashboard/auth/keys", apiKeys.list); app.post("/api/dashboard/auth/keys", express.json(), apiKeys.create); app.delete("/api/dashboard/auth/keys/:id", apiKeys.revoke); app.post(/^\/api\/v1\/.*$/, bodyParser.json(), apiMiddleware, core.post); // app.use("/api/v1", swaggerUi.serve, swaggerUi.setup(swaggerDocument)); }