diff --git a/server/src/router/v1/admin/admin.routes.js b/server/src/router/v1/admin/admin.routes.js index bf31ec9..5e774d6 100644 --- a/server/src/router/v1/admin/admin.routes.js +++ b/server/src/router/v1/admin/admin.routes.js @@ -5,7 +5,7 @@ const multer = require('multer') const { body, param } = require('express-validator') const ctrl = require('./admin.controller') -const { isLoggedIn } = require('../../../utils/auth') +const { isLoggedIn, requireRole } = require('../../../utils/auth') const noindex = require('../../../middleware/noindex') const validate = require('../../../middleware/validate') @@ -14,6 +14,10 @@ const adminRouter = express.Router() // Every admin route requires auth and is kept out of search indexes. adminRouter.use(noindex, isLoggedIn) +// Admin-only gate. Editors may manage content (posts/wiki), but user +// management, site mode, and settings are restricted to the admin role. +const adminOnly = requireRole('admin') + // ── Image uploads (screenshots/gallery) ─────────────────────────────── const UPLOAD_DIR = process.env.UPLOAD_DIR || path.join(__dirname, '..', '..', '..', '..', 'uploads') @@ -39,6 +43,7 @@ const upload = multer({ adminRouter.get('/dashboard', ctrl.dashboard) adminRouter.put( '/site-mode', + adminOnly, body('mode').isIn(['live', 'maintenance']), validate, ctrl.setSiteMode, @@ -135,13 +140,14 @@ adminRouter.post( adminRouter.delete('/wiki/:slug', ctrl.deleteWiki) // ── Settings ────────────────────────────────────────────────────────── -adminRouter.get('/settings', ctrl.getSettings) -adminRouter.put('/settings', ctrl.updateSettings) +adminRouter.get('/settings', adminOnly, ctrl.getSettings) +adminRouter.put('/settings', adminOnly, ctrl.updateSettings) // ── Activity log ────────────────────────────────────────────────────── adminRouter.get('/activity', ctrl.listActivity) -// ── User management ─────────────────────────────────────────────────── +// ── User management (admin only) ────────────────────────────────────── +adminRouter.use('/users', adminOnly) adminRouter.get('/users', ctrl.listUsers) adminRouter.post( '/users', diff --git a/server/src/utils/auth.js b/server/src/utils/auth.js index 327e291..bb29e4d 100644 --- a/server/src/utils/auth.js +++ b/server/src/utils/auth.js @@ -85,6 +85,16 @@ function isLoggedIn(req, res, next) { return next() } +// Gate middleware factory: allow only the listed roles. Assumes isLoggedIn ran +// first so req.user is populated. Use for admin-only endpoints (users, site +// mode, settings) so a lower-privilege editor cannot reach them. +function requireRole(...roles) { + return (req, res, next) => { + if (roles.includes(req.user?.role)) return next() + return res.status(403).json({ message: 'Forbidden' }) + } +} + module.exports = { COOKIE_NAME, signToken, @@ -93,4 +103,5 @@ module.exports = { clearAuthCookie, getUserFromRequest, isLoggedIn, + requireRole, }