feat: functional POST / endpoint (createMod)

This commit is contained in:
Gu://em_ 2025-03-30 17:31:21 +02:00
parent c0dff6df38
commit 36eeec2e6c
10 changed files with 99 additions and 31 deletions

View file

@ -39,15 +39,16 @@ console.debug("Port: ", port);
db = connectDatabase(config.database); db = connectDatabase(config.database);
db = initDatabase(config); db = initDatabase(config);
// -- Usings ---
app.use(handleError); // Error handling
app.use(express.json()); // Request body handling
// --- Routing --- // --- Routing ---
app.use("/", require("./src/routes/index")); app.use("/", require("./src/routes/index"));
app.use("/mods", require("./src/routes/mods")); app.use("/mods", require("./src/routes/mods"));
// -- Error handling ---
app.use(handleError);
// --- Launch --- // --- Launch ---
app.listen(port, () => { app.listen(port, () => {

View file

@ -1,27 +1,36 @@
const handleError = require("../middleware/errors");
const mod_service = require("../services/modService") const mod_service = require("../services/modService")
async function getAllMods(req, res) { async function getAllMods(req, res) {
try { try {
console.debug("Calling controller"); console.debug("Calling controller");
const query_result = await mod_service.getAllMods(); const query_result = await mod_service.getAllMods();
console.debug("Controller OK");
res.json(query_result); res.json(query_result);
} catch (error) { } catch (error) {
console.debug("Error at controller"); console.error("ERROR: Couldn't get mods: ");
res.status(500).json({ error: error.message }); handleError(error, req, res, null);
} }
} }
async function getModByName(req, res) { async function getModByName(req, res) {
try { try {
console.debug("Calling controller");
const query_result = await mod_service.getModByName(req.params.name); const query_result = await mod_service.getModByName(req.params.name);
res.json(query_result); res.json(query_result);
} catch (error) { } catch (error) {
console.debug("Error at controller"); console.error("ERROR: Couldn't get mod " + req.params.name + ": ");
res.status(500).json({ error: error.message }); handleError(error, req, res, null);
}
}
async function createMod(req, res) {
try {
const status = await mod_service.createMod(req.body);
res.status(status);
} catch (error) {
console.error("Cannot create mod:", error.message);
handleError(error, req, res, null);
} }
} }
module.exports = { getAllMods, getModByName }; module.exports = { getAllMods, getModByName, createMod };

View file

@ -46,9 +46,13 @@ class SQLiteDatabase {
} }
async prepare(sql) { async prepare(sql, params = []) {
try { try {
if (params.length > 0) {
return this.db.prepare(sql).run(params);
} else {
return this.db.prepare(sql); return this.db.prepare(sql);
}
} catch (err) { } catch (err) {
console.error("Error executing prepared statement:", err)} console.error("Error executing prepared statement:", err)}
} }

View file

@ -1,11 +1,12 @@
const AppError = require("../utils/AppError"); const AppError = require("../utils/appError");
const handleError = (err, req, res, next) => { const handleError = (err, req, res, next) => {
// Send
// Send error infos
if (err instanceof AppError) { if (err instanceof AppError) {
return res.status(err.statusCode).json({ return res.status(err.statusCode).json({
message: err.message, status: err.status,
status: err.status message: err.message
}); });
} }

View file

@ -17,30 +17,34 @@ async function getModByName(name) {
} }
} catch (err) { } catch (err) {
console.error("Error in getModByName:", err); console.error("Error in getModByName:", err);
throw error; throw err;
} }
} }
async function exists(name) {
return db.exists("mods", "Name", name);
}
// --- WIP --- // --- WIP ---
async function createMod(mod_data) { async function createMod(mod_data) {
console.log("WARNING: using a WIP function : createMod (models/mods.js)") console.warn("WARNING: using a WIP function : createMod (models/mods.js)");
const { name, description } = mod_data; const { name, displayName, author, versions, otherInfos } = mod_data;
return db.query("INSERT INTO mods (name, description) VALUES (?, ?)", [name, description]); return db.prepare("INSERT INTO mods (Name, DisplayName, Author, Versions, OtherInfos) VALUES (?, ?, ?, ?, ?)", [name, displayName, author, versions, otherInfos]);
} }
async function updateMod(mod_data) { async function updateMod(mod_data) {
console.log("WARNING: using a WIP function : updateMod (models/mods.js)") console.log("WARNING: using a WIP function : updateMod (models/mods.js)");
throw new Error("Not implemented"); throw new Error("Not implemented");
// const { name, description } = mod_data; // const { name, description } = mod_data;
// return db.query("INSERT INTO mods (name, description) VALUES (?, ?)", [name, description]); // return db.query("INSERT INTO mods (name, description) VALUES (?, ?)", [name, description]);
} }
async function deleteMod(name) { async function deleteMod(name) {
console.log("WARNING: using a WIP function : deleteMod (models/mods.js)") console.log("WARNING: using a WIP function : deleteMod (models/mods.js)");
return db.query("DELETE FROM mods WHERE name = ?", [name]); return db.query("DELETE FROM mods WHERE name = ?", [name]);
} }
module.exports = { getAllMods, getModByName } module.exports = { getAllMods, getModByName, createMod, exists }

View file

@ -9,10 +9,17 @@ router.get("/", async (req,res) => {
controller.getAllMods(req,res); controller.getAllMods(req,res);
}); });
// Create a mod
router.post("/", async (req, res) => {
console.debug("Creating mod ", req.body.name);
controller.createMod(req, res);
})
//
router.get("/:name", async (req,res) => { router.get("/:name", async (req,res) => {
const name = req.params.name; const name = req.params.name;
console.debug("Accessing mod " + name) console.debug("Accessing mod " + name)
controller.getModByName(req, res); controller.getModByName(req, res);
}) });
module.exports = router; module.exports = router;

0
src/routes/users.js Normal file
View file

View file

@ -1,13 +1,29 @@
const handleError = require("../middleware/errors");
const model = require("../models/mod"); const model = require("../models/mod");
const AppError = require("../utils/appError");
const { validateModData } = require("../utils/validation");
async function getAllMods() { async function getAllMods() {
console.debug("Calling service");
return model.getAllMods(); return model.getAllMods();
} }
async function getModByName(name) { async function getModByName(name) {
console.debug("Calling service");
return model.getModByName(name); return model.getModByName(name);
} }
module.exports = { getAllMods, getModByName }; async function createMod(mod_data) {
// throw new AppError(501, "Not implemented");
// console.debug("Received body: ", JSON.stringify(mod_data));
// Check body validity
await validateModData(mod_data);
// Check authenticity
//TODO no auth provider
console.debug("Passed validity checks");
return model.createMod(mod_data);
}
module.exports = { getAllMods, getModByName, createMod };

View file

@ -3,10 +3,10 @@ class AppError extends Error {
super(message); super(message);
this.statusCode = statusCode; this.statusCode = statusCode;
if (status_code.ToString().startsWith("4")) { if (statusCode.toString().startsWith("4")) {
this.status = "fail"; this.status = "Fail";
} else { } else {
this.status = "error"; this.status = "Error";
} }
} }
} }

26
src/utils/validation.js Normal file
View file

@ -0,0 +1,26 @@
const mod_model = require("../models/mod");
const AppError = require("./appError");
async function validateModData(mod_data) {
// WIP
const not_null = mod_data != null;
mod_data.name &&
mod_data.displayName &&
mod_data.author &&
mod_data.versions &&
mod_data.otherInfos;
if (!not_null) {
console.debug("Item is missing expected fields:", mod_data);
throw new AppError(400, "Bad request: missing expected fields");
}
const exists = await mod_model.exists(mod_data.name);
if (exists) {
console.debug("Error: Item already exists");
throw new AppError(403, "Forbidden: Content with this name already exists");
}
}
module.exports = { validateModData }