Skip to content

taese0ng/Your-Schedule-Server

 
 

Repository files navigation

너의 일정을 짜고 싶어

Server 📖

🔨 개발 도구

Node.js + Express

"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 &

TODO List 📝

[✔] Sing UP

📎 API 통신 예제

  • [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로 변경해야함.
  • [+] 이메일 확인 과정 필요
  • [+] 성향과 묶어야함.

[✔] Login

📎 API 통신 예제

  • [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 설정 필수.
  • [+] 카카오 아이디로 로그인.
  • [+] 네이버 아이디로 로그인.

[✔] Session


[✔] JWT

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 로 숨기기

[✔] Naver Server에 올리기

🗄 Server

  • VSCode Remote - WSL 을 통해 서버의 코드들을 vscode에서 작성 가능 하도록 했음.
  • 도메인 주소 : http://49.50.175.145:3389/

[❌] HTTPS


[✔] 초기 Selections 추가

📎 API 통신 예제

  • [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
        })
    }
}

[✔] Edit Profile

📎 API 통신 예제

  • [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 }
      );

[✔] Change Password

📎 API 통신 예제

  • [POST] '/user-password'
  • Request
// body
{
    oldPassword : 'aa', 
    newPassword : 'zzz', 
    newPassword2 : 'zzz'
}

// header
Authorization : `Bearer ${sessionStorage.getItem('token')}` // 꼭 'Bearer ' 붙여줘야함
  • Response
{
    message: 'Sucess to Change Password'
}

⚙ 동작


[✔] 여행일정 C/R/U/D

📎 API 통신 예제

  1. 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)
  2. 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)
  3. 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)
  4. 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;

[✔] My Page

📎 API 통신 예제

  • [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
        }
    ]
}

⚙ 동작

생략


[✔] Content 얻기

📎 API 통신 예제

  • [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": []
}

[✔] Create Comment

📎 API 통신 예제

  • [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
    }
}

[✔] Delete Comment

📎 API 통신 예제

  • [GET] '/api/comment/${comment id 값}/delete'
    • comment 고유의 _id 값임
  • Request
// header
Authorization : `Bearer ${sessionStorage.getItem('token')}` // 꼭 'Bearer ' 붙여줘야함
  • Response
{
    "message": "Success To Delete Comment"
}

[✔] Itinerary 공유

📎 API 통신 예제

  • [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
    }
}

[✔] Itinerary 공유 해제

📎 API 통신 예제

  • [GET] '/itinerary/${여행 일정 id}/private'
  • Request
// header
Authorization : `Bearer ${sessionStorage.getItem('token')}` // 꼭 'Bearer ' 붙여줘야함
  • Response
// 위 응답과 동일하고 
// ...
    "publish" : false // 이부분만 다름
// ...

[✔] Share Page

📎 API 통신 예제

  • [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 가 편안할 때 하기 (ㅋㅋ)

About

너의 일정을 짜고싶어 Web Server(JWT)

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • JavaScript 100.0%