E-book (5) 관리자 등록

이율곡·2023년 1월 24일
0

Project

목록 보기
7/15
post-thumbnail

서두

관리자 등록하는 페이지를 만들었다. 관리자는 회원가입한 사람중에서 검색하여 등록하게 만들었다. 등록하는 순서로는

관리자 아이디로 로그인 -> 관리자 페이지 로그인(관리자번호)
등록페이지 -> 등록할 회원 검색 -> 등록 순

이런 식으로 만들었다. 이제 차근차근 코드를 어떻게 썼는지 적어야겠다. 폴더 구성이다.


Table

우선 admin 테이블을 만들었다.

CREATE TABLE admin (
	admin_number INT PRIMARY KEY NOT NULL,
    member_number INT NOT NULL,
    manage_grade CHAR(1) NOT NULL DEFAULT 1, 
    boss_number INT,
    created_at TIMESTAMP DEFAULT NOW()
);

평범한 관리자 테이블이다. manage_grade는 관리자 등급을 나타냈다. 그래서 1은 관리만 할 수 있는 관리자, 2는 등록과 관리를 할 수 있는 관리자로 만드려 한다. boss_number은 회원을 관리자로 등록할 때 담당한 담당자의 number이다.


Routes

Routes는 adminRoutes.js를 새롭게 만들어줬다.

const express = require('express');

const adminController = require('../controllers/admin/admin');

const routes = express.Router();

routes.get('/adminCheck', adminController.getCheck);

routes.post('/adminCheck', adminController.adminCheck);

routes.get('/registList', adminController.registList);

routes.get('/adminRegist', adminController.adminRegist);

routes.post('/adminRegist', adminController.searchMember);

routes.post('/adminRegistAction', adminController.adminRegistAction);

module.exports = routes;

관리자를 등록하기까지 지나쳐야 할 과정이 많다.

처음으로 get과 post는 관리자 페이지로 가기 전 관리자 전용 로그인 페이지와 액션페이지이다. 두 번째 get 2개는 관리자 메인페이지와 관리자 등록페이지로 이동하는 get이다. 그 다음 post 2개는 회원을 검색하는 것과 검색한 회원을 등록하는 post다. 이로써 Routes에 맞는 Controller를 연결해줬다.


Controller

Controller도 admin폴더를 만들고 그 안에 admin.js로 만들어줬다.

관리자 로그인

exports.getCheck = (req, res, next) => {
  res.render("admin/adminCheck", {
    pageTitle: "adminCheck Page",
    member: req.session.user ? req.session.user : "",
  });
};

exports.adminCheck = (req, res, next) => {
  let admin_number = req.body.admin_number;
  let member_number = req.session.user.member_number;

  Admin.checkAdmin(admin_number, member_number, (admin) => {
    req.session.admin = admin;
    if (!admin) {
      console.log("관리자 로그인 오류 : " + err);
    } else {
      console.log("관리자 로그인 성공!!");
      res.render("admin/adminIndex", {
        pageTitle: "Welcome E-book Admin Page",
        member: req.session.user,
        admin: req.session.admin,
      });
    }
  });
};

우선 Routes에서 처음 설명한 get과 post에 연결된 코드이다. get은 단순히 페이지를 연결한다. post부분은 모델과 연결하여 로그인한 session의 회원번호가 admin 테이블에 있는 관리자 번호와 맞는지 검사를 하고 로그인 여부를 결정한다.

페이지 이동

exports.registList = (req, res, next) => {
  res.render("admin/registList", {
    pageTitle: "E-Book Regist List",
    member: req.session.user,
    admin: req.session.admin,
  });
};

exports.adminRegist = (req, res, next) => {
  res.render("admin/regist/admin", {
    pageTitle: "E-Book Regist Admin",
    member: req.session.user,
    admin: req.session.admin,
    results: "",
  });
};

이 두 Controller는 관리자 메인페이지 -> 등록 메인페이지로 이동하는 것과 등록 메인페이지 -> 관리자 메인페이지로 이동해주는 컨트롤러다.

검색과 등록

exports.searchMember = (req, res, next) => {
  let userid = req.body.userid;

  if (userid) {
    Admin.searchMember(userid, (result) => {
      let member = result;
      console.log(member);
      res.render("admin/regist/admin", {
        pageTitle: "E-Book Regist Admin",
        member: req.session.user,
        admin: req.session.admin,
        results: member,
      });
    });
  } else {
    console.log("아이디를 입력해주세요.");
  }
};

exports.adminRegistAction = (req, res, next) => {
  let memberNumber = req.body.member_number;
  let adminNumber = req.session.admin.admin_number;

  Admin.adminRegistAction(adminNumber, memberNumber, (err) => {
    if (err) {
      console.log("등록 오류를 확인해주세요.");
    } else {
      res.render("admin/adminIndex", {
        pageTitle: "Welcome E-book Admin Page",
        member: req.session.user,
        admin: req.session.admin,
      });
    }
  });
};

마지막으로 검색과 등록하는 부분이다. 관리자로 등록할 회원을 회원 아이디로 검색하고 찾은 값을 다시 페이지로 돌려준다. 값을 받은 페이지에서는 등록버튼을 통해서 관리자로 등록이 가능하도록 했다.


Model

모델 또한 admin 폴더를 만들어서 admin.js를 만들어줬다.

관리자 로그인

static checkAdmin(adminNumber, memberNumber, cb) {
    if (adminNumber) {
      var sql = "SELECT * FROM admin WHERE admin_number = " + adminNumber;
      connection.query(sql, (err, row, fields) => {
        if (err) {
          console.log("쿼리 1 에러 : " + err);
        } else {
          if (memberNumber != row[0].member_number) {
            console.log("관리자 번호를 정확히 입력해주세요.");
          } else {
            console.log("관리자 로그인 성공!!");
            cb(admin({ ...row[0] }));
            // connection.end();
          }
        }
      });
    } else {
      console.log("관리번호를 입력해주세요.");
    }
  }

Controller에서 받은 값으로 관리자 로그인을 진행한다. 우선 admin 테이블에 입력한 값이 있는지 확인하고 있다면 그 값을 갖고 있는 row와 session에서 받은 memberNumber값이 같은지 확인한다. 이렇게 해서 정확한 회원이 정확한 관리자인지 파악 가능하다.

회원검색

static searchMember(userid, cb) {
    if (userid) {
      var sql = "SELECT * FROM member WHERE userid LIKE '%" + userid + "%'";
      connection.query(sql, (err, row, fields) => {
        if (err) {
          console.log("쿼리 1 에러 : " + err);
        } else {
          if (!row) {
            console.log("아이디를 확인해주세요.");
          } else {
            console.log("회원검색 성공!!");
            cb(searchMember(row));
            // connection.end();
          }
        }
      });
    } else {
      console.log("아이디를 입력해주세요.");
    }
  }

회원검색은 입력한 값을 LIKE로 확인했다. 나온 결과들은 cb으로 다시 Controller에 전달한다. 그러면 컨트롤러에서는 값을 View로 전달하고 View에서 값을 보여준다.

관리자 등록

static adminRegistAction(adminNumber, memberNumber, cb) {
    if (adminNumber && memberNumber) {
      let fourNumber = Math.floor(Math.random() * (9999 - 1000) + 1000);
      console.log(fourNumber);
      var adminSQL =
        "INSERT INTO admin (admin_number, member_number, boss_number) VALUES (?, ?, ?)";
      var adminParam = [fourNumber, memberNumber, adminNumber];
      var memberSQL =
        "UPDATE member SET admin_check = 1 WHERE member_number = " + memberNumber;

      connection.beginTransaction((err) => {
        if (err) {
          console.log("관리자 트랜잭션 에러 :" + err);
        } else {
          connection.query(adminSQL, adminParam, (err, row, fields) => {
            if (err) {
              console.log("관리자 INSERT 구문 오류 : " + err);
              connection.rollback();
            } else {
              connection.query(memberSQL, (err, row, fields) => {
                if (err) {
                  console.log("멤버 UPDATE 구문 오류 : " + err);
                  connection.rollback();
                } else {
                  console.log("관리자 등록 성공!!");
                  connection.commit();
                  cb();
                  connection.end();
                }
              });
            }
          });
        }
      });
    } else {
      console.log("등록자를 확인해주세요.");
    }
  }

관리자 등록은 트랜잭션으로 이루어진다. admin 테이블에 등록하는 것과 member 테이블에 admin_check 부분을 수정해주어야 하기 때문이다.

admin_number은 임의의 숫자 네 자리로 했으며, 범위는 1000~9999까지이다. adminNumber을 인자로 받은 것은 새로운 관리자를 등록한 boss_number로 사용할 거기 때문이다. 이는 후에 재귀 테이블을 사용해 볼 생각이다.


View

View도 마찬가지로 admin폴더를 만들고 이 폴더에서 레이아웃도 나누고 파일도 설정했다.

관리자 로그인

<%- include('../includes/head-nav.ejs')%>
    <div class="container px-4 px-lg-5">
        <div class="row gx-4 gx-lg-5 align-items-center my-5 ">
            <form action="/adminCheck" method="POST">
                <label for="admin_number"> 관리자번호 </label>
                <input type="text" name="admin_number" id="admin_number">
                <button type="submit" class="btn btn-primary"> 들어가기 </button>
            </form>
        </div>
    </div>
<%- include('../includes/footer.ejs')%>        

관리자 페이지 전에 가장 먼저 들어가는 관리자 로그인 페이지이다. 간단하게 관리자 번호를 받고 이 값이 로그인한 유저의 값과 같은 지 확인한다.

관리자 메인페이지

<%- include('../admin/includes/admin-head-nav.ejs')%>
    <div class="container px-4 px-lg-5">
        <div class="row gx-4 gx-lg-5 align-items-center my-5 ">
            <% if(admin.manage_grade == 2) { %>
                <a href="/registList" class="btn btn-primary"> 등록 </a>
            <% } %>
            <a href="/adminManage" class="btn btn-warning"> 관리 </a>
        </div>
    </div>
<%- include('../admin/includes/admin-footer.ejs')%>        

관리자 메인페이지는 등록과 관리버튼밖에 없다. 가장 높은 관리자는 두 버튼을 다 볼 수 있지만, 낮은 관리자는 관리밖에 보지 못한다.

등록 메인페이지

<%- include('../admin/includes/admin-head-nav.ejs')%>
    <div class="container px-4 px-lg-5">
        <div class="row gx-4 gx-lg-5 align-items-center my-5 ">
            <ul class="navbar-nav ms-auto mb-2 mb-lg-0">
                <li class="nav-item"><a class="nav-link active" aria-current="page" href="/adminRegist">관리자 등록</a></li>
            </ul>
            <ul class="navbar-nav ms-auto mb-2 mb-lg-0">
                <li class="nav-item"><a class="nav-link active" aria-current="page" href="/adminRegist">작가 등록</a></li>
                <li class="nav-item"><a class="nav-link active" aria-current="page" href="/adminRegist">이미지 등록</a></li>
                <li class="nav-item"><a class="nav-link active" aria-current="page" href="/adminRegist">도서내용 등록</a></li>
                <li class="nav-item"><a class="nav-link active" aria-current="page" href="/adminRegist">도서 등록</a></li>
            </ul>
        </div>
    </div>
<%- include('../admin/includes/admin-footer.ejs')%>        

등록페이지이다. 앞으로 등록해야 될 것들이 많기에 등록 페이지를 만들었다. 이 중에서 관리자 등록 페이지로 이동해서 관리자를 등록할 수 있다.

관리자 등록페이지

<%- include('../../admin/includes/admin-head-nav.ejs')%>
    <div class="container px-4 px-lg-5">
        <div class="row gx-4 gx-lg-5 align-items-center my-5 ">
            <form action="/adminRegist" method="POST">
                <label for="searchMember">회원검색</label>
                <input type="text" name="userid" id="userid" placeholder="회원 아이디를 입력해주세요">
                <button type="submit" class="btn btn-primary">검색</button>
            </form>
            <% if(results) {%>
                <table>
                    <tr>
                        <th>회원번호</th>
                        <th>이름</th>
                        <th>아이디</th>
                        <th>등록일</th>
                        <th>관리자여부</th>
                        <th>등록</th>
                    </tr>
                    <% for (result in results) { %>
                        <form action="/adminRegistAction" method="POST">
                            <tr>
                                <td><%= results[result].member_number %></td>
                                <td><%= results[result].username %></td>
                                <td><%= results[result].userid %></td>
                                <td><%= results[result].created_at %></td>
                                <td>
                                    <% if(results[result].admin_check == 0) { %>
                                        X
                                    <% } else { %>
                                        O
                                    <% } %>
                                </td>
                                <input type="hidden" name="member_number" id="member_number" value="<%= results[result].member_number %>">
                                <td>
                                    <% if(results[result].admin_check == 0) { %>
                                        <button type="submit" class="btn btn-primary">등록</button>
                                    <% } else { %>
                                        <a class="btn btn-warning">관리자</a>
                                    <% } %>
                                </td>
                            </tr>
                        </form>
                    <% } %>
                </table>
            <% } %>
        </div>
    </div>
<%- include('../../admin/includes/admin-footer.ejs')%>        

관리자 등록페이지는 get과 post로 받을 수 있다. 처음 get으로 들어가면 회원검색만 가능하지만 검색한 결과를 post로 받으면 값의 결과를 확인할 수 있다. ejs 문법들을 활용해서 if와 for in 반복문으로 값을 확인할 수 있다.

정리하기

하나의 챕터를 마칠 때마다 글을 쓰려 했다. 별로 안될 거라 생각했는데 깨달았다. 적당히 정리를 하면서 해야겠다. 이번에 한 번씩 정리하면서 느끼는 점은 아직 코드가 많이 부족하다고 생각한다. 늘 그렇게 생각하지만 일단 되는 코드가 중요하기에 후닥 마무리하고 깔끔하게 정리까지 할 날이 오면 좋겠다.

관리부분이 제대로 된 시작인데 어렵지 않고 무난하게 진입한 거 같다. 글을 쓰지는 않더라도 꾸준히 공부를 하고 있는 결과가 나오는 것 같다. 슬슬 도서 부분에 진입하는데 잘 해보고 싶다.

profile
음악을 좋아하는 사람이 음악을 만들 듯, 개발을 좋아하게 될 사람이 쓰는 개발이야기

0개의 댓글