2023-09-22 11:49:59 +02:00
|
|
|
"use strict";
|
|
|
|
const { randomBytes } = require("node:crypto");
|
2017-02-18 20:21:34 +01:00
|
|
|
|
|
|
|
module.exports = function (app) {
|
2023-09-22 11:49:59 +02:00
|
|
|
const projectsIssues = {};
|
|
|
|
const compulsoryFields = new Set(["issue_title", "issue_text", "created_by"]);
|
|
|
|
const optionalFields = new Set(["assigned_to", "status_text"]);
|
|
|
|
const updateFields = new Set([
|
|
|
|
"issue_title",
|
|
|
|
"issue_text",
|
|
|
|
"created_by",
|
|
|
|
"assigned_to",
|
|
|
|
"status_text",
|
|
|
|
]);
|
|
|
|
const queryFilters = new Set([
|
|
|
|
"_id",
|
|
|
|
"issue_title",
|
|
|
|
"issue_text",
|
|
|
|
"created_by",
|
|
|
|
"assigned_to",
|
|
|
|
"status_text",
|
|
|
|
"open",
|
|
|
|
]);
|
|
|
|
const autoGeneratedFields = new Map([
|
|
|
|
// FXIME: Not handling potential ID collisions
|
|
|
|
["_id", () => randomBytes(20).toString("hex")],
|
|
|
|
["created_on", () => new Date().toISOString()],
|
|
|
|
["updated_on", () => new Date().toISOString()],
|
|
|
|
["open", () => true],
|
|
|
|
]);
|
2017-02-18 20:21:34 +01:00
|
|
|
|
2023-09-22 11:49:59 +02:00
|
|
|
app
|
|
|
|
.route("/api/issues/:project")
|
|
|
|
|
|
|
|
.get(function (req, res) {
|
|
|
|
const project = req.params.project;
|
|
|
|
const issues = projectsIssues[project];
|
|
|
|
const filters = {};
|
|
|
|
for (const name of queryFilters) {
|
|
|
|
if (req.query[name])
|
|
|
|
filters[name] = Array.isArray(req.query[name])
|
|
|
|
? req.query[name][0]
|
|
|
|
: req.query[name];
|
|
|
|
}
|
|
|
|
if (!issues) res.status(404).json({ error: "Project not found" });
|
|
|
|
else
|
|
|
|
res.json(
|
|
|
|
Object.values(issues).filter((issue) =>
|
|
|
|
Object.entries(filters).every(([k, v]) => issue[k] === v)
|
|
|
|
)
|
|
|
|
);
|
2017-02-18 20:21:34 +01:00
|
|
|
})
|
2023-09-22 11:49:59 +02:00
|
|
|
|
|
|
|
.post(function (req, res) {
|
|
|
|
const project = req.params.project;
|
|
|
|
if (!project) {
|
|
|
|
res.status(400).json({ error: "Project not specified" });
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
const issue = {};
|
|
|
|
for (const name of compulsoryFields) {
|
|
|
|
if (!req.body[name]) {
|
|
|
|
res.status(400).json({ error: "required field(s) missing" });
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
issue[name] = req.body[name];
|
|
|
|
}
|
|
|
|
optionalFields.forEach((name) => (issue[name] = req.body[name] ?? ""));
|
|
|
|
autoGeneratedFields.forEach(
|
|
|
|
(generator, name) => (issue[name] = generator())
|
|
|
|
);
|
|
|
|
if (!projectsIssues[project])
|
|
|
|
projectsIssues[project] = { [issue._id]: { ...issue } };
|
|
|
|
else projectsIssues[project][issue._id] = { ...issue };
|
|
|
|
res.json(issue);
|
2017-02-18 20:21:34 +01:00
|
|
|
})
|
2023-09-22 11:49:59 +02:00
|
|
|
|
|
|
|
.put(function (req, res) {
|
|
|
|
const project = req.params.project;
|
|
|
|
if (!project) res.status(400).json({ error: "Project not specified" });
|
|
|
|
const _id = req.body._id;
|
|
|
|
const fields = {};
|
|
|
|
updateFields.forEach((name) => {
|
|
|
|
if (req.body[name]) fields[name] = req.body[name];
|
|
|
|
});
|
|
|
|
if (!_id) res.status(400).json({ error: "missing _id" });
|
|
|
|
else if (!projectsIssues[project][_id])
|
|
|
|
res.status(404).json({ error: "could not update", _id: _id });
|
|
|
|
else if (!Object.entries(fields).length)
|
|
|
|
res.status(400).json({ error: "no update field(s) sent", _id: _id });
|
|
|
|
else {
|
|
|
|
Object.entries(fields).forEach(
|
|
|
|
([name, value]) => (projectsIssues[project][_id][name] = value)
|
|
|
|
);
|
|
|
|
res.json({ result: "successfully updated", _id: _id });
|
|
|
|
}
|
2017-02-18 20:21:34 +01:00
|
|
|
})
|
2023-09-22 11:49:59 +02:00
|
|
|
|
|
|
|
.delete(function (req, res) {
|
|
|
|
const project = req.params.project;
|
|
|
|
if (!project) {
|
|
|
|
res.status(400).json({ error: "Project not specified" });
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
const _id = req.body._id;
|
|
|
|
if (!_id) res.status(400).json({ error: "missing _id" });
|
|
|
|
else if (!projectsIssues[project][_id])
|
|
|
|
res.status(404).json({ error: "could not delete", _id: _id });
|
|
|
|
else {
|
|
|
|
delete projectsIssues[project][_id];
|
|
|
|
res.json({ result: "successfully deleted", _id: _id });
|
|
|
|
}
|
2017-02-18 20:21:34 +01:00
|
|
|
});
|
|
|
|
};
|