bowler-chart/src/routes/kpis.routes.js

71 lines
2.6 KiB
JavaScript

'use strict';
const express = require('express');
const db = require('../../db');
const requireAuth = require('../middleware/requireAuth');
const verifyCsrf = require('../middleware/csrf');
const { ownerOfProject, projectIdOfKpi } = require('../middleware/requireOwnerOrAdmin');
const router = express.Router();
router.use(requireAuth);
const getKpi = db.prepare('SELECT * FROM kpis WHERE id = ?');
const insertKpi = db.prepare(
`INSERT INTO kpis (project_id, name, description, unit, goal_text, sort_order)
VALUES (@project_id, @name, @description, @unit, @goal_text, @sort_order)`
);
const nextSort = db.prepare(
'SELECT COALESCE(MAX(sort_order), -1) + 1 AS n FROM kpis WHERE project_id = ?'
);
// POST /api/kpis — body.project_id authorizes against the owning project.
router.post(
'/',
verifyCsrf,
ownerOfProject((req) => Number(req.body && req.body.project_id)),
(req, res) => {
const name = (req.body.name || '').trim();
if (!name) return res.status(400).json({ error: 'KPI name is required' });
const info = insertKpi.run({
project_id: req.project.id,
name,
description: (req.body.description || '').trim() || null,
unit: (req.body.unit || '').trim() || null,
goal_text: (req.body.goal_text || '').trim() || null,
sort_order: nextSort.get(req.project.id).n,
});
res.status(201).json({ kpi: getKpi.get(info.lastInsertRowid) });
}
);
// Authorize :id routes via the KPI's owning project.
const kpiProject = (req) => projectIdOfKpi(Number(req.params.id));
// PATCH /api/kpis/:id
router.patch('/:id', verifyCsrf, ownerOfProject(kpiProject), (req, res) => {
const id = Number(req.params.id);
const kpi = getKpi.get(id);
const { name, description, unit, goal_text, sort_order } = req.body || {};
const next = {
name: name !== undefined ? (name.trim() || kpi.name) : kpi.name,
description: description !== undefined ? (description || null) : kpi.description,
unit: unit !== undefined ? (unit || null) : kpi.unit,
goal_text: goal_text !== undefined ? (goal_text || null) : kpi.goal_text,
sort_order: sort_order !== undefined ? Number(sort_order) : kpi.sort_order,
id,
};
db.prepare(
`UPDATE kpis SET name=@name, description=@description, unit=@unit,
goal_text=@goal_text, sort_order=@sort_order WHERE id=@id`
).run(next);
res.json({ kpi: getKpi.get(id) });
});
// DELETE /api/kpis/:id (cascades to entries)
router.delete('/:id', verifyCsrf, ownerOfProject(kpiProject), (req, res) => {
db.prepare('DELETE FROM kpis WHERE id = ?').run(Number(req.params.id));
res.json({ ok: true });
});
module.exports = router;