Skip to content

Commit c8e89a6

Browse files
authored
[SWEP-96] 메모장 사진 업로드 및 저장 로직 개선 (#200) (#201)
* [SWEP-96] 메모장 사진 업로드 및 저장 로직 개선 (#200) * fix: 폴더 생성 및 사진 저장 API 주석처리 + multer 미들웨어 실행 전에 폴더 ID 검사 (#202) * [SWEP-96] 메모장 사진 업로드 및 저장 로직 개선 * [SWEP-96] 폴더 생성 및 사진 저장 API 주석처리 + multer 미들웨어 실행 전에 폴더 ID 검사 * fix: tsoa.json 폴더 생성 및 사진 저장 spec requestBody 삭제 (#203) * [SWEP-96] 메모장 사진 업로드 및 저장 로직 개선 * [SWEP-96] 폴더 생성 및 사진 저장 API 주석처리 + multer 미들웨어 실행 전에 폴더 ID 검사 * [SWEP-96] tsoa.json 폴더 생성 및 사진 저장 spec requestBody 삭제
1 parent fbd8fed commit c8e89a6

6 files changed

Lines changed: 147 additions & 375 deletions

File tree

config/tsoa.json

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -19,27 +19,6 @@
1919
}
2020
],
2121
"paths": {
22-
"/memo/image-format/folders": {
23-
"post": {
24-
"requestBody": {
25-
"required": true,
26-
"content": {
27-
"multipart/form-data": {
28-
"schema": {
29-
"type": "object",
30-
"properties": {
31-
"image": {
32-
"type": "string",
33-
"format": "binary",
34-
"description": "파일 업로드"
35-
}
36-
}
37-
}
38-
}
39-
}
40-
}
41-
}
42-
},
4322
"/memo/image-format/folders/{folderId}": {
4423
"post": {
4524
"requestBody": {

src/controllers/tsoa.memo-folder.controller.ts

Lines changed: 116 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,13 @@ import {
77
listMemoFolder,
88
listMemoTextImage,
99
memoFolderCreate,
10-
memoFolderImageCreate,
1110
memoFolderUpdate,
1211
memoSearch,
1312
memoTextUpdate,
1413
} from '../services/memo-folder.service.tsoa.js';
1514
import {memoImageDelete} from '../services/memo-image.service.tsoa.js';
1615
import {bodyToMemoImagesToDelete} from '../dtos/memo-image.dto.tsoa.js';
17-
import {DataValidationError, PhotoValidationError} from '../errors.js';
16+
import {DataValidationError} from '../errors.js';
1817
import {
1918
Response,
2019
Body,
@@ -29,143 +28,139 @@ import {
2928
Path,
3029
Patch,
3130
Example,
32-
FormField,
33-
Middlewares,
3431
} from 'tsoa';
3532
import {
3633
BodyToMemoFolder,
3734
BodyToMemoTextToUpdate,
3835
MemoFolderListResponseDto,
3936
MemoFolderResponseDto,
4037
MemoTextImageListResponseDto,
41-
MemoFolderImageResponseDto,
4238
} from '../models/memo-folder.model.tsoa.js';
4339
import {
4440
ITsoaErrorResponse,
4541
ITsoaSuccessResponse,
4642
TsoaSuccessResponse,
4743
} from '../models/tsoaResponse.js';
4844
import {BodyToMemoImagesToDelete} from '../models/memo-image.model.tsoa.js';
49-
import {Request as ExpressRequest, Express} from 'express';
50-
import {ImageUploadMiddleware} from '../s3/image.uploader.middleware.js';
45+
import {Request as ExpressRequest} from 'express';
5146

5247
@Route('memo')
5348
export class MemoFolderController extends Controller {
54-
/**
55-
* 폴더 생성과 동시에 파일을 저장하는 API입니다.
56-
*
57-
* @summary 폴더 생성 및 사진 저장 API
58-
* @param req
59-
* @param folderName 생성할 폴더 이름
60-
* @param image 파일 업로드
61-
* @returns 성공 시 폴더 생성 및 사진 저장 결과를 반환합니다.
62-
*
63-
*/
64-
@Post('/image-format/folders')
65-
@Middlewares(ImageUploadMiddleware)
66-
@Tags('memo-folder-controller')
67-
@Response<ITsoaErrorResponse>(
68-
StatusCodes.BAD_REQUEST,
69-
'유효하지 않은 데이터 에러',
70-
{
71-
resultType: 'FAIL',
72-
success: null,
73-
error: {
74-
errorCode: 'FOL-400',
75-
reason: '폴더 생성 중 오류가 발생했습니다.',
76-
data: {userId: '1', folderName: 'string'},
77-
},
78-
},
79-
)
80-
@Response<ITsoaErrorResponse>(
81-
StatusCodes.BAD_REQUEST,
82-
'유효하지 않은 데이터 에러',
83-
{
84-
resultType: 'FAIL',
85-
error: {
86-
errorCode: 'PHO-400',
87-
reason: '사진 데이터가 유효하지 않습니다.',
88-
data: {
89-
reason: '저장할 사진이 없습니다.',
90-
},
91-
},
92-
success: null,
93-
},
94-
)
95-
@Response<ITsoaErrorResponse>(
96-
StatusCodes.BAD_REQUEST,
97-
'유효하지 않은 데이터 에러',
98-
{
99-
resultType: 'FAIL',
100-
error: {
101-
errorCode: 'MEM-400',
102-
reason: '메모 사진 추가 중 오류가 발생했습니다.',
103-
data: {
104-
folderId: '1',
105-
imageUrl: 'string',
106-
},
107-
},
108-
success: null,
109-
},
110-
)
111-
@Response<ITsoaErrorResponse>(
112-
StatusCodes.BAD_REQUEST,
113-
'유효하지 않은 데이터 에러',
114-
{
115-
resultType: 'FAIL',
116-
error: {
117-
errorCode: 'PHO-400',
118-
reason: '사진 데이터가 유효하지 않습니다.',
119-
data: {
120-
extension: 'string',
121-
},
122-
},
123-
success: null,
124-
},
125-
)
126-
@Response<ITsoaErrorResponse>(StatusCodes.CONFLICT, '중복 데이터 에러', {
127-
resultType: 'FAIL',
128-
success: null,
129-
error: {
130-
errorCode: 'FOL-409',
131-
reason: '이미 존재하는 폴더 이름입니다.',
132-
data: {folderName: 'string'},
133-
},
134-
})
135-
@SuccessResponse(StatusCodes.OK, '폴더 생성 및 사진 저장 성공 응답')
136-
@Example({
137-
resultType: 'SUCCESS',
138-
error: null,
139-
success: {
140-
folderId: '1',
141-
folderName: 'string',
142-
imageId: '1',
143-
imageUrl: 'string',
144-
},
145-
})
146-
public async handlerMemoFolderImageAdd(
147-
@Request() req: ExpressRequest,
148-
@FormField() folderName: string,
149-
): Promise<ITsoaSuccessResponse<MemoFolderImageResponseDto>> {
150-
try {
151-
const userId = BigInt(req.user!.id);
49+
// /**
50+
// * 폴더 생성과 동시에 파일을 저장하는 API입니다.
51+
// *
52+
// * @summary 폴더 생성 및 사진 저장 API
53+
// * @param req
54+
// * @param folderName 생성할 폴더 이름
55+
// * @param image 파일 업로드
56+
// * @returns 성공 시 폴더 생성 및 사진 저장 결과를 반환합니다.
57+
// *
58+
// */
59+
// @Post('/image-format/folders')
60+
// @Middlewares(ImageUploadMiddleware)
61+
// @Tags('memo-folder-controller')
62+
// @Response<ITsoaErrorResponse>(
63+
// StatusCodes.BAD_REQUEST,
64+
// '유효하지 않은 데이터 에러',
65+
// {
66+
// resultType: 'FAIL',
67+
// success: null,
68+
// error: {
69+
// errorCode: 'FOL-400',
70+
// reason: '폴더 생성 중 오류가 발생했습니다.',
71+
// data: {userId: '1', folderName: 'string'},
72+
// },
73+
// },
74+
// )
75+
// @Response<ITsoaErrorResponse>(
76+
// StatusCodes.BAD_REQUEST,
77+
// '유효하지 않은 데이터 에러',
78+
// {
79+
// resultType: 'FAIL',
80+
// error: {
81+
// errorCode: 'PHO-400',
82+
// reason: '사진 데이터가 유효하지 않습니다.',
83+
// data: {
84+
// reason: '저장할 사진이 없습니다.',
85+
// },
86+
// },
87+
// success: null,
88+
// },
89+
// )
90+
// @Response<ITsoaErrorResponse>(
91+
// StatusCodes.BAD_REQUEST,
92+
// '유효하지 않은 데이터 에러',
93+
// {
94+
// resultType: 'FAIL',
95+
// error: {
96+
// errorCode: 'MEM-400',
97+
// reason: '메모 사진 추가 중 오류가 발생했습니다.',
98+
// data: {
99+
// folderId: '1',
100+
// imageUrl: 'string',
101+
// },
102+
// },
103+
// success: null,
104+
// },
105+
// )
106+
// @Response<ITsoaErrorResponse>(
107+
// StatusCodes.BAD_REQUEST,
108+
// '유효하지 않은 데이터 에러',
109+
// {
110+
// resultType: 'FAIL',
111+
// error: {
112+
// errorCode: 'PHO-400',
113+
// reason: '사진 데이터가 유효하지 않습니다.',
114+
// data: {
115+
// extension: 'string',
116+
// },
117+
// },
118+
// success: null,
119+
// },
120+
// )
121+
// @Response<ITsoaErrorResponse>(StatusCodes.CONFLICT, '중복 데이터 에러', {
122+
// resultType: 'FAIL',
123+
// success: null,
124+
// error: {
125+
// errorCode: 'FOL-409',
126+
// reason: '이미 존재하는 폴더 이름입니다.',
127+
// data: {folderName: 'string'},
128+
// },
129+
// })
130+
// @SuccessResponse(StatusCodes.OK, '폴더 생성 및 사진 저장 성공 응답')
131+
// @Example({
132+
// resultType: 'SUCCESS',
133+
// error: null,
134+
// success: {
135+
// folderId: '1',
136+
// folderName: 'string',
137+
// imageId: '1',
138+
// imageUrl: 'string',
139+
// },
140+
// })
141+
// public async handlerMemoFolderImageAdd(
142+
// @Request() req: ExpressRequest,
143+
// @FormField() folderName: string,
144+
// ): Promise<ITsoaSuccessResponse<MemoFolderImageResponseDto>> {
145+
// try {
146+
// const userId = BigInt(req.user!.id);
152147

153-
if (!req.file) {
154-
throw new PhotoValidationError({reason: '저장할 사진이 없습니다.'});
155-
}
156-
const imageUrl = (req.file as Express.MulterS3File).key;
157-
const folderId = req.uploadDirectory;
158-
const memoFolderImage = await memoFolderImageCreate(
159-
userId,
160-
folderId,
161-
imageUrl,
162-
folderName,
163-
);
164-
return new TsoaSuccessResponse(memoFolderImage);
165-
} catch (error) {
166-
throw error;
167-
}
168-
}
148+
// if (!req.file) {
149+
// throw new PhotoValidationError({reason: '저장할 사진이 없습니다.'});
150+
// }
151+
// const imageUrl = (req.file as Express.MulterS3File).key;
152+
// const folderId = req.uploadDirectory;
153+
// const memoFolderImage = await memoFolderImageCreate(
154+
// userId,
155+
// folderId,
156+
// imageUrl,
157+
// folderName,
158+
// );
159+
// return new TsoaSuccessResponse(memoFolderImage);
160+
// } catch (error) {
161+
// throw error;
162+
// }
163+
// }
169164

170165
/**
171166
* 폴더를 생성하는 API입니다.

src/routers/tsoaRoutes.ts

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -578,37 +578,6 @@ export function RegisterRoutes(app: Router) {
578578
}
579579
});
580580
// WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa
581-
const argsMemoFolderController_handlerMemoFolderImageAdd: Record<string, TsoaRoute.ParameterSchema> = {
582-
req: {"in":"request","name":"req","required":true,"dataType":"object"},
583-
folderName: {"in":"formData","name":"folderName","required":true,"dataType":"string"},
584-
};
585-
app.post('/memo/image-format/folders',
586-
...(fetchMiddlewares<RequestHandler>(MemoFolderController)),
587-
...(fetchMiddlewares<RequestHandler>(MemoFolderController.prototype.handlerMemoFolderImageAdd)),
588-
589-
async function MemoFolderController_handlerMemoFolderImageAdd(request: ExRequest, response: ExResponse, next: any) {
590-
591-
// WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa
592-
593-
let validatedArgs: any[] = [];
594-
try {
595-
validatedArgs = templateService.getValidatedArgs({ args: argsMemoFolderController_handlerMemoFolderImageAdd, request, response });
596-
597-
const controller = new MemoFolderController();
598-
599-
await templateService.apiHandler({
600-
methodName: 'handlerMemoFolderImageAdd',
601-
controller,
602-
response,
603-
next,
604-
validatedArgs,
605-
successStatus: 200,
606-
});
607-
} catch (err) {
608-
return next(err);
609-
}
610-
});
611-
// WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa
612581
const argsMemoFolderController_handlerMemoFolderAdd: Record<string, TsoaRoute.ParameterSchema> = {
613582
req: {"in":"request","name":"req","required":true,"dataType":"object"},
614583
body: {"in":"body","name":"body","required":true,"ref":"BodyToMemoFolder"},

src/s3/image.uploader.middleware.ts

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,30 @@
11
import {Request, Response, NextFunction} from 'express';
22
import {imageUploader} from './image.uploader.js';
3-
// import {PhotoValidationError} from '../errors.js';
4-
5-
export const ImageUploadMiddleware = (
3+
import {getMemoFolder} from 'src/repositories/memo-folder.repository.tsoa.js';
4+
import {DataValidationError, FolderNotFoundError} from 'src/errors.js';
5+
export const ImageUploadMiddleware = async (
66
req: Request,
77
res: Response,
88
next: NextFunction,
99
) => {
10+
const userId = BigInt(req.user!.id);
11+
if (req.params === null) {
12+
return next(
13+
new DataValidationError({reason: 'folderId가 유효하지 않습니다.'}),
14+
);
15+
}
16+
try {
17+
const folderId = req.params.folderId;
18+
const checkFolder = await getMemoFolder(BigInt(folderId));
19+
20+
if (!checkFolder || checkFolder.userId !== userId) {
21+
return next(new FolderNotFoundError({folderId: BigInt(folderId)}));
22+
}
23+
const uploadDirectory = folderId;
24+
req.uploadDirectory = BigInt(uploadDirectory);
25+
} catch (error) {
26+
return next(error);
27+
}
1028
imageUploader.single('image')(req, res, err => {
1129
if (err) {
1230
next(err);

0 commit comments

Comments
 (0)