modified version

This commit is contained in:
Stan
2026-04-21 23:26:13 +02:00
parent e7127f3215
commit bdd06105dd
46 changed files with 1250 additions and 5248 deletions
+44 -9
View File
@@ -5,7 +5,7 @@ import { fileURLToPath } from 'node:url';
import path from 'node:path';
import { errorHandler, notFoundHandler } from './middleware/errorHandler.js';
import { requireAdminAuth, requireUserAuth } from './middleware/authMiddleware.js';
import { requireAdminAuth, requireAnyAuth, requireUserAuth } from './middleware/authMiddleware.js';
import adminRoutes from './routes/adminRoutes.js';
import authRoutes from './routes/authRoutes.js';
import configRoutes from './routes/configRoutes.js';
@@ -37,6 +37,29 @@ app.use(cors());
app.use(cookieParser());
app.use(express.json({ limit: '50mb' }));
/*
* Prevent browsers from serving stale cached HTML pages.
*
* Without an explicit Cache-Control header, browsers apply heuristic freshness
* based on the Last-Modified timestamp. Inside a Docker container the file
* system mtime is frozen at image-build time, so browsers can cache HTML for
* hours or days and users see the old version until they do a hard-refresh.
*
* `no-cache` means "always revalidate with the server before using a cached
* copy". When the file has not changed Express returns a lightweight 304 Not
* Modified (no body) thanks to the ETag it already sends, so the cost is just
* one round-trip. When the file has changed the browser receives the new
* content immediately.
*
* JS and CSS assets are deliberately excluded — their ETags already handle
* freshness correctly and they are larger, so unnecessary revalidation would
* add more overhead.
*/
function noCacheHtml(_req, res, next) {
res.setHeader('Cache-Control', 'no-cache');
next();
}
app.get('/api/v1', (_req, res) => {
res.json({
service: 'check-list-poc-api',
@@ -54,18 +77,18 @@ app.use('/api/v1/health', healthRoutes);
app.use('/api/v1/templates', templateRoutes);
app.use('/api/v1/lookups', lookupRoutes);
app.use('/api/v1/config', configRoutes);
app.use('/api/v1/reports', reportRoutes);
app.use('/api/v1/admin', adminRoutes);
app.use('/api/v1/reports', requireAnyAuth, reportRoutes);
app.use('/api/v1/admin', requireAnyAuth, adminRoutes);
app.use('/api/v1/auth', authRoutes);
/*
* Login pages are served without authentication.
*/
app.get('/login-admin', (_req, res) => {
app.get('/login-admin', noCacheHtml, (_req, res) => {
res.sendFile(loginAdminPath);
});
app.get('/login-user', (_req, res) => {
app.get('/login-user', noCacheHtml, (_req, res) => {
res.sendFile(loginUserPath);
});
@@ -73,7 +96,7 @@ app.get('/login-user', (_req, res) => {
* The root route intentionally serves a neutral portal page. This gives the
* project distinct user and administrator entry points.
*/
app.get('/', (_req, res) => {
app.get('/', noCacheHtml, (_req, res) => {
res.sendFile(portalPath);
});
@@ -81,14 +104,26 @@ app.get('/', (_req, res) => {
* User and admin workspaces live in separate HTML files so each page only loads
* the markup it needs. Authentication is required for both areas.
*/
app.get(['/user', '/user/'], requireUserAuth, (_req, res) => {
app.get(['/user', '/user/'], requireUserAuth, noCacheHtml, (_req, res) => {
res.sendFile(userPagePath);
});
app.get(['/admin', '/admin/'], requireAdminAuth, (_req, res) => {
app.get(['/admin', '/admin/'], requireAdminAuth, noCacheHtml, (_req, res) => {
res.sendFile(adminPagePath);
});
app.use(express.static(publicDir));
/*
* Serve static assets. HTML files get the same no-cache directive (covers
* direct URL access like /user.html). JS/CSS/images use the default
* ETag-based caching — conditional GETs (304) keep them efficient.
*/
app.use(express.static(publicDir, {
setHeaders: (res, filePath) => {
if (filePath.endsWith('.html')) {
res.setHeader('Cache-Control', 'no-cache');
}
}
}));
app.use(notFoundHandler);
app.use(errorHandler);