fixing in user and authentication
This commit is contained in:
@ -1,13 +1,54 @@
|
|||||||
export class AppError extends Error {
|
import { Prisma } from "@prisma/client";
|
||||||
public readonly statusCode: number;
|
import { returnErrorResponse } from "../../callback/httpResponse";
|
||||||
public readonly details?: any;
|
import { AppError } from "../instances/app";
|
||||||
|
import { PrismaErrorCodeList } from "../../../utils/databases/prisma/error/codeList";
|
||||||
|
|
||||||
constructor(statusCode = 400, message: string, details?: any) {
|
export const mainErrorHandler = (set: any, error: unknown) => {
|
||||||
super(message);
|
if (error instanceof AppError) {
|
||||||
this.name = "AppError";
|
return returnErrorResponse(
|
||||||
this.statusCode = statusCode;
|
set,
|
||||||
this.details = details;
|
error.statusCode,
|
||||||
|
error.message,
|
||||||
|
error.details
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Object.setPrototypeOf(this, AppError.prototype);
|
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 { loginWithPasswordSchema } from "../auth.schema";
|
||||||
import { returnErrorResponse } from "../../../helpers/callback/httpResponse";
|
import { returnErrorResponse } from "../../../helpers/callback/httpResponse";
|
||||||
import { LoginWithPasswordRequest } from "../auth.types";
|
import { LoginWithPasswordRequest } from "../auth.types";
|
||||||
import { AppError } from "../../../helpers/error/handler";
|
import { mainErrorHandler } from "../../../helpers/error/handler";
|
||||||
|
|
||||||
export const loginWithPassword = async (
|
export const loginWithPassword = async (
|
||||||
ctx: Context & { body: LoginWithPasswordRequest }
|
ctx: Context & { body: LoginWithPasswordRequest }
|
||||||
@ -16,13 +16,6 @@ export const loginWithPassword = async (
|
|||||||
const result = await loginWithPasswordService(ctx.body);
|
const result = await loginWithPasswordService(ctx.body);
|
||||||
return result;
|
return result;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error instanceof AppError) {
|
return mainErrorHandler(ctx.set, error);
|
||||||
return returnErrorResponse(
|
|
||||||
ctx.set,
|
|
||||||
error.statusCode,
|
|
||||||
error.message,
|
|
||||||
error.details
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,11 +1,19 @@
|
|||||||
|
import bcrypt from "bcrypt";
|
||||||
import { findUserByEmailOrUsernameService } from "../../user/services/findUserByEmailOrUsername.service";
|
import { findUserByEmailOrUsernameService } from "../../user/services/findUserByEmailOrUsername.service";
|
||||||
import { LoginWithPasswordRequest } from "../auth.types";
|
import { LoginWithPasswordRequest } from "../auth.types";
|
||||||
|
import { AppError } from "../../../helpers/error/instances/app";
|
||||||
|
|
||||||
export const loginWithPasswordService = async (
|
export const loginWithPasswordService = async (
|
||||||
data: LoginWithPasswordRequest
|
request: LoginWithPasswordRequest
|
||||||
) => {
|
) => {
|
||||||
try {
|
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;
|
return userData;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw error;
|
throw error;
|
||||||
|
|||||||
@ -2,11 +2,11 @@ import { Prisma } from "@prisma/client";
|
|||||||
import { Context } from "elysia";
|
import { Context } from "elysia";
|
||||||
import { createUserSchema } from "../user.schema";
|
import { createUserSchema } from "../user.schema";
|
||||||
import { createUserService } from "../services/createUser.service";
|
import { createUserService } from "../services/createUser.service";
|
||||||
import { handlePrismaError } from "../../../utils/databases/prisma/error/handler";
|
|
||||||
import {
|
import {
|
||||||
returnErrorResponse,
|
returnErrorResponse,
|
||||||
returnWriteResponse,
|
returnWriteResponse,
|
||||||
} from "../../../helpers/callback/httpResponse";
|
} from "../../../helpers/callback/httpResponse";
|
||||||
|
import { mainErrorHandler } from "../../../helpers/error/handler";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @function createUser
|
* @function createUser
|
||||||
@ -45,8 +45,6 @@ export const createUser = async (
|
|||||||
newUser
|
newUser
|
||||||
);
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// Handle any errors that occur during user creation
|
return mainErrorHandler(ctx.set, error);
|
||||||
const { status, message, details } = handlePrismaError(error);
|
|
||||||
return returnErrorResponse(ctx.set, status, message, details);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
import { handlePrismaError } from "../../../utils/databases/prisma/error/handler";
|
|
||||||
import {
|
import {
|
||||||
returnErrorResponse,
|
returnErrorResponse,
|
||||||
returnReadResponse,
|
returnReadResponse,
|
||||||
} from "../../../helpers/callback/httpResponse";
|
} from "../../../helpers/callback/httpResponse";
|
||||||
import { Context } from "elysia";
|
import { Context } from "elysia";
|
||||||
import { getAllUsersService } from "../services/getAllUser.service";
|
import { getAllUsersService } from "../services/getAllUser.service";
|
||||||
|
import { mainErrorHandler } from "../../../helpers/error/handler";
|
||||||
|
|
||||||
export const getAllUser = async (ctx: Context) => {
|
export const getAllUser = async (ctx: Context) => {
|
||||||
try {
|
try {
|
||||||
@ -16,7 +16,6 @@ export const getAllUser = async (ctx: Context) => {
|
|||||||
allUser
|
allUser
|
||||||
);
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const { status, message, details } = handlePrismaError(error);
|
return mainErrorHandler(ctx.set, error);
|
||||||
return returnErrorResponse(ctx.set, status, message, details);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
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";
|
import { userModel } from "../user.model";
|
||||||
|
|
||||||
export const findUserByEmailOrUsernameRepo = async (identifier: string) => {
|
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 { Prisma } from "@prisma/client";
|
||||||
import { hashPassword } from "../../../helpers/security/password/hash";
|
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) => {
|
export const createUserService = async (userData: Prisma.UserCreateInput) => {
|
||||||
const { password, ...rest } = userData; // Destructure the password and the rest of the user data
|
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
|
const hashedPassword = await hashPassword(password); // Hash the password before saving to the database
|
||||||
|
|
||||||
// Create the user in the database using Prisma
|
|
||||||
try {
|
try {
|
||||||
const newUser = await userModel.create({
|
const newUser = await createUserRepo({
|
||||||
data: {
|
|
||||||
...rest,
|
...rest,
|
||||||
password: hashedPassword,
|
password: hashedPassword,
|
||||||
},
|
|
||||||
});
|
});
|
||||||
return newUser;
|
return newUser;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@ -1,12 +1,8 @@
|
|||||||
import { userModel } from "../user.model";
|
import { getAllUserRepo } from "../repositories/getAllUser.repository";
|
||||||
|
|
||||||
export const getAllUsersService = async () => {
|
export const getAllUsersService = async () => {
|
||||||
try {
|
try {
|
||||||
const allUser = await userModel.findMany({
|
const allUser = await getAllUserRepo();
|
||||||
where: {
|
|
||||||
deletedAt: null,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
return allUser;
|
return allUser;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw error;
|
throw error;
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import {
|
|||||||
} from "../../../helpers/callback/httpResponse";
|
} from "../../../helpers/callback/httpResponse";
|
||||||
import { createUserRoleSchema } from "../userRole.schema";
|
import { createUserRoleSchema } from "../userRole.schema";
|
||||||
import { createUserRoleService } from "../services/createUserRole.service";
|
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";
|
import { JWTDecodeToken } from "../../../helpers/cookies/jwt/decodeToken";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { Context } from "elysia";
|
import { Context } from "elysia";
|
||||||
import { createUserSessionService } from "../services/createUserSession.service";
|
import { createUserSessionService } from "../services/createUserSession.service";
|
||||||
import { getUserHeaderInformation } from "../../../helpers/cookies/userHeader/getUserHeaderInformation";
|
import { getUserHeaderInformation } from "../../../helpers/cookies/userHeader/getUserHeaderInformation";
|
||||||
import { handlePrismaError } from "../../../utils/databases/prisma/error/handler";
|
import { handlePrismaError } from "../../../helpers/error/instances/prisma";
|
||||||
import {
|
import {
|
||||||
returnErrorResponse,
|
returnErrorResponse,
|
||||||
returnWriteResponse,
|
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