Skip to content

Commit d5f66d6

Browse files
authored
Merge pull request #25 from oodd-team/OD-33
유저 정보 수정 기능
2 parents a67ab42 + 23533a2 commit d5f66d6

5 files changed

+155
-6
lines changed

src/user/dto/patch-user.request.ts

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { IsOptional, IsString, IsUrl, MaxLength } from 'class-validator';
2+
import { ApiProperty } from '@nestjs/swagger';
3+
4+
export class PatchUserRequest {
5+
@IsOptional()
6+
@IsString()
7+
@MaxLength(10, { message: '닉네임은 최대 10자까지 입력할 수 있습니다.' })
8+
@ApiProperty({
9+
description: '수정할 닉네임',
10+
example: '새닉네임',
11+
required: false,
12+
})
13+
nickname?: string | null;
14+
15+
@IsOptional()
16+
@IsUrl({}, { message: '유효한 URL 형식이어야 합니다.' })
17+
@ApiProperty({
18+
description: '수정할 프로필 사진 URL',
19+
example: 'https://example.com/profile.jpg',
20+
required: false,
21+
})
22+
profilePictureUrl?: string | null;
23+
24+
@IsOptional()
25+
@IsString()
26+
@MaxLength(100, { message: '자기소개는 최대 100자까지 입력할 수 있습니다.' })
27+
@ApiProperty({
28+
description: '수정할 자기소개',
29+
example: '소개글~~~^^',
30+
required: false,
31+
})
32+
bio?: string | null;
33+
}

src/user/dto/patch-user.response.ts

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { ApiProperty } from '@nestjs/swagger';
2+
3+
export class PatchUserResponse {
4+
@ApiProperty({
5+
description: 'user ID',
6+
example: '19',
7+
})
8+
userId: number;
9+
10+
@ApiProperty({
11+
description: '수정된 닉네임',
12+
example: '새 닉네임',
13+
})
14+
nickname: string;
15+
16+
@ApiProperty({
17+
description: '수정된 프로필 사진 URL',
18+
example: 'https://example.com/profile.jpg',
19+
})
20+
profilePictureUrl: string;
21+
22+
@ApiProperty({
23+
description: '수정된 자기소개',
24+
example: '소개글~~~^^',
25+
})
26+
bio: string;
27+
}

src/user/user.controller.ts

+39-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,12 @@
1-
import { Controller, Get, Patch } from '@nestjs/common';
1+
import {
2+
Body,
3+
Controller,
4+
Get,
5+
Param,
6+
Patch,
7+
Req,
8+
UseGuards,
9+
} from '@nestjs/common';
210
import { UserService } from './user.service';
311
import { ApiBearerAuth, ApiTags } from '@nestjs/swagger';
412
import {
@@ -7,6 +15,15 @@ import {
715
PatchUserTermsSwagger,
816
SignOutSwagger,
917
} from './user.swagger';
18+
import { AuthGuard } from 'src/auth/guards/jwt.auth.guard';
19+
import { PatchUserRequest } from './dto/patch-user.request';
20+
import { BaseResponse } from 'src/common/response/dto';
21+
import { Request } from 'express';
22+
import {
23+
DataNotFoundException,
24+
UnauthorizedException,
25+
} from 'src/common/exception/service.exception';
26+
import { PatchUserResponse } from './dto/patch-user.response';
1027

1128
@ApiBearerAuth('Authorization')
1229
@Controller('user')
@@ -26,10 +43,28 @@ export class UserController {
2643
// return this.userService.getHello();
2744
}
2845

29-
@Patch()
46+
@Patch(':userId')
47+
@UseGuards(AuthGuard)
3048
@PatchUserSwagger('유저 정보 수정 API')
31-
patchUser() {
32-
// return this.userService.getHello();
49+
async patchUser(
50+
@Req() req: Request,
51+
@Param('userId') userId: number,
52+
@Body() body: PatchUserRequest,
53+
): Promise<BaseResponse<PatchUserResponse>> {
54+
if (!(await this.userService.getUserById(userId)))
55+
throw DataNotFoundException('유저가 존재하지 않습니다.');
56+
if (req.user.id !== Number(userId)) {
57+
throw UnauthorizedException('권한이 없습니다.');
58+
}
59+
60+
const updatedUser = await this.userService.PatchUser(userId, body);
61+
62+
return new BaseResponse<PatchUserResponse>(true, '유저 정보 수정 성공', {
63+
userId: updatedUser.id,
64+
nickname: updatedUser.nickname,
65+
profilePictureUrl: updatedUser.profilePictureUrl,
66+
bio: updatedUser.bio,
67+
});
3368
}
3469

3570
@Patch()

src/user/user.service.ts

+26
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { SocialUser } from 'src/auth/dto/auth.dto';
55
import { User } from 'src/common/entities/user.entity';
66
import { InternalServerException } from 'src/common/exception/service.exception';
77
import { DataSource, FindOneOptions, Repository } from 'typeorm';
8+
import { PatchUserRequest } from './dto/patch-user.request';
89

910
@Injectable()
1011
export class UserService {
@@ -53,4 +54,29 @@ export class UserService {
5354
await queryRunner.release();
5455
}
5556
}
57+
58+
async PatchUser(
59+
id: number,
60+
patchUserRequest: PatchUserRequest,
61+
): Promise<User> {
62+
const user = await this.userRepository.findOne({
63+
where: { id: id, status: 'activated' },
64+
});
65+
66+
try {
67+
if (patchUserRequest.nickname !== undefined) {
68+
user.nickname = patchUserRequest.nickname;
69+
}
70+
if (patchUserRequest.profilePictureUrl !== undefined) {
71+
user.profilePictureUrl = patchUserRequest.profilePictureUrl;
72+
}
73+
if (patchUserRequest.bio !== undefined) {
74+
user.bio = patchUserRequest.bio;
75+
}
76+
77+
return await this.userRepository.save(user);
78+
} catch (error) {
79+
throw InternalServerException(error.message);
80+
}
81+
}
5682
}

src/user/user.swagger.ts

+30-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,12 @@
1-
import { ApiOperation } from '@nestjs/swagger';
1+
import {
2+
ApiBadRequestResponse,
3+
ApiInternalServerErrorResponse,
4+
ApiNotFoundResponse,
5+
ApiOperation,
6+
} from '@nestjs/swagger';
7+
import { BaseSwaggerDecorator } from 'nestjs-swagger-decorator';
8+
import { BaseResponse } from 'src/common/response/dto';
9+
import { PatchUserResponse } from './dto/patch-user.response';
210

311
// 유저 조회 API Swagger
412
export function GetUserSwagger(apiSummary: string) {
@@ -12,7 +20,27 @@ export function SignOutSwagger(apiSummary: string) {
1220

1321
// 유저 수정 API Swagger
1422
export function PatchUserSwagger(apiSummary: string) {
15-
return ApiOperation({ summary: apiSummary });
23+
return BaseSwaggerDecorator(
24+
{ summary: apiSummary },
25+
[
26+
{
27+
statusCode: 200,
28+
responseOptions: [
29+
{
30+
model: PatchUserResponse,
31+
exampleTitle: '성공',
32+
exampleDescription: '성공했을 때 값',
33+
},
34+
],
35+
baseResponseDto: BaseResponse,
36+
},
37+
],
38+
[
39+
ApiBadRequestResponse({ description: 'Bad Request' }),
40+
ApiNotFoundResponse({ description: '해당 유저가 존재하지 않습니다.' }),
41+
ApiInternalServerErrorResponse({ description: 'Internal Server Error' }),
42+
],
43+
);
1644
}
1745

1846
// 이용약관 동의 API Swagger

0 commit comments

Comments
 (0)