Make Terms of Service editable at runtime by admins (closes #39)
tos.md was baked into the repo and read once at startup, so changing the terms required a code change and deploy. It's now a Redis-backed singleton (models/tos.js), editable from a new "Terms of Service" card on the admin Dashboard, with the bundled tos.md used only as a one-time seed for new deployments. - routes/tos.js: GET (any authenticated user) / PUT (app_sso_admin only) via /api/tos. Saving can optionally reset every user's tos_accepted flag so they're asked to re-accept -- off by default, since a wording fix shouldn't re-prompt everyone. - routes/index.js: /tos and /onboarding now render the live content instead of a module-level constant computed once at process start.
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
'use strict';
|
||||
|
||||
const router = require('express').Router();
|
||||
const {Tos} = require('../models/tos');
|
||||
const {UserVerification} = require('../models/verification');
|
||||
const permission = require('../utils/permission');
|
||||
|
||||
// Any authenticated user may read the current ToS (it's what they already
|
||||
// see on /tos and during onboarding, and it isn't sensitive) -- only saving
|
||||
// an edit is admin-gated.
|
||||
router.get('/', async function(req, res, next) {
|
||||
try {
|
||||
const tos = await Tos.getCurrent();
|
||||
return res.json(tos);
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
|
||||
router.put('/', async function(req, res, next) {
|
||||
try {
|
||||
await permission.byGroup(req.user, ['app_sso_admin']);
|
||||
|
||||
const {content, resetAcceptance} = req.body;
|
||||
if (!content || !content.trim()) {
|
||||
return res.status(400).json({name: 'ValidationError', message: 'content is required'});
|
||||
}
|
||||
|
||||
const tos = await Tos.getCurrent();
|
||||
await tos.update({content, updated_by: req.user.uid, updated_on: Date.now()});
|
||||
|
||||
// Opt-in: a substantive change may need everyone to agree again, but a
|
||||
// wording/typo fix shouldn't re-prompt every user, so this only runs
|
||||
// when the admin explicitly asks for it.
|
||||
let resetCount = 0;
|
||||
if (resetAcceptance) {
|
||||
const verifications = await UserVerification.listDetail();
|
||||
for (const v of verifications) {
|
||||
if (v.tos_accepted) {
|
||||
// Leave tos_accepted_at as the last acceptance time (a
|
||||
// historical fact) -- only the boolean flips, driving
|
||||
// onboardingNeeds back to including 'tos'.
|
||||
await v.update({tos_accepted: false});
|
||||
resetCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return res.json({results: tos, resetCount});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
Reference in New Issue
Block a user