Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 0 additions & 21 deletions config/tsoa.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,27 +19,6 @@
}
],
"paths": {
"/memo/image-format/folders": {
"post": {
"requestBody": {
"required": true,
"content": {
"multipart/form-data": {
"schema": {
"type": "object",
"properties": {
"image": {
"type": "string",
"format": "binary",
"description": "파일 업로드"
}
}
}
}
}
}
}
},
"/memo/image-format/folders/{folderId}": {
"post": {
"requestBody": {
Expand Down
237 changes: 116 additions & 121 deletions src/controllers/tsoa.memo-folder.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,13 @@ import {
listMemoFolder,
listMemoTextImage,
memoFolderCreate,
memoFolderImageCreate,
memoFolderUpdate,
memoSearch,
memoTextUpdate,
} from '../services/memo-folder.service.tsoa.js';
import {memoImageDelete} from '../services/memo-image.service.tsoa.js';
import {bodyToMemoImagesToDelete} from '../dtos/memo-image.dto.tsoa.js';
import {DataValidationError, PhotoValidationError} from '../errors.js';
import {DataValidationError} from '../errors.js';
import {
Response,
Body,
Expand All @@ -29,143 +28,139 @@ import {
Path,
Patch,
Example,
FormField,
Middlewares,
} from 'tsoa';
import {
BodyToMemoFolder,
BodyToMemoTextToUpdate,
MemoFolderListResponseDto,
MemoFolderResponseDto,
MemoTextImageListResponseDto,
MemoFolderImageResponseDto,
} from '../models/memo-folder.model.tsoa.js';
import {
ITsoaErrorResponse,
ITsoaSuccessResponse,
TsoaSuccessResponse,
} from '../models/tsoaResponse.js';
import {BodyToMemoImagesToDelete} from '../models/memo-image.model.tsoa.js';
import {Request as ExpressRequest, Express} from 'express';
import {ImageUploadMiddleware} from '../s3/image.uploader.middleware.js';
import {Request as ExpressRequest} from 'express';

@Route('memo')
export class MemoFolderController extends Controller {
/**
* 폴더 생성과 동시에 파일을 저장하는 API입니다.
*
* @summary 폴더 생성 및 사진 저장 API
* @param req
* @param folderName 생성할 폴더 이름
* @param image 파일 업로드
* @returns 성공 시 폴더 생성 및 사진 저장 결과를 반환합니다.
*
*/
@Post('/image-format/folders')
@Middlewares(ImageUploadMiddleware)
@Tags('memo-folder-controller')
@Response<ITsoaErrorResponse>(
StatusCodes.BAD_REQUEST,
'유효하지 않은 데이터 에러',
{
resultType: 'FAIL',
success: null,
error: {
errorCode: 'FOL-400',
reason: '폴더 생성 중 오류가 발생했습니다.',
data: {userId: '1', folderName: 'string'},
},
},
)
@Response<ITsoaErrorResponse>(
StatusCodes.BAD_REQUEST,
'유효하지 않은 데이터 에러',
{
resultType: 'FAIL',
error: {
errorCode: 'PHO-400',
reason: '사진 데이터가 유효하지 않습니다.',
data: {
reason: '저장할 사진이 없습니다.',
},
},
success: null,
},
)
@Response<ITsoaErrorResponse>(
StatusCodes.BAD_REQUEST,
'유효하지 않은 데이터 에러',
{
resultType: 'FAIL',
error: {
errorCode: 'MEM-400',
reason: '메모 사진 추가 중 오류가 발생했습니다.',
data: {
folderId: '1',
imageUrl: 'string',
},
},
success: null,
},
)
@Response<ITsoaErrorResponse>(
StatusCodes.BAD_REQUEST,
'유효하지 않은 데이터 에러',
{
resultType: 'FAIL',
error: {
errorCode: 'PHO-400',
reason: '사진 데이터가 유효하지 않습니다.',
data: {
extension: 'string',
},
},
success: null,
},
)
@Response<ITsoaErrorResponse>(StatusCodes.CONFLICT, '중복 데이터 에러', {
resultType: 'FAIL',
success: null,
error: {
errorCode: 'FOL-409',
reason: '이미 존재하는 폴더 이름입니다.',
data: {folderName: 'string'},
},
})
@SuccessResponse(StatusCodes.OK, '폴더 생성 및 사진 저장 성공 응답')
@Example({
resultType: 'SUCCESS',
error: null,
success: {
folderId: '1',
folderName: 'string',
imageId: '1',
imageUrl: 'string',
},
})
public async handlerMemoFolderImageAdd(
@Request() req: ExpressRequest,
@FormField() folderName: string,
): Promise<ITsoaSuccessResponse<MemoFolderImageResponseDto>> {
try {
const userId = BigInt(req.user!.id);
// /**
// * 폴더 생성과 동시에 파일을 저장하는 API입니다.
// *
// * @summary 폴더 생성 및 사진 저장 API
// * @param req
// * @param folderName 생성할 폴더 이름
// * @param image 파일 업로드
// * @returns 성공 시 폴더 생성 및 사진 저장 결과를 반환합니다.
// *
// */
// @Post('/image-format/folders')
// @Middlewares(ImageUploadMiddleware)
// @Tags('memo-folder-controller')
// @Response<ITsoaErrorResponse>(
// StatusCodes.BAD_REQUEST,
// '유효하지 않은 데이터 에러',
// {
// resultType: 'FAIL',
// success: null,
// error: {
// errorCode: 'FOL-400',
// reason: '폴더 생성 중 오류가 발생했습니다.',
// data: {userId: '1', folderName: 'string'},
// },
// },
// )
// @Response<ITsoaErrorResponse>(
// StatusCodes.BAD_REQUEST,
// '유효하지 않은 데이터 에러',
// {
// resultType: 'FAIL',
// error: {
// errorCode: 'PHO-400',
// reason: '사진 데이터가 유효하지 않습니다.',
// data: {
// reason: '저장할 사진이 없습니다.',
// },
// },
// success: null,
// },
// )
// @Response<ITsoaErrorResponse>(
// StatusCodes.BAD_REQUEST,
// '유효하지 않은 데이터 에러',
// {
// resultType: 'FAIL',
// error: {
// errorCode: 'MEM-400',
// reason: '메모 사진 추가 중 오류가 발생했습니다.',
// data: {
// folderId: '1',
// imageUrl: 'string',
// },
// },
// success: null,
// },
// )
// @Response<ITsoaErrorResponse>(
// StatusCodes.BAD_REQUEST,
// '유효하지 않은 데이터 에러',
// {
// resultType: 'FAIL',
// error: {
// errorCode: 'PHO-400',
// reason: '사진 데이터가 유효하지 않습니다.',
// data: {
// extension: 'string',
// },
// },
// success: null,
// },
// )
// @Response<ITsoaErrorResponse>(StatusCodes.CONFLICT, '중복 데이터 에러', {
// resultType: 'FAIL',
// success: null,
// error: {
// errorCode: 'FOL-409',
// reason: '이미 존재하는 폴더 이름입니다.',
// data: {folderName: 'string'},
// },
// })
// @SuccessResponse(StatusCodes.OK, '폴더 생성 및 사진 저장 성공 응답')
// @Example({
// resultType: 'SUCCESS',
// error: null,
// success: {
// folderId: '1',
// folderName: 'string',
// imageId: '1',
// imageUrl: 'string',
// },
// })
// public async handlerMemoFolderImageAdd(
// @Request() req: ExpressRequest,
// @FormField() folderName: string,
// ): Promise<ITsoaSuccessResponse<MemoFolderImageResponseDto>> {
// try {
// const userId = BigInt(req.user!.id);

if (!req.file) {
throw new PhotoValidationError({reason: '저장할 사진이 없습니다.'});
}
const imageUrl = (req.file as Express.MulterS3File).key;
const folderId = req.uploadDirectory;
const memoFolderImage = await memoFolderImageCreate(
userId,
folderId,
imageUrl,
folderName,
);
return new TsoaSuccessResponse(memoFolderImage);
} catch (error) {
throw error;
}
}
// if (!req.file) {
// throw new PhotoValidationError({reason: '저장할 사진이 없습니다.'});
// }
// const imageUrl = (req.file as Express.MulterS3File).key;
// const folderId = req.uploadDirectory;
// const memoFolderImage = await memoFolderImageCreate(
// userId,
// folderId,
// imageUrl,
// folderName,
// );
// return new TsoaSuccessResponse(memoFolderImage);
// } catch (error) {
// throw error;
// }
// }

/**
* 폴더를 생성하는 API입니다.
Expand Down
31 changes: 0 additions & 31 deletions src/routers/tsoaRoutes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -578,37 +578,6 @@ export function RegisterRoutes(app: Router) {
}
});
// 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
const argsMemoFolderController_handlerMemoFolderImageAdd: Record<string, TsoaRoute.ParameterSchema> = {
req: {"in":"request","name":"req","required":true,"dataType":"object"},
folderName: {"in":"formData","name":"folderName","required":true,"dataType":"string"},
};
app.post('/memo/image-format/folders',
...(fetchMiddlewares<RequestHandler>(MemoFolderController)),
...(fetchMiddlewares<RequestHandler>(MemoFolderController.prototype.handlerMemoFolderImageAdd)),

async function MemoFolderController_handlerMemoFolderImageAdd(request: ExRequest, response: ExResponse, next: any) {

// 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

let validatedArgs: any[] = [];
try {
validatedArgs = templateService.getValidatedArgs({ args: argsMemoFolderController_handlerMemoFolderImageAdd, request, response });

const controller = new MemoFolderController();

await templateService.apiHandler({
methodName: 'handlerMemoFolderImageAdd',
controller,
response,
next,
validatedArgs,
successStatus: 200,
});
} catch (err) {
return next(err);
}
});
// 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
const argsMemoFolderController_handlerMemoFolderAdd: Record<string, TsoaRoute.ParameterSchema> = {
req: {"in":"request","name":"req","required":true,"dataType":"object"},
body: {"in":"body","name":"body","required":true,"ref":"BodyToMemoFolder"},
Expand Down
24 changes: 21 additions & 3 deletions src/s3/image.uploader.middleware.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,30 @@
import {Request, Response, NextFunction} from 'express';
import {imageUploader} from './image.uploader.js';
// import {PhotoValidationError} from '../errors.js';

export const ImageUploadMiddleware = (
import {getMemoFolder} from 'src/repositories/memo-folder.repository.tsoa.js';
import {DataValidationError, FolderNotFoundError} from 'src/errors.js';
export const ImageUploadMiddleware = async (
req: Request,
res: Response,
next: NextFunction,
) => {
const userId = BigInt(req.user!.id);
if (req.params === null) {
return next(
new DataValidationError({reason: 'folderId가 유효하지 않습니다.'}),
);
}
try {
const folderId = req.params.folderId;
const checkFolder = await getMemoFolder(BigInt(folderId));

if (!checkFolder || checkFolder.userId !== userId) {
return next(new FolderNotFoundError({folderId: BigInt(folderId)}));
}
const uploadDirectory = folderId;
req.uploadDirectory = BigInt(uploadDirectory);
} catch (error) {
return next(error);
}
imageUploader.single('image')(req, res, err => {
if (err) {
next(err);
Expand Down
Loading