// FILE: backend/src/routes/projects.js import { Router } from "express"; import sql from "../db/index.js"; import { requirePerm } from "../middleware/requirePerm.js"; const r = Router(); // LIST — ORG scope r.get( "/", requirePerm("projects.view", { orgParam: "org_id" }), async (req, res) => { const p = req.principal; const { org_id } = req.query; const params = []; const cond = []; if (!p.is_superadmin) { if (org_id) { if (!p.inOrg(Number(org_id))) return res.status(403).json({ error: "FORBIDDEN_ORG" }); cond.push("p.org_id=?"); params.push(Number(org_id)); } else if (p.org_ids?.length) { cond.push(`p.org_id IN (${p.org_ids.map(() => "?").join(",")})`); params.push(...p.org_ids); } } else if (org_id) { cond.push("p.org_id=?"); params.push(Number(org_id)); } const where = cond.length ? `WHERE ${cond.join(" AND ")}` : ""; const [rows] = await sql.query( `SELECT p.* FROM projects p ${where} ORDER BY p.project_name`, params ); res.json(rows); } ); // GET — PROJECT scope r.get( "/:id", requirePerm("projects.view", { orgParam: "org_id" }), async (req, res) => { const id = Number(req.params.id); const [[row]] = await sql.query( "SELECT * FROM projects WHERE project_id=?", [id] ); if (!row) return res.status(404).json({ error: "Not found" }); const p = req.principal; if (!p.is_superadmin && !p.inOrg(row.org_id)) return res.status(403).json({ error: "FORBIDDEN_ORG" }); res.json(row); } ); // CREATE — ORG scope r.post( "/", requirePerm("projects.manage", { orgParam: "org_id" }), async (req, res) => { const { org_id, project_code, project_name } = req.body || {}; if (!org_id || !project_code || !project_name) { return res .status(400) .json({ error: "org_id, project_code, project_name required" }); } const [rs] = await sql.query( "INSERT INTO projects (org_id, project_code, project_name, created_by) VALUES (?,?,?,?)", [Number(org_id), project_code, project_name, req.principal.user_id] ); res.status(201).json({ project_id: rs.insertId }); } ); // UPDATE — ORG scope r.put( "/:id", requirePerm("projects.manage", { orgParam: "org_id" }), async (req, res) => { const id = Number(req.params.id); const [[row]] = await sql.query( "SELECT * FROM projects WHERE project_id=?", [id] ); if (!row) return res.status(404).json({ error: "Not found" }); const p = req.principal; if (!p.is_superadmin && !p.inOrg(row.org_id)) return res.status(403).json({ error: "FORBIDDEN_ORG" }); const { project_name } = req.body || {}; await sql.query( "UPDATE projects SET project_name=?, updated_by=? WHERE project_id=?", [project_name ?? row.project_name, req.principal.user_id, id] ); res.json({ ok: 1 }); } ); // DELETE — ORG scope r.delete( "/:id", requirePerm("projects.manage", { orgParam: "org_id" }), async (req, res) => { const id = Number(req.params.id); const [[row]] = await sql.query( "SELECT * FROM projects WHERE project_id=?", [id] ); if (!row) return res.status(404).json({ error: "Not found" }); const p = req.principal; if (!p.is_superadmin && !p.inOrg(row.org_id)) return res.status(403).json({ error: "FORBIDDEN_ORG" }); await sql.query("DELETE FROM projects WHERE project_id=?", [id]); res.json({ ok: 1 }); } ); export default r;