fixing in user and authentication

This commit is contained in:
rafiarrafif
2025-05-11 01:41:05 +07:00
parent 954d40df3b
commit 307c5e2d68
15 changed files with 122 additions and 96 deletions

BIN
bun.lockb

Binary file not shown.

View File

@ -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");
};

View 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);
}
}

View File

@ -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);
}
};

View File

@ -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;

View File

@ -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);
}
};

View File

@ -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);
}
};

View 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;
}
};

View File

@ -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) => {

View 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;
}
};

View File

@ -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) {

View File

@ -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;

View File

@ -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";
/**

View File

@ -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,

View File

@ -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,
};
};