125 lines
3.5 KiB
JavaScript
125 lines
3.5 KiB
JavaScript
// 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;
|