"dependencies": {
"@babel/core": "^7.9.6",
"@babel/node": "^7.8.7",
"@babel/preset-env": "^7.9.6",
"body-parser": "^1.19.0",
"cookie-parser": "^1.4.5",
"core-js": "^3.6.5",
"cors": "^2.8.5",
"express": "^4.17.1",
"helmet": "^3.22.0",
"jsonwebtoken": "^8.5.1",
"mongoose": "^5.9.15",
"morgan": "^1.10.0",
"passport": "^0.4.1",
"passport-jwt": "^4.0.0",
"passport-local": "^1.0.0",
"passport-local-mongoose": "^6.0.1",
"validator": "^13.0.0"
}
$ nohup npm start &
- [POST] '/join'
- Request
// body
{
"email": "dlfdyd96@gmail.com", // 아이디
"password": "zz",
"passwordConfirmation": "zz",
"name" : "일용"
}- Response
// 회원가입 후 바로 로그인됨 -> Token Return
// status : 200 OK
data : {
"name": "일용",
"token": "eyJhbGciOiJIUzI..." // token 정보 -> sessionStorage에 저장할 것
}- [✔] 아이디 : Email로 변경해야함.
- [+] 이메일 확인 과정 필요
- [+] 성향과 묶어야함.
- [POST] '/login'
- Request
// body
{
"email" : "dlfdyd96@gmail.com",
"password": "zz"
}- Response
// status : 200 OK
{
"user": {
"_id": "5ecbb09ee0c5c359f7a28cfd",
"email": "ee@naver.com",
"name": "일용",
"_selection": []
},
"token": "eyJhbGciOiJIUzI1NiJ9.ZWVAbmF2ZXIuY29t.fxkUFWxI6kEkKVYebtiOPuLV8T0bzWlF6iw4y-dgYWc"
}
// status : 400 Bad Request
{
"message": "Check the account",
"user": false
}passport-local-mongoose 를 사용하여 local Login 구현
// passport.js
passport.use(User.createStrategy()) // 로 passport-local 쓰지 않고 간단하게 로그인 구현 가능// ./models/User.js
userSchema.plugin(passportLocalMongoose, {usernameField: 'email'}); // passportLocalMongoose를 plugin 해준다.
// email로 로그인하기때문에 usernameField 설정 필수.- [+] 카카오 아이디로 로그인.
- [+] 네이버 아이디로 로그인.
passport-jwt, passport, jsonwebtoken 사용
// passport.js
// JWT Token Authentication
passport.use(
new passportJWT.Strategy({
// options
jwtFromRequest: passportJWT.ExtractJwt.fromAuthHeaderAsBearerToken(),
secretOrKey : 'thisIsMySecret'
},
// callback
function (jwtPayload, cb) {
console.log(jwtPayload);
//find the user in db if needed. This functionality may be omitted if you store everything you'll need in JWT payload.
return User.findOneById(jwtPayload.id)
.then(user => {
return cb(null, user);
})
.catch(err => {
return cb(err);
});
}
)
)// globalRouter
globalRouter.post(routes.login, postLoin);// UserController.js
export const postLoin = (req, res, next) => {
passport.authenticate('local', {session: false},
(err, user, info) => {
if(err) console.log(err);
if (err || !user) {
return res.status(400).json({
message: 'Check the account',
user : user
});
}
req.login(user, {session: false}, (err) => {
if (err) {
res.send(err);
}
// generate a signed son web token with the contents of user object and return it in the response
const token = jwt.sign(user.email, 'thisIsMySecret');
return res.json({name : user.name, token});
});
}
)(req, res);
}- [+] Secret 키는 배포전에 process.env.JWT_SECRET 로 숨기기
VSCode Remote - WSL을 통해 서버의 코드들을 vscode에서 작성 가능 하도록 했음.- 도메인 주소 : http://49.50.175.145:3389/
- https 인증서 발행
- OAuth에 필요
- [POST] '/user/select-tendency'
- Request
// body
{
"selection" : ["경북궁", "해운대"]
}
// header
Authorization : `Bearer ${sessionStorage.getItem('token')}` // 꼭 'Bearer ' 붙여줘야함- Response
{
"message": "Success Update Tedency",
"selection": [
"경북궁",
"해운대"
]
}- Router
userRouter.post(routes.selectTendency,
passport.authenticate('jwt', { session: false}), // 인증 Middleware
postTendency) // 경향 등록- Controller
// 성향 파악 질문
export const postTendency = async (req, res, next) => {
const { body : { selection } } = req;
try {
await User.findOneAndUpdate( { _id: req.user._id },
{ selection }
)
res.status(200).json({
message: 'Success Update Tedency',
selection : selection
})
} catch(err) {
console.log(`Error with Post Tedency : ${err}`)
res.status(400).json({
message: 'Fail to update Tedency',
selection : selection
})
}
}- [POST] '/user/edit-profile'
- Request
// body
{
"name" : "일용"
// Avartar 나 다른 것들 나중에 추가할 것.
}
// header
Authorization : `Bearer ${sessionStorage.getItem('token')}` // 꼭 'Bearer ' 붙여줘야함- Response
{
message: 'Sucess to Update Profile'
}await User.findOneAndUpdate(
{ _id: req.user._id },
{ ...body }
);- [POST] '/user-password'
- Request
// body
{
oldPassword : 'aa',
newPassword : 'zzz',
newPassword2 : 'zzz'
}
// header
Authorization : `Bearer ${sessionStorage.getItem('token')}` // 꼭 'Bearer ' 붙여줘야함- Response
{
message: 'Sucess to Change Password'
}- Create
- [POST] '/itinerary/upload'
- Request
// body { "title" : "부산 여행", "description" : "부산 여행 갔다 ^^", "routes" : [ { "name": "부산역", "locationId": 123 }, // ...Continue... ] } // header Authorization : `Bearer ${sessionStorage.getItem('token')}` // 꼭 'Bearer ' 붙여줘야함
- Response
// Success(200) { "message": "Success Upload Itinerary", "init": { "routes": [ { "name": "부산역", "locationId": 123 }, // ... Continue ... ], "_id": "5ecbda5d726572642507e2e0", // itinerary id "creator": "5ecbb09ee0c5c359f7a28cfd", // user id "title": "부산 여행", "description": "부산 여행 갔다 ^^", "createdAt": "2020-05-25T14:46:53.137Z", "__v": 0 } } // Fail(400)
- Read
- [GET] '/itinerary/${itinerary id값}'
- Request
// None- Response
// Success(200) { "message": "Success Get Itinerary", "itinerary": { "routes": [ { "name": "부산역", "locationId": 123 }, // ... ], "_id": "5ecbda5d726572642507e2e0", "creator": { "selections": [], "_id": "5ecbb09ee0c5c359f7a28cfd", "email": "ee@naver.com", "name": "일용", "createdAt": "2020-05-25T11:48:46.543Z", "__v": 0 }, "title": "부산 여행", "description": "부산 여행 갔다 ^^", "createdAt": "2020-05-25T14:46:53.137Z", "__v": 0 } } // Fail(400)
- Update
- [POST] '/itinerary/${itinerary id 값}/edit'
- Request
// body (수정할 것 만 넣으면 됨) { "title" : "부산 여행", "description" : "부산 여행 갔다 ^^ (수정)", "routes" : [ { "name": "부산역" }, { "name": "해운대" }, { "name": "부산역" } ] } // header Authorization : `Bearer ${sessionStorage.getItem('token')}` // 꼭 'Bearer ' 붙여줘야함
- Response
// Success(200) { "message": "Success Update Itinerary" } // Fail(400)
- Delete
- [GET] '/itinerary/${itinerary id 값}/delete'
- Request
// header Authorization : `Bearer ${sessionStorage.getItem('token')}` // 꼭 'Bearer ' 붙여줘야함
- Response
// Success(200) { "message": "Success To Delete itinerary" } // Fail(400) { "message": "Failed to Delete Itinerary", "error": {} }
- Itineary Model 만들기
- User Model에 ref 연결
import mongoose from 'mongoose';
const itinerarySchema = new mongoose.Schema({
creator : {
type: mongoose.Schema.Types.ObjectId,
ref: "User",
required: "Creator is required"
},
//....
})
const model = mongoose.model('Itinerary', itinerarySchema);
export default model;- [GET] '/user/${사용자 id 값}'
- Request
// None- Response
{
"message": "Success get User Detail",
"user": {
"selections": [],
"_id": "5ecbb09ee0c5c359f7a28cfd",
"email": "ee@naver.com",
"name": "일용",
"createdAt": "2020-05-25T11:48:46.543Z",
"__v": 0
},
"itinerary": [
{
"routes": [
{
"name": "부산역",
"locationId": 123
},
{
"name": "해운대",
"locationId": 321
},
{
"name": "부산역",
"locationId": 123
}
],
"_id": "5ecbdd9a726572642507e2e1",
"creator": "5ecbb09ee0c5c359f7a28cfd",
"title": "부산 여행",
"description": "부산 여행 갔다 ^^",
"createdAt": "2020-05-25T15:00:42.970Z",
"__v": 0
}
]
}생략
- [GET] '/content/${location ID}'
- ex) location ID : 12542 (여수역)
- Request
// None- Response
{
"message": "Success Get Content Detail",
"content": {
"_id": "5ede56660f34f650a8868946",
"content": 123,
"createdAt": "2020-06-08T15:16:54.585Z",
"__v": 0
},
"comments": []
}- [POST] '/content/${content ID}/comment'
- ex) content ID는 위의 Content ID를 클릭 할 경우 생성된 content 고유의 ID
- response 의 content._id 를 참조해야함.
- Request
// body (수정할 것 만 넣으면 됨)
{
"text" : "할말은 많지만 하지 않겠다..."
}
// header
Authorization : `Bearer ${sessionStorage.getItem('token')}` // 꼭 'Bearer ' 붙여줘야함- Response
{
"msg": "Success Post Comment",
"comment": {
"_id": "5ede5aa99a72f3641c7b0ac7",
"comment": "할많하않1",
"author": "5ede501e84a4015658c06625",
"content": "5ede56660f34f650a8868946",
"createdAt": "2020-06-08T15:35:05.863Z",
"__v": 0
}
}- [GET] '/api/comment/${comment id 값}/delete'
- comment 고유의 _id 값임
- Request
// header
Authorization : `Bearer ${sessionStorage.getItem('token')}` // 꼭 'Bearer ' 붙여줘야함- Response
{
"message": "Success To Delete Comment"
}- [GET] '/itinerary/${여행 일정 id}/public'
- Request
// header
Authorization : `Bearer ${sessionStorage.getItem('token')}` // 꼭 'Bearer ' 붙여줘야함- Response
{
"message": "Success to set public",
"item": {
"routes": [
{
"name": "부산역"
},
{
"name": "해운대"
},
{
"name": "부산역"
}
],
"publish": true,
"_id": "5ede50da84a4015658c06626",
"creator": "5ede501e84a4015658c06625",
"title": "부산 여행",
"description": "부산 여행 갔다 ^^ (수정)",
"createdAt": "2020-06-08T14:53:14.515Z",
"__v": 0
}
}- [GET] '/itinerary/${여행 일정 id}/private'
- Request
// header
Authorization : `Bearer ${sessionStorage.getItem('token')}` // 꼭 'Bearer ' 붙여줘야함- Response
// 위 응답과 동일하고
// ...
"publish" : false // 이부분만 다름
// ...- [GET] '/itinerary/'
- Request
// None- Response
{
"message": "Success to get Itineraries",
"items": [
{
"routes": [
{
"name": "부산역"
},
{
"name": "해운대"
},
{
"name": "부산역"
}
],
"publish": true,
"_id": "5ede50da84a4015658c06626",
"creator": "5ede501e84a4015658c06625",
"title": "부산 여행",
"description": "부산 여행 갔다 ^^ (수정)",
"createdAt": "2020-06-08T14:53:14.515Z",
"__v": 0
}
]
}- 언제 하누?
- Front 가 편안할 때 하기 (ㅋㅋ)