From a378c510a1aee98da61d0ed1ae954f9308c72e19 Mon Sep 17 00:00:00 2001
From: Wo-ogie <siwall0105@gmail.com>
Date: Sat, 25 Nov 2023 12:13:35 +0900
Subject: [PATCH] =?UTF-8?q?feat:=20=EB=82=B4=20=EC=8A=A4=EC=BC=80=EC=A4=84?=
 =?UTF-8?q?=20=EC=A0=80=EC=9E=A5=ED=95=98=EA=B8=B0=20API=20=EA=B5=AC?=
 =?UTF-8?q?=ED=98=84?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 app.js                            |  2 ++
 controllers/schedule.js           | 41 +++++++++++++++++++++++++++++++
 dto/response/schedulesResponse.js | 15 +++++++++++
 errors/scheduleErrors.js          |  7 ++++++
 middlewares/auth.js               | 28 +++++++++++++++++++++
 middlewares/index.js              | 13 ----------
 routes/meeting.js                 |  2 +-
 routes/mySchedule.js              |  9 +++++++
 8 files changed, 103 insertions(+), 14 deletions(-)
 create mode 100644 controllers/schedule.js
 create mode 100644 dto/response/schedulesResponse.js
 create mode 100644 errors/scheduleErrors.js
 create mode 100644 middlewares/auth.js
 delete mode 100644 middlewares/index.js
 create mode 100644 routes/mySchedule.js

diff --git a/app.js b/app.js
index 0fd3e42..2897b98 100644
--- a/app.js
+++ b/app.js
@@ -10,6 +10,7 @@ dotenv.config();
 
 const meetingRouter = require('./routes/meeting');
 const participantRouter = require('./routes/participant');
+const myScheduleRouter = require('./routes/mySchedule');
 const { sequelize } = require('./models');
 
 const app = express();
@@ -50,6 +51,7 @@ app.use(
 
 app.use('/meetings', meetingRouter);
 app.use('/meetings/:meetingId/participants', participantRouter);
+app.use('/meetings/:meetingId/my/schedules', myScheduleRouter);
 
 app.use((req, res, next) => {
   const error = new Error(`There is no router. ${req.method} ${req.url}`);
diff --git a/controllers/schedule.js b/controllers/schedule.js
new file mode 100644
index 0000000..56067f5
--- /dev/null
+++ b/controllers/schedule.js
@@ -0,0 +1,41 @@
+const { Schedule, sequelize } = require('../models');
+const { getLoggedInParticipantId } = require('../middlewares/auth');
+const SchedulesResponse = require('../dto/response/schedulesResponse');
+const { createScheduleAlreadyExistError } = require('../errors/scheduleErrors');
+
+async function validateScheduleNotExist(participantId) {
+  const numOfSchedules = await Schedule.count({
+    where: {
+      ParticipantId: participantId,
+    },
+  });
+  if (numOfSchedules > 0) {
+    throw createScheduleAlreadyExistError();
+  }
+}
+
+exports.createMySchedules = async (req, res, next) => {
+  const participantId = getLoggedInParticipantId(req, res, next);
+  const { availableSchedules } = req.body;
+  try {
+    await validateScheduleNotExist(participantId);
+
+    const schedules = await sequelize.transaction(async (transaction) =>
+      Promise.all(
+        availableSchedules.map((availableSchedule) =>
+          Schedule.create(
+            {
+              availableDate: availableSchedule.availableDate,
+              availableTimes: availableSchedule.availableTimes,
+              ParticipantId: participantId,
+            },
+            { transaction },
+          ),
+        ),
+      ),
+    );
+    return res.json(SchedulesResponse.from(schedules));
+  } catch (error) {
+    return next(error);
+  }
+};
diff --git a/dto/response/schedulesResponse.js b/dto/response/schedulesResponse.js
new file mode 100644
index 0000000..db96a75
--- /dev/null
+++ b/dto/response/schedulesResponse.js
@@ -0,0 +1,15 @@
+const ScheduleResponse = require('./scheduleResponse');
+
+class SchedulesResponse {
+  constructor(schedules) {
+    this.schedules = schedules;
+  }
+
+  static from(schedules) {
+    return new SchedulesResponse(
+      schedules.map((schedule) => ScheduleResponse.from(schedule)),
+    );
+  }
+}
+
+module.exports = SchedulesResponse;
diff --git a/errors/scheduleErrors.js b/errors/scheduleErrors.js
new file mode 100644
index 0000000..29ab8f8
--- /dev/null
+++ b/errors/scheduleErrors.js
@@ -0,0 +1,7 @@
+exports.createScheduleAlreadyExistError = () => {
+  const error = new Error(
+    '기존에 저장한 스케줄이 존재합니다. 기존 스케줄 데이터를 삭제한 후 다시 시도하거나, 수정하기 API를 사용해주세요.',
+  );
+  error.status = 409;
+  return error;
+};
diff --git a/middlewares/auth.js b/middlewares/auth.js
new file mode 100644
index 0000000..81884a2
--- /dev/null
+++ b/middlewares/auth.js
@@ -0,0 +1,28 @@
+function parseParticipantData(req, res, next) {
+  let participantData = null;
+  if (req.signedCookies.participantData) {
+    participantData = JSON.parse(req.signedCookies.participantData);
+  }
+  if (!participantData) {
+    const error = new Error('인증 권한이 없습니다.');
+    error.status = 401;
+    return next(error);
+  }
+  return participantData;
+}
+
+exports.isAuthenticated = (req, res, next) => {
+  const participantData = parseParticipantData(req);
+  if (participantData.meetingId !== req.params.meetingId) {
+    const error = new Error('접근 권한이 없습니다.');
+    error.status = 401;
+    next(error);
+    return;
+  }
+  next();
+};
+
+exports.getLoggedInParticipantId = (req, res, next) => {
+  const participantData = parseParticipantData(req, res, next);
+  return participantData?.participantId;
+};
diff --git a/middlewares/index.js b/middlewares/index.js
deleted file mode 100644
index 27afea0..0000000
--- a/middlewares/index.js
+++ /dev/null
@@ -1,13 +0,0 @@
-exports.isAuthenticated = (req, res, next) => {
-  let participantData = null;
-  if (req.signedCookies.participantData) {
-    participantData = JSON.parse(req.signedCookies.participantData);
-  }
-  if (!participantData || participantData.meetingId !== req.params.meetingId) {
-    const error = new Error('접근 권한이 없습니다.');
-    error.status = 401;
-    next(error);
-    return;
-  }
-  next();
-};
diff --git a/routes/meeting.js b/routes/meeting.js
index 7763ca5..956df30 100644
--- a/routes/meeting.js
+++ b/routes/meeting.js
@@ -1,5 +1,5 @@
 const express = require('express');
-const { isAuthenticated } = require('../middlewares/index');
+const { isAuthenticated } = require('../middlewares/auth');
 const {
   createMeeting,
   entry,
diff --git a/routes/mySchedule.js b/routes/mySchedule.js
new file mode 100644
index 0000000..20991db
--- /dev/null
+++ b/routes/mySchedule.js
@@ -0,0 +1,9 @@
+const express = require('express');
+const { isAuthenticated } = require('../middlewares/auth');
+const { createMySchedules } = require('../controllers/schedule');
+
+const router = express.Router({ mergeParams: true });
+
+router.post('/bulk', isAuthenticated, createMySchedules);
+
+module.exports = router;
-- 
GitLab