diff --git a/server.js b/server.js index b9c37b6..404c877 100644 --- a/server.js +++ b/server.js @@ -39,15 +39,16 @@ console.debug("Port: ", port); db = connectDatabase(config.database); db = initDatabase(config); +// -- Usings --- + +app.use(handleError); // Error handling +app.use(express.json()); // Request body handling + // --- Routing --- app.use("/", require("./src/routes/index")); app.use("/mods", require("./src/routes/mods")); -// -- Error handling --- - -app.use(handleError); - // --- Launch --- app.listen(port, () => { diff --git a/src/controllers/mods.js b/src/controllers/mods.js index 73923c5..33cd5f5 100644 --- a/src/controllers/mods.js +++ b/src/controllers/mods.js @@ -1,27 +1,36 @@ +const handleError = require("../middleware/errors"); const mod_service = require("../services/modService") async function getAllMods(req, res) { try { console.debug("Calling controller"); const query_result = await mod_service.getAllMods(); - console.debug("Controller OK"); res.json(query_result); } catch (error) { - console.debug("Error at controller"); - res.status(500).json({ error: error.message }); + console.error("ERROR: Couldn't get mods: "); + handleError(error, req, res, null); } } async function getModByName(req, res) { try { - console.debug("Calling controller"); const query_result = await mod_service.getModByName(req.params.name); res.json(query_result); } catch (error) { - console.debug("Error at controller"); - res.status(500).json({ error: error.message }); + console.error("ERROR: Couldn't get mod " + req.params.name + ": "); + 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 }; \ No newline at end of file +module.exports = { getAllMods, getModByName, createMod }; \ No newline at end of file diff --git a/src/database/sqlite.js b/src/database/sqlite.js index 2267d7b..5e40299 100644 --- a/src/database/sqlite.js +++ b/src/database/sqlite.js @@ -46,9 +46,13 @@ class SQLiteDatabase { } - async prepare(sql) { + async prepare(sql, params = []) { try { - return this.db.prepare(sql); + if (params.length > 0) { + return this.db.prepare(sql).run(params); + } else { + return this.db.prepare(sql); + } } catch (err) { console.error("Error executing prepared statement:", err)} } diff --git a/src/middleware/errors.js b/src/middleware/errors.js index 4d416b4..cb55e59 100644 --- a/src/middleware/errors.js +++ b/src/middleware/errors.js @@ -1,11 +1,12 @@ -const AppError = require("../utils/AppError"); +const AppError = require("../utils/appError"); const handleError = (err, req, res, next) => { - // Send + + // Send error infos if (err instanceof AppError) { return res.status(err.statusCode).json({ - message: err.message, - status: err.status + status: err.status, + message: err.message }); } diff --git a/src/models/mod.js b/src/models/mod.js index 44908ea..1e3e83b 100644 --- a/src/models/mod.js +++ b/src/models/mod.js @@ -17,30 +17,34 @@ async function getModByName(name) { } } catch (err) { console.error("Error in getModByName:", err); - throw error; + throw err; } } +async function exists(name) { + return db.exists("mods", "Name", name); +} + // --- WIP --- async function createMod(mod_data) { - console.log("WARNING: using a WIP function : createMod (models/mods.js)") - const { name, description } = mod_data; - return db.query("INSERT INTO mods (name, description) VALUES (?, ?)", [name, description]); + console.warn("WARNING: using a WIP function : createMod (models/mods.js)"); + const { name, displayName, author, versions, otherInfos } = mod_data; + return db.prepare("INSERT INTO mods (Name, DisplayName, Author, Versions, OtherInfos) VALUES (?, ?, ?, ?, ?)", [name, displayName, author, versions, otherInfos]); } 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"); // const { name, description } = mod_data; // return db.query("INSERT INTO mods (name, description) VALUES (?, ?)", [name, description]); } 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]); } -module.exports = { getAllMods, getModByName } \ No newline at end of file +module.exports = { getAllMods, getModByName, createMod, exists } \ No newline at end of file diff --git a/src/routes/mods.js b/src/routes/mods.js index 3d57ad6..f62e531 100644 --- a/src/routes/mods.js +++ b/src/routes/mods.js @@ -9,10 +9,17 @@ router.get("/", async (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) => { const name = req.params.name; console.debug("Accessing mod " + name) controller.getModByName(req, res); -}) +}); module.exports = router; \ No newline at end of file diff --git a/src/routes/users.js b/src/routes/users.js new file mode 100644 index 0000000..e69de29 diff --git a/src/services/modService.js b/src/services/modService.js index 3f69155..a960367 100644 --- a/src/services/modService.js +++ b/src/services/modService.js @@ -1,13 +1,29 @@ +const handleError = require("../middleware/errors"); const model = require("../models/mod"); +const AppError = require("../utils/appError"); +const { validateModData } = require("../utils/validation"); async function getAllMods() { - console.debug("Calling service"); return model.getAllMods(); } async function getModByName(name) { - console.debug("Calling service"); return model.getModByName(name); } -module.exports = { getAllMods, getModByName }; \ No newline at end of file +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 }; \ No newline at end of file diff --git a/src/utils/AppError.js b/src/utils/appError.js similarity index 74% rename from src/utils/AppError.js rename to src/utils/appError.js index f50f4c9..bf37a85 100644 --- a/src/utils/AppError.js +++ b/src/utils/appError.js @@ -3,10 +3,10 @@ class AppError extends Error { super(message); this.statusCode = statusCode; - if (status_code.ToString().startsWith("4")) { - this.status = "fail"; + if (statusCode.toString().startsWith("4")) { + this.status = "Fail"; } else { - this.status = "error"; + this.status = "Error"; } } } diff --git a/src/utils/validation.js b/src/utils/validation.js new file mode 100644 index 0000000..0e9bdda --- /dev/null +++ b/src/utils/validation.js @@ -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 } \ No newline at end of file