feat(services): refactor user service and improve error handling
- Introduced error handling in `register`, `login`, `getAllUsersService`, and `editUserService` methods. - Improved logging by adding breaks for better visibility. - Refactored code for better readability and maintainability. - Eliminated unnecessary and duplicate imports. - Transitioned from MongoDB to MySQL service. - Added comment flags for testing purposes. Issue: #18 Signed-off-by: Mathis <yidhra@tuta.io>
This commit is contained in:
parent
df28d3aa52
commit
bc12f94e41
@ -5,7 +5,6 @@ import { ErrorType, type ISError } from "@interfaces/services/ISError";
|
|||||||
import CredentialService from "@services/credential.service";
|
import CredentialService from "@services/credential.service";
|
||||||
import JwtService from "@services/jwt.service";
|
import JwtService from "@services/jwt.service";
|
||||||
import MySqlService from "@services/mysql.service";
|
import MySqlService from "@services/mysql.service";
|
||||||
import MysqlService from "@services/mysql.service";
|
|
||||||
import { Logger } from "tslog";
|
import { Logger } from "tslog";
|
||||||
import { v4 } from "uuid";
|
import { v4 } from "uuid";
|
||||||
|
|
||||||
@ -28,7 +27,7 @@ async function getUserByEmail(targetEmail: string): Promise<IDbUser | ISError> {
|
|||||||
try {
|
try {
|
||||||
const dbUser = await MySqlService.User.getByEmail(DbHandler, targetEmail);
|
const dbUser = await MySqlService.User.getByEmail(DbHandler, targetEmail);
|
||||||
if (dbUser === undefined) {
|
if (dbUser === undefined) {
|
||||||
logger.info(`User not found (${targetEmail})`);
|
logger.info(`\n\n> User not found (${targetEmail})\n`);
|
||||||
return {
|
return {
|
||||||
error: ErrorType.NotFound,
|
error: ErrorType.NotFound,
|
||||||
message: "The user was not fund.",
|
message: "The user was not fund.",
|
||||||
@ -53,7 +52,7 @@ async function getUserByEmail(targetEmail: string): Promise<IDbUser | ISError> {
|
|||||||
async function getUserFromIdService(id: string): Promise<IDbUser | ISError> {
|
async function getUserFromIdService(id: string): Promise<IDbUser | ISError> {
|
||||||
try {
|
try {
|
||||||
if (!id || id.length !== 36) {
|
if (!id || id.length !== 36) {
|
||||||
logger.info(`Invalid ID (${id})`);
|
logger.info(`\n\n> Invalid ID (${id})\n`);
|
||||||
return {
|
return {
|
||||||
error: ErrorType.InvalidData,
|
error: ErrorType.InvalidData,
|
||||||
message: "Invalid ID length.",
|
message: "Invalid ID length.",
|
||||||
@ -76,14 +75,22 @@ async function getUserFromIdService(id: string): Promise<IDbUser | ISError> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//ToTest
|
||||||
|
/**
|
||||||
|
* Registers a new user.
|
||||||
|
*
|
||||||
|
* @param {IReqRegister} inputData - The input data for registration.
|
||||||
|
* @return {Promise<ISError | string>} - A Promise that resolves to either an error or a token.
|
||||||
|
*/
|
||||||
async function register(inputData: IReqRegister): Promise<ISError | string> {
|
async function register(inputData: IReqRegister): Promise<ISError | string> {
|
||||||
|
try {
|
||||||
if (inputData.password.length < 6) {
|
if (inputData.password.length < 6) {
|
||||||
return {
|
return {
|
||||||
error: ErrorType.InvalidData,
|
error: ErrorType.InvalidData,
|
||||||
message: "Password must be at least 6 characters long.",
|
message: "Password must be at least 6 characters long.",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
//TODO check Object content keys
|
|
||||||
const passwordHash = await CredentialService.hash(`${inputData.password}`);
|
const passwordHash = await CredentialService.hash(`${inputData.password}`);
|
||||||
|
|
||||||
// Does the new user has accepted GDPR ?
|
// Does the new user has accepted GDPR ?
|
||||||
@ -107,7 +114,7 @@ async function register(inputData: IReqRegister): Promise<ISError | string> {
|
|||||||
}
|
}
|
||||||
if (dbUserIfExist.id) {
|
if (dbUserIfExist.id) {
|
||||||
logger.info(
|
logger.info(
|
||||||
`User already exist for email "${inputData.email}".\n(${dbUserIfExist.username}::${dbUserIfExist.id})\n`,
|
`\n\n> User already exist for email "${inputData.email}".\n(${dbUserIfExist.username}::${dbUserIfExist.id})\n`,
|
||||||
);
|
);
|
||||||
return {
|
return {
|
||||||
error: ErrorType.UnAuthorized,
|
error: ErrorType.UnAuthorized,
|
||||||
@ -133,12 +140,12 @@ async function register(inputData: IReqRegister): Promise<ISError | string> {
|
|||||||
message: "Error when inserting user in database.",
|
message: "Error when inserting user in database.",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
logger.info(`New user created ! (${inputData.username}::${currentId})`);
|
logger.info(`\n\n> New user created ! (${inputData.username}::${currentId})\n`);
|
||||||
|
|
||||||
// JWT
|
// JWT
|
||||||
const token = await JwtService.sign(
|
const token = await JwtService.sign(
|
||||||
{
|
{
|
||||||
sub: NewUser.id,
|
sub: currentId,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
alg: "HS512",
|
alg: "HS512",
|
||||||
@ -147,123 +154,122 @@ async function register(inputData: IReqRegister): Promise<ISError | string> {
|
|||||||
"user",
|
"user",
|
||||||
);
|
);
|
||||||
return token;
|
return token;
|
||||||
}
|
} catch (err) {
|
||||||
|
logger.error(`\n\n${err}\n`);
|
||||||
async function login(ReqData: IReqLogin) {
|
|
||||||
//const passwordHash = await getHashFromPassword(sanitizedData.password);
|
|
||||||
const dbUser = await MysqlService.User.getByUsername(
|
|
||||||
DbHandler,
|
|
||||||
ReqData.username,
|
|
||||||
);
|
|
||||||
if (!dbUser) {
|
|
||||||
console.log(`LoginService :> User does not exist (${ReqData.username})`);
|
|
||||||
return {
|
return {
|
||||||
error: "userNotFound",
|
error: ErrorType.DatabaseError,
|
||||||
|
message: "An unknown error occurred.",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (ReqData.password.length < 6) {
|
}
|
||||||
console.log("X");
|
|
||||||
console.log(`LoginService :> Invalid password (${ReqData.username})`);
|
//ToTest
|
||||||
|
/**
|
||||||
|
* Logs in a user with the provided input data.
|
||||||
|
*
|
||||||
|
* @param inputData - The input data for the login operation.
|
||||||
|
* @property email - The email of the user.
|
||||||
|
* @property password - The password of the user.
|
||||||
|
* @returns A promise that resolves to either an error or a token string.
|
||||||
|
* @throws {ISError} - If an error occurs in the login process.
|
||||||
|
* @throws {string} - If the login was successful, returns a token string.
|
||||||
|
*/
|
||||||
|
async function login(inputData: IReqLogin): Promise<ISError | string> {
|
||||||
|
try {
|
||||||
|
const dbUser = await getUserByEmail(inputData.email);
|
||||||
|
if ("error" in dbUser) {
|
||||||
return {
|
return {
|
||||||
error: "invalidPassword",
|
error: dbUser.error,
|
||||||
|
message: dbUser.message,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (!dbUser.id) {
|
||||||
|
return {
|
||||||
|
error: ErrorType.NotFound,
|
||||||
|
message: "User not found.",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
const isPasswordValid = await CredentialService.compare(
|
const isPasswordValid = await CredentialService.compare(
|
||||||
ReqData.password,
|
inputData.password,
|
||||||
dbUser.hash,
|
dbUser.hash
|
||||||
);
|
);
|
||||||
if (!isPasswordValid) {
|
if (!isPasswordValid) {
|
||||||
console.log(isPasswordValid);
|
|
||||||
console.log(`LoginService :> Invalid password (${ReqData.username})`);
|
|
||||||
return {
|
return {
|
||||||
error: "invalidPassword",
|
error: ErrorType.UnAuthorized,
|
||||||
|
message: "Invalid password.",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
// biome-ignore lint/style/useConst: <explanation>
|
const token = await JwtService.sign(
|
||||||
let userData = {
|
|
||||||
error: "none",
|
|
||||||
jwt: "",
|
|
||||||
user: {
|
|
||||||
id: dbUser.id,
|
|
||||||
username: dbUser.username,
|
|
||||||
displayName: dbUser.displayName,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
userData.jwt = await JwtService.sign(
|
|
||||||
{
|
{
|
||||||
sub: dbUser.id,
|
sub: dbUser.id,
|
||||||
|
p: [{
|
||||||
|
isAdmin: dbUser.is_admin,
|
||||||
|
gdpr: dbUser.gdpr
|
||||||
|
}]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
alg: "HS512",
|
alg: "HS512",
|
||||||
},
|
},
|
||||||
"7d",
|
"1d",
|
||||||
"user",
|
"user"
|
||||||
);
|
);
|
||||||
|
return token;
|
||||||
console.log("USERDATA :>");
|
} catch (err) {
|
||||||
console.log(userData);
|
logger.error(`\n\n${err}\n`);
|
||||||
return userData;
|
return {
|
||||||
|
error: ErrorType.DatabaseError,
|
||||||
|
message: "An unknown error occurred.",
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TOTest
|
||||||
/**
|
/**
|
||||||
* Retrieves all users from the database.
|
* Retrieves all users from the database.
|
||||||
*
|
*
|
||||||
* @async
|
* @returns {Promise<Array<IDbUser> | ISError>} The list of users, or an error object if an error occurred.
|
||||||
* @function getAllUsersService
|
|
||||||
* @returns {Promise<{iat: number, users: Array<user>, length: number}>} - The response object containing the users array and its length.
|
|
||||||
*/
|
*/
|
||||||
async function getAllUsersService() {
|
async function getAllUsersService(): Promise<Array<IDbUser> | ISError> {
|
||||||
const users = await Db.collection("users").find().toArray();
|
try {
|
||||||
// biome-ignore lint/complexity/noForEach: <explanation>
|
const allUsers = await MySqlService.User.getAll(DbHandler);
|
||||||
users.forEach((user) => {
|
if (allUsers === undefined) {
|
||||||
delete user.passwordHash;
|
logger.error(`Error retrieving all users.`);
|
||||||
delete user._id;
|
|
||||||
delete user.gdpr;
|
|
||||||
});
|
|
||||||
logger.info(`Query ${users.length} user(s)`);
|
|
||||||
return {
|
return {
|
||||||
iat: Date.now(),
|
error: ErrorType.DatabaseError,
|
||||||
users: users,
|
message: "An unknown error occurred.",
|
||||||
length: users.length,
|
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
return allUsers;
|
||||||
|
} catch (err) {
|
||||||
|
logger.error(`\n\n${err}\n`);
|
||||||
|
return {
|
||||||
|
error: ErrorType.DatabaseError,
|
||||||
|
message: "An unknown error occurred.",
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
async function editUserService(targetId, inputData: IDbUser): Promise<ISError | boolean> {
|
||||||
* Edits a user in the database.
|
if (!targetId || targetId.length !== 36) {
|
||||||
*
|
logger.info(`\n\n> Invalid ID (${targetId})\n`);
|
||||||
* @param {string} targetId - The ID of the user to be edited.
|
|
||||||
* @param {object} sanitizedData - The sanitized data to update the user with.
|
|
||||||
* @returns {object} - An object indicating the result of the operation.
|
|
||||||
* If the user is not found, the error property will be a string "userNotFound".
|
|
||||||
* Otherwise, the error property will be a string "none".
|
|
||||||
*/
|
|
||||||
async function editUserService(targetId, sanitizedData) {
|
|
||||||
if (sanitizedData.password) {
|
|
||||||
const passwordHash = await getHashFromPassword(sanitizedData.password);
|
|
||||||
delete sanitizedData.password;
|
|
||||||
logger.info(`Changing password for user "${targetId}"`);
|
|
||||||
sanitizedData.passwordHash = passwordHash;
|
|
||||||
}
|
|
||||||
const updatedUserResult = await Db.collection("users").updateOne(
|
|
||||||
{
|
|
||||||
id: targetId,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
$set: sanitizedData,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
if (updatedUserResult.modifiedCount === 0) {
|
|
||||||
logger.info(`EDIT :> User not found (${targetId})`);
|
|
||||||
return {
|
return {
|
||||||
error: "userNotFound",
|
error: ErrorType.InvalidData,
|
||||||
|
message: "Invalid ID length.",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
const dbUser = await MySqlService.User.getById(DbHandler, targetId)
|
||||||
logger.info(`EDIT :> User updated (${targetId})`);
|
if (!dbUser.id) {
|
||||||
return {
|
return {
|
||||||
error: "none",
|
error: ErrorType.NotFound,
|
||||||
|
message: "User not found.",
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
const result = await MySqlService.User.update(DbHandler, {
|
||||||
|
username: inputData.username,
|
||||||
|
firstname: inputData.firstname,
|
||||||
|
lastname: inputData.lastname,
|
||||||
|
dob: inputData.dob,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
x
Reference in New Issue
Block a user