fixing in user and authentication
This commit is contained in:
@ -1,13 +1,54 @@
|
||||
export class AppError extends Error {
|
||||
public readonly statusCode: number;
|
||||
public readonly details?: any;
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { returnErrorResponse } from "../../callback/httpResponse";
|
||||
import { AppError } from "../instances/app";
|
||||
import { PrismaErrorCodeList } from "../../../utils/databases/prisma/error/codeList";
|
||||
|
||||
constructor(statusCode = 400, message: string, details?: any) {
|
||||
super(message);
|
||||
this.name = "AppError";
|
||||
this.statusCode = statusCode;
|
||||
this.details = details;
|
||||
|
||||
Object.setPrototypeOf(this, AppError.prototype);
|
||||
export const mainErrorHandler = (set: any, error: unknown) => {
|
||||
if (error instanceof AppError) {
|
||||
return returnErrorResponse(
|
||||
set,
|
||||
error.statusCode,
|
||||
error.message,
|
||||
error.details
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (error instanceof Prisma.PrismaClientKnownRequestError) {
|
||||
const errorInfo = PrismaErrorCodeList[error.code];
|
||||
|
||||
if (errorInfo)
|
||||
return returnErrorResponse(
|
||||
set,
|
||||
errorInfo.status,
|
||||
errorInfo.message,
|
||||
error.meta ?? {}
|
||||
);
|
||||
}
|
||||
|
||||
if (error instanceof Prisma.PrismaClientUnknownRequestError) {
|
||||
return returnErrorResponse(set, 500, "Unknown database error");
|
||||
}
|
||||
|
||||
if (error instanceof Prisma.PrismaClientRustPanicError) {
|
||||
return returnErrorResponse(
|
||||
set,
|
||||
500,
|
||||
"Database engine crashed unexpectedly"
|
||||
);
|
||||
}
|
||||
|
||||
if (error instanceof Prisma.PrismaClientInitializationError) {
|
||||
return returnErrorResponse(set, 500, "Database initialization failed");
|
||||
}
|
||||
|
||||
if (error instanceof Prisma.PrismaClientValidationError) {
|
||||
return returnErrorResponse(
|
||||
set,
|
||||
400,
|
||||
"Invalid input to query",
|
||||
error.message
|
||||
);
|
||||
}
|
||||
|
||||
return returnErrorResponse(set, 500, "Internal server error");
|
||||
};
|
||||
|
||||
13
src/helpers/error/instances/app.ts
Normal file
13
src/helpers/error/instances/app.ts
Normal file
@ -0,0 +1,13 @@
|
||||
export class AppError extends Error {
|
||||
public readonly statusCode: number;
|
||||
public readonly details?: any;
|
||||
|
||||
constructor(statusCode = 400, message: string, details?: any) {
|
||||
super(message);
|
||||
this.name = "AppError";
|
||||
this.statusCode = statusCode;
|
||||
this.details = details;
|
||||
|
||||
Object.setPrototypeOf(this, AppError.prototype);
|
||||
}
|
||||
}
|
||||
@ -3,7 +3,7 @@ import { loginWithPasswordService } from "../services/loginWithPassword.service"
|
||||
import { loginWithPasswordSchema } from "../auth.schema";
|
||||
import { returnErrorResponse } from "../../../helpers/callback/httpResponse";
|
||||
import { LoginWithPasswordRequest } from "../auth.types";
|
||||
import { AppError } from "../../../helpers/error/handler";
|
||||
import { mainErrorHandler } from "../../../helpers/error/handler";
|
||||
|
||||
export const loginWithPassword = async (
|
||||
ctx: Context & { body: LoginWithPasswordRequest }
|
||||
@ -16,13 +16,6 @@ export const loginWithPassword = async (
|
||||
const result = await loginWithPasswordService(ctx.body);
|
||||
return result;
|
||||
} catch (error) {
|
||||
if (error instanceof AppError) {
|
||||
return returnErrorResponse(
|
||||
ctx.set,
|
||||
error.statusCode,
|
||||
error.message,
|
||||
error.details
|
||||
);
|
||||
}
|
||||
return mainErrorHandler(ctx.set, error);
|
||||
}
|
||||
};
|
||||
|
||||
@ -1,11 +1,19 @@
|
||||
import bcrypt from "bcrypt";
|
||||
import { findUserByEmailOrUsernameService } from "../../user/services/findUserByEmailOrUsername.service";
|
||||
import { LoginWithPasswordRequest } from "../auth.types";
|
||||
import { AppError } from "../../../helpers/error/instances/app";
|
||||
|
||||
export const loginWithPasswordService = async (
|
||||
data: LoginWithPasswordRequest
|
||||
request: LoginWithPasswordRequest
|
||||
) => {
|
||||
try {
|
||||
const userData = await findUserByEmailOrUsernameService(data.identifier);
|
||||
// search for user data using an identifier (username or email)
|
||||
const userData = await findUserByEmailOrUsernameService(request.identifier);
|
||||
|
||||
// Validate the password in the request with the existing one
|
||||
if (!(await bcrypt.compare(request.password, userData.password)))
|
||||
throw new AppError(401, "Password incorrect");
|
||||
|
||||
return userData;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
|
||||
@ -2,11 +2,11 @@ import { Prisma } from "@prisma/client";
|
||||
import { Context } from "elysia";
|
||||
import { createUserSchema } from "../user.schema";
|
||||
import { createUserService } from "../services/createUser.service";
|
||||
import { handlePrismaError } from "../../../utils/databases/prisma/error/handler";
|
||||
import {
|
||||
returnErrorResponse,
|
||||
returnWriteResponse,
|
||||
} from "../../../helpers/callback/httpResponse";
|
||||
import { mainErrorHandler } from "../../../helpers/error/handler";
|
||||
|
||||
/**
|
||||
* @function createUser
|
||||
@ -45,8 +45,6 @@ export const createUser = async (
|
||||
newUser
|
||||
);
|
||||
} catch (error) {
|
||||
// Handle any errors that occur during user creation
|
||||
const { status, message, details } = handlePrismaError(error);
|
||||
return returnErrorResponse(ctx.set, status, message, details);
|
||||
return mainErrorHandler(ctx.set, error);
|
||||
}
|
||||
};
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
import { handlePrismaError } from "../../../utils/databases/prisma/error/handler";
|
||||
import {
|
||||
returnErrorResponse,
|
||||
returnReadResponse,
|
||||
} from "../../../helpers/callback/httpResponse";
|
||||
import { Context } from "elysia";
|
||||
import { getAllUsersService } from "../services/getAllUser.service";
|
||||
import { mainErrorHandler } from "../../../helpers/error/handler";
|
||||
|
||||
export const getAllUser = async (ctx: Context) => {
|
||||
try {
|
||||
@ -16,7 +16,6 @@ export const getAllUser = async (ctx: Context) => {
|
||||
allUser
|
||||
);
|
||||
} catch (error) {
|
||||
const { status, message, details } = handlePrismaError(error);
|
||||
return returnErrorResponse(ctx.set, status, message, details);
|
||||
return mainErrorHandler(ctx.set, error);
|
||||
}
|
||||
};
|
||||
|
||||
17
src/modules/user/repositories/createUser.repository.ts
Normal file
17
src/modules/user/repositories/createUser.repository.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { userModel } from "../user.model";
|
||||
|
||||
export const createUserRepo = async (data: Prisma.UserCreateInput) => {
|
||||
try {
|
||||
const userData = await userModel.create({
|
||||
data,
|
||||
omit: {
|
||||
password: true,
|
||||
},
|
||||
});
|
||||
|
||||
return userData;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
@ -1,4 +1,4 @@
|
||||
import { AppError } from "../../../helpers/error/handler";
|
||||
import { AppError } from "../../../helpers/error/instances/app";
|
||||
import { userModel } from "../user.model";
|
||||
|
||||
export const findUserByEmailOrUsernameRepo = async (identifier: string) => {
|
||||
|
||||
15
src/modules/user/repositories/getAllUser.repository.ts
Normal file
15
src/modules/user/repositories/getAllUser.repository.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import { userModel } from "../user.model";
|
||||
|
||||
export const getAllUserRepo = async () => {
|
||||
try {
|
||||
const data = await userModel.findMany({
|
||||
where: {
|
||||
deletedAt: null,
|
||||
},
|
||||
});
|
||||
|
||||
return data;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
@ -1,18 +1,15 @@
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { hashPassword } from "../../../helpers/security/password/hash";
|
||||
import { userModel } from "../user.model";
|
||||
import { createUserRepo } from "../repositories/createUser.repository";
|
||||
|
||||
export const createUserService = async (userData: Prisma.UserCreateInput) => {
|
||||
const { password, ...rest } = userData; // Destructure the password and the rest of the user data
|
||||
const hashedPassword = await hashPassword(password); // Hash the password before saving to the database
|
||||
|
||||
// Create the user in the database using Prisma
|
||||
try {
|
||||
const newUser = await userModel.create({
|
||||
data: {
|
||||
...rest,
|
||||
password: hashedPassword,
|
||||
},
|
||||
const newUser = await createUserRepo({
|
||||
...rest,
|
||||
password: hashedPassword,
|
||||
});
|
||||
return newUser;
|
||||
} catch (error) {
|
||||
|
||||
@ -1,12 +1,8 @@
|
||||
import { userModel } from "../user.model";
|
||||
import { getAllUserRepo } from "../repositories/getAllUser.repository";
|
||||
|
||||
export const getAllUsersService = async () => {
|
||||
try {
|
||||
const allUser = await userModel.findMany({
|
||||
where: {
|
||||
deletedAt: null,
|
||||
},
|
||||
});
|
||||
const allUser = await getAllUserRepo();
|
||||
return allUser;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
|
||||
@ -6,7 +6,7 @@ import {
|
||||
} from "../../../helpers/callback/httpResponse";
|
||||
import { createUserRoleSchema } from "../userRole.schema";
|
||||
import { createUserRoleService } from "../services/createUserRole.service";
|
||||
import { handlePrismaError } from "../../../utils/databases/prisma/error/handler";
|
||||
import { handlePrismaError } from "../../../helpers/error/instances/prisma";
|
||||
import { JWTDecodeToken } from "../../../helpers/cookies/jwt/decodeToken";
|
||||
|
||||
/**
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { Context } from "elysia";
|
||||
import { createUserSessionService } from "../services/createUserSession.service";
|
||||
import { getUserHeaderInformation } from "../../../helpers/cookies/userHeader/getUserHeaderInformation";
|
||||
import { handlePrismaError } from "../../../utils/databases/prisma/error/handler";
|
||||
import { handlePrismaError } from "../../../helpers/error/instances/prisma";
|
||||
import {
|
||||
returnErrorResponse,
|
||||
returnWriteResponse,
|
||||
|
||||
@ -1,51 +0,0 @@
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { PrismaErrorCodeList } from "./codeList";
|
||||
import { PrismaErrorTypes } from "./types";
|
||||
|
||||
/**
|
||||
* Handles Prisma-specific errors and returns a structured response.
|
||||
*
|
||||
* This helper is designed to standardize error handling for Prisma operations
|
||||
* and provide clear differentiation between client-side and server-side errors.
|
||||
*
|
||||
* It maps known Prisma errors to HTTP status codes and human-readable messages,
|
||||
* allowing consistent and centralized error handling across the application.
|
||||
*
|
||||
* ### Supported Error Codes:
|
||||
* - P2002: Duplicate field detected.
|
||||
* - P2025: Record not found.
|
||||
* - P2003: Foreign key constraint failed
|
||||
* - Validation errors handled via `PrismaClientValidationError`.
|
||||
*
|
||||
* @param {unknown} error - The error thrown by a Prisma operation.
|
||||
* @returns {ErrorResponse} A structured error response object.
|
||||
*/
|
||||
export const handlePrismaError = (error: unknown): PrismaErrorTypes => {
|
||||
// Check for Prisma known request errors (e.g., P2002, P2025)
|
||||
if (error instanceof Prisma.PrismaClientKnownRequestError) {
|
||||
const mappedError = PrismaErrorCodeList[error.code];
|
||||
if (mappedError) {
|
||||
return {
|
||||
status: mappedError.status,
|
||||
message: mappedError.message,
|
||||
details: error.meta,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Handle Prisma validation errors
|
||||
if (error instanceof Prisma.PrismaClientValidationError) {
|
||||
return {
|
||||
status: 400,
|
||||
message: "Validation failed",
|
||||
details: error.message,
|
||||
};
|
||||
}
|
||||
|
||||
// Fallback for unknown errors (typically server errors)
|
||||
return {
|
||||
status: 500,
|
||||
message: "An unexpected error occurred",
|
||||
details: error,
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user