diff --git a/src/services/user.service.ts b/src/services/user.service.ts index 52ae207..a885123 100644 --- a/src/services/user.service.ts +++ b/src/services/user.service.ts @@ -1,10 +1,14 @@ -import type { IReqLogin } from "@interfaces/requests/IReqLogin"; -import type { IReqRegister } from "@interfaces/requests/IReqRegister"; +import type {IDbUser} from "@interfaces/database/IDbUser"; +import type {IReqLogin} from "@interfaces/requests/IReqLogin"; +import type {IReqRegister} from "@interfaces/requests/IReqRegister"; +import {ErrorType, type ISError} from "@interfaces/services/ISError"; import CredentialService from "@services/credential.service"; import JwtService from "@services/jwt.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"; + const logger = new Logger({ name: "UserService", @@ -13,92 +17,124 @@ const logger = new Logger({ const DbHandler = new MySqlService.Handler("UserService"); /** - * Retrieves a user object from the database based on the given username. + * Retrieves a user from the database by the given email address. * - * @param {string} username - The username of the user to retrieve. - * @returns {Promise} - The user object if found, or null if not found. + * @param {string} targetEmail - The email address of the user to retrieve. + * @returns {Promise} + * - A promise that resolves with the user. + * - If the user is not found, an error object is returned. + * - If an error occurs during the database operation, an error object is returned. */ -async function getUserFromUsername(username: string): Promise { - const dbUser = await MySqlService.User.getByUsername(DbHandler, username); - if (dbUser === undefined) return null; - return dbUser; -} - -async function getUserFromIdService(id: string | undefined) { - const dbUser = await MySqlService.User.getById(DbHandler, id); - if (dbUser === undefined) return null; - return dbUser; -} - -async function register(ReqData: IReqRegister) { - if (ReqData.password.length < 6) { - logger.info(`REGISTER :> Invalid password (${ReqData.username})`); +async function getUserByEmail(targetEmail: string): Promise { + try { + const dbUser = await MySqlService.User.getByEmail(DbHandler, targetEmail); + if (dbUser === undefined) { + logger.info(`User not found (${targetEmail})`); + return { + error: ErrorType.NotFound, + message: "The user was not fund.", + }; + } + return dbUser; + } catch (err) { + logger.error(err); return { - error: "invalidPassword", + error: ErrorType.DatabaseError, + message: "An unknown error occurred.", }; } - const passwordHash = await CredentialService.hash(ReqData.password); +} + +/** + * Retrieves a user from the database based on the provided ID. + * + * @param {string} id - The ID of the user to retrieve. + * @returns {Promise} - A promise that resolves with the user object if found, or an error object if not. + */ +async function getUserFromIdService(id: string): Promise { + try { + if (!id || id.length !== 36) { + logger.info(`Invalid ID (${id})`); + return { + error: ErrorType.InvalidData, + message: "Invalid ID length.", + }; + } + const dbUser = await MySqlService.User.getById(DbHandler, id); + if (dbUser === undefined) { + logger.info(`User not found (${id})`); + return { + error: ErrorType.NotFound, + message: "The user was not found.", + }; + } + return dbUser; + } catch (err) { + return { + error: ErrorType.DatabaseError, + message: "An unknown error occurred.", + }; + } +} + +async function register(ReqData: IReqRegister): Promise { + if (ReqData.password.length < 6) { + return { + error: ErrorType.InvalidData, + message: "Password must be at least 6 characters long.", + }; + } + const passwordHash = await CredentialService.hash(`${ReqData.password}`); // Does the new user has accepted GDPR ? if (ReqData.gdpr !== true) { - logger.info(`REGISTER :> GDPR not validated (${ReqData.username})`); return { - error: "gdprNotApproved", + error: ErrorType.InvalidData, + message: "GDPR acceptance is required.", }; } - - // Check if exist and return - - const dbUserIfExist = await getUserFromUsername(ReqData.username); - if (dbUserIfExist) { - logger.info( - `REGISTER :> User exist (${dbUserIfExist.username})\n ID:${dbUserIfExist.id}`, - ); - return { - error: "exist", - }; - } - const currentDate = new Date(); - // New UserService (class) + // Check if exist and return + const dbUserIfExist: IDbUser | ISError = await getUserByEmail(ReqData.email); + if ("error" in dbUserIfExist) { + return { + error: dbUserIfExist.error, + message: dbUserIfExist.message, + }; + } - const NewUser = new User( - ReqData.username, - ReqData.displayName, - passwordHash, - currentDate, - ); - NewUser.setFirstName(ReqData.firstName); - NewUser.setLastName(ReqData.lastName); + const NewUser = await MySqlService.User.insert(DbHandler, { + id: v4(), + email: ReqData.email, + username: ReqData.username, + firstname: ReqData.firstName, + lastname: ReqData.lastName, + dob: ReqData.dob, + hash: passwordHash, + gdpr: currentDate, + is_admin: false, + is_mail_verified: false, + }); + if ("error" in NewUser || !NewUser.id) { + return { + error: ErrorType.DatabaseError, + message: 'Error when inserting user in database.' + }; + } // JWT - - const alg = "HS512"; const token = await JwtService.sign( { sub: NewUser.id, }, - alg, + { + alg: "HS512", + }, "1d", "user", ); - - const userData = { - error: "none", - jwt: token, - user: { - id: NewUser.id, - username: NewUser.username, - displayName: NewUser.displayName, - firstName: NewUser.firstName, - lastName: NewUser.lastName, - }, - }; - logger.info(userData); - await Db.collection("users").insertOne(NewUser); - logger.info(`REGISTER :> Inserted new user (${NewUser.username})`); - return userData; + return token; } async function login(ReqData: IReqLogin) {