cookie-session, userController

김종민·2022년 10월 25일
0

Youtube

목록 보기
9/23

  1. cookie-session은 브라우져에 server에서 req가 들어가면,
    server에서 브라우저에게 id를 하나(session) 건네줌.
    F12, application에서 확인 가능.
    이것은 서버를 저장하거나, 서버를 껐다가 켜면 지워지는데,
    이 세션을 mongoDB에 저장시키면, 서버를 저장하든,
    끝다 키든, login상태를 유지시킬 수 있다.
    매우 중요한 부분이죠!!1

1. src/server.js

import './db'
import Video from './models/Video'
import User from './models/User'
import express from 'express'
import session from 'express-session' 
///session을 위해서 npm i express-session

import MongoStore from 'connect-mongo'
///session을 mongo에 save하기 위해서 npm i connect-mongo

import morgan from 'morgan'
import rootRouter from './routes/rootRouter'
import userRouter from './routes/userRouter'
import videoRouter from './routes/videoRouter'
import { localsMiddleware } from './middlewares'
///session에 user, session등의 정보를 저장하기 위해서 사용.

const PORT = 4000
const app = express()
const logger = morgan('dev')

///express는 반드시 app.~~~의 순서가 매우 중요하다!!!!
app.set('view engine', 'pug')
app.set('views', process.cwd() + '/src/views')
app.use(logger)
app.use(express.urlencoded({ extended: true }))
///req.body를 받기위해서 urlencoded
app.use(
  session({
    secret: 'hello',
    resave: false, //true하면 req요청때마다, cookie만듬, false는 login떄만 만듬
    saveUninitialized: false, ///위와 동일
    store: MongoStore.create({ mongoUrl: 'mongodb://127.0.0.1:27017/jmtube' }),
    ///여기서 session을 MongoStore에 저장함.
  })
)
///session을 사용하기 위한 문법!!!!잘 봐둘것!!!
///이것으로 인해서 브라우져에 접속하면, session(Id)을 하나 받음.

// app.use((req, res, next) => {
//   res.locals.sexy = 'you' //pug파일에서 sexy로 접근가능
//   res.locals.siteName = 'jmTube' //pug파일에서 siteName으로 접근가능
//   console.log(res)
//   res.sessionStore.all((error, sessions) => {
//     console.log(sessions)
//     next()
//   })
// })
-------->session 처리과정을 보기 위해서 중간에 넣은 middleware.
-------->처리과정을 보기위한 것이므로, 실제로 코딩은 안해줘도 된다.

app.use(localsMiddleware) ///이부분이 매우 중요!!! 아래에서 확인.
///이 부분이 모든 router의 맨 위에 존재해야 아래 router에 다 적용됨.
app.use('/', rootRouter)
app.use('/videos', videoRouter)
app.use('/users', userRouter)

app.listen(PORT, () => console.log('Server start in 4000'))

2. src/middlewares.js

export const localsMiddleware = (req, res, next) => {
  res.locals.loggedIn = Boolean(req.session.loggedIn)
  res.locals.loggedInUser = req.session.user;
  res.locals.siteName = 'jmTube'
  console.log(res.locals)
  next()
}
///res.locals는 localstorage처럼, data들을 담아주는것
///일종의 context에 token을 담아서 req떄마다, token을 같이 보내주는것과 비슷
///res.locals.loggedIn에 true, false정보를 담고,
///res.locals.loggedInUser에 user의 정보를 담고,
///res.locals.siteName에 name의 정보를 담아서,
///pug파일에서든 어디든 공유할 수 있음.
///res.locals에 담은 정보들은 위의 
///import MongoStore from 'connect-mongo'를 이용해 mongo에 session을
///저장시키면, login기능을 계속 유지시킬 수 있음.

3.src/controllers/userController.js

import User from '../models/User'
import bcrypt from 'bcrypt'

export const getJoin = (req, res) => {
  return res.render('createAccount', { pageTitle: 'Create Account' })
}
export const postJoin = async (req, res) => {
  const { email, username, password, password2, location, name } = req.body
  ///createAccount.pug에서 email, username등등을 받아옴.
  
  const exists = await User.exists({ $or: [{ username }, { email }] })
  ///username, email이 DB에 같은 값이 있는지 check함.
  ///두개 항목을 같이 체크할떄, $or을 사용함.
  
  if (password !== password2) {
    return res.status(400).render('createAccount', {
      pageTitle: 'Create Account',
      errorMessage: 'Password does not match.',
    })
  }
  ///입력된 2개의 password가 같은지를 check함.
  
  if (exists) {
    return res.status(400).render('createAccount', {
      pageTitle: 'Create Account',
      errorMessage: 'This username/email is already taken',
    })
  }
  ///username, email이 같은 값이 있으면, errorMessage날려줌.
  
  
  --->위에서 $or을 쓰지 않고 username, email을 따로 체크하는경우
  //   const emailExists = await User.exists({ email: email })
  //   if (emailExists) {
  //     return res.render('createAccount', {
  //       pageTitle: 'Create Account',
  //       errorMessage: 'This Email is already taken',
  //     })
  //   }
  --->username, email을 따로 check하는 경우.
  
  try {
    await User.create({
      email,
      username,
      name,
      location,
      password,
    })
    return res.redirect('/login')
    ///여기까지 진행되었으면, User를 create함.
    
  } catch (error) {
    return res.status(400).render('createAccount', {
      pageTitle: 'Create Account',
      errorMessage: error._message,
    })
  }
}
///error있을 경우, errorMessage를 날려줌.

export const removeUser = (req, res) => res.send('remove')
export const editUser = (req, res) => res.send('editUser')
export const getLogin = (req, res) => {
  res.render('login', { pageTitle: 'Login' })
}

///login POST구현.
export const postLogin = async (req, res) => {
  const { username, password } = req.body
  const user = await User.findOne({ username })
  ///username, password를 pug파일로부터 받아옴.
  
  if (!user) {
    return res.status(400).render('login', {
      pageTitle: 'Login',
      errorMessage: 'Username does not exist.',
    })
  }
  ///user가 없을 경우 errorMessage 리턴함.
  
  const ok = await bcrypt.compare(password, user.password)
  if (!ok) {
    return res.status(400).render('login', {
      pageTitle: 'Login',
      errorMessage: 'Wrong Password',
    })
  }
  ///req.body로 받은 password를 bcrypt로, DB에 bcrypt화 되어
  ///저장되어 있는 password와 비교함.
  
  ///session에 아래 항목을 저장시키고, 마지막에 홈 path('/')로
  ///redirect함.
  req.session.loggedIn = true
  req.session.user = user
  res.redirect('/')
}
export const logoutUser = (req, res) => res.send('logout')
export const seeUser = (req, res) => res.send('see user')


profile
코딩하는초딩쌤

0개의 댓글