Skip to content

Commit fa1f3d2

Browse files
authored
Merge pull request #63 from gkdmsgus/refactor/jwt-auth-controllers
[REFACTOR] userId Path 파라미터를 JWT 인증 방식으로 변경
2 parents 63e1851 + 9d38d54 commit fa1f3d2

4 files changed

Lines changed: 119 additions & 79 deletions

File tree

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,16 @@
1-
import { Controller, Get, Put, Route, Tags, Path, Body, SuccessResponse, Response } from 'tsoa';
1+
import {
2+
Controller,
3+
Get,
4+
Put,
5+
Route,
6+
Tags,
7+
Body,
8+
SuccessResponse,
9+
Response,
10+
Security,
11+
Request,
12+
} from 'tsoa';
13+
import { Request as ExpressRequest } from 'express';
214
import ProfileService from '../service/profile_service';
315
import { ProfileResponseDto, UpdateProfileRequestDto } from '../DTO/profile_dto';
416
import { TsoaSuccessResponse } from '../config/response_interface';
@@ -13,46 +25,44 @@ import { uuidToBuffer } from '../util/uuid_util';
1325
export class ProfileController extends Controller {
1426
/**
1527
* 프로필 조회
16-
* @param userId - 사용자 ID (UUID 문자열)
28+
* @param req Express Request (JWT에서 userId 추출)
1729
* @returns 프로필 정보
1830
*/
19-
@Get('{userId}')
31+
@Get('me')
32+
@Security('jwt')
2033
@SuccessResponse('200', '프로필 조회 성공')
34+
@Response(401, 'Unauthorized')
2135
@Response(404, 'User Not Found')
2236
@Response(500, 'Internal Server Error')
23-
public async getProfile(@Path() userId: string): Promise<TsoaSuccessResponse<ProfileResponseDto>> {
24-
// UUID 문자열을 Buffer로 변환
37+
public async getProfile(
38+
@Request() req: ExpressRequest,
39+
): Promise<TsoaSuccessResponse<ProfileResponseDto>> {
40+
const userId = (req.user as unknown as { id: string }).id;
2541
const userIdBuffer = uuidToBuffer(userId);
26-
27-
// Service 호출
2842
const profile = await ProfileService.getProfile(userIdBuffer);
29-
30-
// 성공 응답 반환
3143
return new TsoaSuccessResponse(profile);
3244
}
3345

3446
/**
3547
* 프로필 수정
36-
* @param userId - 사용자 ID (UUID 문자열)
48+
* @param req Express Request (JWT에서 userId 추출)
3749
* @param requestBody - 수정할 프로필 데이터
3850
* @returns 수정된 프로필 정보
3951
*/
40-
@Put('{userId}')
52+
@Put('me')
53+
@Security('jwt')
4154
@SuccessResponse('200', '프로필 수정 성공')
4255
@Response(400, 'Bad Request')
56+
@Response(401, 'Unauthorized')
4357
@Response(404, 'User Not Found')
4458
@Response(500, 'Internal Server Error')
4559
public async updateProfile(
46-
@Path() userId: string,
60+
@Request() req: ExpressRequest,
4761
@Body() requestBody: UpdateProfileRequestDto,
4862
): Promise<TsoaSuccessResponse<ProfileResponseDto>> {
49-
// UUID 문자열을 Buffer로 변환
63+
const userId = (req.user as unknown as { id: string }).id;
5064
const userIdBuffer = uuidToBuffer(userId);
51-
52-
// Service 호출
5365
const profile = await ProfileService.updateProfile(userIdBuffer, requestBody);
54-
55-
// 성공 응답 반환
5666
return new TsoaSuccessResponse(profile);
5767
}
5868
}
Lines changed: 45 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,27 @@
1-
import { Controller, Get, Put, Delete, Route, Tags, Path, Body, Query, SuccessResponse, Response } from 'tsoa';
1+
import {
2+
Controller,
3+
Get,
4+
Put,
5+
Delete,
6+
Route,
7+
Tags,
8+
Path,
9+
Body,
10+
Query,
11+
SuccessResponse,
12+
Response,
13+
Security,
14+
Request,
15+
} from 'tsoa';
16+
import { Request as ExpressRequest } from 'express';
217
import ReviewService from '../service/review_service';
3-
import { ReviewResponseDto, ReviewListResponseDto, UpdateReviewRequestDto } from '../DTO/review_dto';
18+
import {
19+
ReviewResponseDto,
20+
ReviewListResponseDto,
21+
UpdateReviewRequestDto,
22+
} from '../DTO/review_dto';
423
import { TsoaSuccessResponse } from '../config/response_interface';
24+
import { uuidToBuffer } from '../util/uuid_util';
525

626
/**
727
* Review Controller
@@ -12,19 +32,22 @@ import { TsoaSuccessResponse } from '../config/response_interface';
1232
export class ReviewController extends Controller {
1333
/**
1434
* 내 리뷰 목록 조회
15-
* @param userId - 사용자 ID (UUID 문자열)
35+
* @param req Express Request (JWT에서 userId 추출)
1636
* @param sort - 정렬 방식 ('latest' = 최신순, 'oldest' = 오래된순)
1737
* @returns 리뷰 목록
1838
*/
19-
@Get('{userId}/reviews')
39+
@Get('me/reviews')
40+
@Security('jwt')
2041
@SuccessResponse('200', '리뷰 목록 조회 성공')
42+
@Response(401, 'Unauthorized')
2143
@Response(404, 'User Not Found')
2244
@Response(500, 'Internal Server Error')
2345
public async getMyReviews(
24-
@Path() userId: string,
46+
@Request() req: ExpressRequest,
2547
@Query() sort: 'latest' | 'oldest' = 'latest',
2648
): Promise<TsoaSuccessResponse<ReviewListResponseDto>> {
27-
const userIdBuffer = this.uuidToBuffer(userId);
49+
const userId = (req.user as unknown as { id: string }).id;
50+
const userIdBuffer = uuidToBuffer(userId);
2851
const orderBy = sort === 'latest' ? 'desc' : 'asc';
2952

3053
const reviews = await ReviewService.getReviewsByUserId(userIdBuffer, orderBy);
@@ -34,24 +57,27 @@ export class ReviewController extends Controller {
3457

3558
/**
3659
* 리뷰 수정
37-
* @param userId - 사용자 ID (UUID 문자열)
60+
* @param req Express Request (JWT에서 userId 추출)
3861
* @param reviewId - 리뷰 ID (UUID 문자열)
3962
* @param requestBody - 수정할 리뷰 데이터
4063
* @returns 수정된 리뷰 정보
4164
*/
42-
@Put('{userId}/reviews/{reviewId}')
65+
@Put('me/reviews/{reviewId}')
66+
@Security('jwt')
4367
@SuccessResponse('200', '리뷰 수정 성공')
4468
@Response(400, 'Bad Request')
69+
@Response(401, 'Unauthorized')
4570
@Response(403, 'Forbidden - 본인의 리뷰만 수정 가능')
4671
@Response(404, 'Review Not Found')
4772
@Response(500, 'Internal Server Error')
4873
public async updateReview(
49-
@Path() userId: string,
74+
@Request() req: ExpressRequest,
5075
@Path() reviewId: string,
5176
@Body() requestBody: UpdateReviewRequestDto,
5277
): Promise<TsoaSuccessResponse<ReviewResponseDto>> {
53-
const userIdBuffer = this.uuidToBuffer(userId);
54-
const reviewIdBuffer = this.uuidToBuffer(reviewId);
78+
const userId = (req.user as unknown as { id: string }).id;
79+
const userIdBuffer = uuidToBuffer(userId);
80+
const reviewIdBuffer = uuidToBuffer(reviewId);
5581

5682
const review = await ReviewService.updateReview(reviewIdBuffer, userIdBuffer, requestBody);
5783

@@ -60,33 +86,26 @@ export class ReviewController extends Controller {
6086

6187
/**
6288
* 리뷰 삭제
63-
* @param userId - 사용자 ID (UUID 문자열)
89+
* @param req Express Request (JWT에서 userId 추출)
6490
* @param reviewId - 리뷰 ID (UUID 문자열)
6591
*/
66-
@Delete('{userId}/reviews/{reviewId}')
92+
@Delete('me/reviews/{reviewId}')
93+
@Security('jwt')
6794
@SuccessResponse('200', '리뷰 삭제 성공')
95+
@Response(401, 'Unauthorized')
6896
@Response(403, 'Forbidden - 본인의 리뷰만 삭제 가능')
6997
@Response(404, 'Review Not Found')
7098
@Response(500, 'Internal Server Error')
7199
public async deleteReview(
72-
@Path() userId: string,
100+
@Request() req: ExpressRequest,
73101
@Path() reviewId: string,
74102
): Promise<TsoaSuccessResponse<{ message: string }>> {
75-
const userIdBuffer = this.uuidToBuffer(userId);
76-
const reviewIdBuffer = this.uuidToBuffer(reviewId);
103+
const userId = (req.user as unknown as { id: string }).id;
104+
const userIdBuffer = uuidToBuffer(userId);
105+
const reviewIdBuffer = uuidToBuffer(reviewId);
77106

78107
await ReviewService.deleteReview(reviewIdBuffer, userIdBuffer);
79108

80109
return new TsoaSuccessResponse({ message: '리뷰가 삭제되었습니다.' });
81110
}
82-
83-
/**
84-
* UUID 문자열을 Uint8Array로 변환
85-
* @param uuid - UUID 문자열 (예: "550e8400-e29b-41d4-a716-446655440000")
86-
* @returns Uint8Array
87-
*/
88-
private uuidToBuffer(uuid: string): Uint8Array {
89-
const hex = uuid.replace(/-/g, '');
90-
return Buffer.from(hex, 'hex');
91-
}
92111
}
Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,20 @@
1-
import { Controller, Get, Put, Route, Tags, Path, Body, SuccessResponse, Response } from 'tsoa';
1+
import {
2+
Controller,
3+
Get,
4+
Put,
5+
Route,
6+
Tags,
7+
Body,
8+
SuccessResponse,
9+
Response,
10+
Security,
11+
Request,
12+
} from 'tsoa';
13+
import { Request as ExpressRequest } from 'express';
214
import SettlementService from '../service/settlement_service';
315
import { SettlementResponseDto, UpdateSettlementRequestDto } from '../DTO/settlement_dto';
416
import { TsoaSuccessResponse } from '../config/response_interface';
17+
import { uuidToBuffer } from '../util/uuid_util';
518

619
/**
720
* Settlement Controller
@@ -12,46 +25,44 @@ import { TsoaSuccessResponse } from '../config/response_interface';
1225
export class SettlementController extends Controller {
1326
/**
1427
* 계좌 정보 조회
15-
* @param userId - 사용자 ID (UUID 문자열)
28+
* @param req Express Request (JWT에서 userId 추출)
1629
* @returns 계좌 정보
1730
*/
18-
@Get('{userId}/settlement')
31+
@Get('me/settlement')
32+
@Security('jwt')
1933
@SuccessResponse('200', '계좌 정보 조회 성공')
34+
@Response(401, 'Unauthorized')
2035
@Response(404, 'User Not Found')
2136
@Response(500, 'Internal Server Error')
2237
public async getSettlement(
23-
@Path() userId: string,
38+
@Request() req: ExpressRequest,
2439
): Promise<TsoaSuccessResponse<SettlementResponseDto>> {
25-
const userIdBuffer = this.uuidToBuffer(userId);
40+
const userId = (req.user as unknown as { id: string }).id;
41+
const userIdBuffer = uuidToBuffer(userId);
2642
const settlement = await SettlementService.getSettlement(userIdBuffer);
2743
return new TsoaSuccessResponse(settlement);
2844
}
2945

3046
/**
3147
* 계좌 정보 수정
32-
* @param userId - 사용자 ID (UUID 문자열)
48+
* @param req Express Request (JWT에서 userId 추출)
3349
* @param requestBody - 수정할 계좌 정보
3450
* @returns 수정된 계좌 정보
3551
*/
36-
@Put('{userId}/settlement')
52+
@Put('me/settlement')
53+
@Security('jwt')
3754
@SuccessResponse('200', '계좌 정보 수정 성공')
3855
@Response(400, 'Bad Request')
56+
@Response(401, 'Unauthorized')
3957
@Response(404, 'User Not Found')
4058
@Response(500, 'Internal Server Error')
4159
public async updateSettlement(
42-
@Path() userId: string,
60+
@Request() req: ExpressRequest,
4361
@Body() requestBody: UpdateSettlementRequestDto,
4462
): Promise<TsoaSuccessResponse<SettlementResponseDto>> {
45-
const userIdBuffer = this.uuidToBuffer(userId);
63+
const userId = (req.user as unknown as { id: string }).id;
64+
const userIdBuffer = uuidToBuffer(userId);
4665
const settlement = await SettlementService.updateSettlement(userIdBuffer, requestBody);
4766
return new TsoaSuccessResponse(settlement);
4867
}
49-
50-
/**
51-
* UUID 문자열을 Uint8Array로 변환
52-
*/
53-
private uuidToBuffer(uuid: string): Uint8Array {
54-
const hex = uuid.replace(/-/g, '');
55-
return Buffer.from(hex, 'hex');
56-
}
5768
}

src/controller/settlement_history_controller.ts

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,15 @@
1-
import { Controller, Get, Route, Tags, Path, Query, SuccessResponse, Response } from 'tsoa';
1+
import {
2+
Controller,
3+
Get,
4+
Route,
5+
Tags,
6+
Query,
7+
SuccessResponse,
8+
Response,
9+
Security,
10+
Request,
11+
} from 'tsoa';
12+
import { Request as ExpressRequest } from 'express';
213
import SettlementHistoryService from '../service/settlement_history_service';
314
import { SettlementHistoryResponseDto } from '../DTO/settlement_history_dto';
415
import { TsoaSuccessResponse } from '../config/response_interface';
@@ -13,34 +24,23 @@ import { uuidToBuffer } from '../util/uuid_util';
1324
export class SettlementHistoryController extends Controller {
1425
/**
1526
* 정산 내역 조회 API
16-
* @param userId 사용자 ID (UUID 문자열)
27+
* @param req Express Request (JWT에서 userId 추출)
1728
* @param status 정산 상태 필터 (all: 전체, waiting: 정산 대기, paid: 정산 완료, unpaid: 미정산)
1829
* @returns 정산 내역 목록
1930
*/
20-
@Get('{userId}')
31+
@Get('me')
32+
@Security('jwt')
2133
@SuccessResponse('200', '정산 내역 조회 성공')
22-
@Response(400, 'Bad Request')
23-
@Response(404, 'User Not Found')
34+
@Response(401, 'Unauthorized')
2435
@Response(500, 'Internal Server Error')
2536
public async getSettlementHistory(
26-
@Path() userId: string,
37+
@Request() req: ExpressRequest,
2738
@Query() status: 'all' | 'waiting' | 'paid' | 'unpaid' = 'all',
2839
): Promise<TsoaSuccessResponse<SettlementHistoryResponseDto>> {
29-
// UUID 형식 검증
30-
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
31-
if (!uuidRegex.test(userId)) {
32-
this.setStatus(400);
33-
throw new Error('유효하지 않은 사용자 ID 형식입니다.');
34-
}
35-
36-
// UUID 문자열을 Buffer로 변환
40+
const userId = (req.user as unknown as { id: string }).id;
3741
const userIdBuffer = uuidToBuffer(userId);
3842

39-
// Service 호출
40-
const history = await SettlementHistoryService.getSettlementHistory(
41-
userIdBuffer,
42-
status,
43-
);
43+
const history = await SettlementHistoryService.getSettlementHistory(userIdBuffer, status);
4444

4545
return new TsoaSuccessResponse(history);
4646
}

0 commit comments

Comments
 (0)