Files
jlinc-server/backend/http/index.js
2026-08-20 15:08:32 +00:00

131 lines
4.2 KiB
JavaScript

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));
}