diff --git a/src/app.ts b/src/app.ts index 2c7658e..ff6f999 100644 --- a/src/app.ts +++ b/src/app.ts @@ -28,7 +28,7 @@ import {authRouter} from './routers/auth.routers.js'; import {userRouter} from './routers/user.router.js'; import {tagRouter} from './routers/tag.router.js'; import {myPageRouter} from './routers/mypage.routers.js'; - +import {trustRouter} from './routers/trust.router.js'; dotenv.config(); const app = express(); @@ -115,6 +115,7 @@ app.use('/memo', memoFolderRouter); app.use('/challenge', challengeRouter); app.use('/user/mypage',myPageRouter); app.use('/tag', tagRouter); +app.use('/trust',trustRouter); app.post('/image/ai', labelDetectionController); RegisterRoutes(app); diff --git a/src/controllers/trust.controller.ts b/src/controllers/trust.controller.ts index b1e3583..b2d5c12 100644 --- a/src/controllers/trust.controller.ts +++ b/src/controllers/trust.controller.ts @@ -1,149 +1,61 @@ -import {Request, Response} from 'express'; +import {Request, Response, NextFunction} from 'express'; +import * as trustService from '../services/trust.service.js'; +import {SearchNoResultsError,ServerError,DataValidationError} from 'src/errors.js'; import {StatusCodes} from 'http-status-codes'; -import {imageStatusUpdate, imageDelete} from '../services/trust.service.js'; -import {bodyToImage} from '../dtos/image.dto.js'; - -async function handleImageStatus(req: Request, res: Response): Promise { - /* - #swagger.tags = ['trust-controller'] - #swagger.summary = '이미지 상태 변화 API'; - #swagger.description = '이미지를 활성화(1) 또는 비활성화(0) 시키는 API입니다. 유저나 이미지 고유 id를 통해 이미지 상태를 변경할 수 있습니다.' - #swagger.requestBody = { - required: true, - content: { - "multipart/form-data": { - schema: { - type: "object", - required: ['userId', 'imageId'], - properties: { - userId: { type: "interger", description: "사용자 ID" }, - imageId: { type: "integer", description: "이미지 고유 ID" , example: 1000100124} - } - } +export const handleImageStatus = async (req: Request, res: Response, next:NextFunction): Promise => { + try { + const {mediaId} = req.body; + const parsedMediaId = parseInt(mediaId); + if (isNaN(parsedMediaId)) { + throw new SearchNoResultsError({searchKeyword: 'mediaId가 올바르지 않습니다'}); } - } + const updatedImage = await trustService.deactivateImages(mediaId); + if (!updatedImage) { + throw new SearchNoResultsError({ searchKeyword: '해당 mediaId에 대한 이미지가 존재하지 않습니다' }); + } + const result = { + mediaId: updatedImage.mediaId, + status: updatedImage.status }; - #swagger.responses[200] = { - description: "이미지 상태 변화 성공 응답", - content: { - "application/json": { - schema: { - type: "object", - properties: { - resultType: { type: "string", example: "SUCCESS" }, - error: { type: "object", nullable: true, example: null }, - success: { - type: "object", - properties: { - id: { type: "string", example: "1" }, - mediaId: { type: "string", example: "1000100124" }, - userId: { type: "string", example: "1" }, - createdAt: { type: "string", example: "2021-08-31T07:00:00.000Z" }, - updatedAt: { type: "string", example: "2021-08-31T07:00:00.000Z" }, - status: { type: "number", example: 1 } - } - } - } - } - } - } - }; - #swagger.responses[400] = { - description: "이미지 상태 변화 실패 응답", - content: { - "application/json": { - schema: { - type: "object", - properties: { - resultType: { type: "string", example: "FAIL" }, - error: { - type: "object", - properties: { - errorCode: { type: "string", example: "U400" }, - reason: { type: "string", example: "이미지 조회 에러" }, - data: { - type: "object", - example: null - } - } - }, - success: { type: "object", nullable: true, example: null } - } - } - } - } - } - }; - */ - const updateImageStatus = await imageStatusUpdate(bodyToImage(req.body)); - res.status(StatusCodes.OK).success(updateImageStatus); -} + res.status(StatusCodes.OK).success(result); + } catch (error) { + next(error); + } +}; -async function handleImageDelete(req: Request, res: Response): Promise { - /* - #swagger.tags = ['trust-controller'] - #swagger.summary = '휴지통 비우기 API'; - #swagger.description = '비활성화(0)된 이미지를 일괄 삭제시키는 API입니다. 유저 상태를 이용하여 변경할 수 있습니다.' - #swagger.requestBody = { - required: true, - content: { - "multipart/form-data": { - schema: { - type: "object", - required: ['userId', 'imageId'], - properties: { - userId: { type: "interger", description: "사용자 ID" }, - } - } - } - } - }; - #swagger.responses[200] = { - description: "휴지통 비우기 성공 응답", - content: { - "application/json": { - schema: { - type: "object", - properties: { - resultType: { type: "string", example: "SUCCESS" }, - error: { type: "object", nullable: true, example: null }, - success: { type: "boolean", example: "true" } - } - } - } - } - } - }; - #swagger.responses[400] = { - description: "휴지통 비우기 실패 응답", - content: { - "application/json": { - schema: { - type: "object", - properties: { - resultType: { type: "string", example: "FAIL" }, - error: { - type: "object", - properties: { - errorCode: { type: "string", example: "U400" }, - reason: { type: "string", example: "유저 조회 에러" }, - data: { - type: "object", - example: null - } - } - }, - success: { type: "object", nullable: true, example: null } - } - } - } - } - } - }; - */ - const deleteImage = await imageDelete(req.body.userId); - res.status(StatusCodes.OK).success(deleteImage); -} +export const handleImageRestore = async (req: Request, res: Response, next: NextFunction): Promise => { + try { + const {mediaIds} = req.body; + if (!Array.isArray(mediaIds)) { + throw new SearchNoResultsError({searchKeyword: 'mediaIds가 올바르지 않습니다'}); + } + const restoredImages = await trustService.restoreImages(mediaIds); + if (!restoredImages.length) { + throw new SearchNoResultsError({ searchKeyword: '해당 mediaIds에 대한 이미지가 존재하지 않습니다' }); + } + const result = restoredImages.map(image => ({ + mediaId: image.mediaId, + status: image.status + })); + res.status(StatusCodes.OK).success(result); + } catch (error) { + next(error); + } +}; -export {handleImageStatus, handleImageDelete}; \ No newline at end of file +export const handleImageDelete = async (req: Request, res: Response, next: NextFunction): Promise => { + try { + const { mediaIds } = req.body; + if (!Array.isArray(mediaIds)) { + throw new SearchNoResultsError({searchKeyword: 'mediaIds가 올바르지 않습니다'}); + } + const deleteable = await trustService.deleteImages(mediaIds); + if(!deleteable) { + throw new DataValidationError({reason: '해당 사진이 휴지통에 존재하지 않습니다'}); + } + res.status(StatusCodes.OK).success(deleteable); + } catch (error) { + next(error); + } +}; \ No newline at end of file diff --git a/src/repositories/trust.repositories.ts b/src/repositories/trust.repositories.ts index 5a8a3ac..065cba7 100644 --- a/src/repositories/trust.repositories.ts +++ b/src/repositories/trust.repositories.ts @@ -1,88 +1,25 @@ import {prisma} from '../db.config.js'; -import {BodyToImage, ResponseFromImage} from '../models/image.model.js'; -export async function updateStatusImage(image: BodyToImage): Promise { - const {mediaId, userId} = image; - let imageStatus: 0 | 1 = 0; - - const user = await prisma.user.findFirst({ - where: { - id: userId, - }, - }); - - if (user === null) { - throw new Error('유저 조회 에러'); - } - - const imageData = await prisma.image.findFirst({ - where: { - mediaId: mediaId, - userId: userId, - }, - }); - - if (imageData === null) { - throw new Error('이미지 조회 에러'); - } - - if (imageData.status === 0) { - imageStatus = 1; - } else { - imageStatus = 0; - } - - const updated = await prisma.image.update({ - where: { - id: imageData.id, - }, - data: { - status: imageStatus, - }, - }); - - if (updated === null) { - throw new Error('이미지 상태 변경 에러'); - } - - return updated.id; -} - -export async function deleteImage(userId: bigint): Promise { - const user = await prisma.user.findFirst({ - where: { - id: userId, - }, - }); - - if (user === null) { - throw new Error('유저 조회 에러'); - } - - const deleted = await prisma.image.deleteMany({ - where: { - userId, - status: 0, - }, +export const updateImageStatus = async (mediaIds: number[], status: number): Promise => { + await prisma.image.updateMany({ + where: { mediaId: { in: mediaIds } }, + data: { status } + }); +}; + +export const removeImages = async (mediaIds: number[]): Promise => { + await prisma.image.deleteMany({ + where: { mediaId: { in: mediaIds }, status: 0 } + }); +}; + +export const getImagesByIds = async (mediaIds: number[]): Promise<{ mediaId: number; status: number }[]> => { + const images = await prisma.image.findMany({ + where: { mediaId: { in: mediaIds } }, + select: { mediaId: true, status: true } }); - - if (deleted === null) { - throw new Error('이미지 삭제 에러'); - } - - return true; -} - -export async function getImage(imageId: bigint): Promise { - const image = await prisma.image.findFirst({ - where: { - id: imageId, - }, - }); // 이미지 조회 - - if (image === null) { - throw new Error('이미지 조회 에러'); - } // 이미지 조회 실패 시 null 반환 - - return image; -} \ No newline at end of file + return images.map(({ mediaId, status }) => ({ + mediaId: Number(mediaId), // 변환 적용 + status + })); +}; \ No newline at end of file diff --git a/src/routers/mypage.routers.ts b/src/routers/mypage.routers.ts index 33592ba..49169e4 100644 --- a/src/routers/mypage.routers.ts +++ b/src/routers/mypage.routers.ts @@ -1,10 +1,7 @@ import express from 'express'; export const myPageRouter = express.Router(); -import { updateUserNameController, updateUserGoalCountController } from '../controllers/user.controller.js'; import {getUser, logOutUser, deleteUser} from '../controllers/user.mypage.controllers.js'; -myPageRouter.get('/', getUser); -myPageRouter.patch('/name', updateUserNameController); -myPageRouter.patch('/goal', updateUserGoalCountController); +myPageRouter.get('/', getUser myPageRouter.get('/logout', logOutUser); myPageRouter.patch('/', deleteUser); \ No newline at end of file diff --git a/src/routers/trust.router.ts b/src/routers/trust.router.ts index 622e567..bf669d3 100644 --- a/src/routers/trust.router.ts +++ b/src/routers/trust.router.ts @@ -2,8 +2,10 @@ import express from 'express'; export const trustRouter = express.Router(); import { handleImageStatus, + handleImageRestore, handleImageDelete, } from '../controllers/trust.controller.js'; trustRouter.patch('/active', handleImageStatus); // 이미지 비활성화 +trustRouter.patch('/restore', handleImageRestore); //이미지 복구 trustRouter.delete('/', handleImageDelete); // 비활성화된 이미지 삭제 diff --git a/src/services/trust.service.ts b/src/services/trust.service.ts index 8de1d9b..b4d08e3 100644 --- a/src/services/trust.service.ts +++ b/src/services/trust.service.ts @@ -1,30 +1,21 @@ -import {BodyToImage, ResponseFromImage} from '../models/image.model.js'; -import {responseFromImage} from '../dtos/image.dto.js'; -import { - updateStatusImage, - getImage, - deleteImage, -} from '../repositories/trust.repositories.js'; +import * as trustRepository from '../repositories/trust.repositories.js'; -async function imageStatusUpdate( - image: BodyToImage, -): Promise { - console.log('imageStatusUpdate 실행'); - console.log('image: ', image); +export const deactivateImages = async (mediaId: number): Promise <{mediaId: number; status: number}> => { + await trustRepository.updateImageStatus([mediaId], 0); + const [updatedImage] = await trustRepository.getImagesByIds([mediaId]); + return updatedImage; +}; - const newImageId = await updateStatusImage(image); - const imageData = await getImage(newImageId); +export const restoreImages = async (mediaIds: number[]): Promise<{ mediaId: number; status: number }[]> => { + await trustRepository.updateImageStatus(mediaIds, 1); + return trustRepository.getImagesByIds(mediaIds); +}; - return responseFromImage(imageData); -} - -async function imageDelete(userId: bigint): Promise { - console.log('imageDelete 실행'); - console.log('userId: ', userId); - - const deleted = await deleteImage(userId); - - return deleted; -} - -export {imageStatusUpdate, imageDelete}; +export const deleteImages = async (mediaIds: number[]): Promise => { + const images = await trustRepository.getImagesByIds(mediaIds); + if (!images.length || images.some(({ status }) => status ===1)){ + return false; + } + await trustRepository.removeImages(mediaIds); + return true; +}; \ No newline at end of file diff --git a/src/utils/tag.utils.ts b/src/utils/tag.utils.ts deleted file mode 100644 index 9169f63..0000000 --- a/src/utils/tag.utils.ts +++ /dev/null @@ -1,8 +0,0 @@ -import {BaseBodyToTag} from '../models/tag.model.js'; - -export function tagcategory(tags: BaseBodyToTag[]): String[] { - const tagcategory = tags.map(tag => { - return tag.content; - }); - return tagcategory; -}