POST /trails
에 이어 GET /trails
도 작성했는데, 처음 로그인하고 나타나는 메인 페이지에서 이미 DB에 등록된 산책로들의 정보들을 가져오는 요청이다.
const jwt = require('jsonwebtoken');
const secretObj = require('../../config/jwt');
const {
trails,
users,
locations,
categories,
images,
} = require('../../models');
module.exports = {
/**
* 로그인하고 myPage를 처음 산책로들을 render 할 때 보내는 요청.
* -주의: trail에 있는 userId는 작성자의 정보, token 과 같이 들어오는 id는 현재 접속한 유저!
*/
get: (req, res) => {
const token = req.cookies.user;
// 토큰 인증 절차 -> 없으면 401
jwt.verify(token, secretObj.secret, async (err, decoded) => {
// 토큰이 존재한다면,
if (decoded) {
// 테이블에서 쿼리한 값들을 모아 응답으로 보낼 배열.
const trailsWithInfo = [];
// 각 trail의 foreign key로 연결된 테이블들에서 username, location들, tag 를 가져와 배열에 요소로 추가한다.
// eslint-disable-next-line no-await-in-loop
const eachInfos = await trails
.findAll({
include: [ // 테이블들을 조인
{
model: users, // 원하는 테이블에서
required: true,
attributes: ['username'], // 원하는 요소만 select.
},
{
model: locations,
required: true,
attributes: [
'location1',
'location2',
'location3',
'location4',
'location5',
],
},
{
model: categories,
required: true,
attributes: ['tag'],
},
],
raw: true, // datavalues 만 가져오는 옵션
nest: true, // 객체 형태로 구성
})
.catch((error) => {
console.log(error);
res.sendStatus(500);
});
// 각 가져온 값들에서 location들을 병합.
for (let i = 0; i < eachInfos.length; i += 1) {
trailsWithInfo.push(eachInfos[i]);
trailsWithInfo[i].location = [
eachInfos[i].location.location1,
eachInfos[i].location.location2,
eachInfos[i].location.location3,
eachInfos[i].location.location4,
eachInfos[i].location.location5,
];
}
if (!trailsWithInfo.length) {
res.sendStatus(404);
} else {
res.status(200).json({ trails: trailsWithInfo });
}
} else {
res.sendStatus(401);
}
});
},
}
tag.js
는 req.params로 들어오는 태그를 이용하여, 해당 태그에 속한 trail들을 필터하여 응답으로 보내주는 파일이다. API 형식은 /trails/:tag 가 된다.
/* eslint-disable no-console */
/* eslint-disable object-shorthand */
const jwt = require('jsonwebtoken');
const secretObj = require('../../config/jwt');
const {
trails,
users,
locations,
categories,
} = require('../../models');
/**
* ex) http://localhost:3000/trails/:tag
* myPage 접속 후 태그를 클릭할 때마다 보내는 요청.
* 필요한 데이터: token(decoded -> userId, email 포함)으로 인증, req.params.tag
* -주의: trail에 있는 userId는 작성자의 정보, token 과 같이 들어오는 id는 현재 접속한 유저!
*/
module.exports = (req, res) => {
// 선택한 tag
const { tag } = req.params;
const token = req.cookies.user;
// 토큰 인증 절차 -> 없으면 401
jwt.verify(token, secretObj.secret, async (err, decoded) => {
// 토큰이 존재한다면,
if (decoded) {
// req.params.tag 와 같은 tagId를 체크
const checkTag = await categories.findOne({
where: {
tag: tag,
},
raw: true,
}).catch((error) => {
console.error(error);
res.sendStatus(500);
});
// 존재하지 않는 tag라면 404
if (!checkTag) {
res.sendStatus(404);
}
// checkTag에서 확인한 id를 이용하여 해당 id를 가진 trails를 findAll()
const checkTrailsByTag = await trails.findAll({
where: {
categoryId: checkTag.id, // 필터할 query문
},
include: [ // 조인하여 가져올 테이블들
{
model: users, // 조인할 테이블
required: true,
attributes: ['username'], // 테이블에서 가져올 요소
},
{
model: locations,
required: true,
attributes: ['location1', 'location2', 'location3', 'location4', 'location5'],
},
{
model: categories,
required: true,
attributes: ['tag'],
},
],
raw: true,
nest: true,
}).catch((error) => {
console.error(error);
res.sendStatus(500);
});
// locations 하나로 병합 -> 5개의 각각의 키값으로 이루어진 좌표들을 하나의 배열에 포함시킨다.
const combineTrailsLocation = [];
for (let i = 0; i < checkTrailsByTag.length; i += 1) {
combineTrailsLocation.push(checkTrailsByTag[i]);
combineTrailsLocation[i].location = [
checkTrailsByTag[i].location.location1,
checkTrailsByTag[i].location.location2,
checkTrailsByTag[i].location.location3,
checkTrailsByTag[i].location.location4,
checkTrailsByTag[i].location.location5,
];
}
// 해당 태그의 trail이 없다면 404
if (!combineTrailsLocation) {
res.sendState(404);
}
res.status(200).json(combineTrailsLocation);
// token이 없다면 401
} else {
res.sendStatus(401);
}
});
};