From b197081d1e83428bc4663e5cdeaf2adcfaa2bd65 Mon Sep 17 00:00:00 2001 From: Hyein Jeong Date: Tue, 12 Nov 2024 17:49:05 +0900 Subject: [PATCH] =?UTF-8?q?[BE][Feat]=20:=20=EC=B1=84=EB=84=90=EC=97=90=20?= =?UTF-8?q?guest=20=EC=B6=94=EA=B0=80=20api=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 채널에 guest 추가하는 api에 대한 swagger 문서 추가 - guest 추가하는 api 구현 --- backend/src/controllers/channelController.js | 29 +++- backend/src/repositories/channelRepository.js | 16 +++ backend/src/repositories/guestRepository.js | 2 +- backend/src/routes/channelRouter.js | 95 ++++++++++++- backend/src/routes/example.js | 13 -- backend/src/services/channelService.js | 30 ++++- backend/swaggerConfig.js | 125 ++++++++++++++++++ 7 files changed, 289 insertions(+), 21 deletions(-) delete mode 100644 backend/src/routes/example.js diff --git a/backend/src/controllers/channelController.js b/backend/src/controllers/channelController.js index da24d063..4be62cc7 100644 --- a/backend/src/controllers/channelController.js +++ b/backend/src/controllers/channelController.js @@ -1,4 +1,4 @@ -import { createChannelService } from '../services/channelService.js'; +import { addGuestService, createChannelService } from '../services/channelService.js'; export const createChannelController = async (req, res) => { try { @@ -19,3 +19,30 @@ export const createChannelController = async (req, res) => { }); } }; + +export const addGuestController = async (req, res) => { + try { + const { channelId } = req.params; + const { guests } = req.body; + + const updatedChannel = await addGuestService(channelId, guests); + + if (!updatedChannel) { + return res.status(404).json({ + success: false, + message: 'Channel not found', + }); + } + + return res.status(200).json({ + success: true, + message: 'Guests added successfully', + }); + } catch (err) { + console.error(err); + return res.status(500).json({ + success: false, + message: 'Server error', + }); + } +}; diff --git a/backend/src/repositories/channelRepository.js b/backend/src/repositories/channelRepository.js index 335d134b..89619a21 100644 --- a/backend/src/repositories/channelRepository.js +++ b/backend/src/repositories/channelRepository.js @@ -13,3 +13,19 @@ export const createChannelInDB = async (name, host_id) => { return result.rows[0]; }; + +export const getChannelById = async channelId => { + const query = ` + SELECT * + FROM "main"."channel" + WHERE id = $1; + `; + const values = [channelId]; + const result = await pool.query(query, values); + + if (result.rows.length === 0) { + return null; + } + + return result.rows[0]; +}; diff --git a/backend/src/repositories/guestRepository.js b/backend/src/repositories/guestRepository.js index 6f29611b..35e8c7d5 100644 --- a/backend/src/repositories/guestRepository.js +++ b/backend/src/repositories/guestRepository.js @@ -1,7 +1,7 @@ import { v4 as uuidv4 } from 'uuid'; import { pool } from '../db/db.js'; -export const addGuestInDB = async ( +export const addGuestToChannel = async ( channel_id, name, start_location, diff --git a/backend/src/routes/channelRouter.js b/backend/src/routes/channelRouter.js index 9b229fdd..0738bb36 100644 --- a/backend/src/routes/channelRouter.js +++ b/backend/src/routes/channelRouter.js @@ -1,6 +1,6 @@ import express from 'express'; import { body } from 'express-validator'; -import { createChannelController } from '../controllers/channelController.js'; +import { addGuestController, createChannelController } from '../controllers/channelController.js'; import { validationMiddleware } from '../middleware/validationMiddleware.js'; export const channelRouter = express.Router(); @@ -40,3 +40,96 @@ channelRouter.post( validationMiddleware, createChannelController, ); + +/** + * @swagger + * /channels/{channelId}/guests: + * post: + * summary: 'Add guests to an existing channel' + * description: 'Add new guests to an existing channel by providing guest information.' + * operationId: 'addGuest' + * parameters: + * - in: path + * name: channelId + * required: true + * description: 'ID of the channel to which guests are being added' + * schema: + * type: string + * example: '123e4567-e89b-12d3-a456-426614174000' + * requestBody: + * description: 'Guest data to be added to the channel' + * content: + * application/json: + * schema: + * type: object + * properties: + * guests: + * type: array + * items: + * type: object + * properties: + * name: + * type: string + * description: 'Guest\'s name' + * start_location: + * type: object + * properties: + * lat: + * type: number + * description: 'Latitude of the start location' + * lng: + * type: number + * description: 'Longitude of the start location' + * end_location: + * type: object + * properties: + * lat: + * type: number + * description: 'Latitude of the end location' + * lng: + * type: number + * description: 'Longitude of the end location' + * path: + * type: array + * items: + * type: object + * properties: + * lat: + * type: number + * description: 'Latitude of a waypoint' + * lng: + * type: number + * description: 'Longitude of a waypoint' + * marker_style: + * type: object + * properties: + * color: + * type: string + * description: 'Color for the guest marker' + * responses: + * 200: + * description: 'Guests added successfully' + * content: + * application/json: + * schema: + * type: object + * properties: + * success: + * type: boolean + * example: true + * message: + * type: string + * example: 'Guests added successfully' + * 400: + * description: 'Invalid input data' + * 404: + * description: 'Channel not found' + * 500: + * description: 'Server error' + */ +channelRouter.post( + '/:channelId/guests', + [body('guests').isArray().withMessage('Guests must be an array')], + validationMiddleware, + addGuestController, +); diff --git a/backend/src/routes/example.js b/backend/src/routes/example.js deleted file mode 100644 index e9168225..00000000 --- a/backend/src/routes/example.js +++ /dev/null @@ -1,13 +0,0 @@ -/** - * @swagger - * /example: - * get: - * summary: Example endpoint - * description: Returns a simple "Hello World" message - * responses: - * 200: - * description: Successful response - */ -app.get('/example', (req, res) => { - res.send('Hello World'); -}); diff --git a/backend/src/services/channelService.js b/backend/src/services/channelService.js index 4c2ecc03..062a1013 100644 --- a/backend/src/services/channelService.js +++ b/backend/src/services/channelService.js @@ -1,14 +1,12 @@ -import { createChannelInDB } from '../repositories/channelRepository.js'; -import { addGuestInDB } from '../repositories/guestRepository.js'; +import { createChannelInDB, getChannelById } from '../repositories/channelRepository.js'; +import { addGuestToChannel } from '../repositories/guestRepository.js'; export const createChannelService = async (name, host_id, guests) => { - // 채널 생성 const channel = await createChannelInDB(name, host_id); - // 게스트 추가 const guestPromises = guests.map(guest => { const { name, start_location, end_location, path, marker_style } = guest; - return addGuestInDB( + return addGuestToChannel( channel.id, name, start_location, @@ -23,3 +21,25 @@ export const createChannelService = async (name, host_id, guests) => { return channel; }; + +export const addGuestService = async (channelId, guests) => { + const channel = await getChannelById(channelId); + if (!channel) return null; + + const guestPromises = guests.map(guest => { + const { name, start_location, end_location, path, marker_style } = guest; + return addGuestToChannel( + channelId, + name, + start_location, + end_location, + path, + marker_style, + channel.host_id, + ); + }); + + await Promise.all(guestPromises); + + return channel; +}; diff --git a/backend/swaggerConfig.js b/backend/swaggerConfig.js index 3b5aa786..9a18f563 100644 --- a/backend/swaggerConfig.js +++ b/backend/swaggerConfig.js @@ -163,6 +163,92 @@ const swaggerDefinition = { }, }, }, + // 게스트 추가 요청 스키마 + AddGuestRequest: { + type: 'object', + properties: { + channel_id: { + type: 'string', + description: '채널 ID (UUID 형태)', + }, + guest: { + type: 'object', + properties: { + name: { + type: 'string', + description: '게스트의 이름', + }, + start_location: { + type: 'object', + properties: { + lat: { + type: 'number', + description: '출발지 마커의 위도', + }, + lng: { + type: 'number', + description: '출발지 마커의 경도', + }, + }, + }, + end_location: { + type: 'object', + properties: { + lat: { + type: 'number', + description: '도착지 마커의 위도', + }, + lng: { + type: 'number', + description: '도착지 마커의 경도', + }, + }, + }, + path: { + type: 'array', + items: { + type: 'object', + properties: { + lat: { + type: 'number', + description: '경로 n번째 지점의 위도', + }, + lng: { + type: 'number', + description: '경로 n번째 지점의 경도', + }, + }, + }, + description: '게스트의 경로 (위도, 경도)를 담은 배열', + }, + marker_style: { + type: 'object', + properties: { + color: { + type: 'string', + description: '게스트를 구분하는 색상 스타일', + }, + }, + }, + }, + }, + }, + }, + + // 게스트 추가 응답 스키마 + AddGuestResponse: { + type: 'object', + properties: { + success: { + type: 'boolean', + description: '요청이 성공적으로 처리되었는지 여부', + }, + message: { + type: 'string', + description: '응답 메시지', + }, + }, + }, }, }, paths: { @@ -241,6 +327,45 @@ const swaggerDefinition = { }, }, }, + '/channel/guests': { + post: { + summary: '채널에 게스트 추가 API', + description: '주어진 채널에 새로운 게스트를 추가합니다.', + operationId: 'addGuest', + requestBody: { + description: '채널에 게스트를 추가하기 위한 데이터', + content: { + 'application/json': { + schema: { + $ref: '#/components/schemas/AddGuestRequest', + }, + }, + }, + required: true, + }, + responses: { + 200: { + description: '게스트 추가 성공', + content: { + 'application/json': { + schema: { + $ref: '#/components/schemas/AddGuestResponse', + }, + }, + }, + }, + 400: { + description: '잘못된 요청, 채널 ID나 게스트 정보가 잘못됨', + }, + 404: { + description: '채널을 찾을 수 없음', + }, + 500: { + description: '서버 에러', + }, + }, + }, + }, }, };