Compare commits

...

5 Commits

Author SHA1 Message Date
bdfc598218
feat(services): update user service dynamic types and enhance error handling
- Refactored `editUserService` function to use `IUserUpdate` type for `inputData` instead of `IDbUser`.
- Enhanced error handling in `editUserService` and `deleteUserService` by checking for affected rows in the returned result.
- Updated `deleteUserService` from using MongoDB method to MySqlService method.

Issue: #18
Signed-off-by: Mathis <yidhra@tuta.io>
2024-05-02 15:37:39 +02:00
1cbc771251
feat(app): update debug syntax, refactor HTTP status codes
- Updated import and usage of `isDebugMode` function across multiple controllers and services for better readability
- Improved the use of HTTP status codes in `auth.controller.ts` for more accurate responses
- Refactored HTTP status codes `HttpStatusCode` enum to include detailed comments

Signed-off-by: Mathis <yidhra@tuta.io>
2024-05-02 15:29:19 +02:00
8644b5add6
feat(services): update user.service.ts for better error handling and debugging
The updated `user.service.ts` now includes better error handling using optional chaining and also generates a JSDoc definition for HTML status codes. An extra logger trace has also been added, which provides token related information in debug mode. This will capture user login token details for debugging purposes. Also cleaned up code formatting for readability.

Issue: #18
Signed-off-by: Mathis <yidhra@tuta.io>
2024-05-02 15:28:45 +02:00
b66a5aff6d
feat(interfaces): add HttpStatusCode enum
Added a new file `HttpStatusCode.ts` in the `interfaces` scope. This file defines an enum which represents all the possible HTTP Status Codes, enhancing readability and maintainability in the code base by replacing hard-coded numbers with meaningful names.

Signed-off-by: Mathis <yidhra@tuta.io>
2024-05-02 14:37:46 +02:00
3d3da77df0
feat(services): add getByEmailService to user.service.ts
A new method `getByEmailService` has been added to `user.service.ts`. This method retrieves a user from the database by their email. The tracing log adjustment has also been performed, where logging only happens when it's in debug mode. If there are multiple users with the same email, this method will return the first user.

Issue: #18
Signed-off-by: Mathis <yidhra@tuta.io>
2024-05-02 14:25:10 +02:00
13 changed files with 390 additions and 88 deletions

View File

@ -52,11 +52,11 @@ try {
try {
app.listen(process.env["APP_PORT"]);
logger.info(
`Server is running !\n >> Memory total: ${
Math.round(process.memoryUsage().rss / 1_000_000)
} Mio\n >> Memory heap: ${
Math.round(process.memoryUsage().heapUsed / 1_000_000)
} Mio\n`,
`Server is running !\n >> Memory total: ${Math.round(
process.memoryUsage().rss / 1_000_000,
)} Mio\n >> Memory heap: ${Math.round(
process.memoryUsage().heapUsed / 1_000_000,
)} Mio\n`,
);
} catch (error) {
logger.error(`Server failed to start: ${error}`);

View File

@ -1,22 +1,31 @@
import JwtService from "@services/jwt.service";
import type { IReqEditUserData } from "@interfaces/IReqEditUserData";
import { HttpStatusCode } from "@interfaces/requests/HttpStatusCode";
import type { IReqRegister } from "@interfaces/requests/IReqRegister";
import UserService from "@services/user.service";
import { isDebugMode } from "@utils/debugState";
import { isEmail } from "@utils/validators/email";
import type { Request, Response } from "express";
import { Logger } from "tslog";
import {isDebugMode} from "@utils/debugState";
const logger = new Logger({
name: "AuthController",
});
async function registerUser(req: Request, res: Response): Promise<unknown> {
/**
* Registers a user.
*
* @param {Request} req - The request object.
* @param {Response} res - The response object.
*
* @return {Promise} - A promise that resolves with the registration result or rejects with an error.
*/
async function registerUser(req: Request, res: Response): Promise<Response> {
const body: IReqRegister = req.body;
if (!body) {
logger.warn(`Invalid input data (${req.ip})`);
return res.type("application/json").status(400).json({
return res.type("application/json").status(HttpStatusCode.BadRequest).json({
error: "Invalid input data",
});
}
@ -28,14 +37,14 @@ async function registerUser(req: Request, res: Response): Promise<unknown> {
!body.email
) {
logger.warn(`Field(s) missing (${req.ip})`);
return res.type("application/json").status(400).json({
return res.type("application/json").status(HttpStatusCode.BadRequest).json({
error: "Field(s) missing",
});
}
if (!isEmail(body.email)) {
logger.warn(`Invalid email format (${req.ip})`);
return res.type("application/json").status(400).json({
return res.type("application/json").status(HttpStatusCode.BadRequest).json({
error: "Invalid email format",
});
}
@ -55,16 +64,19 @@ async function registerUser(req: Request, res: Response): Promise<unknown> {
const RegisterServiceResult = await UserService.register(sanitizeData);
if (RegisterServiceResult.error === "gdprNotApproved") {
if (typeof RegisterServiceResult !== 'string' && RegisterServiceResult.message === "GDPR acceptance is required.") {
logger.warn(`GDPR not approved (${req.ip})`);
return res.status(400).json({
return res.status(HttpStatusCode.BadRequest).json({
error: RegisterServiceResult.error,
message: "GDPR not accepted.",
});
}
if (typeof RegisterServiceResult !== 'string' && RegisterServiceResult.error === 5) {
if (
typeof RegisterServiceResult !== "string" &&
RegisterServiceResult.error === 5
) {
logger.warn(`The user already exists (${sanitizeData.email})`);
return res.type("application/json").status(400).json({
return res.type("application/json").status(HttpStatusCode.Conflict).json({
error: RegisterServiceResult.error,
message: "The user already exists.",
});
@ -72,7 +84,10 @@ async function registerUser(req: Request, res: Response): Promise<unknown> {
// SUCCESS
//logger.info(`User registered successfully (${sanitizeData.username})`);
return res.type("application/json").status(201).json({token:RegisterServiceResult});
return res
.type("application/json")
.status(HttpStatusCode.Ok)
.json({ token: RegisterServiceResult });
}
/**
@ -86,19 +101,19 @@ async function registerUser(req: Request, res: Response): Promise<unknown> {
async function loginUser(req: Request, res: Response): Promise<void> {
const body = req.body;
if (!body) {
res.type("application/json").status(400).json({
res.type("application/json").status(HttpStatusCode.BadRequest).json({
error: "Invalid input data",
});
}
if (!body.password || !body.username) {
if (!body.password || !body.email) {
logger.warn(`Field(s) missing (${req.ip})`);
res.type("application/json").status(400).json({
res.type("application/json").status(HttpStatusCode.BadRequest).json({
error: "Field(s) missing",
});
}
const loginData = {
username: `${body.username}`,
email: `${body.email}`,
password: `${body.password}`,
};
console.log(body);
@ -107,13 +122,13 @@ async function loginUser(req: Request, res: Response): Promise<void> {
if (LoginServiceResult.error === "userNotFound") {
console.log("POOL");
res.type("application/json").status(404).json({
res.type("application/json").status(HttpStatusCode.NotFound).json({
error: LoginServiceResult.error,
message: "User not found.",
});
}
if (LoginServiceResult.error === "invalidPassword") {
res.type("application/json").status(401).json({
res.type("application/json").status(HttpStatusCode.NotAcceptable).json({
error: LoginServiceResult.error,
message: "Invalid password.",
});
@ -126,35 +141,35 @@ async function getAllUsers(req: Request, res: Response) {
const bearerToken = authHeader?.split(" ")[1];
if (!bearerToken) {
logger.warn(`Bearer token not provided (${req.ip})`);
return res.type("application/json").status(401).json({
error: "Unauthorized",
return res.type("application/json").status(HttpStatusCode.Forbidden).json({
error: "Invalid token",
});
}
const payload = await JwtService.verify(bearerToken);
if (!payload) {
if (!payload || !payload.sub) {
logger.warn(`Unauthorized access attempt (${req.ip})`);
return res.type("application/json").status(401).json({
error: "Unauthorized",
return res.type("application/json").status(HttpStatusCode.Forbidden).json({
error: "Invalid token",
});
}
const sourceUser = await UserService.getFromId(payload.sub);
if (!sourceUser) {
return res.type("application/json").status(404).json({
return res.type("application/json").status(HttpStatusCode.ImATeapot).json({
error: "You dont exist anymore",
});
}
if (!sourceUser.is_admin) {
return res.type("application/json").status(403).json({
return res.type("application/json").status(HttpStatusCode.Forbidden).json({
error: "Unauthorized",
});
}
const AllUserResponse = await UserService.getAll();
if (!AllUserResponse.users) {
return res.type("application/json").status(500).json({
return res.type("application/json").status(HttpStatusCode.InternalServerError).json({
error: "Internal server error",
});
}
return res.type("application/json").status(200).json(AllUserResponse);
return res.type("application/json").status(HttpStatusCode.Found).json(AllUserResponse);
}
async function getUser(req: Request, res: Response) {
@ -162,25 +177,25 @@ async function getUser(req: Request, res: Response) {
const bearerToken = authHeader?.split(" ")[1];
if (!bearerToken) {
logger.warn(`Bearer token not provided (${req.ip})`);
return res.type("application/json").status(401).json({
return res.type("application/json").status(HttpStatusCode.Unauthorized).json({
error: "Unauthorized",
});
}
const payload = await JwtService.verify(bearerToken);
if (!payload) {
if (!payload || !payload.sub) {
logger.warn(`Unauthorized access attempt (${req.ip})`);
return res.type("application/json").status(401).json({
return res.type("application/json").status(HttpStatusCode.Unauthorized).json({
error: "Unauthorized",
});
}
const sourceUser = await UserService.getFromId(payload.sub);
if (!sourceUser) {
return res.type("application/json").status(404).json({
return res.type("application/json").status(HttpStatusCode.ImATeapot).json({
error: "You dont exist anymore",
});
}
if (!sourceUser.is_admin) {
return res.type("application/json").status(403).json({
if ("username" in sourceUser && !sourceUser.is_admin) {
return res.type("application/json").status(HttpStatusCode.Unauthorized).json({
error: "Unauthorized",
});
}
@ -188,7 +203,7 @@ async function getUser(req: Request, res: Response) {
const dbUser = await UserService.getFromId(userId);
if (!dbUser) {
logger.warn(`User not found (${req.ip})`);
return res.type("application/json").status(404).json({
return res.type("application/json").status(HttpStatusCode.NotFound).json({
error: "User not found",
});
}
@ -196,7 +211,7 @@ async function getUser(req: Request, res: Response) {
delete dbUser.passwordHash;
// @ts-ignore
delete dbUser._id;
return res.type("application/json").status(200).json(dbUser);
return res.type("application/json").status(HttpStatusCode.Found).json(dbUser);
}
//FEAT - Implement re-auth by current password in case of password change
@ -216,7 +231,7 @@ async function editUser(req: Request, res: Response) {
});
}
const payload = await JwtService.verify(bearerToken);
if (!payload) {
if (!payload || !payload.sub) {
logger.warn(`Unauthorized access attempt (${req.ip})`);
return res.type("application/json").status(401).json({
error: "Unauthorized",
@ -373,24 +388,24 @@ async function getSelf(req: Request, res: Response) {
});
}
const payload = await JwtService.verify(bearerToken);
if (!payload) {
if (!payload || !payload.sub) {
logger.warn(`Unauthorized access attempt (${req.ip})`);
return res.type("application/json").status(401).json({
error: "Unauthorized",
});
}
const dbUser = await UserService.getFromId(payload.sub);
if (!dbUser) {
const GetUserResult = await UserService.getFromId(payload.sub);
if (!GetUserResult) {
return res.type("application/json").status(404).json({
error: "User not found",
});
}
return res.type("application/json").status(200).json({
id: dbUser.id,
username: dbUser.username,
firstName: dbUser.firstname,
lastName: dbUser.firstname,
isAdmin: dbUser.firstname,
id: GetUserResult.id,
username: GetUserResult.username,
firstName: GetUserResult.firstname,
lastName: GetUserResult.firstname,
isAdmin: GetUserResult.firstname,
});
}

View File

@ -1,8 +1,8 @@
import type IDbCategory from "@interfaces/database/IDbCategory";
import CategoryService from "@services/category.service";
import { isDebugMode } from "@utils/debugState";
import type { Request, Response } from "express";
import { Logger } from "tslog";
import {isDebugMode} from "@utils/debugState";
//import {validationResult} from "express-validator";
const logger = new Logger({

View File

@ -1,9 +1,9 @@
import type IDbModel from "@interfaces/database/IDbModel";
import CategoryService from "@services/category.service";
import ModelService from "@services/model.service";
import { isDebugMode } from "@utils/debugState";
import type { Request, Response } from "express";
import { Logger } from "tslog";
import {isDebugMode} from "@utils/debugState";
//import {validationResult} from "express-validator";
const logger = new Logger({

View File

@ -0,0 +1,269 @@
export enum HttpStatusCode {
/**
* Status code for a request indicating that the server received the request headers
* and the client should proceed to send the request body.
* @enum {number}
*/
Continue = 100,
/**
* Status code for a request indicating that the requester has asked the server to switch protocols.
* @enum {number}
*/
SwitchingProtocols = 101,
/**
* Status code for a request indicating that the server has received and is processing the request,
* but no response is available yet.
* @enum {number}
*/
Processing = 102,
/**
* Successful HTTP response
* @enum {number}
*/
Ok = 200,
/**
* Request has been fulfilled; new resource created as a result.
* @enum {number}
*/
Created = 201,
/**
* Request accepted, but not yet processed.
* @enum {number}
*/
Accepted = 202,
/**
* Request successful. Meta-information returned is from original server, not local.
* @enum {number}
*/
NonAuthoritativeInformation = 203,
/**
* Request processed. No content returned.
* @enum {number}
*/
NoContent = 204,
/**
* Server specifies part of document should be reset.
* @enum {number}
*/
ResetContent = 205,
/**
* Partial content returned due to GET.
* @enum {number}
*/
PartialContent = 206,
/**
* Multiple Resource Meta-Data: Could be used for collection instances.
* @enum {number}
*/
MultiStatus = 207,
/**
* Status code used to indicate that a certain request has been already reported.
* @enum {number}
*/
AlreadyReported = 208,
/**
* The server has fulfilled the request for the content, and the content is being conveyed in a manner described by the Content-Encoding, Content-Range, and Content-Type headers.
* @enum {number}
*/
ImUsed = 226,
/**
* @enum {number}
* @description HTTP status code for multiple choices
*/
MultipleChoices = 300,
/**
* @enum {number}
* @description HTTP status code for moved permanently
*/
MovedPermanently = 301,
/**
* @enum {number}
* @description HTTP status code for found
*/
Found = 302,
/**
* @enum {number}
* @description HTTP status code for see other
*/
SeeOther = 303,
/**
* @enum {number}
* @description HTTP status code for not modified
*/
NotModified = 304,
/**
* @enum {number}
* @description HTTP status code for use proxy
*/
UseProxy = 305,
/**
* @enum {number}
* @description HTTP status code for temporary redirect
*/
TemporaryRedirect = 307,
/**
* @enum {number}
* @description HTTP status code for permanent redirect
*/
PermanentRedirect = 308,
/** @description Client error: The server could not understand the request due to invalid syntax. */
BadRequest = 400,
/** @description Client error: The client must authenticate itself to get the requested response. */
Unauthorized = 401,
/** @description Client error: This response code is reserved for future use. */
PaymentRequired = 402,
/** @description Client error: The client does not have access rights to the content; that is, it is unauthorized, so the server is refusing to give the requested resource. */
Forbidden = 403,
/** @description Client error: The server cannot find requested resource. */
NotFound = 404,
/** @description Client error: The request method is not supported by the server and cannot be handled. */
MethodNotAllowed = 405,
/** @description Client error: This response is sent when the web server, after performing server-driven content negotiation, doesn't find any content following the criteria given by the user agent. */
NotAcceptable = 406,
/** @description Client error: This is similar to 401 (Unauthorised), but indicates that the client must authenticate itself to get the requested response. */
ProxyAuthenticationRequired = 407,
/** @description Client error: This response is sent on an idle connection by some servers, even without any previous request by the client. */
RequestTimeout = 408,
/** @description Client error: This response is sent when a request conflicts with the current state of the server. */
Conflict = 409,
/** @description Client error: This response is sent when the requested content has been permanently deleted from server, with no forwarding address. */
Gone = 410,
/** @description Client error: The server refuses to accept the request without a defined Content- Length. */
LengthRequired = 411,
/** @description Client error: The precondition given in the request evaluated to false by the server. */
PreconditionFailed = 412,
/** @description Client error: Request entity is larger than limits defined by server. */
PayloadTooLarge = 413,
/** @description Client error: The URI requested by the client is longer than the server is willing to interpret. */
UriTooLong = 414,
/** @description Client error: The media format of the requested data is not supported by the server, so the server is rejecting the request. */
UnsupportedMediaType = 415,
/** @description Client error: The range specified by the Range header field in the request can't be fulfilled. */
RangeNotSatisfiable = 416,
/** @description Client error: This response code means the expectation indicated by the Expect request header field can't be met by the server. */
ExpectationFailed = 417,
/** @description Client error: The server refuses to brew coffee because it is, permanently, a teapot. */
ImATeapot = 418,
/**
* @enum
* @name MisdirectedRequest
* @description Represents HTTP status code 421: Misdirected Request.
* The client should switch to a different protocol such as TLS/1.0.
*/
MisdirectedRequest = 421,
/**
* @enum
* @name UnprocessableEntity
* @description Represents HTTP status code 422: Unprocessable Entity.
* The request was well-formed but was unable to be followed due to semantic errors.
*/
UnprocessableEntity = 422,
/**
* @enum
* @name Locked
* @description Represents HTTP status code 423: Locked.
* The resource that is being accessed is locked.
*/
Locked = 423,
/**
* @enum
* @name FailedDependency
* @description Represents HTTP status code 424: Failed Dependency.
* The request failed because it depended on another request and that request failed.
*/
FailedDependency = 424,
/**
* @enum
* @name TooEarly
* @description Represents HTTP status code 425: Too Early.
* Indicates that the server is unwilling to risk processing a request that might be replayed.
*/
TooEarly = 425,
/**
* @enum
* @name UpgradeRequired
* @description Represents HTTP status code 426: Upgrade Required.
* The client should switch to a different protocol.
*/
UpgradeRequired = 426,
/**
* @enum
* @name PreconditionRequired
* @description Represents HTTP status code 428: Precondition Required.
* The client must first fulfill certain precondition.
*/
PreconditionRequired = 428,
/**
* @enum
* @name TooManyRequests
* @description Represents HTTP status code 429: Too Many Requests.
* The user has sent too many requests in a certain amount of time.
*/
TooManyRequests = 429,
/**
* @enum
* @name RequestHeaderFieldsTooLarge
* @description Represents HTTP status code 431: Request Header Fields Too Large.
* The server is unwilling to process the request because its header fields are too large.
*/
RequestHeaderFieldsTooLarge = 431,
/**
* @enum
* @name UnavailableForLegalReasons
* @description Represents HTTP status code 451: Unavailable For Legal Reasons.
* The server is denying access for legal reasons.
*/
UnavailableForLegalReasons = 451,
InternalServerError = 500,
NotImplemented = 501,
BadGateway = 502,
ServiceUnavailable = 503,
GatewayTimeout = 504,
HttpVersionNotSupported = 505,
VariantAlsoNegotiates = 506,
InsufficientStorage = 507,
LoopDetected = 508,
NotExtended = 510,
NetworkAuthenticationRequired = 511,
}

View File

@ -1,8 +1,8 @@
import type IDbBrand from "@interfaces/database/IDbBrand";
import MysqlService from "@services/mysql.service";
import { isDebugMode } from "@utils/debugState";
import { Logger } from "tslog";
import { v4 as uuidv4 } from "uuid";
import {isDebugMode} from "@utils/debugState";
const DbHandler = new MysqlService.Handler("BrandService");
const logger = new Logger({

View File

@ -1,8 +1,8 @@
import type { IDbCategory } from "@interfaces/database/IDbCategory";
import MysqlService from "@services/mysql.service";
import { isDebugMode } from "@utils/debugState";
import { Logger } from "tslog";
import { v4 as uuidv4 } from "uuid";
import {isDebugMode} from "@utils/debugState";
const DbHandler = new MysqlService.Handler("CategoryService");
const logger = new Logger({

View File

@ -1,3 +1,4 @@
import { isDebugMode } from "@utils/debugState";
import {
type JWTHeaderParameters,
type JWTPayload,
@ -5,7 +6,6 @@ import {
jwtVerify,
} from "jose";
import { Logger } from "tslog";
import {isDebugMode} from "@utils/debugState";
const logger = new Logger({
name: "JwtService",

View File

@ -1,8 +1,8 @@
import type IDbModel from "@interfaces/database/IDbModel";
import MysqlService from "@services/mysql.service";
import { isDebugMode } from "@utils/debugState";
import { Logger } from "tslog";
import { v4 as uuidv4 } from "uuid";
import {isDebugMode} from "@utils/debugState";
const DbHandler = new MysqlService.Handler("ModelService");
const logger = new Logger({

View File

@ -10,9 +10,9 @@ import type { IDbStatusResult } from "@interfaces/database/IDbStatusResult";
import type { IDbUser } from "@interfaces/database/IDbUser";
import type { IDbVehicle } from "@interfaces/database/IDbVehicle";
import type { IUserUpdate } from "@interfaces/services/IUserUpdate";
import { isDebugMode } from "@utils/debugState";
import mysql, { type Connection, type ConnectionOptions } from "mysql2";
import { Logger } from "tslog";
import {isDebugMode} from "@utils/debugState";
const access: ConnectionOptions = {
host: `${process.env["MYSQL_HOST"]}`,
@ -38,7 +38,8 @@ class MysqlHandler {
this.Logger.error(`\n\n> Error connecting to MySQL: \n${err}\n`);
process.exit(1);
}
if (isDebugMode()) this.Logger.debug(
if (isDebugMode())
this.Logger.debug(
`\n\n> Connected to MySQL database (${access.database})\n`,
);
});
@ -82,12 +83,16 @@ class MysqlHandler {
(key: string) => `${key}`,
);
const values = Object.values(data.values).map((val) => val);
if (isDebugMode()) this.Logger.debug(
if (isDebugMode())
this.Logger.debug(
`\n\n>-> Factorized ${_sqlQueryKeys.length} keys for a prepare Query.\n>-> Action: ${data.actionName}\n`,
);
const sqlQueryKeys = _sqlQueryKeys.join(", ");
if (_id && _id.length > 2) {
if (isDebugMode()) this.Logger.trace(`\n\n> Id post-pushed in factorized data.\n ${_id}`);
if (isDebugMode())
this.Logger.trace(
`\n\n> Id post-pushed in factorized data.\n ${_id}`,
);
values.push(_id);
}

View File

@ -5,9 +5,10 @@ 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 { isDebugMode } from "@utils/debugState";
import { Logger } from "tslog";
import { v4 } from "uuid";
import {isDebugMode} from "@utils/debugState";
import {IUserUpdate} from "@interfaces/services/IUserUpdate";
const logger = new Logger({
name: "UserService",
@ -203,7 +204,7 @@ async function login(inputData: IReqLogin): Promise<ISError | string> {
message: dbUser.message,
};
}
if (!dbUser.id) {
if (!dbUser?.id) {
return {
error: ErrorType.NotFound,
message: "User not found.",
@ -219,6 +220,7 @@ async function login(inputData: IReqLogin): Promise<ISError | string> {
message: "Invalid password.",
};
}
// Generate the JSDoc definition for those html status code
const token = await JwtService.sign(
{
sub: dbUser.id,
@ -235,6 +237,10 @@ async function login(inputData: IReqLogin): Promise<ISError | string> {
"1d",
"user",
);
if (isDebugMode())
logger.trace(
`\n\n> New token for login of "${dbUser.username}".\n${token}`,
);
return token;
} catch (err) {
logger.error(`\n\n${err}\n`);
@ -245,14 +251,21 @@ async function login(inputData: IReqLogin): Promise<ISError | string> {
}
}
/**
* Retrieves a user from the database by email.
*
* @param {string} email - The email associated with the user.
* @return {Promise<IDbUser | false>} - A Promise that resolves to the user (if found) or false (if not found).
*/
async function getByEmailService(email: string): Promise<IDbUser | false> {
const dbUser = await MySqlService.User.getByEmail(DbHandler, email);
if (dbUser === undefined) {
logger.trace(`\n\n> User not found in DB (${email})\n`);
if (dbUser.length === 0) {
if (isDebugMode()) logger.trace(`\n\n> User not found in DB (${email})\n`);
return false;
}
logger.trace(dbUser);
return dbUser;
if (isDebugMode()) logger.trace(dbUser);
if (dbUser.length > 1 && dbUser[0]) return dbUser[0];
return false;
}
//TOTest
@ -282,8 +295,8 @@ async function getAllUsersService(): Promise<Array<IDbUser> | ISError> {
}
async function editUserService(
targetId,
inputData: IDbUser,
targetId: string,
inputData: IUserUpdate,
): Promise<ISError | boolean> {
if (!targetId || targetId.length !== 36) {
logger.info(`\n\n> Invalid ID (${targetId})\n`);
@ -293,18 +306,20 @@ async function editUserService(
};
}
const dbUser = await MySqlService.User.getById(DbHandler, targetId);
if (!dbUser.id) {
if (!dbUser[0] || !dbUser[0].id) {
return {
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,
});
const result = await MySqlService.User.update(DbHandler, inputData);
if (result.affectedRows === 0) {
return {
error: ErrorType.DatabaseError,
message: "An unknown error occurred.",
};
}
return true;
}
/**
@ -313,13 +328,12 @@ async function editUserService(
* @param {string} targetId - The ID of the user to be deleted.
* @return {Promise<boolean>} - A promise that resolves to true if the user is successfully deleted, or false if an error occurs.
*/
async function deleteUserService(targetId) {
async function deleteUserService(targetId: string): Promise<boolean> {
logger.info(`Deleting user ${targetId}`);
try {
await Db.collection("users").deleteOne({
id: targetId,
});
return true;
const DeleteResult = await MySqlService.User.delete(DbHandler, targetId)
if (DeleteResult.affectedRows !== 0) return true;
return false;
} catch (e) {
logger.warn(e);
return false;

View File

@ -1,8 +1,7 @@
import process from "node:process";
export function isDebugMode() {
if (process.env["DEBUG"] === 'true') {
if (process.env["DEBUG"] === "true") {
return true;
}
return false;