Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FEAT] GET /room/code/:code 참여코드로 대기방 조회 API 구현 #5

Merged
merged 8 commits into from
Jan 11, 2022
1 change: 1 addition & 0 deletions functions/api/routes/room/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const express = require('express');
const router = express.Router();
const { checkUser } = require('../../../middlewares/auth');

router.get('/code/:code', checkUser, require('./roomCodeGET'));
router.post('', checkUser, require('./roomPOST'));

module.exports = router;
86 changes: 86 additions & 0 deletions functions/api/routes/room/roomCodeGET.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/**
* @코드로_대기_방_정보_확인
* @route GET /room/code/:code
* @error
* 1. 참여 코드가 전달되지 않음
* 2. 참여코드에 일치하는 방이 없는 경우
* 3. 이미 시작된 습관방인 경우
* 4. 이미 참여중인 방인 경우
* 5. 한번 내보내진 사용자인 경우
*/

const functions = require('firebase-functions');
const util = require('../../../lib/util');
const statusCode = require('../../../constants/statusCode');
const responseMessage = require('../../../constants/responseMessage');
const db = require('../../../db/db');
const { userDB, roomDB } = require('../../../db');

module.exports = async (req, res) => {
const { code } = req.params;
const user = req.user;
const userId = user.userId;

// @error 1. 참여 코드가 전달되지 않음
if (!code) {
return res.status(statusCode.BAD_REQUEST).send(util.fail(statusCode.BAD_REQUEST, responseMessage.NULL_VALUE));
}

let client;

try {
client = await db.connect(req);

const room = await roomDB.getRoomByCode(client, code);

// @error 2. 참여 코드에 일치하는 방이 없음
if (!room) {
return res.status(statusCode.BAD_REQUEST).send(util.fail(statusCode.BAD_REQUEST, responseMessage.GET_WAITROOM_DATA_NULL));
}

// @error 3. 참여 코드에 해당하는 방은 이미 습관 시작한 방임
if (room.isStarted) {
return res.status(statusCode.BAD_REQUEST).send(util.fail(statusCode.BAD_REQUEST, responseMessage.GET_WAITROOM_DATA_STARTED));
}

// @error 5. 한번 내보내진 사용자인 경우
const isKicked = await roomDB.checkKickedByRoomIdAndUserId(client, room.roomId, userId);
if (isKicked) {
return res.status(statusCode.BAD_REQUEST).send(util.fail(statusCode.BAD_REQUEST, responseMessage.GET_WAITROOM_DATA_KICKED));
}

const creator = await userDB.getUserById(client, room.creator);
const entries = await roomDB.getEntriesByRoomId(client, room.roomId);
const imageNum = 3;
let profileImgs = [];

for (let i = 0; i < entries.length; i++) {
if (i < imageNum) {
let user = await userDB.getUserById(client, entries[i].userId);
profileImgs.push(user.profileImg);
}
Comment on lines +52 to +61
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getEntriesByRoomId 에서 user테이블을 조인해 profileImg를 가져오는 방법도 있을 것 같아요!
해당 방법의 장점은, DB에 접근하는 횟수를 줄여준다는 점?! (현재는 for문 안에서 DB에 접근을 함)
어떤 방법이 더 좋을지는 저도 잘 모르겠어서, 고민해보면 좋을 것 같아요!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@xxeol2
현재 코드에서는 Join연산이 나을것도 같은데,,, 다른 api에서 roomId로 entry 접근하는 경우가 되게 많을거로 예상되는데
getEntriesByroomId 내부로직이 간결한게 좋을거 같아서 이렇게 작성했습니당~
사실 모든 참여자의 사진이 필요한것도 아니구 해서...?
쫌 더 생각해볼게요~~~ 감사합니당 :0


// @error 4. 이미 해당 습관에 참여중인 사용자
if (userId === entries[i].userId) {
return res.status(statusCode.BAD_REQUEST).send(util.fail(statusCode.BAD_REQUEST, responseMessage.GET_WAITROOM_DATA_ALREADY));
}
}

const data = {
roomId: room.roomId,
roomName: room.roomName,
creatorName: creator.nickname,
createrImg: creator.profileImg,
profileImgs,
totalNums: entries.length,
};

res.status(statusCode.OK).send(util.success(statusCode.OK, responseMessage.READ_ONE_POST_SUCCESS, data));
} catch (error) {
functions.logger.error(`[ERROR] [${req.method.toUpperCase()}] ${req.originalUrl}`, `[CONTENT] ${error}`);
console.log(error);
res.status(statusCode.INTERNAL_SERVER_ERROR).send(util.fail(statusCode.INTERNAL_SERVER_ERROR, responseMessage.INTERNAL_SERVER_ERROR));
} finally {
client.release();
}
};
6 changes: 6 additions & 0 deletions functions/constants/responseMessage.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,10 @@ module.exports = {
// Room
CREATE_ROOM_SUCCESS: '습관 방 생성 성공',
CREATE_ROOM_FAIL: '습관 방 생성 실패',
GET_WAITROOM_DATA_SUCCESS: '대기방 정보 확인 완료',
GET_WAITROOM_DATA_NULL: '참여코드와 일치하는 습관 방이 존재하지 않습니다',
GET_WAITROOM_DATA_STARTED: '이미 습관 형성에 도전중인 방입니다',
GET_WAITROOM_DATA_ALREADY: '이미 사용자가 참가중인 방입니다',
GET_WAITROOM_DATA_FAIL: '대기방 정보 확인 실패',
GET_WAITROOM_DATA_KICKED: '습관 방 생성자에 의해 내보내진 방입니다',
};
43 changes: 42 additions & 1 deletion functions/db/room.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,45 @@ const isCodeUnique = async (client, code) => {
return false;
};

module.exports = { addRoom, isCodeUnique };
const getRoomByCode = async (client, code) => {
const { rows } = await client.query(
`
SELECT * FROM spark.room
WHERE code = $1
AND is_deleted = FALSE
`,
[code],
);
return convertSnakeToCamel.keysToCamel(rows[0]);
};

const getEntriesByRoomId = async (client, roomId) => {
const { rows } = await client.query(
`
SELECT * FROM spark.entry
WHERE room_id = $1
AND is_out = FALSE
AND is_kicked = FALSE
AND is_deleted = FALSE
ORDER BY created_at
`,
[roomId],
);
return convertSnakeToCamel.keysToCamel(rows);
};

const checkKickedByRoomIdAndUserId = async (client, roomId, userId) => {
const { rows } = await client.query(
`
SELECT * FROM spark.entry
WHERE room_id = $1
AND user_id = $2
AND is_kicked = TRUE
AND is_deleted = FALSE
`,
[roomId, userId],
);
return convertSnakeToCamel.keysToCamel(rows);
};

module.exports = { addRoom, isCodeUnique, getRoomByCode, getEntriesByRoomId, checkKickedByRoomIdAndUserId };