Skip to content
Snippets Groups Projects
Commit 4e156572 authored by Wo-ogie's avatar Wo-ogie
Browse files

feat: 약속 참여하기(entry) API 구현 및 기존 router에 권한 확인 middleware 추가

parent fb091426
No related branches found
No related tags found
No related merge requests found
const bcrypt = require('bcrypt');
const { Meeting, Participant, Schedule } = require('../models');
const {
getMeetingNotFoundError,
getMeetingIsAlreadyClosedError,
getAdminPasswordNotMatchedError,
createMeetingNotFoundError,
createMeetingIsAlreadyClosedError,
createPasswordNotMatchedError,
createPasswordIsNullError,
} = require('../errors/meetingErrors');
const MeetingResponse = require('../dto/response/meetingResponse');
const MeetingWithParticipantsResponse = require('../dto/response/meetingWithParticipantsResponse');
const ParticipantResponse = require('../dto/response/participantResponse');
const HASHING_ROUND = 12;
const getMeetingById = async (meetingId) => {
async function encryptPassword(password, next) {
if (!password) {
return next(createPasswordIsNullError());
}
try {
const salt = await bcrypt.genSalt(HASHING_ROUND);
return await bcrypt.hash(password, salt);
} catch (error) {
return next(error);
}
}
async function getMeetingById(meetingId) {
const meeting = await Meeting.findOne({
where: { id: meetingId },
});
if (!meeting) {
throw getMeetingNotFoundError();
throw createMeetingNotFoundError();
}
return meeting;
};
}
const getMeetingWithParticipantsAndSchedulesById = async (meetingId) => {
async function getMeetingWithParticipantsAndSchedulesById(meetingId) {
const meeting = await Meeting.findOne({
where: { id: meetingId },
include: [
......@@ -35,18 +49,55 @@ const getMeetingWithParticipantsAndSchedulesById = async (meetingId) => {
],
});
if (!meeting) {
throw getMeetingNotFoundError();
throw createMeetingNotFoundError();
}
return meeting;
}
async function validatePasswordIsMatched(requestPassword, exPassword) {
if (!requestPassword) {
throw createPasswordIsNullError();
}
const isCorrectPassword = await bcrypt.compare(requestPassword, exPassword);
if (!isCorrectPassword) {
throw createPasswordNotMatchedError();
}
}
function setParticipantDataToCookie(req, res, participant) {
const cookieName = 'participantData';
const cookieOptions = {
httpOnly: true,
signed: true,
};
const existCookie = req.signedCookies.participantData;
res.clearCookie(
cookieName,
JSON.stringify({
meetingId: existCookie.meetingId,
name: existCookie.name,
}),
cookieOptions,
);
res.cookie(
cookieName,
JSON.stringify({
meetingId: participant.MeetingId,
name: participant.name,
}),
cookieOptions,
);
}
exports.createMeeting = async (req, res, next) => {
try {
const salt = await bcrypt.genSalt(HASHING_ROUND);
const hash = await bcrypt.hash(req.body.adminPassword, salt);
const passwordEncrypted = await encryptPassword(
req.body.adminPassword,
next,
);
const meeting = await Meeting.create({
title: req.body.title,
adminPassword: hash,
adminPassword: passwordEncrypted,
purpose: req.body.purpose,
startDate: req.body.startDate,
endDate: req.body.endDate,
......@@ -59,6 +110,40 @@ exports.createMeeting = async (req, res, next) => {
}
};
exports.entry = async (req, res, next) => {
const meetingIdToEntry = req.params.meetingId;
const nameToEntry = req.body.name;
const passwordToEntry = req.body.password;
try {
const participant = await Participant.findOne({
where: {
name: nameToEntry,
MeetingId: meetingIdToEntry,
},
});
if (!participant) {
const passwordEncrypted = await encryptPassword(passwordToEntry, next);
const participantCreated = await Participant.create({
name: nameToEntry,
password: passwordEncrypted,
email: req.body.email,
MeetingId: meetingIdToEntry,
});
setParticipantDataToCookie(req, res, participantCreated);
return res.status(201).json(ParticipantResponse.from(participantCreated));
}
if (participant.password) {
await validatePasswordIsMatched(passwordToEntry, participant.password);
}
setParticipantDataToCookie(req, res, participant);
return res.status(204).end();
} catch (error) {
return next(error);
}
};
exports.getMeetingById = async (req, res, next) => {
try {
const meeting = await getMeetingById(req.params.meetingId);
......@@ -79,29 +164,19 @@ exports.getMeetingDetailById = async (req, res, next) => {
}
};
const validateAdminPassword = async (
requestAdminPassword,
meetingAdminPassword,
) => {
const isCorrectPassword = await bcrypt.compare(
requestAdminPassword,
meetingAdminPassword,
);
if (!isCorrectPassword) {
throw getAdminPasswordNotMatchedError();
}
};
const validateMeetingIsNotClosed = (meeting) => {
if (meeting.isClosed === true) {
throw getMeetingIsAlreadyClosedError();
throw createMeetingIsAlreadyClosedError();
}
};
exports.closeMeeting = async (req, res, next) => {
try {
const meeting = await getMeetingById(req.params.meetingId);
await validateAdminPassword(req.body.adminPassword, meeting.adminPassword);
await validatePasswordIsMatched(
req.body.adminPassword,
meeting.adminPassword,
);
validateMeetingIsNotClosed(meeting);
meeting.isClosed = true;
......
exports.getMeetingNotFoundError = () => {
exports.createMeetingNotFoundError = () => {
const error = new Error('일치하는 약속을 찾을 수 없습니다.');
error.status = 404;
return error;
};
exports.getMeetingIsAlreadyClosedError = () => {
exports.createMeetingIsAlreadyClosedError = () => {
const error = new Error('이미 닫힌 약속입니다.');
error.status = 409;
return error;
};
exports.getAdminPasswordNotMatchedError = () => {
const error = new Error('약속 관리 비밀번호가 일치하지 않습니다.');
exports.createPasswordNotMatchedError = () => {
const error = new Error('비밀번호가 일치하지 않습니다.');
error.status = 401;
return error;
};
exports.createPasswordIsNullError = () => {
const error = new Error('필요한 비밀번호가 전달되지 않았습니다.');
error.status = 400;
return error;
};
exports.isAuthenticated = (req, res, next) => {
const participantData = JSON.parse(req.signedCookies.participantData);
if (!participantData || participantData.meetingId !== req.params.meetingId) {
const error = new Error('접근 권한이 없습니다.');
error.status = 401;
next(error);
return;
}
next();
};
const express = require('express');
const { isAuthenticated } = require('../middlewares/index');
const {
createMeeting,
entry,
getMeetingById,
getMeetingDetailById,
closeMeeting,
......@@ -10,13 +12,12 @@ const router = express.Router();
router.post('/', createMeeting);
// TODO: 접근 권한 확인 로직 추가 필요
router.get('/:meetingId', getMeetingById);
router.post('/:meetingId/entry', entry);
// TODO: 접근 권한 확인 로직 추가 필요
router.get('/:meetingId/details', getMeetingDetailById);
router.get('/:meetingId', isAuthenticated, getMeetingById);
// TODO: 접근 권한 확인 로직 추가 필요
router.patch('/:meetingId/close', closeMeeting);
router.get('/:meetingId/details', isAuthenticated, getMeetingDetailById);
router.patch('/:meetingId/close', isAuthenticated, closeMeeting);
module.exports = router;
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment