From 32dc3dae4a059c9030bf59215f5cd90722221f04 Mon Sep 17 00:00:00 2001 From: rafiarrafif Date: Wed, 7 May 2025 03:46:22 +0700 Subject: [PATCH] add controller and service for create user --- bun.lockb | Bin 30694 -> 50845 bytes package.json | 2 + src/helpers/security/password/hash.ts | 6 ++ .../user/controller/createUser.controller.ts | 56 ++++++++++++++++++ src/modules/user/index.ts | 5 +- .../user/services/createUser.service.ts | 22 +++++++ src/modules/user/user.model.ts | 3 + src/modules/user/user.schema.ts | 15 +++++ .../controller/createUserRole.controller.ts | 19 +++--- 9 files changed, 118 insertions(+), 10 deletions(-) create mode 100644 src/helpers/security/password/hash.ts diff --git a/bun.lockb b/bun.lockb index e4fd7e65f77e8666732ac404558ac978aef11d15..9e8bf1e30db9ed230df71c4f40839e5d7dea4c35 100644 GIT binary patch delta 17126 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 diff --git a/package.json b/package.json index cfd7221..b677444 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,9 @@ }, "dependencies": { "@prisma/client": "^6.7.0", + "@types/bcrypt": "^5.0.2", "@types/jsonwebtoken": "^9.0.9", + "bcrypt": "^5.1.1", "cookie": "^1.0.2", "elysia": "latest", "joi": "^17.13.3", diff --git a/src/helpers/security/password/hash.ts b/src/helpers/security/password/hash.ts new file mode 100644 index 0000000..de949d2 --- /dev/null +++ b/src/helpers/security/password/hash.ts @@ -0,0 +1,6 @@ +import bcrypt from "bcrypt"; + +export const hashPassword = async (password: string): Promise => { + const saltRounds = Number(process.env.SALT_ROUNDS); + return await bcrypt.hash(password, saltRounds); +}; diff --git a/src/modules/user/controller/createUser.controller.ts b/src/modules/user/controller/createUser.controller.ts index e69de29..c3387d4 100644 --- a/src/modules/user/controller/createUser.controller.ts +++ b/src/modules/user/controller/createUser.controller.ts @@ -0,0 +1,56 @@ +import { Prisma } from "@prisma/client"; +import { Context } from "elysia"; +import { createUserSchema } from "../user.schema"; +import { createUserService } from "../services/createUser.service"; +import { PrismaErrorTypes } from "../../../utils/databases/prisma/error/types"; +import { + returnErrorResponse, + returnWriteResponse, +} from "../../../helpers/callback/httpResponse"; + +/** + * @function createUser + * @description Creates a new user in the database. + * + * @param {Context & { body: Prisma.UserCreateInput }} ctx - The context object containing the request body. + * @param {Prisma.UserCreateInput} ctx.body - The user data to be created. + * + * @returns {Promise} A response object indicating success or failure. + * @throws {Object} An error response object if validation fails or an error occurs during user creation. + * + * @example + * Request route: POST /users + * Request body: + * { + * "username": "john_doe", + * "email": "john@example.com", + * "password": "password123" + * } + */ +export const createUser = async ( + ctx: Context & { body: Prisma.UserCreateInput } +) => { + // Validate the user input using a validation schema + const { error } = createUserSchema.validate(ctx.body); + if (error) + return returnErrorResponse(ctx.set, 400, "Invalid user input", error); + + // Create the user in the database using the service + createUserService(ctx.body) + .then((result) => { + return returnWriteResponse( + ctx.set, + 201, + "User created successfully", + result + ); + }) + .catch((error: PrismaErrorTypes) => { + return returnErrorResponse( + ctx.set, + error.status, + error.message, + error.details + ); + }); +}; diff --git a/src/modules/user/index.ts b/src/modules/user/index.ts index 3a2b134..6a4e208 100644 --- a/src/modules/user/index.ts +++ b/src/modules/user/index.ts @@ -1,6 +1,7 @@ import Elysia from "elysia"; import { getAllUser } from "./controller/getAllUser.controller"; +import { createUser } from "./controller/createUser.controller"; export const userModule = new Elysia({ prefix: "/users" }) - .get("/", () => "Hello User Module") - .post("/", () => getAllUser); + .get("/", () => getAllUser) + .post("/", () => createUser); diff --git a/src/modules/user/services/createUser.service.ts b/src/modules/user/services/createUser.service.ts index e69de29..a31b225 100644 --- a/src/modules/user/services/createUser.service.ts +++ b/src/modules/user/services/createUser.service.ts @@ -0,0 +1,22 @@ +import { Prisma } from "@prisma/client"; +import { hashPassword } from "../../../helpers/security/password/hash"; +import { userModel } from "../user.model"; +import { handlePrismaError } from "../../../utils/databases/prisma/error/handler"; + +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, + }, + }); + return newUser; + } catch (error) { + return handlePrismaError(error); + } +}; diff --git a/src/modules/user/user.model.ts b/src/modules/user/user.model.ts index e69de29..80f0114 100644 --- a/src/modules/user/user.model.ts +++ b/src/modules/user/user.model.ts @@ -0,0 +1,3 @@ +import { prisma } from "../../utils/databases/prisma/connection"; + +export const userModel = prisma.user; diff --git a/src/modules/user/user.schema.ts b/src/modules/user/user.schema.ts index e69de29..3021ddf 100644 --- a/src/modules/user/user.schema.ts +++ b/src/modules/user/user.schema.ts @@ -0,0 +1,15 @@ +import Joi from "joi"; + +export const createUserSchema = Joi.object({ + name: Joi.string().min(4).max(255).required(), + username: Joi.string().min(4).max(255).required(), + email: Joi.string().email().required(), + password: Joi.string().min(8).max(255).required(), + birthdate: Joi.date(), + gender: Joi.string().valid("male", "female"), + phoneCC: Joi.string().min(2).max(2), + phoneNumber: Joi.string().min(7).max(15), + bioProfile: Joi.string().max(300), + profilePicture: Joi.string().uri(), + commentPicture: Joi.string().uri(), +}); diff --git a/src/modules/userRole/controller/createUserRole.controller.ts b/src/modules/userRole/controller/createUserRole.controller.ts index 97d596a..ba5167f 100644 --- a/src/modules/userRole/controller/createUserRole.controller.ts +++ b/src/modules/userRole/controller/createUserRole.controller.ts @@ -4,10 +4,8 @@ import { returnErrorResponse, returnWriteResponse, } from "../../../helpers/callback/httpResponse"; -import { handlePrismaError } from "../../../utils/databases/prisma/error/handler"; import { createUserRoleSchema } from "../userRole.schema"; import { JWTDecodeToken } from "../../../helpers/jwt/decodeToken"; -import { prisma } from "../../../utils/databases/prisma/connection"; import { createUserRoleService } from "../services/createUserRole.service"; import { PrismaErrorTypes } from "../../../utils/databases/prisma/error/types"; @@ -72,10 +70,15 @@ export const createUserRole = async ( }; createUserRoleService(dataPayload) - .then((result) => - returnWriteResponse(ctx.set, 201, "User role created", result) - ) - .catch((error: PrismaErrorTypes) => - returnErrorResponse(ctx.set, error.status, error.message, error.details) - ); + .then((result) => { + return returnWriteResponse(ctx.set, 201, "User role created", result); + }) + .catch((error: PrismaErrorTypes) => { + return returnErrorResponse( + ctx.set, + error.status, + error.message, + error.details + ); + }); };