From 5d508c473179005341bc83d9504a344b9696cf13 Mon Sep 17 00:00:00 2001 From: JakkrapartXD Date: Wed, 14 Jan 2026 16:29:18 +0700 Subject: [PATCH] add update user api --- Backend/src/controllers/UserController.ts | 19 +++++++++- Backend/src/services/user.service.ts | 45 +++++++++++++++++++++++ Backend/src/validators/user.validator.ts | 2 +- 3 files changed, 64 insertions(+), 2 deletions(-) diff --git a/Backend/src/controllers/UserController.ts b/Backend/src/controllers/UserController.ts index 8f4cecc0..f51deceb 100644 --- a/Backend/src/controllers/UserController.ts +++ b/Backend/src/controllers/UserController.ts @@ -1,4 +1,4 @@ -import { Get, Body, Post, Route, Tags, SuccessResponse, Response, Example, Controller, Security, Request } from 'tsoa'; +import { Get, Body, Post, Route, Tags, SuccessResponse, Response, Example, Controller, Security, Request, Put } from 'tsoa'; import { UserService } from '../services/user.service'; import { UserResponse, @@ -36,6 +36,23 @@ export class UserController { return await this.userService.getUserProfile(token); } + @Put('me') + @Security('jwt') + @SuccessResponse('200', 'Profile updated successfully') + @Response('401', 'Invalid or expired token') + @Response('400', 'Validation error') + public async updateProfile(@Request() request: any, @Body() body: ProfileUpdate): Promise { + const { error } = profileUpdateSchema.validate(body); + if (error) { + throw new ValidationError(error.details[0].message); + } + const token = request.headers.authorization?.replace('Bearer ', ''); + if (!token) { + throw new ValidationError('No token provided'); + } + return await this.userService.updateProfile(token, body); + } + /** * Change password * @summary Change user password using old password diff --git a/Backend/src/services/user.service.ts b/Backend/src/services/user.service.ts index 3c0e75c7..9a101674 100644 --- a/Backend/src/services/user.service.ts +++ b/Backend/src/services/user.service.ts @@ -108,6 +108,51 @@ export class UserService { } } + /** + * Update user profile + */ + async updateProfile(token: string, profile: ProfileUpdate): Promise { + try { + // Decode JWT token to get user ID + const decoded = jwt.verify(token, config.jwt.secret) as { id: number; username: string; email: string; roleCode: string }; + + const user = await prisma.user.findUnique({ where: { id: decoded.id } }); + if (!user) throw new UnauthorizedError('User not found'); + + // Update profile + const updatedProfile = await prisma.userProfile.update({ + where: { user_id: user.id }, + data: profile + }); + + logger.info('Profile updated successfully', { userId: user.id }); + return { + code: 200, + message: 'Profile updated successfully', + data: { + id: updatedProfile.id, + prefix: updatedProfile.prefix as { th?: string; en?: string } | undefined, + first_name: updatedProfile.first_name, + last_name: updatedProfile.last_name, + avatar_url: updatedProfile.avatar_url, + phone: updatedProfile.phone, + birth_date: updatedProfile.birth_date + } + }; + } catch (error) { + if (error instanceof jwt.JsonWebTokenError) { + logger.error('Invalid JWT token:', error); + throw new UnauthorizedError('Invalid token'); + } + if (error instanceof jwt.TokenExpiredError) { + logger.error('JWT token expired:', error); + throw new UnauthorizedError('Token expired'); + } + logger.error('Failed to update profile', { error }); + throw error; + } + } + /** * Format user response */ diff --git a/Backend/src/validators/user.validator.ts b/Backend/src/validators/user.validator.ts index 79396915..eb25061c 100644 --- a/Backend/src/validators/user.validator.ts +++ b/Backend/src/validators/user.validator.ts @@ -18,7 +18,7 @@ export const profileUpdateSchema = Joi.object({ .max(15) .optional(), avatar_url: Joi.string().optional(), - birthday: Joi.date().optional() + birth_date: Joi.date().optional() }); export const changePasswordSchema = Joi.object({