From cd50037fdb12ca67e6419d24cadd2fce2a64e901 Mon Sep 17 00:00:00 2001 From: bkw535 Date: Wed, 30 Jul 2025 20:36:10 +0900 Subject: [PATCH 1/5] =?UTF-8?q?[REFACTOR]=20=EC=B1=84=ED=8C=85=EB=B0=A9=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C=20API=20jwt=20=EC=9D=B8=EC=A6=9D=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/chat/chat.routes.js | 3 ++- src/chat/controller/chatroom.controller.js | 3 +++ src/chat/dto/chatroom.dto.js | 9 +++++---- src/chat/repository/chatroom.repository.js | 6 ++++-- src/chat/service/chatroom.service.js | 2 +- 5 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/chat/chat.routes.js b/src/chat/chat.routes.js index 749a165..92a7733 100644 --- a/src/chat/chat.routes.js +++ b/src/chat/chat.routes.js @@ -4,6 +4,7 @@ import { showChatroom } from "./controller/chatroom.controller.js"; import { deleteChatrooms } from "./controller/chatroom.controller.js"; import { showMessages } from "./controller/chat.controller.js"; import { getMessageByKeyword } from "./controller/chat.controller.js"; +import { authenticate } from "../middlewares/auth.middleware.js"; const router = express.Router(); @@ -11,7 +12,7 @@ const router = express.Router(); router.post("", createChatroom); // 채팅방 삭제 API -router.delete("/delete", deleteChatrooms); +router.delete("/delete", authenticate, deleteChatrooms); // 채팅 메시지 검색 API router.get("/search/messages", getMessageByKeyword); diff --git a/src/chat/controller/chatroom.controller.js b/src/chat/controller/chatroom.controller.js index a276a0a..3fdc23f 100644 --- a/src/chat/controller/chatroom.controller.js +++ b/src/chat/controller/chatroom.controller.js @@ -39,9 +39,12 @@ export const showChatroom = async (req, res, next) => { export const deleteChatrooms = async (req, res, next) => { try { + const userId = BigInt(req.user.userId); + const dto = new DeleteChatroomDto({ chatroomIds: req.body.chatroomIds, userType: req.body.userType, + userId: userId, }); const chatrooms = await ChatroomService.softDeleteChatroomsByUser(dto); diff --git a/src/chat/dto/chatroom.dto.js b/src/chat/dto/chatroom.dto.js index bc75415..209f875 100644 --- a/src/chat/dto/chatroom.dto.js +++ b/src/chat/dto/chatroom.dto.js @@ -13,8 +13,9 @@ export class ShowChatroomDto { } export class DeleteChatroomDto { - constructor({ chatroomIds, userType }) { - this.chatroomIds = chatroomIds.map(id => BigInt(id)); - this.userType = userType; - } + constructor({ chatroomIds, userType, userId }) { + this.chatroomIds = chatroomIds.map(id => BigInt(id)); + this.userType = userType; + this.userId = BigInt(userId); + } } \ No newline at end of file diff --git a/src/chat/repository/chatroom.repository.js b/src/chat/repository/chatroom.repository.js index 91ff292..9147ad1 100644 --- a/src/chat/repository/chatroom.repository.js +++ b/src/chat/repository/chatroom.repository.js @@ -30,12 +30,14 @@ export const ChatroomRepository = { }); }, - async softDeleteChatrooms(chatroomIds, userType) { + async softDeleteChatrooms(chatroomIds, userType, userId) { const hiddenField = userType === "consumer" ? "hiddenConsumer" : "hiddenArtist"; + const userField = userType === "consumer" ? "consumerId" : "artistId"; await prisma.chatroom.updateMany({ where: { - id: { in: chatroomIds } + id: { in: chatroomIds }, + [userField]: userId }, data: { [hiddenField]: true diff --git a/src/chat/service/chatroom.service.js b/src/chat/service/chatroom.service.js index 56bb9ad..5bf20d3 100644 --- a/src/chat/service/chatroom.service.js +++ b/src/chat/service/chatroom.service.js @@ -62,7 +62,7 @@ export const ChatroomService = { throw new ChatroomNotFoundError({ chatroomIds: dto.chatroomIds }); } - await ChatroomRepository.softDeleteChatrooms(dto.chatroomIds, dto.userType); + await ChatroomRepository.softDeleteChatrooms(dto.chatroomIds, dto.userType, dto.userId); const chatrooms = await ChatroomRepository.findChatroomsByIds(dto.chatroomIds); From 4d97aff381ff5b3b7ad6c19febe57c1cc234e3e6 Mon Sep 17 00:00:00 2001 From: bkw535 Date: Wed, 30 Jul 2025 21:23:46 +0900 Subject: [PATCH 2/5] =?UTF-8?q?[REFACTOR]=20=EC=B1=84=ED=8C=85=EB=B0=A9=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20API=20JWT=20=EC=9D=B8=EC=A6=9D=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9,=20CD=20=ED=8C=8C=EC=9D=B4=EC=96=B4=EB=B2=A0=EC=9D=B4?= =?UTF-8?q?=EC=8A=A4=20=EC=9D=B8=EC=A6=9D=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/cd.yml | 6 ++++++ src/chat/chat.routes.js | 4 ++-- src/chat/controller/chatroom.controller.js | 8 ++++---- src/chat/dto/chatroom.dto.js | 4 ++-- src/chat/repository/chatroom.repository.js | 3 ++- 5 files changed, 16 insertions(+), 9 deletions(-) diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index 545365b..520d62d 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -42,6 +42,12 @@ jobs: ssh ec2 "echo '$ENV_FILE' > /opt/app/.env" env: ENV_FILE: ${{ secrets.ENV_FILE }} + + - name: Restore Firebase service account key + run: | + ssh ec2 "mkdir -p /opt/app/config && echo $FIREBASE_SERVICE_ACCOUNT_BASE64 | base64 -d > /opt/app/config/service-account-key.json" + env: + FIREBASE_SERVICE_ACCOUNT_BASE64: ${{ secrets.FIREBASE_SERVICE_ACCOUNT_BASE64 }} - name: Install dependencies run: ssh ec2 "cd /opt/app && npm install" diff --git a/src/chat/chat.routes.js b/src/chat/chat.routes.js index 92a7733..a284fa5 100644 --- a/src/chat/chat.routes.js +++ b/src/chat/chat.routes.js @@ -1,6 +1,6 @@ import express from "express"; import { createChatroom } from "./controller/chatroom.controller.js"; -import { showChatroom } from "./controller/chatroom.controller.js"; +import { getChatroom } from "./controller/chatroom.controller.js"; import { deleteChatrooms } from "./controller/chatroom.controller.js"; import { showMessages } from "./controller/chat.controller.js"; import { getMessageByKeyword } from "./controller/chat.controller.js"; @@ -18,7 +18,7 @@ router.delete("/delete", authenticate, deleteChatrooms); router.get("/search/messages", getMessageByKeyword); // 채팅방 조회 API -router.get("/:consumerId", showChatroom); +router.get("", getChatroom); // 채팅 메시지 조회 API router.get("/:chatroomId/messages", showMessages); diff --git a/src/chat/controller/chatroom.controller.js b/src/chat/controller/chatroom.controller.js index 3fdc23f..e6ac0e6 100644 --- a/src/chat/controller/chatroom.controller.js +++ b/src/chat/controller/chatroom.controller.js @@ -1,7 +1,7 @@ import { StatusCodes } from "http-status-codes"; import { ChatroomService } from "../service/chatroom.service.js"; import { CreateChatroomDto } from "../dto/chatroom.dto.js"; -import { ShowChatroomDto } from "../dto/chatroom.dto.js"; +import { GetChatroomDto } from "../dto/chatroom.dto.js"; import { DeleteChatroomDto } from "../dto/chatroom.dto.js"; import { parseWithBigInt, stringifyWithBigInt } from "../../bigintJson.js"; @@ -22,10 +22,10 @@ export const createChatroom = async (req, res, next) => { } }; -export const showChatroom = async (req, res, next) => { +export const getChatroom = async (req, res, next) => { try { - const dto = new ShowChatroomDto({ - consumerId: BigInt(req.params.consumerId) + const dto = new GetChatroomDto({ + consumerId: BigInt(req.user.userId) }); const chatrooms = await ChatroomService.getChatroomsByUserId(dto); diff --git a/src/chat/dto/chatroom.dto.js b/src/chat/dto/chatroom.dto.js index 209f875..61f6c84 100644 --- a/src/chat/dto/chatroom.dto.js +++ b/src/chat/dto/chatroom.dto.js @@ -6,9 +6,9 @@ export class CreateChatroomDto { } } -export class ShowChatroomDto { +export class GetChatroomDto { constructor({ consumerId }) { - this.consumerId = consumerId; + this.consumerId = BigInt(consumerId); } } diff --git a/src/chat/repository/chatroom.repository.js b/src/chat/repository/chatroom.repository.js index 9147ad1..d344949 100644 --- a/src/chat/repository/chatroom.repository.js +++ b/src/chat/repository/chatroom.repository.js @@ -26,7 +26,8 @@ export const ChatroomRepository = { return await prisma.chatroom.findMany({ where: { consumerId: consumerId, - }, + hiddenConsumer: false, + } }); }, From bad3635cfe5c27bb10960b4cec2e03244f377677 Mon Sep 17 00:00:00 2001 From: bkw535 Date: Wed, 30 Jul 2025 21:34:20 +0900 Subject: [PATCH 3/5] =?UTF-8?q?[REFACTOR]=20=EC=B1=84=ED=8C=85=20=EB=A9=94?= =?UTF-8?q?=EC=8B=9C=EC=A7=80=20=EC=A1=B0=ED=9A=8C=20API=20JWT=20=EC=9D=B8?= =?UTF-8?q?=EC=A6=9D=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/chat/chat.routes.js | 6 +++--- src/chat/controller/chat.controller.js | 9 ++++++--- src/chat/dto/chat.dto.js | 5 +++-- src/chat/service/chat.service.js | 5 +++++ src/common/errors/chat.errors.js | 11 +++++++++++ 5 files changed, 28 insertions(+), 8 deletions(-) diff --git a/src/chat/chat.routes.js b/src/chat/chat.routes.js index a284fa5..575291a 100644 --- a/src/chat/chat.routes.js +++ b/src/chat/chat.routes.js @@ -2,7 +2,7 @@ import express from "express"; import { createChatroom } from "./controller/chatroom.controller.js"; import { getChatroom } from "./controller/chatroom.controller.js"; import { deleteChatrooms } from "./controller/chatroom.controller.js"; -import { showMessages } from "./controller/chat.controller.js"; +import { getMessages } from "./controller/chat.controller.js"; import { getMessageByKeyword } from "./controller/chat.controller.js"; import { authenticate } from "../middlewares/auth.middleware.js"; @@ -18,9 +18,9 @@ router.delete("/delete", authenticate, deleteChatrooms); router.get("/search/messages", getMessageByKeyword); // 채팅방 조회 API -router.get("", getChatroom); +router.get("", authenticate, getChatroom); // 채팅 메시지 조회 API -router.get("/:chatroomId/messages", showMessages); +router.get("/:chatroomId/messages", authenticate, getMessages); export default router; \ No newline at end of file diff --git a/src/chat/controller/chat.controller.js b/src/chat/controller/chat.controller.js index 156bb4c..ba31245 100644 --- a/src/chat/controller/chat.controller.js +++ b/src/chat/controller/chat.controller.js @@ -1,15 +1,18 @@ import { StatusCodes } from "http-status-codes"; import { parseWithBigInt, stringifyWithBigInt } from "../../bigintJson.js"; -import { ShowMessagesDto } from "../dto/chat.dto.js"; +import { GetMessagesDto } from "../dto/chat.dto.js"; import { ChatService } from "../service/chat.service.js"; import { FindChatroomByMessageDto } from "../dto/chat.dto.js"; -export const showMessages = async (req, res, next) => { +export const getMessages = async (req, res, next) => { try { - const dto = new ShowMessagesDto ({ + const userId = BigInt(req.user.userId); + + const dto = new GetMessagesDto ({ chatroomId: BigInt(req.params.chatroomId), limit: req.query.limit, cursor: req.query.cursor, + userId: userId, }); const messages = await ChatService.getMessagesByChatroomId(dto); diff --git a/src/chat/dto/chat.dto.js b/src/chat/dto/chat.dto.js index 4799f3f..99d794d 100644 --- a/src/chat/dto/chat.dto.js +++ b/src/chat/dto/chat.dto.js @@ -1,8 +1,9 @@ -export class ShowMessagesDto { - constructor({ chatroomId, limit, cursor }) { +export class GetMessagesDto { + constructor({ chatroomId, limit, cursor, userId }) { this.chatroomId = chatroomId; this.limit = limit ? Number(limit) : 20; this.cursor = cursor ? BigInt(cursor) : null; + this.userId = BigInt(userId); } } diff --git a/src/chat/service/chat.service.js b/src/chat/service/chat.service.js index 3d89767..fb34b43 100644 --- a/src/chat/service/chat.service.js +++ b/src/chat/service/chat.service.js @@ -1,6 +1,7 @@ import { ChatroomRepository } from "../repository/chatroom.repository.js"; import { ChatRepository } from "../repository/chat.repository.js"; import { ChatroomNotFoundError } from "../../common/errors/chat.errors.js"; +import { ForbiddenError } from "../../common/errors/chat.errors.js"; export const ChatService = { async getMessagesByChatroomId(dto) { @@ -8,6 +9,10 @@ export const ChatService = { if (!chatroom) { throw new ChatroomNotFoundError({ chatroomId: dto.chatroomId }); } + + if (dto.userId !== chatroom.consumerId && dto.userId !== chatroom.artistId) { + throw new ForbiddenError({ consumerId: dto.userId }); + } const messages = await ChatRepository.findMessagesWithImages(dto); return messages; diff --git a/src/common/errors/chat.errors.js b/src/common/errors/chat.errors.js index fe016fd..b63f269 100644 --- a/src/common/errors/chat.errors.js +++ b/src/common/errors/chat.errors.js @@ -9,4 +9,15 @@ export class ChatroomNotFoundError extends BaseError { data, }); } +} + +export class ForbiddenError extends BaseError { + constructor(data = null) { + super({ + errorCode: "M002", + reason: "권한이 없습니다.", + statusCode: 403, + data, + }); + } } \ No newline at end of file From 78491f4fb259ac4cdcf39a4b1d057dabb29b2ead Mon Sep 17 00:00:00 2001 From: bkw535 Date: Wed, 30 Jul 2025 21:51:31 +0900 Subject: [PATCH 4/5] =?UTF-8?q?[REFACTOR]=20=EC=B1=84=ED=8C=85=20=EB=A9=94?= =?UTF-8?q?=EC=8B=9C=EC=A7=80=20=EA=B2=80=EC=83=89=20API=20JWT=20=EC=9D=B8?= =?UTF-8?q?=EC=A6=9D=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/chat/chat.routes.js | 4 ++-- src/chat/controller/chat.controller.js | 9 +++++++-- src/chat/dto/chat.dto.js | 5 +++-- src/chat/service/chat.service.js | 7 +++++-- 4 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/chat/chat.routes.js b/src/chat/chat.routes.js index 575291a..3b89fe3 100644 --- a/src/chat/chat.routes.js +++ b/src/chat/chat.routes.js @@ -14,8 +14,8 @@ router.post("", createChatroom); // 채팅방 삭제 API router.delete("/delete", authenticate, deleteChatrooms); -// 채팅 메시지 검색 API -router.get("/search/messages", getMessageByKeyword); +// 채팅 메시지 검색 API (다중) +router.get("/search/messages", authenticate, getMessageByKeyword); // 채팅방 조회 API router.get("", authenticate, getChatroom); diff --git a/src/chat/controller/chat.controller.js b/src/chat/controller/chat.controller.js index ba31245..f667ec6 100644 --- a/src/chat/controller/chat.controller.js +++ b/src/chat/controller/chat.controller.js @@ -26,9 +26,14 @@ export const getMessages = async (req, res, next) => { export const getMessageByKeyword = async (req, res, next) => { try { - const dto = new FindChatroomByMessageDto(req.query); + const userId = BigInt(req.user.userId); + + const dto = new FindChatroomByMessageDto({ + keyword: req.query.keyword, + userId: userId, + }); - const messages = await ChatService.searchMessagesByKeyword(dto.keyword); + const messages = await ChatService.searchMessagesByKeyword(dto); const responseData = parseWithBigInt(stringifyWithBigInt(messages)); res.status(StatusCodes.OK).success(responseData); diff --git a/src/chat/dto/chat.dto.js b/src/chat/dto/chat.dto.js index 99d794d..4fe7adc 100644 --- a/src/chat/dto/chat.dto.js +++ b/src/chat/dto/chat.dto.js @@ -8,7 +8,8 @@ export class GetMessagesDto { } export class FindChatroomByMessageDto { - constructor(query) { - this.keyword = query.keyword; + constructor({ keyword, userId }) { + this.keyword = keyword; + this.userId = BigInt(userId); } } \ No newline at end of file diff --git a/src/chat/service/chat.service.js b/src/chat/service/chat.service.js index fb34b43..bf98dc0 100644 --- a/src/chat/service/chat.service.js +++ b/src/chat/service/chat.service.js @@ -18,8 +18,11 @@ export const ChatService = { return messages; }, - async searchMessagesByKeyword(keyword) { - const messages = await ChatRepository.searchByKeyword(keyword); + async searchMessagesByKeyword(dto) { + const userChatrooms = await ChatroomRepository.findChatroomsByUser(dto.userId); + const chatroomIds = userChatrooms.map(cr => cr.id); + + const messages = await ChatRepository.searchByKeyword(dto.keyword, chatroomIds); return messages; }, }; \ No newline at end of file From 3f7eaba34297f1fa47439359613cca41aa35e495 Mon Sep 17 00:00:00 2001 From: bkw535 Date: Wed, 30 Jul 2025 22:47:00 +0900 Subject: [PATCH 5/5] =?UTF-8?q?[REFACTOR]=20=EC=B1=84=ED=8C=85=EB=B0=A9=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20API=20JWT=20=EC=9D=B8=EC=A6=9D=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/chat/chat.routes.js | 4 +- src/chat/controller/chatroom.controller.js | 4 +- src/common/swagger/chat.json | 210 ++++++++++++++++++--- 3 files changed, 194 insertions(+), 24 deletions(-) diff --git a/src/chat/chat.routes.js b/src/chat/chat.routes.js index 3b89fe3..908623f 100644 --- a/src/chat/chat.routes.js +++ b/src/chat/chat.routes.js @@ -9,7 +9,7 @@ import { authenticate } from "../middlewares/auth.middleware.js"; const router = express.Router(); // 채팅방 생성 API -router.post("", createChatroom); +router.post("", authenticate, createChatroom); // 채팅방 삭제 API router.delete("/delete", authenticate, deleteChatrooms); @@ -18,7 +18,7 @@ router.delete("/delete", authenticate, deleteChatrooms); router.get("/search/messages", authenticate, getMessageByKeyword); // 채팅방 조회 API -router.get("", authenticate, getChatroom); +router.get("/list", authenticate, getChatroom); // 채팅 메시지 조회 API router.get("/:chatroomId/messages", authenticate, getMessages); diff --git a/src/chat/controller/chatroom.controller.js b/src/chat/controller/chatroom.controller.js index e6ac0e6..240e895 100644 --- a/src/chat/controller/chatroom.controller.js +++ b/src/chat/controller/chatroom.controller.js @@ -7,8 +7,10 @@ import { parseWithBigInt, stringifyWithBigInt } from "../../bigintJson.js"; export const createChatroom = async (req, res, next) => { try { + const consumerId = BigInt(req.user.userId); + const dto = new CreateChatroomDto({ - consumerId: BigInt(req.body.consumerId), + consumerId: consumerId, artistId: BigInt(req.body.artistId), requestId: BigInt(req.body.requestId), }); diff --git a/src/common/swagger/chat.json b/src/common/swagger/chat.json index 4100f76..e483125 100644 --- a/src/common/swagger/chat.json +++ b/src/common/swagger/chat.json @@ -4,6 +4,11 @@ "post": { "summary": "채팅방 생성", "description": "consumerId, artistId, requestId로 채팅방을 생성합니다.", + "security": [ + { + "bearerAuth": [] + } + ], "tags": ["Chat"], "requestBody": { "required": true, @@ -45,28 +50,41 @@ } }, "404": { - "description": "사용자, 작가, 요청 중 하나를 찾을 수 없음" + "description": "사용자를 찾을 수 없음", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "resultType": { "type": "string", "example": "FAIL" }, + "error": { + "type": "object", + "properties": { + "errorCode": { "type": "string", "example": "U001" }, + "reason": { "type": "string", "example": "사용자 id를 찾을 수 없습니다." }, + "data": { "type": "object" } + } + }, + "success": { "type": "object", "nullable": true, "example": null } + } + } + } + } } } } }, - "/api/chatrooms/{consumerId}": { + "/api/chatrooms/list": { "get": { - "summary": "사용자 ID로 채팅방 목록 조회", - "description": "사용자 ID를 바탕으로 해당 사용자가 참여한 채팅방 목록을 조회합니다.", - "tags": ["Chat"], - "parameters": [ + "summary": "채팅방 목록 조회", + "description": "사용자가 참여한 채팅방 목록을 조회합니다.", + "security": [ { - "name": "consumerId", - "in": "path", - "required": true, - "schema": { - "type": "string", - "example": "1" - }, - "description": "조회할 사용자의 ID" + "bearerAuth": [] } ], + "tags": ["Chat"], + "parameters": [], "responses": { "200": { "description": "채팅방 목록 조회 성공", @@ -132,6 +150,11 @@ "delete": { "summary": "채팅방 소프트 삭제 (hidden 처리) 및 조건부 하드 삭제", "description": "사용자가 선택한 채팅방들을 hidden 처리 후, hiddenUser와 hiddenArtist가 모두 true인 경우 DB에서 삭제합니다.", + "security": [ + { + "bearerAuth": [] + } + ], "tags": ["Chat"], "requestBody": { "required": true, @@ -163,10 +186,54 @@ "description": "삭제 처리 완료 (내용 없음)" }, "400": { - "description": "잘못된 요청 파라미터" + "description": "잘못된 요청 파라미터", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "resultType": { "type": "string", "example": "FAIL" }, + "error": { + "type": "object", + "properties": { + "errorCode": { "type": "string", "example": "C001" }, + "reason": { "type": "string", "example": "userType은 'consumer' 또는 'artist'여야 합니다." }, + "data": { "type": "object", "example": {} } + } + }, + "success": { + "type": ["object", "null"], + "example": null + } + } + } + } + } }, "404": { - "description": "채팅방을 찾을 수 없음" + "description": "채팅방을 찾을 수 없음", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "resultType": { "type": "string", "example": "FAIL" }, + "error": { + "type": "object", + "properties": { + "errorCode": { "type": "string", "example": "C002" }, + "reason": { "type": "string", "example": "요청한 채팅방을 찾을 수 없습니다." }, + "data": { "type": "object", "example": { "chatroomIds": [999] } } + } + }, + "success": { + "type": ["object", "null"], + "example": null + } + } + } + } + } } } } @@ -174,7 +241,12 @@ "/api/chatrooms/{chatroomId}/messages": { "get": { "summary": "채팅방 메시지 조회", - "description": "채팅방 ID를 기반으로 해당 채팅방의 메시지를 조회합니다. 무한 스크롤을 위해 cursor(이전 페이지 마지막 메시지 id)와 limit을 query로 받습니다.", + "description": "해당 채팅방의 메시지를 조회합니다. 무한 스크롤을 위해 cursor(이전 페이지 마지막 메시지 id)와 limit을 query로 받습니다.", + "security": [ + { + "bearerAuth": [] + } + ], "tags": ["Chat"], "parameters": [ { @@ -277,10 +349,57 @@ } }, "404": { - "description": "채팅방을 찾을 수 없음" + "description": "채팅방을 찾을 수 없음", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "resultType": { "type": "string", "example": "FAIL" }, + "error": { + "type": "object", + "properties": { + "errorCode": { "type": "string", "example": "C002" }, + "reason": { "type": "string", "example": "요청한 채팅방을 찾을 수 없습니다." }, + "data": { + "type": "object", + "example": { "chatroomIds": [999] } + } + } + }, + "success": { + "type": ["object", "null"], + "example": null + } + } + } + } + } }, "500": { - "description": "서버 오류" + "description": "서버 오류", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "resultType": { "type": "string", "example": "FAIL" }, + "error": { + "type": "object", + "properties": { + "errorCode": { "type": "string", "example": "S001" }, + "reason": { "type": "string", "example": "알 수 없는 서버 오류가 발생했습니다." }, + "data": { "type": "object", "example": {} } + } + }, + "success": { + "type": ["object", "null"], + "example": null + } + } + } + } + } } } } @@ -289,6 +408,11 @@ "get": { "summary": "메시지 키워드 검색", "description": "키워드가 포함된 메시지를 검색하여 반환합니다.", + "security": [ + { + "bearerAuth": [] + } + ], "tags": ["Chat"], "parameters": [ { @@ -361,10 +485,54 @@ } }, "400": { - "description": "잘못된 요청" + "description": "잘못된 요청", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "resultType": { "type": "string", "example": "FAIL" }, + "error": { + "type": "object", + "properties": { + "errorCode": { "type": "string", "example": "R001" }, + "reason": { "type": "string", "example": "keyword 쿼리 파라미터는 필수입니다." }, + "data": { "type": "object", "example": {} } + } + }, + "success": { + "type": ["object", "null"], + "example": null + } + } + } + } + } }, "500": { - "description": "서버 오류" + "description": "서버 오류", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "resultType": { "type": "string", "example": "FAIL" }, + "error": { + "type": "object", + "properties": { + "errorCode": { "type": "string", "example": "S001" }, + "reason": { "type": "string", "example": "알 수 없는 서버 오류가 발생했습니다." }, + "data": { "type": "object", "example": {} } + } + }, + "success": { + "type": ["object", "null"], + "example": null + } + } + } + } + } } } }