1- import { Controller , Get , UseGuards , Body , Patch , Query } from '@nestjs/common' ;
1+ import {
2+ Controller ,
3+ Get ,
4+ UseGuards ,
5+ Body ,
6+ Patch ,
7+ Query ,
8+ Post ,
9+ UseInterceptors ,
10+ UploadedFile ,
11+ BadRequestException ,
12+ } from '@nestjs/common' ;
213import { UserService } from './user.service' ;
314import { JwtAuthGuard } from 'src/auth/jwt.auth.strategy' ;
415import { GetUser } from './decorator/get-user.decorator' ;
516import { UserInfo } from 'src/auth/types/userInfo.type' ;
617import {
718 ApiBearerAuth ,
19+ ApiConsumes ,
820 ApiInternalServerErrorResponse ,
921 ApiOkResponse ,
1022 ApiOperation ,
1123 ApiQuery ,
1224 ApiTags ,
1325 ApiUnauthorizedResponse ,
26+ ApiBody ,
1427} from '@nestjs/swagger' ;
1528import { UserInfoDto } from './dto/res/userInfo.dto' ;
1629import { UpdateNicknameDto } from './dto/req/updateNickname.dto' ;
1730import { NicknameDuplicateCheckDto } from './dto/res/nicknameDuplicateCheck.dto' ;
31+ import { FileInterceptor } from '@nestjs/platform-express' ;
32+ import { User } from '@prisma/client' ;
1833
1934@ApiTags ( 'User' )
2035@Controller ( 'user' )
@@ -35,8 +50,8 @@ export class UserController {
3550 @ApiBearerAuth ( 'JWT' )
3651 @Get ( 'profile' )
3752 @UseGuards ( JwtAuthGuard )
38- async getProfile ( @GetUser ( ) user : UserInfo ) : Promise < UserInfo > {
39- return user ;
53+ async getProfile ( @GetUser ( ) user : User ) : Promise < UserInfo > {
54+ return this . userService . formatUserForResponse ( user ) ;
4055 }
4156
4257 @ApiOperation ( {
@@ -75,12 +90,67 @@ export class UserController {
7590 @Patch ( 'nickname' )
7691 @UseGuards ( JwtAuthGuard )
7792 async updateNickname (
78- @GetUser ( ) user : UserInfo ,
93+ @GetUser ( ) user : User ,
7994 @Body ( ) updateNicknameDto : UpdateNicknameDto ,
8095 ) : Promise < UserInfo > {
81- return this . userService . updateNickname (
96+ const updatedUser = await this . userService . updateNickname (
8297 user . uuid ,
8398 updateNicknameDto . nickname ,
8499 ) ;
100+ return this . userService . formatUserForResponse ( updatedUser ) ;
101+ }
102+
103+ @ApiOperation ( {
104+ summary : 'upload profile image' ,
105+ description :
106+ '프로필 이미지를 업로드합니다. 이미지는 1:1 비율로 자동 크롭됩니다.' ,
107+ } )
108+ @ApiConsumes ( 'multipart/form-data' )
109+ @ApiBody ( {
110+ schema : {
111+ type : 'object' ,
112+ properties : {
113+ image : {
114+ type : 'string' ,
115+ format : 'binary' ,
116+ description : '프로필 이미지 파일 (jpg, jpeg, png만 가능)' ,
117+ } ,
118+ } ,
119+ } ,
120+ } )
121+ @ApiOkResponse ( {
122+ type : UserInfoDto ,
123+ description : 'Return updated profile' ,
124+ } )
125+ @ApiUnauthorizedResponse ( { description : 'Unauthorized' } )
126+ @ApiInternalServerErrorResponse ( {
127+ description : 'Internal Server Error' ,
128+ } )
129+ @ApiBearerAuth ( 'JWT' )
130+ @Post ( 'profile-image' )
131+ @UseGuards ( JwtAuthGuard )
132+ @UseInterceptors (
133+ FileInterceptor ( 'image' , {
134+ fileFilter : ( req , file , cb ) => {
135+ if ( ! file . mimetype . match ( / ^ i m a g e \/ ( j p g | j p e g | p n g ) $ / ) ) {
136+ cb ( new BadRequestException ( 'Only image files are allowed' ) , false ) ;
137+ }
138+ cb ( null , true ) ;
139+ } ,
140+ } ) ,
141+ )
142+ async uploadProfileImage (
143+ @GetUser ( ) user : User ,
144+ @UploadedFile ( ) file : Express . Multer . File ,
145+ ) : Promise < UserInfo > {
146+ if ( ! file ) {
147+ throw new BadRequestException ( 'No file uploaded' ) ;
148+ }
149+
150+ const updatedUser = await this . userService . updateProfileImage (
151+ user . uuid ,
152+ file ,
153+ ) ;
154+ return this . userService . formatUserForResponse ( updatedUser ) ;
85155 }
86156}
0 commit comments