Files
sso-manager-node/nodejs/routes/docs.js
T
wmantly 955189d08a Air-gap: remove dead CDN reference + in-app /docs
- Removed a dead IE<9-only html5shim script tag pointing at a domain
  that no longer resolves.
- New GET /docs (index) and /docs/:slug routes render this project's
  own README, DEPLOYMENT, API.md, docs/*.md, and directory_spec.md
  server-side via marked -- so the documentation is readable from the
  running app with no route to GitHub Pages, where it otherwise only
  lives. Public, no auth, rate-limited (middleware/rate_limit.js) like
  the other public routes.
- .dockerignore/Dockerfile.openldap updated to copy DEPLOYMENT.md,
  API.md, directory_spec.md, and docs/ into the image, mirroring the
  existing tos.md -> /tos.md convention.
2026-07-16 15:33:46 -04:00

72 lines
2.8 KiB
JavaScript

'use strict';
const fs = require('fs');
const path = require('path');
const router = require('express').Router();
const {marked} = require('marked');
const conf = require('@simpleworkjs/conf');
const buildInfo = require('../utils/build_info');
const rateLimit = require('../middleware/rate_limit');
const values = {
title: conf.environment !== 'production' ? `dev` : '',
titleIcon: conf.environment !== 'production' ? `<i class="fa-brands fa-dev"></i>` : '',
name: conf.name,
...buildInfo,
};
// Full local copy of the project's documentation, rendered server-side --
// so an operator running air-gapped (no route to GitHub Pages, where this
// content otherwise only lives) can still read it from the running app.
// An explicit slug -> file allowlist, never a user-suppliable path, so
// there's no way to make this read outside the doc set below.
// docs/deployment.md is deliberately excluded -- it's just a stub pointing
// back at the root DEPLOYMENT.md (see docs/deployment.md itself), which is
// already covered by the "deployment" entry.
const DOCS = {
overview: {title: 'Overview', file: path.join(__dirname, '../../README.md')},
deployment: {title: 'Deployment', file: path.join(__dirname, '../../DEPLOYMENT.md')},
api: {title: 'API Reference', file: path.join(__dirname, '../../API.md')},
ldap: {title: 'LDAP', file: path.join(__dirname, '../../docs/ldap.md')},
oauth: {title: 'OAuth', file: path.join(__dirname, '../../docs/oauth.md')},
configuration: {title: 'Configuration', file: path.join(__dirname, '../../docs/configuration.md')},
'directory-spec': {title: 'Directory Spec (draft)', file: path.join(__dirname, '../../directory_spec.md')},
};
const docList = Object.entries(DOCS).map(([slug, d]) => ({slug, title: d.title}));
// README.md links its screenshots as repo-relative "docs/images/...", which
// only resolves correctly on GitHub. Serve that same folder here and rewrite
// the rendered markup to point at it absolutely, so the images work when
// read from /docs/overview too.
router.use('/images', require('express').static(path.join(__dirname, '../../docs/images')));
function fixImagePaths(html) {
return html.replace(/(["(])docs\/images\//g, '$1/docs/images/');
}
router.use(rateLimit.docs);
router.get('/', function(req, res) {
res.render('docs_index', {...values, docs: docList});
});
router.get('/:slug', function(req, res, next) {
const doc = DOCS[req.params.slug];
if (!doc) return next({status: 404, message: 'Doc not found'});
try {
const content = fs.readFileSync(doc.file, 'utf8');
res.render('docs_page', {
...values,
docs: docList,
currentSlug: req.params.slug,
docTitle: doc.title,
docHtml: fixImagePaths(marked(content)),
});
} catch (error) {
next(error);
}
});
module.exports = router;