From fdfafcd2e0129a44add58fe8cbbcd247e8767baf Mon Sep 17 00:00:00 2001 From: rafiarrafif Date: Tue, 17 Jun 2025 16:13:04 +0700 Subject: [PATCH] add:module:user:*update | add all service in module user for updating data --- src/modules/debug/debug.controller.ts | 19 +------ .../user/controller/editUser.controller.ts | 10 ++-- src/modules/user/index.ts | 2 +- ...ailAndUsernameAvailabillity.repository.ts} | 13 ++--- .../repositories/updateUser.repository.ts | 13 ++--- ...erEmailAndUsernameAvailabillity.service.ts | 20 +++++++ src/modules/user/services/editUser.service.ts | 52 ++++++++++++++++--- 7 files changed, 83 insertions(+), 46 deletions(-) rename src/modules/user/repositories/{checkUserEmailAndUsernameAvailability.repository.ts => checkUserEmailAndUsernameAvailabillity.repository.ts} (50%) create mode 100644 src/modules/user/services/checkUserEmailAndUsernameAvailabillity.service.ts diff --git a/src/modules/debug/debug.controller.ts b/src/modules/debug/debug.controller.ts index c5c2351..44ff492 100644 --- a/src/modules/debug/debug.controller.ts +++ b/src/modules/debug/debug.controller.ts @@ -1,24 +1,7 @@ import { Context } from "elysia"; -import { mainErrorHandler } from "../../helpers/error/handler"; -import { debugService } from "./debug.service"; -import { returnWriteResponse } from "../../helpers/callback/httpResponse"; -import { getCookie } from "../../helpers/http/userHeader/cookies/getCookies"; -import { checkUserEmailAndUsernameAvailabillity } from "../user/repositories/checkUserEmailAndUsernameAvailability.repository"; -import { jwtDecode } from "../../helpers/http/jwt/decode"; export const debugController = async (ctx: Context) => { - try { - const userCookie = getCookie(ctx); - const jwtSession = jwtDecode(userCookie.auth_token!); - jwtSession.user.email = ctx.params.email; - jwtSession.user.username = ctx.params.username; - const checkAvailabillity = await checkUserEmailAndUsernameAvailabillity( - jwtSession.user - ); - return checkAvailabillity; - } catch (error) { - return mainErrorHandler(ctx.set, error); - } + return "OK"; }; // buat debug untuk date to number (second) diff --git a/src/modules/user/controller/editUser.controller.ts b/src/modules/user/controller/editUser.controller.ts index dc90db3..5ecac13 100644 --- a/src/modules/user/controller/editUser.controller.ts +++ b/src/modules/user/controller/editUser.controller.ts @@ -10,20 +10,16 @@ import { getCookie } from "../../../helpers/http/userHeader/cookies/getCookies"; export const editUserController = async ( ctx: Context & { - params: { username: string }; body: Prisma.UserUncheckedCreateInput; } ) => { try { const userCookie = getCookie(ctx); - if (!userCookie.auth_token) + const auth_token = userCookie.auth_token; + if (!auth_token) return returnErrorResponse(ctx.set, 401, "User Unauthenticated"); - const editUser = await editUserService( - ctx.params.username, - userCookie.auth_token, - ctx.body - ); + const editUser = await editUserService(auth_token, ctx.body); return editUser; } catch (error) { return mainErrorHandler(ctx.set, error); diff --git a/src/modules/user/index.ts b/src/modules/user/index.ts index e787bda..02467f6 100644 --- a/src/modules/user/index.ts +++ b/src/modules/user/index.ts @@ -6,4 +6,4 @@ import { editUserController } from "./controller/editUser.controller"; export const userModule = new Elysia({ prefix: "/users" }) .get("/", getAllUserController) .post("/", createUserController) - .put("/:username", editUserController); + .put("/", editUserController); diff --git a/src/modules/user/repositories/checkUserEmailAndUsernameAvailability.repository.ts b/src/modules/user/repositories/checkUserEmailAndUsernameAvailabillity.repository.ts similarity index 50% rename from src/modules/user/repositories/checkUserEmailAndUsernameAvailability.repository.ts rename to src/modules/user/repositories/checkUserEmailAndUsernameAvailabillity.repository.ts index bb89b51..23b26a0 100644 --- a/src/modules/user/repositories/checkUserEmailAndUsernameAvailability.repository.ts +++ b/src/modules/user/repositories/checkUserEmailAndUsernameAvailabillity.repository.ts @@ -1,18 +1,19 @@ -import { Prisma } from "@prisma/client"; import { userModel } from "../user.model"; -export const checkUserEmailAndUsernameAvailabillity = async ( - payload: Partial>> +export const checkUserEmailAndUsernameAvailabillityRepo = async ( + id: string, + username: string, + email: string ) => { try { const checkUsernameAndEmailAvailabillity = await userModel.findFirst({ where: { OR: [ - { username: payload.username ?? undefined }, - { email: payload.email ?? undefined }, + { username: username ?? undefined }, + { email: email ?? undefined }, ], NOT: { - id: payload.id, + id: id, }, }, }); diff --git a/src/modules/user/repositories/updateUser.repository.ts b/src/modules/user/repositories/updateUser.repository.ts index 31e77d1..b44aeeb 100644 --- a/src/modules/user/repositories/updateUser.repository.ts +++ b/src/modules/user/repositories/updateUser.repository.ts @@ -1,20 +1,17 @@ import { Prisma } from "@prisma/client"; import { userModel } from "../user.model"; +import { JWTSessionPayload } from "../../auth/auth.types"; export const updateUserRepo = async ( - identifier: string, - payload: Prisma.UserUncheckedCreateInput + username: string, + payload: Prisma.UserUpdateInput ) => { try { const userData = await userModel.update({ where: { - username: identifier, - }, - data: { - username: payload.username, - name: payload.name, - birthDate: payload.name, + username, }, + data: payload, }); return userData; } catch (error) { diff --git a/src/modules/user/services/checkUserEmailAndUsernameAvailabillity.service.ts b/src/modules/user/services/checkUserEmailAndUsernameAvailabillity.service.ts new file mode 100644 index 0000000..4d8f456 --- /dev/null +++ b/src/modules/user/services/checkUserEmailAndUsernameAvailabillity.service.ts @@ -0,0 +1,20 @@ +import { Prisma } from "@prisma/client"; +import { ErrorForwarder } from "../../../helpers/error/instances/forwarder"; +import { checkUserEmailAndUsernameAvailabillityRepo } from "../repositories/checkUserEmailAndUsernameAvailabillity.repository"; + +export const checkUserEmailAndUsernameAvailabillityService = async ( + payload: Prisma.UserUpdateInput, + idException: string +) => { + try { + const usernameAndEmailAvailabillity = + checkUserEmailAndUsernameAvailabillityRepo( + idException!, + payload.username as string, + payload.email as string + ); + return usernameAndEmailAvailabillity; + } catch (error) { + ErrorForwarder(error); + } +}; diff --git a/src/modules/user/services/editUser.service.ts b/src/modules/user/services/editUser.service.ts index ad5eb96..32bb070 100644 --- a/src/modules/user/services/editUser.service.ts +++ b/src/modules/user/services/editUser.service.ts @@ -3,20 +3,60 @@ import { jwtDecode } from "../../../helpers/http/jwt/decode"; import { AppError } from "../../../helpers/error/instances/app"; import { ErrorForwarder } from "../../../helpers/error/instances/forwarder"; import { updateUserRepo } from "../repositories/updateUser.repository"; +import { checkUserEmailAndUsernameAvailabillityService } from "./checkUserEmailAndUsernameAvailabillity.service"; export const editUserService = async ( - identifier: string, cookie: string, - payload: Prisma.UserUncheckedCreateInput + payload: Prisma.UserUpdateInput ) => { try { // Decode the JWT token and verify the user, if the user is not the same as the identifier, throw an error const jwtSession = jwtDecode(cookie); - if (jwtSession.user.username !== identifier) { - throw new AppError(401, "Unauthorized"); - } - const updateUser = updateUserRepo(identifier, payload); + // Check if the username or email is being taken by another user, if so, throw an error + const isUsernameOrEmailIsBeingTaken = + await checkUserEmailAndUsernameAvailabillityService( + payload, + jwtSession.userId + ); + if (isUsernameOrEmailIsBeingTaken) + throw new AppError( + 409, + "The username or email has already taken by another user." + ); + + const fieldsToUpdate: Partial = { + ...(payload.username && payload.username !== jwtSession.user.username + ? { username: payload.username } + : {}), + + ...(payload.name !== undefined ? { name: payload.name } : {}), + ...(payload.birthDate !== undefined + ? { birthDate: payload.birthDate } + : {}), + ...(payload.gender !== undefined ? { gender: payload.gender } : {}), + ...(payload.phoneCC !== undefined ? { phoneCC: payload.phoneCC } : {}), + ...(payload.phoneNumber !== undefined + ? { phoneNumber: payload.phoneNumber } + : {}), + ...(payload.bioProfile !== undefined + ? { bioProfile: payload.bioProfile } + : {}), + ...(payload.profilePicture !== undefined + ? { profilePicture: payload.profilePicture } + : {}), + ...(payload.commentPicture !== undefined + ? { commentPicture: payload.commentPicture } + : {}), + ...(payload.deletedAt !== undefined + ? { deletedAt: payload.deletedAt } + : {}), + }; + + const updateUser = await updateUserRepo( + jwtSession.user.username, + fieldsToUpdate + ); return updateUser; } catch (error) { ErrorForwarder(error, 500, "Internal server error");