feat: Delete mod enpoint is functional
feat: Sanitize, md converter and validate utilities feat: Ability to alidate, convert and sanitize CreateMod requests (still WIP)
This commit is contained in:
parent
36eeec2e6c
commit
480df977fb
11 changed files with 543 additions and 53 deletions
|
|
@ -24,13 +24,24 @@ async function getModByName(req, res) {
|
|||
|
||||
async function createMod(req, res) {
|
||||
try {
|
||||
const status = await mod_service.createMod(req.body);
|
||||
res.status(status);
|
||||
await mod_service.createMod(req.body);
|
||||
res.sendStatus(200);
|
||||
} catch (error) {
|
||||
console.error("Cannot create mod:", error.message);
|
||||
console.error("ERROR: Couldn't create mod:", error.message);
|
||||
handleError(error, req, res, null);
|
||||
}
|
||||
}
|
||||
|
||||
async function deleteMod(req, res) {
|
||||
try {
|
||||
await mod_service.deleteMod(req.params.name);
|
||||
return res.sendStatus(200);
|
||||
} catch (error) {
|
||||
console.error("ERROR: Couldn't delete mod " + req.params.name + ":", error.message);
|
||||
handleError(error, req, res, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module.exports = { getAllMods, getModByName, createMod };
|
||||
|
||||
module.exports = { getAllMods, getModByName, createMod, deleteMod };
|
||||
|
|
@ -1,4 +1,3 @@
|
|||
// TODO promisify
|
||||
const sqlite = require("better-sqlite3");
|
||||
|
||||
class SQLiteDatabase {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
const { getDatabase } = require('../database/index');
|
||||
const AppError = require('../utils/appError');
|
||||
const db = getDatabase();
|
||||
|
||||
async function getAllMods() {
|
||||
console.debug("Calling model");
|
||||
return db.query("SELECT * FROM mods");
|
||||
}
|
||||
|
||||
|
|
@ -26,25 +26,35 @@ async function exists(name) {
|
|||
return db.exists("mods", "Name", name);
|
||||
}
|
||||
|
||||
// --- WIP ---
|
||||
|
||||
async function createMod(mod_data) {
|
||||
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)");
|
||||
throw new Error("Not implemented");
|
||||
// const { name, description } = mod_data;
|
||||
// return db.query("INSERT INTO mods (name, description) VALUES (?, ?)", [name, description]);
|
||||
const { name, displayName, author, versions, otherInfos } = mod_data;
|
||||
const { description, links, tags, screenshots, license, changelogs, counts } = otherInfos;
|
||||
|
||||
await db.prepare("INSERT INTO mods (Name, DisplayName, Author, Versions) \
|
||||
VALUES (?, ?, ?, ?)", [name, displayName, author, versions]);
|
||||
// db.prepare("INSERT INTO modsDescription (Name, Description, Links, Tags, Screenshots, License, Changelogs, Counts) \
|
||||
// VALUES (?, ?, ?, ?, ?, ?, ?, ?)", [name, description, links, tags, screenshots, license, changelogs, counts]);
|
||||
return;
|
||||
}
|
||||
|
||||
async function deleteMod(name) {
|
||||
console.log("WARNING: using a WIP function : deleteMod (models/mods.js)");
|
||||
return db.query("DELETE FROM mods WHERE name = ?", [name]);
|
||||
db.prepare("DELETE FROM mods WHERE Name = ?", [name]);
|
||||
// db.prepare("DELETE FROM modsDescription WHERE Name = ?", [name]);
|
||||
return;
|
||||
}
|
||||
|
||||
// --- WIP ---
|
||||
|
||||
async function updateMod(mod_data) {
|
||||
console.log("WARNING: using a WIP function : updateMod (models/mods.js)");
|
||||
throw new AppError(501, "Not implemented");
|
||||
// const { name, description } = mod_data;
|
||||
// return db.query("INSERT INTO mods (name, description) VALUES (?, ?)", [name, description]);
|
||||
}
|
||||
|
||||
|
||||
module.exports = { getAllMods, getModByName, createMod, exists }
|
||||
|
||||
|
||||
module.exports = { getAllMods, getModByName, createMod, deleteMod, exists }
|
||||
|
|
@ -22,4 +22,12 @@ router.get("/:name", async (req,res) => {
|
|||
controller.getModByName(req, res);
|
||||
});
|
||||
|
||||
//
|
||||
router.delete("/:name", async (req,res) => {
|
||||
const name = req.params.name;
|
||||
console.debug("Deleting mod " + name)
|
||||
controller.deleteMod(req, res);
|
||||
});
|
||||
|
||||
|
||||
module.exports = router;
|
||||
|
|
@ -1,7 +1,8 @@
|
|||
const handleError = require("../middleware/errors");
|
||||
const model = require("../models/mod");
|
||||
const AppError = require("../utils/appError");
|
||||
const { validateModData } = require("../utils/validation");
|
||||
const { validateModData } = require("../utils/validate");
|
||||
const { mdToHtml } = require("../utils/convert");
|
||||
const { sanitizeModData } = require("../utils/sanitize");
|
||||
|
||||
async function getAllMods() {
|
||||
return model.getAllMods();
|
||||
|
|
@ -11,10 +12,7 @@ async function getModByName(name) {
|
|||
return model.getModByName(name);
|
||||
}
|
||||
|
||||
async function createMod(mod_data) {
|
||||
// throw new AppError(501, "Not implemented");
|
||||
|
||||
// console.debug("Received body: ", JSON.stringify(mod_data));
|
||||
async function createMod(mod_data) {
|
||||
|
||||
// Check body validity
|
||||
await validateModData(mod_data);
|
||||
|
|
@ -22,8 +20,33 @@ async function createMod(mod_data) {
|
|||
// Check authenticity
|
||||
//TODO no auth provider
|
||||
|
||||
// Convert
|
||||
mod_data.otherInfos.description = await mdToHtml(mod_data.otherInfos.description);
|
||||
mod_data.otherInfos.changelogs = await mdToHtml(mod_data.otherInfos.changelogs);
|
||||
|
||||
// Sanitize
|
||||
await sanitizeModData(mod_data);
|
||||
|
||||
|
||||
|
||||
console.debug("Passed validity checks");
|
||||
return model.createMod(mod_data);
|
||||
model.createMod(mod_data);
|
||||
return;
|
||||
}
|
||||
|
||||
module.exports = { getAllMods, getModByName, createMod };
|
||||
async function deleteMod(name) {
|
||||
|
||||
// Check existence
|
||||
const exists = await model.exists(name);
|
||||
if (!exists) {
|
||||
throw new AppError(404, "Not found: Cannot find mod with this name");
|
||||
}
|
||||
|
||||
// Check authenticity
|
||||
//TODO no auth provider
|
||||
|
||||
model.deleteMod(name);
|
||||
return;
|
||||
}
|
||||
|
||||
module.exports = { getAllMods, getModByName, createMod, deleteMod };
|
||||
11
src/utils/convert.js
Normal file
11
src/utils/convert.js
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
const marked = require("marked");
|
||||
|
||||
async function mdToHtml(md_content) {
|
||||
if (md_content) {
|
||||
return marked.parse(md_content);
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { mdToHtml };
|
||||
18
src/utils/sanitize.js
Normal file
18
src/utils/sanitize.js
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
const createDOMPurify = require("dompurify");
|
||||
const { JSDOM } = require("jsdom");
|
||||
|
||||
// Initialize
|
||||
const window = new JSDOM("").window;
|
||||
const DOMPurify = createDOMPurify(window);
|
||||
|
||||
async function sanitizeText(text) {
|
||||
return DOMPurify.sanitize(text);
|
||||
}
|
||||
|
||||
async function sanitizeModData(mod_data) {
|
||||
mod_data.displayName = await sanitizeText(mod_data.displayName);
|
||||
mod_data.otherInfos.description = await sanitizeText(mod_data.otherInfos.description);
|
||||
mod_data.otherInfos.changelogs = await sanitizeText(mod_data.otherInfos.changelogs);
|
||||
}
|
||||
|
||||
module.exports = { sanitizeText, sanitizeModData };
|
||||
49
src/utils/validate.js
Normal file
49
src/utils/validate.js
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
const mod_model = require("../models/mod");
|
||||
const AppError = require("./appError");
|
||||
|
||||
async function validateModData(mod_data) {
|
||||
//TODO WIP
|
||||
// Check fields existence
|
||||
const not_null = mod_data &&
|
||||
Object.keys(mod_data).length == 5 &&
|
||||
mod_data.name &&
|
||||
mod_data.displayName &&
|
||||
mod_data.author &&
|
||||
mod_data.versions != null;
|
||||
|
||||
// mod_data.otherInfos != null &&
|
||||
// Object.keys(mod_data.otherInfos).length == 0 &&
|
||||
// mod_data.otherInfos.description != null &&
|
||||
// mod_data.otherInfos.links != null &&
|
||||
// mod_data.otherInfos.tags != null &&
|
||||
// mod_data.otherInfos.screenshots != null &&
|
||||
// mod_data.otherInfos.license != null &&
|
||||
// mod_data.otherInfos.changelogs != null;
|
||||
|
||||
if (!not_null) {
|
||||
console.debug("Item is missing expected fields:", mod_data);
|
||||
throw new AppError(400, "Bad request: missing expected fields");
|
||||
}
|
||||
|
||||
// Check fields format (check if sanitized)
|
||||
const is_valid_name = /^[a-zA-Z0-9_]+$/.test(mod_data.name);
|
||||
const is_valid_displayName = true;
|
||||
// const is_valid_displayName = /^[a-zA-Z0-9_]+$/.test(mod_data.name); // Temporary
|
||||
// const
|
||||
|
||||
const is_valid = is_valid_name && is_valid_displayName;
|
||||
if (!is_valid) {
|
||||
console.debug("Fields are not following the expected formats");
|
||||
throw new AppError(400, "Bad request: The provided fields don't match the expected format");
|
||||
}
|
||||
|
||||
// Check if mod already exists
|
||||
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 }
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
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 }
|
||||
Loading…
Add table
Add a link
Reference in a new issue