A LOT of fixes
This commit is contained in:
parent
ca080b3e59
commit
106646f306
|
@ -12,5 +12,8 @@
|
|||
"type": "sqlite"
|
||||
},
|
||||
|
||||
"JWT_secret": "HGF7654EGBNKJNBJH6754356788GJHGY"
|
||||
"auth": {
|
||||
"JWT_secret": "HGF7654EGBNKJNBJH6754356788GJHGY",
|
||||
"tokenExpiry": "1h"
|
||||
}
|
||||
}
|
|
@ -3,10 +3,15 @@ const authService = require("../services/authService");
|
|||
|
||||
async function login(req, res) {
|
||||
try {
|
||||
const token = await authService.login(req.body.username, req.body.password);
|
||||
const username = req.body.username;
|
||||
const email = req.body.email;
|
||||
const password = req.body.password
|
||||
const token = await authService.login(username, email, password);
|
||||
res.json({ token });
|
||||
} catch (err) {
|
||||
handleError(err, res);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
module.exports = { login };
|
|
@ -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 Mods(name)
|
||||
);`);
|
||||
|
||||
// Mods tags
|
||||
|
|
|
@ -29,11 +29,11 @@ async function authorizeModModification(req) {
|
|||
// Auth token
|
||||
await authenticateToken(req);
|
||||
// Get mod infos
|
||||
if (!req.params || req.params.id) {
|
||||
if (!req.params || !req.params.name) {
|
||||
throw new AppError(400, "No mod name was scpecified", "Bad request");
|
||||
}
|
||||
const mod_name = req.params.id;
|
||||
const mod = getModByName(mod_name);
|
||||
const mod_name = req.params.name;
|
||||
const mod = await getModByName(mod_name);
|
||||
if (!mod) {
|
||||
throw new AppError(404, "No mod was found with this name", "Not found");
|
||||
}
|
||||
|
@ -48,11 +48,11 @@ async function authorizeModpackModification(req) {
|
|||
// Auth token
|
||||
await authenticateToken(req);
|
||||
// Get mod infos
|
||||
if (!req.params || req.params.id) {
|
||||
if (!req.params || !req.params.name) {
|
||||
throw new AppError(400, "No mod name was scpecified", "Bad request");
|
||||
}
|
||||
const modpack_name = req.params.id;
|
||||
const modpack = getModpackByName(modpack_name);
|
||||
const modpack_name = req.params.name;
|
||||
const modpack = await getModpackByName(modpack_name);
|
||||
if (!modpack) {
|
||||
throw new AppError(404, "No mod was found with this name", "Not found");
|
||||
}
|
||||
|
@ -67,17 +67,17 @@ async function authorizeUserModification(req) {
|
|||
// Auth token
|
||||
await authenticateToken(req);
|
||||
// Get mod infos
|
||||
if (!req.params || req.params.id) {
|
||||
if (!req.params || !req.params.name) {
|
||||
throw new AppError(400, "No mod name was scpecified", "Bad request");
|
||||
}
|
||||
const user_name = req.params.id;
|
||||
const user = getUserByName(user_name);
|
||||
const user_name = req.params.name;
|
||||
const user = await getUserByName(user_name);
|
||||
if (!user) {
|
||||
throw new AppError(404, "No mod was found with this name", "Not found");
|
||||
throw new AppError(404, "No user was found with this name", "Not found");
|
||||
}
|
||||
// Authorize
|
||||
if ( user.username != req.token_infos.username) {
|
||||
throw new AppError(401, "Mod author differs from current user", "Unauthorized");
|
||||
throw new AppError(401, "User to modify differs from current user", "Unauthorized");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,16 @@ const handleError = (err, res) => {
|
|||
|
||||
// Send error infos
|
||||
if (err instanceof AppError) {
|
||||
|
||||
// Log
|
||||
if (err.statusCode == 500) {
|
||||
console.error("Error:", err.message);
|
||||
if (err.debugMsg) {
|
||||
console.debug(" >", err.debugMsg);
|
||||
}
|
||||
}
|
||||
|
||||
// Response
|
||||
return res.status(err.statusCode).json({
|
||||
status: err.status,
|
||||
message: err.message
|
||||
|
@ -11,6 +21,7 @@ const handleError = (err, res) => {
|
|||
}
|
||||
|
||||
// Default error
|
||||
console.error("Error:", err.message);
|
||||
res.status(500).json({
|
||||
message: 'Internal server error',
|
||||
status: 500
|
||||
|
|
|
@ -62,22 +62,27 @@ async function createMod(name, display_name, author, description, mod_infos) {
|
|||
[name, display_name, author, description]);
|
||||
|
||||
// ModInfos table
|
||||
await db.prepare(`INSERT INTO ModInfos (mod, full_description, license, links, creation_date)
|
||||
VALUES (?, ?, ?, ?, ?)`,
|
||||
[name, full_description, license.type, links.toString(), creation_date]);
|
||||
await db.prepare(`INSERT INTO ModInfos (mod, full_description, license, links, creation_date, downloads_count)
|
||||
VALUES (?, ?, ?, ?, ?, ?)`,
|
||||
[name, full_description, license.type, links.toString(), creation_date, 0]);
|
||||
|
||||
// Tags
|
||||
const tags_proc = addTags(name, tags, []);
|
||||
if (tags) {
|
||||
const tags_proc = addTags(name, tags, []);
|
||||
}
|
||||
|
||||
|
||||
// License
|
||||
if (license_type == "custom") {
|
||||
if (license.type == "custom") {
|
||||
await db.prepare(`UPDATE ModInfos SET custom_license = ?
|
||||
WHERE mod = ?`,
|
||||
[license.content, name]);
|
||||
}
|
||||
|
||||
// Await
|
||||
await tags_proc;
|
||||
if (tags) {
|
||||
await tags_proc;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -5,8 +5,8 @@ const db = getDatabase();
|
|||
|
||||
// --- Get ---
|
||||
|
||||
async function getAllUsers(name) {
|
||||
return db.query("SELECT username, display_name, email, profile_picture FROM Users WHERE username = ?", [name]);
|
||||
async function getAllUsers() {
|
||||
return db.query("SELECT username, display_name, email, profile_picture FROM Users");
|
||||
}
|
||||
|
||||
async function getUserByName(name) {
|
||||
|
@ -35,8 +35,9 @@ async function exists(name) {
|
|||
async function createUser( username, email, password, displayName, profilePicture, settings ) {
|
||||
|
||||
// Create user
|
||||
await db.prepare("INSERT INTO Users (username, email, password, display_name, role) \
|
||||
VALUES (?, ?, ?, ?, ?)", [username, email, password, displayName, "user"]);
|
||||
await db.prepare(`INSERT INTO Users (username, email, password, display_name, role )
|
||||
VALUES (?, ?, ?, ?, ? )`,
|
||||
[username, email, password, displayName, "user"]);
|
||||
|
||||
// Handle nullable fields
|
||||
if (profilePicture) {
|
||||
|
|
|
@ -5,27 +5,21 @@ const router = express.Router();
|
|||
|
||||
// List users
|
||||
router.get("/", async (req,res) => {
|
||||
console.debug("Accessing users list");
|
||||
controller.listUsers(req,res);
|
||||
});
|
||||
|
||||
// Create a user
|
||||
router.post("/", async (req, res) => {
|
||||
console.debug("Creating user ", req.body.name);
|
||||
controller.createUser(req, res);
|
||||
})
|
||||
|
||||
// Get user infos
|
||||
router.get("/:name", async (req,res) => {
|
||||
const name = req.params.name;
|
||||
console.debug("Accessing user " + name)
|
||||
controller.getUserByName(req, res);
|
||||
});
|
||||
|
||||
// Delete user
|
||||
router.delete("/:name", async (req,res) => {
|
||||
const name = req.params.name;
|
||||
console.debug("Deleting user " + name)
|
||||
controller.deleteUser(req, res);
|
||||
});
|
||||
|
||||
|
|
|
@ -1,48 +1,79 @@
|
|||
const bcrypt = require("bcrypt");
|
||||
const jwt = require("jsonwebtoken");
|
||||
const userModel = require("../models/user");
|
||||
const AppError = require("../utils/appError");
|
||||
const cryptoUtils = require("../utils/crypto");
|
||||
const configManager = require("../utils/configManager");
|
||||
const validate = require("../utils/validate_legacy");
|
||||
|
||||
const JWT_Secret = configManager.getJWTSecret();
|
||||
|
||||
async function login(identifier, password) {
|
||||
async function login(username, email, password) {
|
||||
|
||||
// Check for null
|
||||
if (!username || !password) {
|
||||
if (!(username || email) || !password) {
|
||||
throw new AppError(400, "Bad request", "missing credentials");
|
||||
}
|
||||
|
||||
// Get user data
|
||||
let user;
|
||||
if (validate.isEmail(identifier)) { // If matches email
|
||||
user = await userModel.getUserByEmail(username);
|
||||
let user_get;
|
||||
if (email) { // If matches email
|
||||
user_get = await userModel.getUserByEmail(email);
|
||||
} else
|
||||
if (validate.isID(identifier)) { // if matches username
|
||||
user = await userModel.getUserByName(username);
|
||||
if (username) { // if matches username
|
||||
user_get = await userModel.getUserByName(username);
|
||||
} else {
|
||||
console.debug("Failed finding user, weird...")
|
||||
throw new AppError(401, "Unauthorized", "Invalid credentials");
|
||||
}
|
||||
|
||||
// Check if user exists
|
||||
if (!user || user.length == 0) {
|
||||
if (!user_get || user_get.length == 0) {
|
||||
// throw new AppError(401, "Unauthorized: No user with this name");
|
||||
throw new AppError(401, "Unauthorized", "Invalid credentials");
|
||||
}
|
||||
// Just in case
|
||||
if (user.length > 1) {
|
||||
if (user_get.length > 1) {
|
||||
throw new AppError(500, "Internal server error", "Found multiple users with this name or email, please contact administration");
|
||||
}
|
||||
|
||||
const user = user_get[0];
|
||||
|
||||
// Get user password
|
||||
const saved_password_get = await userModel.getUserPassword(user.username);
|
||||
// Check if retrieved password sucessfully
|
||||
if (!saved_password_get || saved_password_get.length == 0) {
|
||||
throw new AppError(500, "Unable to retrieve user password");
|
||||
}
|
||||
saved_password = saved_password_get[0].password;
|
||||
// Check if retrieved password sucessfully again
|
||||
if (!saved_password) {
|
||||
throw new AppError(500, "Unable to retrieve user password");
|
||||
}
|
||||
|
||||
// Check if passwords match
|
||||
const passwords_match = await bcrypt.compare(password, user[0].password);
|
||||
const passwords_match = await cryptoUtils.passwordsMatch(password, saved_password)
|
||||
if (!passwords_match) {
|
||||
// throw new AppError(401, "Unauthorized: Invalid password");
|
||||
console.debug(password, "differs from", saved_password);
|
||||
throw new AppError(401, "Unauthorized", "Invalid credentials");
|
||||
}
|
||||
|
||||
return jwt.sign({ username: user[0].username, role: user[0].role }, await JWT_Secret);
|
||||
const payload = { type: "user",
|
||||
username: user.username,
|
||||
email: user.email,
|
||||
role: user.role };
|
||||
|
||||
const token = await cryptoUtils.signToken(payload);
|
||||
return token;
|
||||
|
||||
// // Check if passwords match
|
||||
// const passwords_match = await bcrypt.compare(password, user[0].password);
|
||||
// if (!passwords_match) {
|
||||
// // throw new AppError(401, "Unauthorized: Invalid password");
|
||||
// console.debug("Password doesn't match")
|
||||
// throw new AppError(401, "Unauthorized", "Invalid credentials");
|
||||
// }
|
||||
|
||||
// return jwt.sign({ username: user[0].username, role: user[0].role }, await JWT_Secret);
|
||||
}
|
||||
|
||||
// function authorizeRole(user, roles) {
|
||||
|
|
|
@ -51,10 +51,10 @@ async function createMod(mod_data, author) {
|
|||
mod_infos.full_description = await mdToHtml(mod_infos.full_description); // Convert
|
||||
await sanitizeModData(mod_data); // Sanitize
|
||||
//TODO
|
||||
// mod_infos.creation_date = ...
|
||||
mod_infos.creation_date = 0
|
||||
|
||||
// Write changes to database
|
||||
model.createMod(name, display_name, author, description, mod_data);
|
||||
await model.createMod(name, display_name, author, description, mod_infos);
|
||||
|
||||
// Return
|
||||
return getModByName(name);
|
||||
|
|
|
@ -1,30 +1,32 @@
|
|||
const model = require("../models/user");
|
||||
const AppError = require("../utils/appError");
|
||||
const cryptoUtils = require("../utils/crypto");
|
||||
const { validateUserData } = require("../utils/validate_legacy");
|
||||
const { sanitizeUserData } = require("../utils/sanitize");
|
||||
|
||||
async function getAllUsers() {
|
||||
return model.getAllUsers();
|
||||
return await model.getAllUsers();
|
||||
}
|
||||
|
||||
async function getUserByName(name) {
|
||||
return model.getUserByName(name);
|
||||
const res = await model.getUserByName(name);
|
||||
return res[0];
|
||||
}
|
||||
|
||||
async function createUser(user_data) {
|
||||
|
||||
// Check body validity
|
||||
await validateUserData(user_data);
|
||||
|
||||
// Check authenticity
|
||||
//TODO no auth provider
|
||||
// TODO
|
||||
|
||||
// Sanitize
|
||||
await sanitizeUserData(user_data);
|
||||
// TODO
|
||||
|
||||
console.debug("Passed validity checks");
|
||||
model.createUser(user_data);
|
||||
return;
|
||||
// Gather data
|
||||
const { username, email, password, display_name, profile_picture, settings } = user_data
|
||||
const password_hash = await cryptoUtils.hashPassword(password);
|
||||
|
||||
await model.createUser(username, email, password_hash, display_name, null, null);
|
||||
return model.getUserByName(username);
|
||||
}
|
||||
|
||||
async function deleteUser(name, token_user) {
|
||||
|
@ -35,13 +37,10 @@ async function deleteUser(name, token_user) {
|
|||
throw new AppError(404, "Cannot find user with this name", "Not found");
|
||||
}
|
||||
|
||||
// Check authenticity
|
||||
if (name != token_user) {
|
||||
throw new AppError(401, "", "Unauthorized");
|
||||
}
|
||||
const res = await model.getUserByName(name);
|
||||
await model.deleteUser(name);
|
||||
|
||||
model.deleteUser(name);
|
||||
return;
|
||||
return res;
|
||||
}
|
||||
|
||||
module.exports = { getAllUsers, getUserByName, createUser, deleteUser };
|
|
@ -31,7 +31,8 @@ const default_config = {
|
|||
},
|
||||
|
||||
"auth" : {
|
||||
"JWT_secret": "HGF7654EGBNKJNBJH6754356788GJHGY"
|
||||
"JWT_secret": "HGF7654EGBNKJNBJH6754356788GJHGY",
|
||||
"tokenExpiry": "1h"
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -48,7 +49,7 @@ function loadConfig() {
|
|||
user_config = JSON.parse(fs.readFileSync(path.resolve(path.join(config_folder, config_file_name))));
|
||||
|
||||
// Warns
|
||||
if (!user_config.auth || !user_config.auth.jwtSecret) {
|
||||
if (!user_config.auth || !user_config.auth.JWT_secret) {
|
||||
console.warn("WARNING: No JWT secret provided, using the default one. Please note that using the default secret is a major security risk.")
|
||||
}
|
||||
|
||||
|
@ -75,7 +76,7 @@ async function getConfig() {
|
|||
}
|
||||
|
||||
async function getJWTSecret() {
|
||||
return config.auth.JWT_Secret || process.env.JWT_Secret;
|
||||
return config.auth.JWT_secret || process.env.JWT_secret;
|
||||
}
|
||||
|
||||
async function getVersion() {
|
||||
|
|
|
@ -10,9 +10,10 @@ async function sanitizeText(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);
|
||||
console.warn("Skipping sanitanization (not implemented)");
|
||||
// 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 };
|
Loading…
Reference in a new issue