diff --git a/server.js b/server.js index cf1216d..33b1df6 100644 --- a/server.js +++ b/server.js @@ -2,12 +2,12 @@ const express = require("express"); const app = express(); -const { loadConfig } = require("./src/utils/configManager"); +const configManager = require("./src/utils/configManager"); const { connectDatabase, initDatabase } = require('./src/database/index'); // --- Load configuration --- -const config = loadConfig(); +const config = configManager.loadConfig(); // --- Body parsing --- app.use(express.json()); // Necessary to parse JSON bodies @@ -15,6 +15,7 @@ app.use(express.json()); // Necessary to parse JSON bodies // Database connection (async () => { + // --- Database connection --- await connectDatabase(); await initDatabase(); @@ -23,6 +24,7 @@ app.use(express.json()); // Necessary to parse JSON bodies app.use("/", require("./src/routes/index")); app.use("/mods", require("./src/routes/mods")); app.use("/users", require("./src/routes/users")); + app.use("/list", require("./src/routes/list")); app.use("/login", require("./src/routes/login")); })(); @@ -30,7 +32,7 @@ app.use(express.json()); // Necessary to parse JSON bodies // --- Launch --- -const port = config.server.port; +const port = config.port; app.listen(port, () => { console.log("Server listening on port " + port + "..."); }) \ No newline at end of file diff --git a/src/controllers/auth.js b/src/controllers/auth.js index a96c813..0a55dde 100644 --- a/src/controllers/auth.js +++ b/src/controllers/auth.js @@ -6,7 +6,7 @@ async function login(req, res) { const token = await authService.login(req.body.username, req.body.password); res.json({ token }); } catch (err) { - handleError(err, req, res, null); + handleError(err, res); } } \ No newline at end of file diff --git a/src/controllers/mods.js b/src/controllers/mods.js index 63bc80c..d1f36dc 100644 --- a/src/controllers/mods.js +++ b/src/controllers/mods.js @@ -1,47 +1,68 @@ const handleError = require("../middleware/errors"); -const mod_service = require("../services/modService") +const mod_service = require("../services/modService"); +const { authorizeModModification, authenticateToken } = require("../middleware/auth"); -async function getAllMods(req, res) { +async function listMods(req, res) { try { - console.debug("Calling controller"); + // Query const query_result = await mod_service.getAllMods(); res.json(query_result); } catch (error) { - console.error("ERROR: Couldn't get mods: "); - handleError(error, req, res, null); - } -} - -async function getModByName(req, res) { - try { - const query_result = await mod_service.getModByName(req.params.name); - res.json(query_result); - } catch (error) { - console.error("ERROR: Couldn't get mod " + req.params.name + ": "); - handleError(error, req, res, null); + handleError(error, res); } } async function createMod(req, res) { try { - await mod_service.createMod(req.body); - res.sendStatus(200); + // Authenticate + await authenticateToken(req); + // Query + const mod_data = req.body; + const user = req.token_infos.username; + const query_result = await mod_service.createMod(mod_data, user); + res.json(query_result); } catch (error) { - console.error("ERROR: Couldn't create mod:", error.message); - handleError(error, req, res, null); + handleError(error, res); + } +} + +async function modifyMod(req, res) { + try { + // Authorize + authorizeModModification(req); + // Query + const mod_data = req.body; + const query_result = await mod_service.modifyMod(mod_data); + res.json(query_result); + } catch (error) { + handleError(error, res); + } +} + +async function getModByName(req, res) { + try { + // Query + const name = req.params.name + const query_result = await mod_service.getModByName(name); + res.json(query_result); + } catch (error) { + handleError(error, res); } } async function deleteMod(req, res) { try { - await mod_service.deleteMod(req.params.name); - return res.sendStatus(200); + // Authorize + authorizeModModification(req); + // Query + const name = req.params.name + const query_result = await mod_service.deleteMod(name); + res.json(query_result); } catch (error) { - console.error("ERROR: Couldn't delete mod " + req.params.name + ":", error.message); - handleError(error, req, res, null); + handleError(error, res); } } -module.exports = { getAllMods, getModByName, createMod, deleteMod }; \ No newline at end of file +module.exports = { listMods, getModByName, createMod, modifyMod, deleteMod }; \ No newline at end of file diff --git a/src/controllers/users.js b/src/controllers/users.js index 61bf0d0..71e475f 100644 --- a/src/controllers/users.js +++ b/src/controllers/users.js @@ -1,47 +1,63 @@ const handleError = require("../middleware/errors"); const user_service = require("../services/userService") +const { authorizeUserModification } = require("../middleware/auth"); -async function getAllUsers(req, res) { + +async function listUsers(req, res) { try { - console.debug("Calling controller"); + // Query const query_result = await user_service.getAllUsers(); res.json(query_result); } catch (error) { - console.error("ERROR: Couldn't get users: "); - handleError(error, req, res, null); + handleError(error, res); } } async function getUserByName(req, res) { try { + // Query const query_result = await user_service.getUserByName(req.params.name); res.json(query_result); } catch (error) { - console.error("ERROR: Couldn't get user " + req.params.name + ": "); - handleError(error, req, res, null); + handleError(error, res); } } async function createUser(req, res) { try { - await user_service.createUser(req.body); - res.sendStatus(200); + // Query + const query_result = await user_service.createUser(req.body); + res.json(query_result); } catch (error) { - console.error("ERROR: Couldn't create user:", error.message); - handleError(error, req, res, null); + handleError(error, res); + } +} + +async function modifyUser(req, res) { + try { + // Query + const diff_data = req.body; + const query_result = await user_service.modifyUser(diff_data); + res.json(query_result); + } catch (error) { + handleError(error, res); } } async function deleteUser(req, res) { try { - await user_service.deleteUser(req.params.name); - return res.sendStatus(200); + // Authenticate + await authorizeUserModification(req); + // Query + const user = req.params.name; + const token_user = req.token_infos + const query_result = await user_service.deleteUser(user, token_user); + return res.json(query_result); } catch (error) { - console.error("ERROR: Couldn't delete user " + req.params.name + ":", error.message); - handleError(error, req, res, null); + handleError(error, res); } } -module.exports = { getAllUsers, getUserByName, createUser, deleteUser }; \ No newline at end of file +module.exports = { listUsers, getUserByName, createUser, modifyUser, deleteUser }; \ No newline at end of file diff --git a/src/database/index.js b/src/database/index.js index bb70866..8c32752 100644 --- a/src/database/index.js +++ b/src/database/index.js @@ -10,12 +10,12 @@ async function connectDatabase() { const config = await getConfig(); // Choose database type - if (config.type === "mysql") { - db = new MySQLDatabase(config); - } else if (config.type === "sqlite") { - db = new SQLiteDatabase(config); + if (config.database.type === "mysql") { + db = new MySQLDatabase(config.database); + } else if (config.database.type === "sqlite") { + db = new SQLiteDatabase(config.database); } else { - throw new Error("Invalid database type: ", config.type); + throw new Error("Invalid database type: ", config.database.type); } // Connect @@ -40,8 +40,8 @@ async function initDatabase() { email TINYTEXT NOT NULL, password TINYTEXT NOT NULL, profile_picture LONGTEXT, - role TINYTEXT, NOT NULL, - settings LONGTEXT, + role TINYTEXT NOT NULL, + settings LONGTEXT );`); // --- Mods --- @@ -53,7 +53,7 @@ async function initDatabase() { author TINYTEXT NOT NULL, description TINYTEXT NOT NULL, - FOREIGN KEY author REFERENCES Users(username) + FOREIGN KEY (author) REFERENCES Users(username) );`); // Mods complementary infos @@ -66,7 +66,7 @@ async function initDatabase() { creation_date TINYTEXT NOT NULL, downloads_count INT NOT NULL, - FOREIGN KEY mod REFERENCES Users(username) + FOREIGN KEY (mod) REFERENCES Users(username) );`); // Mods tags @@ -74,7 +74,7 @@ async function initDatabase() { mod TINYTEXT NOT NULL, tag TINYTEXT NOT NULL, - FOREIGN KEY mod REFERENCES Mods(name) + FOREIGN KEY (mod) REFERENCES Mods(name) );`); // Mods versions @@ -89,7 +89,7 @@ async function initDatabase() { environment TINYTEXT NOT NULL, url TINYTEXT NOT NULL, - FOREGIN KEY mod REFERENCES Mods(name) + FOREIGN KEY (mod) REFERENCES Mods(name) );`); // User favorites (mods) @@ -97,8 +97,8 @@ async function initDatabase() { username TINYTEXT NOT NULL, mod TINYTEXT NOT NULL, - FOREIGN KEY username REFERENCES Users(username), - FOREGIN KEY mod REFERENCES Mods(name) + FOREIGN KEY (username) REFERENCES Users(username), + FOREIGN KEY (mod) REFERENCES Mods(name) );`); } diff --git a/src/middleware/auth.js b/src/middleware/auth.js index 8506166..ba0d1c8 100644 --- a/src/middleware/auth.js +++ b/src/middleware/auth.js @@ -19,6 +19,8 @@ async function authenticateToken(req) { } catch (err) { throw new AppError(403, "Forbidden: Error verifying the authorization token"); } + + return req.token_infos; } diff --git a/src/middleware/errors.js b/src/middleware/errors.js index cb55e59..34ecb1c 100644 --- a/src/middleware/errors.js +++ b/src/middleware/errors.js @@ -1,6 +1,6 @@ const AppError = require("../utils/appError"); -const handleError = (err, req, res, next) => { +const handleError = (err, res) => { // Send error infos if (err instanceof AppError) { diff --git a/src/models/index.js b/src/models/index.js index b5f3bfb..7b8c71c 100644 --- a/src/models/index.js +++ b/src/models/index.js @@ -1,8 +1,8 @@ -const { getVersion } = require("../utils/configManager"); +const configManager = require("../utils/configManager"); async function getVersion() { - const version = await getVersion(); + const version = await configManager.getVersion(); const res = { version: version }; diff --git a/src/models/mod.js b/src/models/mod.js index 0794436..98ee457 100644 --- a/src/models/mod.js +++ b/src/models/mod.js @@ -18,7 +18,7 @@ async function getModFullInfos(name) { // Query const base_infos = db.query(`SELECT * FROM Mods WHERE name = ?`, [name]); - const other_infos = db.query(`SELECT full_description, license, links, creation_date + const other_infos = db.query(`SELECT full_description, license, links, creation_date, downloads_count FROM ModInfos WHERE name = ?`, [name]); const tags = getModTags(name); @@ -28,7 +28,7 @@ async function getModFullInfos(name) { return res; } -async function getAllVersions(mod_name) { +async function listVersions(mod_name) { return await db.query("SELECT * FROM ModVersions WHERE mod = ?", [mod_name]); } @@ -162,7 +162,7 @@ async function updateModInfosAttribute(name, attribute, value) { return; } -async function ModExists(name) { +async function exists(name) { return db.exists("Mods", "name", name); } @@ -179,8 +179,8 @@ async function containsTag(name, tag) { // --- Exports --- -module.exports = { getAllMods, getModByName, getFullModInfos, - getAllModVersions, getVersionByNumber, getVersion, +module.exports = { getAllMods, getModByName, getModFullInfos, + listVersions, getVersionByNumber, getVersion, createMod, addVersion, addTags, updateMod, deleteMod, deleteVersion, deleteTags, diff --git a/src/routes/list.js b/src/routes/list.js new file mode 100644 index 0000000..2829954 --- /dev/null +++ b/src/routes/list.js @@ -0,0 +1,24 @@ +const express = require("express"); +const { listMods } = require("../controllers/mods"); +// const { listModpacks } = require("../controllers/modpacks"); +const { listUsers } = require("../controllers/users"); + +const router = express.Router(); + +// List mods +router.get("/mods", async (req,res) => { + listMods(req, res); +}); + +// List modpacks +// router.get("/modpacks", async (req,res) => { +// listModpacks(req, res); +// }); + +// List users +router.get("/users", async (req,res) => { + listUsers(req, res); +}); + + +module.exports = router; \ No newline at end of file diff --git a/src/routes/mods.js b/src/routes/mods.js index 3226f22..82c1e02 100644 --- a/src/routes/mods.js +++ b/src/routes/mods.js @@ -3,29 +3,23 @@ const controller = require("../controllers/mods"); const router = express.Router(); -// List mods -router.get("/", async (req,res) => { - console.debug("Accessing mods list"); - controller.getAllMods(req,res); -}); - // Create a mod router.post("/", async (req, res) => { - console.debug("Creating mod ", req.body.name); controller.createMod(req, res); }); +// Modify mod +router.put("/:name", async (req,res) => { + controller.modifyMod(req,res); +}); + // Get mod infos router.get("/:name", async (req,res) => { - const name = req.params.name; - console.debug("Accessing mod " + name) controller.getModByName(req, res); }); // Delete mod router.delete("/:name", async (req,res) => { - const name = req.params.name; - console.debug("Deleting mod " + name) controller.deleteMod(req, res); }); diff --git a/src/routes/users.js b/src/routes/users.js index 85a4d2d..16a0826 100644 --- a/src/routes/users.js +++ b/src/routes/users.js @@ -6,7 +6,7 @@ const router = express.Router(); // List users router.get("/", async (req,res) => { console.debug("Accessing users list"); - controller.getAllUsers(req,res); + controller.listUsers(req,res); }); // Create a user diff --git a/src/services/modService.js b/src/services/modService.js index 56b9a70..19b04dd 100644 --- a/src/services/modService.js +++ b/src/services/modService.js @@ -50,6 +50,8 @@ async function createMod(mod_data, author) { const { name, display_name, description, mod_infos } = mod_data; mod_infos.full_description = await mdToHtml(mod_infos.full_description); // Convert await sanitizeModData(mod_data); // Sanitize + //TODO + // mod_infos.creation_date = ... // Write changes to database model.createMod(name, display_name, author, description, mod_data); @@ -89,8 +91,8 @@ async function addTags(mod, tags) { await model.addTags(mod, tags); // Return - const { tags } = await model.getFullModInfos(mod); - return { "mod": mod, "tags": tags}; + const { tags:res } = await model.getFullModInfos(mod); + return { "mod": mod, "tags": res}; } @@ -109,6 +111,9 @@ async function deleteMod(name) { // Check existence const mod = await model.getModByName(name); + if (!mod) { + throw new AppError(404, "No was found with this name", "Not found") + } // Authorize // TODO move outside of this function @@ -137,13 +142,20 @@ async function deleteVersion(version_infos) { // Return return res; - - } -async function deleteTags(tags) { +async function deleteTags(mod, tags) { - // Check existence + // Validate (check existence) + //TODO + console.warn("Skipping validity checks for deleteTags"); + + // Wites changes to db + await model.deleteTags(mod, tags); + + // Return + const { tags:res } = await model.getFullModInfos(mod); + return { "mod": mod, "tags": res}; } module.exports = { getAllMods, getModByName, getFullModInfos, diff --git a/src/services/userService.js b/src/services/userService.js index 1eb2ca5..36fb406 100644 --- a/src/services/userService.js +++ b/src/services/userService.js @@ -27,16 +27,18 @@ async function createUser(user_data) { return; } -async function deleteUser(name) { +async function deleteUser(name, token_user) { // Check existence const exists = await model.exists(name); if (!exists) { - throw new AppError(404, "Not found: Cannot find user with this name"); + throw new AppError(404, "Cannot find user with this name", "Not found"); } // Check authenticity - //TODO no auth provider + if (name != token_user) { + throw new AppError(401, "", "Unauthorized"); + } model.deleteUser(name); return; diff --git a/src/utils/configManager.js b/src/utils/configManager.js index fdf9170..5862b59 100644 --- a/src/utils/configManager.js +++ b/src/utils/configManager.js @@ -15,7 +15,7 @@ let config = {}; // --- Default config --- -const defaault_config = { +const default_config = { "port": 8000,