Fixed all database CREATE queries, made all controllers and routes files, and many various fixes

This commit is contained in:
Gu://em_ 2025-05-04 19:31:03 +02:00
parent ff33af92b7
commit ca080b3e59
15 changed files with 159 additions and 86 deletions

View file

@ -2,12 +2,12 @@
const express = require("express"); const express = require("express");
const app = express(); const app = express();
const { loadConfig } = require("./src/utils/configManager"); const configManager = require("./src/utils/configManager");
const { connectDatabase, initDatabase } = require('./src/database/index'); const { connectDatabase, initDatabase } = require('./src/database/index');
// --- Load configuration --- // --- Load configuration ---
const config = loadConfig(); const config = configManager.loadConfig();
// --- Body parsing --- // --- Body parsing ---
app.use(express.json()); // Necessary to parse JSON bodies app.use(express.json()); // Necessary to parse JSON bodies
@ -15,6 +15,7 @@ app.use(express.json()); // Necessary to parse JSON bodies
// Database connection // Database connection
(async () => { (async () => {
// --- Database connection --- // --- Database connection ---
await connectDatabase(); await connectDatabase();
await initDatabase(); await initDatabase();
@ -23,6 +24,7 @@ app.use(express.json()); // Necessary to parse JSON bodies
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"));
app.use("/users", require("./src/routes/users")); app.use("/users", require("./src/routes/users"));
app.use("/list", require("./src/routes/list"));
app.use("/login", require("./src/routes/login")); app.use("/login", require("./src/routes/login"));
})(); })();
@ -30,7 +32,7 @@ app.use(express.json()); // Necessary to parse JSON bodies
// --- Launch --- // --- Launch ---
const port = config.server.port; const port = config.port;
app.listen(port, () => { app.listen(port, () => {
console.log("Server listening on port " + port + "..."); console.log("Server listening on port " + port + "...");
}) })

View file

@ -6,7 +6,7 @@ async function login(req, res) {
const token = await authService.login(req.body.username, req.body.password); const token = await authService.login(req.body.username, req.body.password);
res.json({ token }); res.json({ token });
} catch (err) { } catch (err) {
handleError(err, req, res, null); handleError(err, res);
} }
} }

View file

@ -1,47 +1,68 @@
const handleError = require("../middleware/errors"); 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 { try {
console.debug("Calling controller"); // Query
const query_result = await mod_service.getAllMods(); const query_result = await mod_service.getAllMods();
res.json(query_result); res.json(query_result);
} catch (error) { } catch (error) {
console.error("ERROR: Couldn't get mods: "); handleError(error, res);
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);
} }
} }
async function createMod(req, res) { async function createMod(req, res) {
try { try {
await mod_service.createMod(req.body); // Authenticate
res.sendStatus(200); 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) { } catch (error) {
console.error("ERROR: Couldn't create mod:", error.message); handleError(error, res);
handleError(error, req, res, null); }
}
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) { async function deleteMod(req, res) {
try { try {
await mod_service.deleteMod(req.params.name); // Authorize
return res.sendStatus(200); authorizeModModification(req);
// Query
const name = req.params.name
const query_result = await mod_service.deleteMod(name);
res.json(query_result);
} catch (error) { } catch (error) {
console.error("ERROR: Couldn't delete mod " + req.params.name + ":", error.message); handleError(error, res);
handleError(error, req, res, null);
} }
} }
module.exports = { getAllMods, getModByName, createMod, deleteMod }; module.exports = { listMods, getModByName, createMod, modifyMod, deleteMod };

View file

@ -1,47 +1,63 @@
const handleError = require("../middleware/errors"); const handleError = require("../middleware/errors");
const user_service = require("../services/userService") const user_service = require("../services/userService")
const { authorizeUserModification } = require("../middleware/auth");
async function getAllUsers(req, res) {
async function listUsers(req, res) {
try { try {
console.debug("Calling controller"); // Query
const query_result = await user_service.getAllUsers(); const query_result = await user_service.getAllUsers();
res.json(query_result); res.json(query_result);
} catch (error) { } catch (error) {
console.error("ERROR: Couldn't get users: "); handleError(error, res);
handleError(error, req, res, null);
} }
} }
async function getUserByName(req, res) { async function getUserByName(req, res) {
try { try {
// Query
const query_result = await user_service.getUserByName(req.params.name); const query_result = await user_service.getUserByName(req.params.name);
res.json(query_result); res.json(query_result);
} catch (error) { } catch (error) {
console.error("ERROR: Couldn't get user " + req.params.name + ": "); handleError(error, res);
handleError(error, req, res, null);
} }
} }
async function createUser(req, res) { async function createUser(req, res) {
try { try {
await user_service.createUser(req.body); // Query
res.sendStatus(200); const query_result = await user_service.createUser(req.body);
res.json(query_result);
} catch (error) { } catch (error) {
console.error("ERROR: Couldn't create user:", error.message); handleError(error, res);
handleError(error, req, res, null); }
}
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) { async function deleteUser(req, res) {
try { try {
await user_service.deleteUser(req.params.name); // Authenticate
return res.sendStatus(200); 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) { } catch (error) {
console.error("ERROR: Couldn't delete user " + req.params.name + ":", error.message); handleError(error, res);
handleError(error, req, res, null);
} }
} }
module.exports = { getAllUsers, getUserByName, createUser, deleteUser }; module.exports = { listUsers, getUserByName, createUser, modifyUser, deleteUser };

View file

@ -10,12 +10,12 @@ async function connectDatabase() {
const config = await getConfig(); const config = await getConfig();
// Choose database type // Choose database type
if (config.type === "mysql") { if (config.database.type === "mysql") {
db = new MySQLDatabase(config); db = new MySQLDatabase(config.database);
} else if (config.type === "sqlite") { } else if (config.database.type === "sqlite") {
db = new SQLiteDatabase(config); db = new SQLiteDatabase(config.database);
} else { } else {
throw new Error("Invalid database type: ", config.type); throw new Error("Invalid database type: ", config.database.type);
} }
// Connect // Connect
@ -40,8 +40,8 @@ async function initDatabase() {
email TINYTEXT NOT NULL, email TINYTEXT NOT NULL,
password TINYTEXT NOT NULL, password TINYTEXT NOT NULL,
profile_picture LONGTEXT, profile_picture LONGTEXT,
role TINYTEXT, NOT NULL, role TINYTEXT NOT NULL,
settings LONGTEXT, settings LONGTEXT
);`); );`);
// --- Mods --- // --- Mods ---
@ -53,7 +53,7 @@ async function initDatabase() {
author TINYTEXT NOT NULL, author TINYTEXT NOT NULL,
description TINYTEXT NOT NULL, description TINYTEXT NOT NULL,
FOREIGN KEY author REFERENCES Users(username) FOREIGN KEY (author) REFERENCES Users(username)
);`); );`);
// Mods complementary infos // Mods complementary infos
@ -66,7 +66,7 @@ async function initDatabase() {
creation_date TINYTEXT NOT NULL, creation_date TINYTEXT NOT NULL,
downloads_count INT NOT NULL, downloads_count INT NOT NULL,
FOREIGN KEY mod REFERENCES Users(username) FOREIGN KEY (mod) REFERENCES Users(username)
);`); );`);
// Mods tags // Mods tags
@ -74,7 +74,7 @@ async function initDatabase() {
mod TINYTEXT NOT NULL, mod TINYTEXT NOT NULL,
tag TINYTEXT NOT NULL, tag TINYTEXT NOT NULL,
FOREIGN KEY mod REFERENCES Mods(name) FOREIGN KEY (mod) REFERENCES Mods(name)
);`); );`);
// Mods versions // Mods versions
@ -89,7 +89,7 @@ async function initDatabase() {
environment TINYTEXT NOT NULL, environment TINYTEXT NOT NULL,
url TINYTEXT NOT NULL, url TINYTEXT NOT NULL,
FOREGIN KEY mod REFERENCES Mods(name) FOREIGN KEY (mod) REFERENCES Mods(name)
);`); );`);
// User favorites (mods) // User favorites (mods)
@ -97,8 +97,8 @@ async function initDatabase() {
username TINYTEXT NOT NULL, username TINYTEXT NOT NULL,
mod TINYTEXT NOT NULL, mod TINYTEXT NOT NULL,
FOREIGN KEY username REFERENCES Users(username), FOREIGN KEY (username) REFERENCES Users(username),
FOREGIN KEY mod REFERENCES Mods(name) FOREIGN KEY (mod) REFERENCES Mods(name)
);`); );`);
} }

View file

@ -19,6 +19,8 @@ async function authenticateToken(req) {
} catch (err) { } catch (err) {
throw new AppError(403, "Forbidden: Error verifying the authorization token"); throw new AppError(403, "Forbidden: Error verifying the authorization token");
} }
return req.token_infos;
} }

View file

@ -1,6 +1,6 @@
const AppError = require("../utils/appError"); const AppError = require("../utils/appError");
const handleError = (err, req, res, next) => { const handleError = (err, res) => {
// Send error infos // Send error infos
if (err instanceof AppError) { if (err instanceof AppError) {

View file

@ -1,8 +1,8 @@
const { getVersion } = require("../utils/configManager"); const configManager = require("../utils/configManager");
async function getVersion() { async function getVersion() {
const version = await getVersion(); const version = await configManager.getVersion();
const res = { const res = {
version: version version: version
}; };

View file

@ -18,7 +18,7 @@ async function getModFullInfos(name) {
// Query // Query
const base_infos = db.query(`SELECT * FROM Mods WHERE name = ?`, [name]); 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]); FROM ModInfos WHERE name = ?`, [name]);
const tags = getModTags(name); const tags = getModTags(name);
@ -28,7 +28,7 @@ async function getModFullInfos(name) {
return res; return res;
} }
async function getAllVersions(mod_name) { async function listVersions(mod_name) {
return await db.query("SELECT * FROM ModVersions WHERE mod = ?", [mod_name]); return await db.query("SELECT * FROM ModVersions WHERE mod = ?", [mod_name]);
} }
@ -162,7 +162,7 @@ async function updateModInfosAttribute(name, attribute, value) {
return; return;
} }
async function ModExists(name) { async function exists(name) {
return db.exists("Mods", "name", name); return db.exists("Mods", "name", name);
} }
@ -179,8 +179,8 @@ async function containsTag(name, tag) {
// --- Exports --- // --- Exports ---
module.exports = { getAllMods, getModByName, getFullModInfos, module.exports = { getAllMods, getModByName, getModFullInfos,
getAllModVersions, getVersionByNumber, getVersion, listVersions, getVersionByNumber, getVersion,
createMod, addVersion, addTags, createMod, addVersion, addTags,
updateMod, updateMod,
deleteMod, deleteVersion, deleteTags, deleteMod, deleteVersion, deleteTags,

24
src/routes/list.js Normal file
View file

@ -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;

View file

@ -3,29 +3,23 @@ const controller = require("../controllers/mods");
const router = express.Router(); const router = express.Router();
// List mods
router.get("/", async (req,res) => {
console.debug("Accessing mods list");
controller.getAllMods(req,res);
});
// Create a mod // Create a mod
router.post("/", async (req, res) => { router.post("/", async (req, res) => {
console.debug("Creating mod ", req.body.name);
controller.createMod(req, res); controller.createMod(req, res);
}); });
// Modify mod
router.put("/:name", async (req,res) => {
controller.modifyMod(req,res);
});
// Get mod infos // Get mod infos
router.get("/:name", async (req,res) => { router.get("/:name", async (req,res) => {
const name = req.params.name;
console.debug("Accessing mod " + name)
controller.getModByName(req, res); controller.getModByName(req, res);
}); });
// Delete mod // Delete mod
router.delete("/:name", async (req,res) => { router.delete("/:name", async (req,res) => {
const name = req.params.name;
console.debug("Deleting mod " + name)
controller.deleteMod(req, res); controller.deleteMod(req, res);
}); });

View file

@ -6,7 +6,7 @@ const router = express.Router();
// List users // List users
router.get("/", async (req,res) => { router.get("/", async (req,res) => {
console.debug("Accessing users list"); console.debug("Accessing users list");
controller.getAllUsers(req,res); controller.listUsers(req,res);
}); });
// Create a user // Create a user

View file

@ -50,6 +50,8 @@ async function createMod(mod_data, author) {
const { name, display_name, description, mod_infos } = mod_data; const { name, display_name, description, mod_infos } = mod_data;
mod_infos.full_description = await mdToHtml(mod_infos.full_description); // Convert mod_infos.full_description = await mdToHtml(mod_infos.full_description); // Convert
await sanitizeModData(mod_data); // Sanitize await sanitizeModData(mod_data); // Sanitize
//TODO
// mod_infos.creation_date = ...
// Write changes to database // Write changes to database
model.createMod(name, display_name, author, description, mod_data); model.createMod(name, display_name, author, description, mod_data);
@ -89,8 +91,8 @@ async function addTags(mod, tags) {
await model.addTags(mod, tags); await model.addTags(mod, tags);
// Return // Return
const { tags } = await model.getFullModInfos(mod); const { tags:res } = await model.getFullModInfos(mod);
return { "mod": mod, "tags": tags}; return { "mod": mod, "tags": res};
} }
@ -109,6 +111,9 @@ async function deleteMod(name) {
// Check existence // Check existence
const mod = await model.getModByName(name); const mod = await model.getModByName(name);
if (!mod) {
throw new AppError(404, "No was found with this name", "Not found")
}
// Authorize // Authorize
// TODO move outside of this function // TODO move outside of this function
@ -137,13 +142,20 @@ async function deleteVersion(version_infos) {
// Return // Return
return res; 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, module.exports = { getAllMods, getModByName, getFullModInfos,

View file

@ -27,16 +27,18 @@ async function createUser(user_data) {
return; return;
} }
async function deleteUser(name) { async function deleteUser(name, token_user) {
// Check existence // Check existence
const exists = await model.exists(name); const exists = await model.exists(name);
if (!exists) { 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 // Check authenticity
//TODO no auth provider if (name != token_user) {
throw new AppError(401, "", "Unauthorized");
}
model.deleteUser(name); model.deleteUser(name);
return; return;

View file

@ -15,7 +15,7 @@ let config = {};
// --- Default config --- // --- Default config ---
const defaault_config = { const default_config = {
"port": 8000, "port": 8000,