Skip to content

Commit ada20fa

Browse files
committed
feat: Add participants feature and update server configuration
- Introduced AddParticipantsDTO for validating participant addition requests, and added new endpoint to chatRoute for adding participants to a chat room - Updated Swagger documentation to include the new endpoint - Changed server URL in swagger configuration to the new AWS instance - Removed unused Discord notification functionality and related code - Removed IP whitelist - Cleaned up .env.sample by removing unnecessary variables
1 parent bebb03d commit ada20fa

File tree

10 files changed

+287
-120
lines changed

10 files changed

+287
-120
lines changed

.env.sample

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
ALLOWED_IPS=
2-
IP_NAMES=
3-
41
PORT=3000
52
DB_HOST=
63
DB_USER=
@@ -13,6 +10,4 @@ BASIC_AUTH_PASSWORD=
1310
AWS_ACCESS_KEY_ID=
1411
AWS_SECRET_ACCESS_KEY=
1512
AWS_BUCKET_NAME=
16-
AWS_REGION=
17-
18-
DISCORD_WEBHOOK_URL=
13+
AWS_REGION=

src/controllers/chatController.js

Lines changed: 96 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,14 @@ const {
44
getChatList,
55
createRoom,
66
createChallengeRoom,
7+
addParticipants,
78
} = require('../services/chatService');
89

910
const CreateChatRoomDTO = require('../dto/CreateChatRoom.dto');
1011
const CreateChallengeRoomDTO = require('../dto/CreateChallengeRoom.dto');
1112
const ChatRoomDTO = require('../dto/ChatRoom.dto');
1213
const ChatMessageDTO = require('../dto/ChatMessage.dto');
14+
const AddParticipantsDTO = require('../dto/AddParticipants.dto');
1315

1416
/**
1517
* @swagger
@@ -48,19 +50,106 @@ const createChatRoomController = async (req, res) => {
4850
const createUserId = req.headers['user-id'];
4951

5052
if (!createUserId) {
51-
console.log('User ID is missing in the request headers.');
5253
return res.status(400).json({ message: 'User ID is required in the header' });
5354
}
5455

56+
const { roomName, type, participants } = req.body;
57+
58+
if (!roomName || !type || !Array.isArray(participants)) {
59+
return res.status(400).json({ message: 'Invalid request body: roomName, type, and participants are required' });
60+
}
61+
62+
if (participants.length < 2) {
63+
return res.status(400).json({ message: 'Failed to create room: must select at least 2 participants' });
64+
}
65+
5566
try {
56-
const { roomName, type, participants } = req.body;
5767
const createChatRoomDTO = new CreateChatRoomDTO(roomName, type, participants);
58-
59-
const result = await createRoom(createChatRoomDTO, createUserId);
60-
res.status(201).json(new ChatRoomDTO(result.roomId, result.roomName, result.roomType));
68+
const result = await createRoom(createChatRoomDTO);
69+
return res.status(201).json(new ChatRoomDTO(result.roomId, result.roomName, result.roomType));
6170
} catch (error) {
6271
console.error('Failed to create room:', error);
63-
res.status(500).json({ message: 'Failed to create room' });
72+
return res.status(500).json({ message: 'Failed to create room' });
73+
}
74+
};
75+
76+
/**
77+
* @swagger
78+
* /chat/add:
79+
* post:
80+
* summary: 채팅방에 인원을 추가합니다.
81+
* tags:
82+
* - Chat
83+
* parameters:
84+
* - in: header
85+
* name: user-id
86+
* required: true
87+
* schema:
88+
* type: string
89+
* requestBody:
90+
* description: 추가할 인원과 방 ID
91+
* required: true
92+
* content:
93+
* application/json:
94+
* schema:
95+
* type: object
96+
* properties:
97+
* roomId:
98+
* type: string
99+
* description: 추가할 채팅방 ID
100+
* participants:
101+
* type: array
102+
* items:
103+
* type: string
104+
* description: 추가할 사용자 ID 목록
105+
* responses:
106+
* '200':
107+
* description: 인원 추가 성공
108+
* content:
109+
* application/json:
110+
* schema:
111+
* type: object
112+
* properties:
113+
* message:
114+
* type: string
115+
* example: Participants added successfully
116+
* '400':
117+
* description: 잘못된 요청 (요청 데이터가 유효하지 않을 경우)
118+
* content:
119+
* application/json:
120+
* schema:
121+
* type: object
122+
* properties:
123+
* message:
124+
* type: string
125+
* example: Invalid request data
126+
* '500':
127+
* description: 서버 오류 (추가 실패 시)
128+
* content:
129+
* application/json:
130+
* schema:
131+
* type: object
132+
* properties:
133+
* message:
134+
* type: string
135+
* example: Failed to add participants
136+
*/
137+
const addParticipantsController = async (req, res) => {
138+
try {
139+
const createUserId = req.headers['user-id'];
140+
141+
if (!createUserId) {
142+
return res.status(400).json({ message: 'User ID is required in the header' });
143+
}
144+
145+
const { roomId, participants } = req.body;
146+
const addParticipantsDTO = new AddParticipantsDTO(roomId, participants);
147+
148+
await addParticipants(addParticipantsDTO.roomId, addParticipantsDTO.participants);
149+
150+
res.status(200).json({ message: 'Participants added successfully' });
151+
} catch (error) {
152+
res.status(400).json({ message: error.message });
64153
}
65154
};
66155

@@ -304,4 +393,5 @@ module.exports = {
304393
getChallengeRoomListController,
305394
getChatMessagesController,
306395
createChallengeRoomController,
396+
addParticipantsController,
307397
};

src/discordNoti.js

Lines changed: 0 additions & 82 deletions
This file was deleted.

src/dto/AddParticipants.dto.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
class AddParticipantsDTO {
2+
/**
3+
* @param {string} roomId
4+
* @param {Array<string>} participants
5+
*/
6+
constructor(roomId, participants) {
7+
if (!roomId || typeof roomId !== "string") {
8+
throw new Error("Invalid roomId: must be a non-empty string");
9+
}
10+
11+
if (!Array.isArray(participants) || participants.length === 0) {
12+
throw new Error("Invalid participants: must be a non-empty array");
13+
}
14+
15+
participants.forEach((participant) => {
16+
if (typeof participant !== "string") {
17+
throw new Error(`Invalid participant ID: ${participant}`);
18+
}
19+
});
20+
21+
this.roomId = roomId;
22+
this.participants = participants;
23+
}
24+
}
25+
26+
module.exports = AddParticipantsDTO;

src/middlewares/ipFilter.js

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
require('dotenv').config();
21
const { IpFilter, IpDeniedError } = require('express-ipfilter');
32

43
const ips = process.env.ALLOWED_IPS ? process.env.ALLOWED_IPS.split(',') : [];
@@ -16,7 +15,6 @@ if (ips.length === 0) {
1615
process.exit(1);
1716
}
1817

19-
// IP 필터 미들웨어 설정
2018
const ipFilterMiddleware = IpFilter(ips, { mode: 'allow' });
2119

2220
const ipFilterErrorHandler = (err, req, res, next) => {
@@ -27,11 +25,4 @@ const ipFilterErrorHandler = (err, req, res, next) => {
2725
}
2826
};
2927

30-
const logRequestWithIpName = (req, res, next) => {
31-
const ip = req.ip;
32-
const name = ipNameMap[ip] || ip;
33-
console.log(`Access granted to: ${name}`);
34-
next();
35-
};
36-
37-
module.exports = { ipFilterMiddleware, ipFilterErrorHandler, logRequestWithIpName };
28+
module.exports = { ipFilterMiddleware, ipFilterErrorHandler };

src/routes/chatRoute.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,14 @@ const {
66
getGroupRoomListController,
77
createChallengeRoomController,
88
deleteRoomController,
9+
addParticipantsController,
910
} = require('../controllers/chatController');
1011

1112
const router = express.Router();
1213

1314
router.get('/list/group', getGroupRoomListController);
1415
router.get('/list/challenge', getChallengeRoomListController);
16+
router.post('/add', addParticipantsController);
1517
router.get('/message/:roomId', getChatMessagesController);
1618
router.post('/create', createChatRoomController);
1719
router.post('/create/challenge/:challengeId', createChallengeRoomController);

src/server.js

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,11 @@ const express = require('express');
22
const http = require('http');
33
const { Server } = require('socket.io');
44
const cors = require('cors');
5-
const { ipFilterMiddleware, ipFilterErrorHandler } = require('./middlewares/ipFilter'); // IP 화이트리스트 미들웨어
65
const chatRoutes = require('./routes/chatRoute');
76
const imageRoutes = require('./routes/imageRoute');
87
const defaultRoutes = require('./routes/defaultRoute');
98
const socketHandler = require('./socket/socketHandler');
109
const swaggerUi = require('swagger-ui-express');
11-
const {sendDiscordShutdownNotification, sendDiscordNotification} = require('./discordNoti');
1210
const path = require('path');
1311
const app = express();
1412
const server = http.createServer(app);
@@ -20,21 +18,18 @@ app.use(express.urlencoded({ extended: true }));
2018
app.use('/swagger/swagger-output.json', express.static(path.join(__dirname, 'swagger', 'swagger-output.json')));
2119
app.use('/swagger/swagger-output.yaml', express.static(path.join(__dirname, 'swagger', 'swagger-output.yaml')));
2220

21+
app.use(basicAuth({
22+
users: { [process.env.BASIC_AUTH_USER]: process.env.BASIC_AUTH_PASSWORD },
23+
challenge: true
24+
}));
25+
2326
app.use(cors({
2427
origin: ['http://localhost:3000', 'http://127.0.0.1:5500', 'http://210.183.4.67:8081', 'http://210.183.4.67:8080' , 'http://localhost:3001'],
2528
methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
2629
allowedHeaders: ['Content-Type', 'Authorization', 'user-id'],
2730
credentials: true
2831
}));
2932

30-
app.use(basicAuth({
31-
users: { [process.env.BASIC_AUTH_USER]: process.env.BASIC_AUTH_PASSWORD },
32-
challenge: true
33-
}));
34-
35-
app.use(ipFilterMiddleware);
36-
app.use(ipFilterErrorHandler);
37-
3833
app.use('', defaultRoutes);
3934
app.use('/chat', chatRoutes);
4035
app.use('/chat/image', imageRoutes);
@@ -54,7 +49,6 @@ socketHandler(io);
5449
const PORT = process.env.PORT || 3000;
5550
server.listen(PORT, () => {
5651
console.log(`Server is running on port ${PORT}`);
57-
// sendDiscordNotification();
5852
});
5953

6054
let isNotified = false;
@@ -63,7 +57,6 @@ const handleShutdown = async () => {
6357
if (isNotified) return;
6458
isNotified = true;
6559
console.log('Server is shutting down...');
66-
// await sendDiscordShutdownNotification();
6760
process.exit();
6861
};
6962

0 commit comments

Comments
 (0)