From e4e6958ff981eece42e8f89a89f7438da4281cef Mon Sep 17 00:00:00 2001 From: jtricerolph Date: Mon, 13 Jul 2026 09:24:55 +0000 Subject: [PATCH] Gate planner config write endpoints with requireCap('planner') MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Six PUT /api/config/* routes were missing per-route capability checks — any authenticated hk-planner user could modify staff, time requirements, pickup data, tasks, adjustments, and last-reviewed regardless of their cap. Co-Authored-By: Claude Sonnet 4.6 --- backend/src/routes/config.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/backend/src/routes/config.js b/backend/src/routes/config.js index 461b348..d6d40ae 100644 --- a/backend/src/routes/config.js +++ b/backend/src/routes/config.js @@ -42,7 +42,7 @@ export async function configRoutes(app) { // ── PUT /api/config/time-requirements ──────────────────────────────────── - app.put('/api/config/time-requirements', async (req, reply) => { + app.put('/api/config/time-requirements', { preHandler: requireCap('planner') }, async (req, reply) => { const { cat, action, value } = req.body || {} if (!cat || !['depart', 'stay', 'arrive'].includes(action)) { return reply.status(400).send({ error: 'Invalid data' }) @@ -57,7 +57,7 @@ export async function configRoutes(app) { // ── PUT /api/config/staff ───────────────────────────────────────────────── - app.put('/api/config/staff', async (req, reply) => { + app.put('/api/config/staff', { preHandler: requireCap('planner') }, async (req, reply) => { const { staff_data } = req.body || {} if (!Array.isArray(staff_data)) return reply.status(400).send({ error: 'Invalid data' }) @@ -76,7 +76,7 @@ export async function configRoutes(app) { // ── PUT /api/config/pickup ──────────────────────────────────────────────── - app.put('/api/config/pickup', async (req, reply) => { + app.put('/api/config/pickup', { preHandler: requireCap('planner') }, async (req, reply) => { const { pickup_data } = req.body || {} if (!pickup_data || typeof pickup_data !== 'object') { return reply.status(400).send({ error: 'Invalid data' }) @@ -100,7 +100,7 @@ export async function configRoutes(app) { // ── PUT /api/config/general-tasks ──────────────────────────────────────── - app.put('/api/config/general-tasks', async (req, reply) => { + app.put('/api/config/general-tasks', { preHandler: requireCap('planner') }, async (req, reply) => { const { general_tasks } = req.body || {} if (!Array.isArray(general_tasks)) return reply.status(400).send({ error: 'Invalid data' }) @@ -118,7 +118,7 @@ export async function configRoutes(app) { // ── PUT /api/config/last-reviewed ──────────────────────────────────────── - app.put('/api/config/last-reviewed', async (req, reply) => { + app.put('/api/config/last-reviewed', { preHandler: requireCap('planner') }, async (req, reply) => { const { date } = req.body || {} if (!date || !/^\d{4}-\d{2}-\d{2}$/.test(date)) { return reply.status(400).send({ error: 'Invalid date' }) @@ -142,7 +142,7 @@ export async function configRoutes(app) { // ── PUT /api/config/adjustments ────────────────────────────────────────── - app.put('/api/config/adjustments', async (req, reply) => { + app.put('/api/config/adjustments', { preHandler: requireCap('planner') }, async (req, reply) => { const { adjustments } = req.body || {} if (!Array.isArray(adjustments)) return reply.status(400).send({ error: 'Invalid data' })