본문 바로가기
프로그래밍 개발/Express

Express - 다중 사용자 구현(회원가입)

by Jinseok Kim 2021. 1. 19.
반응형

 

 

다중 사용자 구현(회원가입)

 

 

 

 

1. 회원가입 UI 구현

 

lib/auth.js

module.exports = {
    isOwner: function(request, response){
    if(request.user){
        return true;
    } else{
        return false;
    }
}, statusUI: function(request, response){                 //register UI 추가
    var authStatusUI = '<a href="/auth/login">login</a> | <a href="/auth/register">Register</a>'
    if(this.isOwner(request, response)){
        authStatusUI = `${request.user.nickname} | <a href="/auth/logout">logout</a>`;
    }
    return authStatusUI;
}


}

 

 

lib/template.js

module.exports = {                                          
  HTML:function(title, list, body, control, authStatusUI = 
                                      //register UI 추가
  '<a href="/auth/login">login</a> | <a href="/auth/register">Register</a>'){
    return `
    <!doctype html>
    <html>
    <head>
      <title>WEB1 - ${title}</title>
      <meta charset="utf-8">
    </head>
    <body>
      ${authStatusUI}
      <h1><a href="/">WEB</a></h1>
      ${list}
      ${control}
      ${body}
    </body>
    </html>
    `;
  },list:function(filelist){
    var list = '<ul>';
    var i = 0;
    while(i < filelist.length){
      list = list + `<li><a href="/topic/${filelist[i]}">${filelist[i]}</a></li>`;
      i = i + 1;
    }
    list = list+'</ul>';
    return list;
  }
}

 

 

 

 

routes/auth.js

var express = require('express');
var router = express.Router();
var path = require('path');
var fs = require('fs');
var sanitizeHtml = require('sanitize-html');
var template = require('../lib/template.js');


module.exports = function (passport) {
  router.get('/login', function (request, response) {
    var fmsg = request.flash();
    var feedback = '';
    if (fmsg.error) {
      feedback = fmsg.error[0];
    }
    var title = 'WEB - login';
    var list = template.list(request.list);
    var html = template.HTML(title, list, `
      <div style="color:red;">${feedback}</div>
      <form action="/auth/login_process" method="post">
        <p><input type="text" name="email" placeholder="email"></p>
        <p><input type="password" name="pwd" placeholder="password"></p>
        <p>
          <input type="submit" value="login">
        </p>
      </form>
    `, '');
    response.send(html);
  });

  router.post('/login_process',
    passport.authenticate('local', {
      successRedirect: '/',
      failureRedirect: '/auth/login',
      failureFlash: true,
      successFlash: true
    }));
    
    ////register을 위해 데이터를 입력할 폼 생성 코드 
    router.get('/register', function (request, response) {
    var fmsg = request.flash();
    var feedback = '';
    if (fmsg.error) {
      feedback = fmsg.error[0];
    }
    var title = 'WEB - login';
    var list = template.list(request.list);
    var html = template.HTML(title, list, `
        <div style="color:red;">${feedback}</div>
        <form action="/auth/register_process" method="post">
          <p><input type="text" name="email" placeholder="email"></p>
          <p><input type="password" name="pwd" placeholder="password"></p>
          <p><input type="password" name="pwd2" placeholder="password"></p>
          <p><input type="text" name="displayName" placeholder="display name"></p>
          <p>
            <input type="submit" value="register">
          </p>
        </form>
      `, '');
    response.send(html);
  });

  router.get('/logout', function (request, response) {
    request.logout();
    request.session.save(function () {
      response.redirect('/');
    });
});

  return router;
} 

 

 

 

 

 

 

 

2. 회원 정보 저장

 

npm install lowdb

회원 정보 저장에 lowdb라는 프로그램을 사용할 것이므로 위의 명령어로 lowdb을 다운 받는다.

 

 

 

 

const low = require('lowdb')
const FileSync = require('lowdb/adapters/FileSync')

const adapter = new FileSync('db.json')
const db = low(adapter)

그리고 위의 코드를 lowdb을 사용할 코드 파일에 붙여줘야 한다.

 

 

 

 

routes/auth.js

var express = require('express');
var router = express.Router();
var path = require('path');
var fs = require('fs');
var sanitizeHtml = require('sanitize-html');
var template = require('../lib/template.js');

//lowdb을 사용하기 위한 코드 아래와 같이 붙여주었다.
const low = require('lowdb') //lowdb을 연동시키고
const FileSync = require('lowdb/adapters/FileSync') //동기 방식으로 파일을 저장하고
const adapter = new FileSync('db.json') //db.json에 데이터를 저장하겠다라는
const db = low(adapter); //db 변수에 담아주었다.

//lowdb에 인해 자동으로 생성되는 db.json에 users:[]가 쓰여지도록 하였다.
db.defaults({users:[]}).write(); 


module.exports = function (passport) {
  router.get('/login', function (request, response) {
    var fmsg = request.flash();
    var feedback = '';
    if (fmsg.error) {
      feedback = fmsg.error[0];
    }
    var title = 'WEB - login';
    var list = template.list(request.list);
    var html = template.HTML(title, list, `
      <div style="color:red;">${feedback}</div>
      <form action="/auth/login_process" method="post">
        <p><input type="text" name="email" placeholder="email"></p>
        <p><input type="password" name="pwd" placeholder="password"></p>
        <p>
          <input type="submit" value="login">
        </p>
      </form>
    `, '');
    response.send(html);
  });

  router.post('/login_process',
    passport.authenticate('local', {
      successRedirect: '/',
      failureRedirect: '/auth/login',
      failureFlash: true,
      successFlash: true
    }));
    
    router.get('/register', function (request, response) {
    var fmsg = request.flash();
    var feedback = '';
    if (fmsg.error) {
      feedback = fmsg.error[0];
    }
    var title = 'WEB - login';
    var list = template.list(request.list);
    var html = template.HTML(title, list, `
        <div style="color:red;">${feedback}</div>
        <form action="/auth/register_process" method="post">
          <p><input type="text" name="email" placeholder="email"></p>
          <p><input type="password" name="pwd" placeholder="password"></p>
          <p><input type="password" name="pwd2" placeholder="password"></p>
          <p><input type="text" name="displayName" placeholder="display name"></p>
          <p>
            <input type="submit" value="register">
          </p>
        </form>
      `, '');
    response.send(html);
  });
 
 //register을 위해 폼에 입력하고 전송 받은 데이터를 처리하는 코드를 추가함.
router.post('/register_process', function (request, response) {
    var post = request.body;
    var email = post.email;
    var pwd = post.pwd;
    var pwd2 = post.pwd2;
    var displayName = post.displayName;
    db.get('users').push({ //lowdb의 db.json에 users 객체에 전송받은 폼 데이터를 push함.
      email:email,
      password:pwd,
      displayName:displayName
    }).write(); //write();을 해줘야 데이터가 적힌다.
    response.redirect('/');
  });    

  router.get('/logout', function (request, response) {
    request.logout();
    request.session.save(function () {
      response.redirect('/');
    });
});

  return router;
} 

lowdb을 적용하자 이렇게 자동으로 회원가입 정보를 받을 db.json 파일이 생성된 것을 확인 할 수 있었다.

 

 

폼에 회원가입 정보를 입력하고 전송버트을 누르자 db.json에 데이터가 담긴 것을 확인 할 수 있었다.

 

 

 

 

 

npm install -s shortid

이제 회원정보마다 중복되지 않는 고유의 id 값을 각자 지정해주어야 하는데 shortid라는 프로그램을 사용하면 해결할 수 있다. 위의 명령어를 입력하고 프로그램 다운한다.

 

 

 

var shortid = require('shortid');

그리고 위의 코드를 shortid을 사용할 파일 코드에 붙여준다.

 

 

 

 

routes/auth.js

var express = require('express');
var router = express.Router();
var path = require('path');
var fs = require('fs');
var sanitizeHtml = require('sanitize-html');
var template = require('../lib/template.js');
var shortid = require('shortid'); //shortid 연동 추가

const low = require('lowdb')
const FileSync = require('lowdb/adapters/FileSync')

const adapter = new FileSync('db.json')
const db = low(adapter);
db.defaults({users:[]}).write();


module.exports = function (passport) {
  router.get('/login', function (request, response) {
    var fmsg = request.flash();
    var feedback = '';
    if (fmsg.error) {
      feedback = fmsg.error[0];
    }
    var title = 'WEB - login';
    var list = template.list(request.list);
    var html = template.HTML(title, list, `
      <div style="color:red;">${feedback}</div>
      <form action="/auth/login_process" method="post">
        <p><input type="text" name="email" placeholder="email"></p>
        <p><input type="password" name="pwd" placeholder="password"></p>
        <p>
          <input type="submit" value="login">
        </p>
      </form>
    `, '');
    response.send(html);
  });

  router.post('/login_process',
    passport.authenticate('local', {
      successRedirect: '/',
      failureRedirect: '/auth/login',
      failureFlash: true,
      successFlash: true
    }));
    
    router.get('/register', function (request, response) {
    var fmsg = request.flash();
    var feedback = '';
    if (fmsg.error) {
      feedback = fmsg.error[0];
    }
    var title = 'WEB - login';
    var list = template.list(request.list);
    var html = template.HTML(title, list, `
        <div style="color:red;">${feedback}</div>
        <form action="/auth/register_process" method="post">
          <p><input type="text" name="email" placeholder="email"></p>
          <p><input type="password" name="pwd" placeholder="password"></p>
          <p><input type="password" name="pwd2" placeholder="password"></p>
          <p><input type="text" name="displayName" placeholder="display name"></p>
          <p>
            <input type="submit" value="register">
          </p>
        </form>
      `, '');
    response.send(html);
  });
    
router.post('/register_process', function (request, response) {
    var post = request.body;
    var email = post.email;
    var pwd = post.pwd;
    var pwd2 = post.pwd2;
    var displayName = post.displayName;
    //if문을 사용하여 회원가입을 위한 패스워드가 확인 패스워드와 일치하지 않으면 플래시 메세지와
    //다시 회원가입 초기 페이지 상태로 돌아가도록 보안하였다.
   if(pwd !== pwd2){
      request.flash('error', 'Password must same!');
      response.redirect('/auth/register');
    } else {
      db.get('users').push({
        id:shortid.generate(),
        email:email,
        password:pwd,
        displayName:displayName
      }).write();
      response.redirect('/');
    }
  });    

  router.get('/logout', function (request, response) {
    request.logout();
    request.session.save(function () {
      response.redirect('/');
    });
});

  return router;
} 

확인을 위한 2차 패스워드가 틀리자 플래시 메세지가 등장하고, 새로운 회원 정보를 입력하여 가입하자 shortid의 기능으로 인하여 고유한 id 값이 따로 생긴 것을 확인 할 수 있다.

 

 

 

 

 

 

 

 

3. 세션 스토어에 인증 정보 저장

 

lib/db.js

var low = require('lowdb');
var FileSync = require('lowdb/adapters/FileSync');
var adapter = new FileSync('db.json');
var db = low(adapter);
db.defaults({users:[]}).write();
module.exports = db;

//lowdb 기능을 외부에서 분배해서 쓰기 위해서 db.js으로 lowdb 연동 코드들을 따로 불리시켜주었다.

 

 

 

lib/passport.js

var db = require('../lib/db'); //lowdb을 연동시키는 코드의 파일 db.js와 외부 연동 추가.

module.exports = function (app) {

    var authData = {
  email: 'k0502s@naver.com',
  password: '061599',
  nickname: 'jin seok'
      };

    var passport = require('passport'),
        LocalStrategy = require('passport-local').Strategy;

    app.use(passport.initialize());
    app.use(passport.session());

    passport.serializeUser(function (user, done) {
    //lowdb에 저장된 shortid을 이용하여 만든 회원정보의 고유 id 값을 가져옴.
        done(null, user.id);
    });

    passport.deserializeUser(function (id, done) {
  //lowdb가 생성한 db.json 파일 속 회원정보들이 들어있는 객체 'users'을 가져와 find() 메소드를 통해
  //id 값을 찾아와 value() 메소드를 붙여주어 user 변수에 담아줌.
        var user = db.get('users').find({id:id}).value();
        done(null, user);
    });

    passport.use(new LocalStrategy({
            usernameField: 'email',
            passwordField: 'pwd'
        },
        function (username, password, done) {
            if (username === authData.email) {
                if (password === authData.password) {
                    return done(null, authData, {
                        message: 'Welcome.'
                    });
                } else {
                    return done(null, false, {
                        message: 'Incorrect password.'
                    });
                }
            } else {
                return done(null, false, {
                    message: 'Incorrect username.'
                });
            }
        }
    ));
    return passport;
}

 

 

 

세션 스토어를 사용하기 위한 log in 코드 참고. 이 코드를 통해 passport에서 로그인 할 수 있고 UI도 바꿀 수 있다.

routes/auth.js

var express = require('express');
var router = express.Router();
var path = require('path');
var fs = require('fs');
var sanitizeHtml = require('sanitize-html');
var template = require('../lib/template.js');
var shortid = require('shortid');
var db = require('../lib/db'); //lowdb을 위한 연동 코드를 모은 db.js와 연동 추가.


module.exports = function (passport) {
  router.get('/login', function (request, response) {
    var fmsg = request.flash();
    var feedback = '';
    if (fmsg.error) {
      feedback = fmsg.error[0];
    }
    var title = 'WEB - login';
    var list = template.list(request.list);
    var html = template.HTML(title, list, `
      <div style="color:red;">${feedback}</div>
      <form action="/auth/login_process" method="post">
        <p><input type="text" name="email" placeholder="email"></p>
        <p><input type="password" name="pwd" placeholder="password"></p>
        <p>
          <input type="submit" value="login">
        </p>
      </form>
    `, '');
    response.send(html);
  });

  router.post('/login_process',
    passport.authenticate('local', {
      successRedirect: '/',
      failureRedirect: '/auth/login',
      failureFlash: true,
      successFlash: true
    }));
    
    router.get('/register', function (request, response) {
    var fmsg = request.flash();
    var feedback = '';
    if (fmsg.error) {
      feedback = fmsg.error[0];
    }
    var title = 'WEB - login';
    var list = template.list(request.list);
    var html = template.HTML(title, list, `
        <div style="color:red;">${feedback}</div>
        <form action="/auth/register_process" method="post">
          <p><input type="text" name="email" placeholder="email"></p>
          <p><input type="password" name="pwd" placeholder="password"></p>
          <p><input type="password" name="pwd2" placeholder="password"></p>
          <p><input type="text" name="displayName" placeholder="display name"></p>
          <p>
            <input type="submit" value="register">
          </p>
        </form>
      `, '');
    response.send(html);
  });
    
router.post('/register_process', function (request, response) {
    var post = request.body;
    var email = post.email;
    var pwd = post.pwd;
    var pwd2 = post.pwd2;
    var displayName = post.displayName;
   if(pwd !== pwd2){
      request.flash('error', 'Password must same!');
      response.redirect('/auth/register');
    } else {
      var user = {
        id:shortid.generate(),
        email:email,
        password:pwd,
        displayName:displayName
      };
      //db.json의 회원정보가 담길 객체 'users'에 회원가입 폼에서 받은 데이터를 push()와
      //write() 메소드를 통해 전달해주었다.
         db.get('users').push(user).write();
         
       //login이 완료되면 아래 코드에 의하여 login()메소드의 첫번째 인자로 로그인 정보를
       //담은 것을 주라는 약속이 있다. 이때 회원정보가 담긴 user 변수를 인자로 넣어준 것이다.
       //동시에 콜백함수가 실행된다. 콜백함수 내용은 초기 화면으로 돌아가는 것이다.
       //이 아래의 코드는 passport 프로그램에 인하여 생긴 특수한 상황들이다.
      request.login(user, function(err){
        return response.redirect('/');
      })
      
    }
  });    

  router.get('/logout', function (request, response) {
    request.logout();
    request.session.save(function () {
      response.redirect('/');
    });
});

  return router;
} 

 

 

 

lib/auth.js

module.exports = {
    isOwner: function(request, response){
    if(request.user){
        return true;
    } else{
        return false;
    }
}, statusUI: function(request, response){
    var authStatusUI = '<a href="/auth/login">login</a> | <a href="/auth/register">Register</a>'
    if(this.isOwner(request, response)){
                        //이제 db.json에서 회원정보를 가져오므로 displayName로 변경
        authStatusUI = `${request.user.displayName} | <a href="/auth/logout">logout</a>`;
    }
    return authStatusUI;
}


}

회원가입을 완료하면 동시에 로그인이 되면서 초기화면으로 돌아간다. 그리고 db.json에는 새로운 id 값을 가진 회원정보가 객체에 추가된다.

 

 

 

 

 

 

 

4. 로그인 구현

 

lib/passport.js

var db = require('../lib/db');

module.exports = function (app) {


    var passport = require('passport'),
        LocalStrategy = require('passport-local').Strategy;

    app.use(passport.initialize());
    app.use(passport.session());

    passport.serializeUser(function (user, done) {
        done(null, user.id);
    });

    passport.deserializeUser(function (id, done) {
        var user = db.get('users').find({id:id}).value();
        done(null, user);
    });

    passport.use(new LocalStrategy({
            usernameField: 'email',
            passwordField: 'pwd'
        },
        //이제 로그인 구현 쪽도 lowdb에 저장된 회원정보에서 데이터를 가지고와 사용하게
        //코드를 바꿔주었다.
        function (email, password, done) {
        var user = db.get('users').find({
            email:email,
            password:password
        }).value(); //전송받은 폼 데이터들 db.json에 삽입
           if(user){
                    return done(null, user, { //db.json의 회원 데이터가 담긴 변수 user로 교체
                        message: 'Welcome.'
                    });
               }
                 else {
                    return done(null, false, {
                        message: 'Incorrect password.'
                    });
                }
            
            }
    ));
    return passport;
}

로그인이 완료되면 이제 초기화면으로 돌아가는 동시에 welcome의 플래시 메세지가 등장하고 마찬가지로 로그인 정보가 올바르지 못하면 오류 내용의 플래시 메세지가 등장하게끔 하였다.

 

 

 

 

 

 

5. 접근 제어- 글 생성

 

lib/db.js

var low = require('lowdb');
var FileSync = require('lowdb/adapters/FileSync');
var adapter = new FileSync('db.json');
var db = low(adapter);
db.defaults({users:[], topics:[]}).write(); //db.json에 topics 생성
module.exports = db;

 

 

 

 routes/topic.js

var express = require('express');
var router = express.Router();
var path = require('path');
var fs = require('fs');
var sanitizeHtml = require('sanitize-html');
var template = require('../lib/template.js');
var auth = require('../lib/auth');
var db = require('../lib/db'); //db.js와 연동
var shortid = require('shortid'); //shortid 프로그램 연동


router.get('/create', function(request, response){
    if (!auth.isOwner(request, response)) {
    response.redirect('/');
    return false;
  }
    var title = 'WEB - create';
    var list = template.list(request.list);
    var html = template.HTML(title, list, `
      <form action="/topic/create_process" method="post">
        <p><input type="text" name="title" placeholder="title"></p>
        <p>
          <textarea name="description" placeholder="description"></textarea>
        </p>
        <p>
          <input type="submit">
        </p>
      </form>
    `, '', auth.statusUI(request, response));
    response.send(html);
  });

  router.post('/create_process', function(request, response){
      if (!auth.isOwner(request, response)) {
    response.redirect('/');
    return false;
  }
    var post = request.body;
    var title = post.title;
    var description = post.description;
    //id 변수에 shortid의 고유 id 값 삽입
    var id = shortid.generate();
     //db.json안의 topics에 push메소드를 이용해 폼으로 받은 생성 데이터 삽입
      db.get('topics').push({
          id: id,
          title: title,
          description: description,
          user_id: request.user.id //누가 생성한 글인지 고유 id값으로 구별하기 위해 추가
      }).write();
      response.redirect(`/topic/${id}`);
    
  });

  router.get('/update/:pageId', function(request, response){
      if (!auth.isOwner(request, response)) {
    response.redirect('/');
    return false;
  }
    var filteredId = path.parse(request.params.pageId).base;
    fs.readFile(`data/${filteredId}`, 'utf8', function(err, description){
      var title = request.params.pageId;
      var list = template.list(request.list);
      var html = template.HTML(title, list,
        `
        <form action="/topic/update_process" method="post">
          <input type="hidden" name="id" value="${title}">
          <p><input type="text" name="title" placeholder="title" value="${title}"></p>
          <p>
            <textarea name="description" placeholder="description">${description}</textarea>
          </p>
          <p>
            <input type="submit">
          </p>
        </form>
        `,
        `<a href="/topic/create">create</a> <a href="/topic/update/${title}">update</a>`,
        auth.statusUI(request, response)
      );
      response.send(html);
    });
  });

  router.post('/update_process', function(request, response){
      if (!auth.isOwner(request, response)) {
    response.redirect('/');
    return false;
  }
    var post = request.body;
    var id = post.id;
    var title = post.title;
    var description = post.description;
    fs.rename(`data/${id}`, `data/${title}`, function(error){
      fs.writeFile(`data/${title}`, description, 'utf8', function(err){
        response.redirect(`/topic/${title}`);
      })
    });
  });

  router.post('/delete_process', function(request, response){
      if (!auth.isOwner(request, response)) {
    response.redirect('/');
    return false;
  }
    var post = request.body;
    var id = post.id;
    var filteredId = path.parse(id).base;
    fs.unlink(`data/${filteredId}`, function(error){
      response.redirect('/');
    });
  });

  router.get('/:pageId', function(request, response, next) { 
      
      //db.json의 topics의 id값에 :pageId 삽입 
    var topic = db.get('topics').find({
        id:request.params.pageId
    }).value();
    
//db.json의 user의 id값에 topics의 user_id 값정보가 담긴 변수 topic을 이용하여 user_id 값 삽입 
      var user = db.get('users').find({
          id:topic.user_id
      }).value();
        var sanitizedTitle = sanitizeHtml(topic.title);
        var sanitizedDescription = sanitizeHtml(topic.description, {
          allowedTags:['h1']
        });
        var list = template.list(request.list);
        var html = template.HTML(sanitizedTitle, list,
          `<h2>${sanitizedTitle}</h2>${sanitizedDescription}
          <p>by ${user.displayName}</p>`, //어떤 사용자가  글을 생성했는지 UI 추가.
          ` <a href="/topic/create">create</a>
            <a href="/topic/update/${sanitizedTitle}">update</a>
            <form action="/topic/delete_process" method="post">
              <input type="hidden" name="id" value="${sanitizedTitle}">
              <input type="submit" value="delete">
            </form>`,
           auth.statusUI(request, response)
        );
        response.send(html);
    
  });
  module.exports = router;

 

 

 

main.js

var express = require('express');
var app = express();
var fs = require('fs');
var bodyParser = require('body-parser');
var compression = require('compression');
var helmet = require('helmet')
app.use(helmet());
var session = require('express-session')
var FileStore = require('session-file-store')(session)
var flash = require('connect-flash');
var db = require('./lib/db'); //db.js을 연동시켜 lowdb 사용 준비함.

app.use(express.static('public'));
app.use(bodyParser.urlencoded({ extended: false }));
app.use(compression());
app.use(session({
  secret: 'asadlfkj!@#!@#dfgasdg',
  resave: false,
  saveUninitialized: true,
  store:new FileStore()
}))
app.use(flash());

var passport = require('./lib/passport')(app);

//파일을 읽어오는 것이 아닌 lowdb로 저장된 데이터를 불러오도록 코드 수정함
app.get('*', function(request, response, next){
 request.list = db.get('topics').value();
    next();
});

var indexRouter = require('./routes/index');
var topicRouter = require('./routes/topic');
var authRouter = require('./routes/auth')(passport);

app.use('/', indexRouter);
app.use('/topic', topicRouter);
app.use('/auth', authRouter);

app.use(function(req, res, next) {
  res.status(404).send('Sorry cant find that!');
});
app.use(function (err, req, res, next) {
  console.error(err.stack)
  res.status(500).send('Something broke!')
});
app.listen(3000, function() {
  console.log('Example app listening on port 3000!')
});

 

 

 

lib/template.js

module.exports = {
  HTML:function(title, list, body, control, authStatusUI = '<a href="/auth/login">login</a> | <a href="/auth/register">Register</a>'){
    return `
    <!doctype html>
    <html>
    <head>
      <title>WEB1 - ${title}</title>
      <meta charset="utf-8">
    </head>
    <body>
      ${authStatusUI}
      <h1><a href="/">WEB</a></h1>
      ${list}
      ${control}
      ${body}
    </body>
    </html>
    `;
  },list:function(filelist){
    var list = '<ul>';
    var i = 0;
    while(i < filelist.length){ //이제 list가 db.json의 topics 배열의 객체값으로 바뀌었으니
                                // filelist에는 .id, .title로 수정해주었다.
      list = list + `<li><a href="/topic/${filelist[i].id}">${filelist[i].title}</a></li>`;
      i = i + 1;
    }
    list = list+'</ul>';
    return list;
  }
}

이제 글을 생성하면 어떤 사용자가 생성했는지 표시하였고 db.json에 생성된 글 데이터가 있는 것도 확인 가능하다.

 

 

 

 

 

 

 

6. 접근 제어-글 수정

 

 

routes/topic.js

var express = require('express');
var router = express.Router();
var path = require('path');
var fs = require('fs');
var sanitizeHtml = require('sanitize-html');
var template = require('../lib/template.js');
var auth = require('../lib/auth');
var db = require('../lib/db');
var shortid = require('shortid');


router.get('/create', function(request, response){
    if (!auth.isOwner(request, response)) {
    response.redirect('/');
    return false;
  }
    var title = 'WEB - create';
    var list = template.list(request.list);
    var html = template.HTML(title, list, `
      <form action="/topic/create_process" method="post">
        <p><input type="text" name="title" placeholder="title"></p>
        <p>
          <textarea name="description" placeholder="description"></textarea>
        </p>
        <p>
          <input type="submit">
        </p>
      </form>
    `, '', auth.statusUI(request, response));
    response.send(html);
  });

  router.post('/create_process', function(request, response){
      if (!auth.isOwner(request, response)) {
    response.redirect('/');
    return false;
  }
    var post = request.body;
    var title = post.title;
    var description = post.description;
    var id = shortid.generate();
      db.get('topics').push({
          id: id,
          title: title,
          description: description,
          user_id: request.user.id
      }).write();
      response.redirect(`/topic/${id}`);
    
  });

  router.get('/update/:pageId', function(request, response){
      if (!auth.isOwner(request, response)) {
    response.redirect('/');
    return false;
  }
    var topic = db.get('topics').find({id:request.params.pageId}).value();
      request.flash('error', 'Not yours');
      if(topic.user_id !== request.user.id){
           request.flash('error', 'Not yours');
      }
      var title = topic.title;
      var description = topic.description;
      var list = template.list(request.list);
      var html = template.HTML(title, list,
        `
        <form action="/topic/update_process" method="post">
          <input type="hidden" name="id" value="${topic.id}">
          <p><input type="text" name="title" placeholder="title" value="${title}"></p>
          <p>
            <textarea name="description" placeholder="description">${description}</textarea>
          </p>
          <p>
            <input type="submit">
          </p>
        </form>
        `,
        `<a href="/topic/create">create</a> <a href="/topic/update/${topic.id}">update</a>`,
        auth.statusUI(request, response)
      );
      response.send(html);
    
  });

  router.post('/update_process', function(request, response){
      if (!auth.isOwner(request, response)) {
    response.redirect('/');
    return false;
  }
    var post = request.body;
    var id = post.id;
    var title = post.title;
    var description = post.description;
    var topic = db.get('topics').find({id:id}).value();
      if(topic.user_id !== request.user.id){
          request.flash('error', 'Not yours!');
          return response.redirect('/');
      }
      db.get('topics').find({id:id}).assign({
          title:title, description:description
      }).write();
      response.redirect(`/topic/${topic.id}`);
  });

  router.post('/delete_process', function(request, response){
      if (!auth.isOwner(request, response)) {
    response.redirect('/');
    return false;
  }
    var post = request.body;
    var id = post.id;
    var filteredId = path.parse(id).base;
    fs.unlink(`data/${filteredId}`, function(error){
      response.redirect('/');
    });
  });

  router.get('/:pageId', function(request, response, next) { 
      
    var topic = db.get('topics').find({
        id:request.params.pageId
    }).value();
      var user = db.get('users').find({
          id: topic.user_id
      }).value();
        var sanitizedTitle = sanitizeHtml(topic.title);
        var sanitizedDescription = sanitizeHtml(topic.description, {
          allowedTags:['h1']
        });
        var list = template.list(request.list);
        var html = template.HTML(sanitizedTitle, list,
          `<h2>${sanitizedTitle}</h2>${sanitizedDescription}
          <p>by ${user.displayName}</p>`,
          ` <a href="/topic/create">create</a>
            <a href="/topic/update/${topic.id}">update</a>
            <form action="/topic/delete_process" method="post">
              <input type="hidden" name="id" value="${sanitizedTitle}">
              <input type="submit" value="delete">
            </form>`,
           auth.statusUI(request, response)
        );
        response.send(html);
    
  });
  module.exports = router;

다른 사용자 아이디로 다른 사용자가 생성한 글을 업데이트 하려하자 되질 않는다.

 

 

 

원래 글을 생성했던 사용자 아이디로 업데이트는 가능하다.

 

 

 

 

 

 

 

 

 

7. 접근제어 - 글 삭제

 

routes/topic.js

.
.
.
.
.
.
router.post('/delete_process', function(request, response){
      if (!auth.isOwner(request, response)) {
    response.redirect('/');
    return false;
  }
    var post = request.body;
    var id = post.id;
    //db.json의 topics에 id 값을 삽입하고
    var topic = db.get('topics').find({id:id}).value();
    
    //마찬가지로 topic.user_id와 request.user.id이 같지 않으면 초기화면으로 가서 
    //오류를 알리는 플래시 메세지를 등장시킨다.
  if(topic.user_id !== request.user.id){
    request.flash('error', 'Not yours!');
    return response.redirect('/');
  }
  //topic.user_id와 request.user.id이 같으면 .remove 메소드를 이용하여 topics의 id 값을
  //제거하여 삭제 기능을 구현시킨다.
  //그리고 다시 초기 화면으로 되돌린다.
  db.get('topics').remove({id:id}).write();
  response.redirect('/');
  });
  .
  .
  .
  .
  .
  router.get('/:pageId', function(request, response, next) { 
      
    var topic = db.get('topics').find({
        id:request.params.pageId
    }).value();
      var user = db.get('users').find({
          id: topic.user_id
      }).value();
        var sanitizedTitle = sanitizeHtml(topic.title);
        var sanitizedDescription = sanitizeHtml(topic.description, {
          allowedTags:['h1']
        });
        var list = template.list(request.list);
        var html = template.HTML(sanitizedTitle, list,
          `<h2>${sanitizedTitle}</h2>${sanitizedDescription}
          <p>by ${user.displayName}</p>`,
          ` <a href="/topic/create">create</a>
            <a href="/topic/update/${topic.id}">update</a>
            <form action="/topic/delete_process" method="post">
              <input type="hidden" name="id" value="${topic.id}"> //topic.id로 수정
              <input type="submit" value="delete">
            </form>`,
           auth.statusUI(request, response)
        );
        response.send(html);
    
  });
  module.exports = router;

다른 사용자 아이디로 다른 사용자가 쓴 글을 삭제하면 초기화면으로 튕기면서 오류를 알리는 플래시 메세지를 등장시킨다.

 

 

원래 사용자 아이디로는 삭제가 가능하다.

 

 

 

 

 

 

반응형

댓글