잡다한 사전

(2023.12.13) (백오피스 프로젝트) 관리자 로그인 본문

프로그래밍 언어/node.js

(2023.12.13) (백오피스 프로젝트) 관리자 로그인

잡사전집사 2023. 12. 19. 16:29
반응형

이번 백오피스 프로젝트에서는 유저 아이디와 관리자 권한 아이디로 로그인을 하는 것을 구현을 해야했다.

이부분에서 나는 로그인 구현을 맡아서 어떻게 관리자 로그인을 구현을 해야할지 고민을 하였다.

 

고민을 하던 도중 로그인을 하는 것을 2개로 나누는 것이 좋겠다라는 생각을 하게 되었고, 유저 로그인 부분과 관리자 로그인 부분을 나누어서 작업을 시작하였다. 

 

1. Prisma 생성하기

먼저 유저 prisma와 admin Prisma를 생성을 해주었다.

model Users {
    userId Int @id @default(autoincrement()) @map("userId")
    email String @unique @map("email")
    password String @map("password")
    nickname String @unique @map("nickname")
    address String @map("address")
    phoneNumber String @map("phoneNumber")
    type String @default("USER") @map("type")
    point Int @default(1000000) @map("point") 


    createdAt DateTime @default(now()) @map("createdAt")
    updatedAt DateTime @updatedAt @map("updatedAt")
	Orders Orders[]
    @@map("Users")
}

model Admin {
  adminId Int @id @default(autoincrement()) @map("adminId")
  email String @unique @map("email")
  password String @map("password")
  nickname String @unique @map("nickname")
  address String @map("address")
  marketNum String @map("marketNum")
  type String @default("ADMIN") @map("type")
  point Int @default(0) @map("point")

  createdAt DateTime @default(now()) @map("createdAt")
  updatedAt DateTime @updatedAt @map("updatedAt")
  Diner Diners?
  @@map("Admin")
}

 

유저 Prisma인 경우에는 생성을 하였을 때 기본적으로 100만 포인트를 지급을 하기 위해서 default값으로 포인트를 주었으며, 유저인 것을 확인하기 위해서 type에 USER를 default 값으로 넣어주었다.

 

관리자 Prisma는 판매를 진행 했을 때 포인트가 들어오는 것을 확인하기 위해 0원으로 시작하였으며, type에는 관리자를 확인하기 위해서 ADMIN을 default 값으로 넣어주었다.

 

2. API 구현

이번 백오피스 프로젝트에서는 3계층 아키텍쳐를 적용하였기 때문에 routes 부분부터 user.router.js 파일로 나누어서 작업을 진행하였습니다. 

 

// routes/users.router.js

import express from 'express';
import { UsersController } from '../controllers/users.controller.js';
// 유저 인증 미들웨어
import { authMiddleware } from '../middlewares/authMiddleware.js';
// 관리자 인증 미들웨어
import { authAdminMiddleware } from '../middlewares/authAdminMiddleware.js';
// 회원과입을 진행할때 입력칸이 비어있을 때 확인하는 미들웨어
import ValidationCheck from '../middlewares/validationMiddleware.js';

const router = express.Router();
const usersController = new UsersController();

// 회원가입
router.post('/', ValidationCheck, usersController.userSignup);
router.post('/admin', ValidationCheck, usersController.adminSignup);
router.post('/auth/user', usersController.userSignin);
router.post('/auth/admin', usersController.adminSignin);

router.get('/auth/user/me', authMiddleware, usersController.usercheckToken);
router.get(
  '/auth/admin/me',
  authAdminMiddleware,
  usersController.admincheckToken,
);
router.post('/logout', usersController.userLogout);
export default router;

 

2-1 Controller Part

import { UsersService } from '../services/users.service.js';
import { sendEmail } from '../server/email.js';

import resBody from '../server/resBody.js';

export class UsersController {
  usersService = new UsersService();

  //eamil 인증 구현
  emailSend = async (req, res, next) => {
    try {
      const { email, auth } = req.body;
      sendEmail(email, auth);

      return res.status(200).json({ success: true });
    } catch (err) {
      next(err);
    }
  };

// 유저 회원가입	
  userSignup = async (req, res, next) => {
    try {
      const {
        email,
        nickname,
        password,
        confirmpassword,
        address,
        phoneNumber,
      } = req.body;

      const users = await this.usersService.signupUser(
        email,
        nickname,
        password,
        confirmpassword,
        address,
        phoneNumber,
      );

      return res
        .status(200)
        .json({ message: '회원가입이 완료되었습니다.', data: users });
    } catch (err) {
      next(err);
    }
  };

// 관리자 회원가입
  adminSignup = async (req, res, next) => {
    try {
      const { email, nickname, password, confirmpassword, address, marketNum } =
        req.body;

      const admin = await this.usersService.signupAdmin(
        email,
        nickname,
        password,
        confirmpassword,
        address,
        marketNum,
      );

      return res
        .status(200)
        .json({ message: '(사장님) 회원가입이 되었습니다.', data: admin });
    } catch (err) {
      next(err);
    }
  };

//유저 로그인
  userSignin = async (req, res, next) => {
    try {
      const { email, password } = req.body;

      const userLogin = await this.usersService.userLogin(email, password);

      res.cookie('Authorization', 'Bearer ' + userLogin);
      res.header('Authorization', `Bearer ${userLogin}`);
      return res.status(200).json({
        message: '사용자 로그인입니다.',
        token: `Bearer ${userLogin}`,
      });
    } catch (err) {
      next(err);
    }
  };

//관리자 로그인
  adminSignin = async (req, res, next) => {
    try {
      const { email, password } = req.body;

      const adminLogin = await this.usersService.adminLogin(email, password);

      res.cookie('Authorization', 'Bearer ' + adminLogin);
      res.header('Authorization', `Bearer ${adminLogin}`);
      return res.status(200).json({
        message: '사장님 로그인입니다.',
        token: adminLogin,
      });
    } catch (err) {
      next(err);
    }
  };

// 유저 토큰 인증
  usercheckToken = async (req, res, next) => {
    try {
      const { email, nickname, userId } = res.locals.user;

      return res.status(200).json({
        message: '토큰이 정상적입니다.',
        data: { email, nickname, userId },
      });
    } catch (err) {
      next(err);
    }
  };

// 관리자 토큰 인증
  admincheckToken = async (req, res, next) => {
    try {
      const { email, nickname, adminId } = res.locals.admin;

      return res.status(200).json({
        message: '토큰이 정상적입니다.',
        data: { email, nickname, adminId },
      });
    } catch (err) {
      next(err);
    }
  };

// 로그 아웃 기능
  userLogout = async (req, res, next) => {
    try {
      res.clearCookie('Authorization');
      return res.status(200).json({ ...resBody(true, '로그아웃 되었습니다.') });
    } catch (err) {
      next(err);
    }
  };
}

 

유저와 관리자 회원가입, 로그인, 토큰 인증을 나누어서 진행을 하였으며, 위에서 api가 나누어진 상태로 회원가입, 로그인 등을 다른 창에서 진행하도록 하였습니다. 

 

2-2 Services Part

 

import { UsersService } from '../services/users.service.js';
import { sendEmail } from '../server/email.js';

import resBody from '../server/resBody.js';

export class UsersController {
  usersService = new UsersService();

  //eamil 인증 구현
  emailSend = async (req, res, next) => {
    try {
      const { email, auth } = req.body;
      sendEmail(email, auth);

      return res.status(200).json({ success: true });
    } catch (err) {
      next(err);
    }
  };

  userSignup = async (req, res, next) => {
    try {
      const {
        email,
        nickname,
        password,
        confirmpassword,
        address,
        phoneNumber,
      } = req.body;

      const users = await this.usersService.signupUser(
        email,
        nickname,
        password,
        confirmpassword,
        address,
        phoneNumber,
      );

      return res
        .status(200)
        .json({ message: '회원가입이 완료되었습니다.', data: users });
    } catch (err) {
      next(err);
    }
  };

  adminSignup = async (req, res, next) => {
    try {
      const { email, nickname, password, confirmpassword, address, marketNum } =
        req.body;

      const admin = await this.usersService.signupAdmin(
        email,
        nickname,
        password,
        confirmpassword,
        address,
        marketNum,
      );

      return res
        .status(200)
        .json({ message: '(사장님) 회원가입이 되었습니다.', data: admin });
    } catch (err) {
      next(err);
    }
  };

  userSignin = async (req, res, next) => {
    try {
      const { email, password } = req.body;

      const userLogin = await this.usersService.userLogin(email, password);

      res.cookie('Authorization', 'Bearer ' + userLogin);
      res.header('Authorization', `Bearer ${userLogin}`);
      return res.status(200).json({
        message: '사용자 로그인입니다.',
        token: `Bearer ${userLogin}`,
      });
    } catch (err) {
      next(err);
    }
  };

  adminSignin = async (req, res, next) => {
    try {
      const { email, password } = req.body;

      const adminLogin = await this.usersService.adminLogin(email, password);

      res.cookie('Authorization', 'Bearer ' + adminLogin);
      res.header('Authorization', `Bearer ${adminLogin}`);
      return res.status(200).json({
        message: '사장님 로그인입니다.',
        token: adminLogin,
      });
    } catch (err) {
      next(err);
    }
  };

  usercheckToken = async (req, res, next) => {
    try {
      const { email, nickname, userId } = res.locals.user;

      return res.status(200).json({
        message: '토큰이 정상적입니다.',
        data: { email, nickname, userId },
      });
    } catch (err) {
      next(err);
    }
  };

  admincheckToken = async (req, res, next) => {
    try {
      const { email, nickname, adminId } = res.locals.admin;

      return res.status(200).json({
        message: '토큰이 정상적입니다.',
        data: { email, nickname, adminId },
      });
    } catch (err) {
      next(err);
    }
  };

  userLogout = async (req, res, next) => {
    try {
      res.clearCookie('Authorization');
      return res.status(200).json({ ...resBody(true, '로그아웃 되었습니다.') });
    } catch (err) {
      next(err);
    }
  };
}

 

2-3 Repositoryies Part

 

import { prisma } from '../utils/prisma/index.js';
export class UsersRepository {
  //user signup
  signupUser = async (email, nickname, hash, address, phoneNumber) => {
    const signupUser = await prisma.users.create({
      data: {
        email,
        nickname,
        password: hash,
        address: address,
        phoneNumber: phoneNumber,
      },
    });
    return signupUser;
  };

  //admin signup
  signupAdmin = async (email, nickname, hash, address, marketNum) => {
    const signupAdmin = await prisma.admin.create({
      data: {
        email,
        nickname,
        password: hash,
        address: address,
        marketNum: marketNum,
      },
    });
    return signupAdmin;
  };

  // user email 중복 확인
  existsEmail = async (email) => {
    const existsEmail = await prisma.users.findUnique({
      where: {
        email,
      },
    });

    return existsEmail;
  };

  // user nickname 중복 확인
  existsNickname = async (nickname) => {
    const existsNickname = await prisma.users.findUnique({
      where: {
        nickname,
      },
    });
    return existsNickname;
  };

  // admin email 중복 확인
  existsAdminEmail = async (email) => {
    const existsAdminEmail = await prisma.admin.findUnique({
      where: {
        email,
      },
    });

    return existsAdminEmail;
  };

  // admin nickname 중복 확인
  existsAdminNickname = async (nickname) => {
    const existsAdminNickname = await prisma.admin.findUnique({
      where: {
        nickname,
      },
    });
    return existsAdminNickname;
  };

  // user login
  userLogin = async (email) => {
    const userLogin = await prisma.users.findUnique({
      where: {
        email,
      },
    });

    return userLogin;
  };

  // admin login
  adminLogin = async (email) => {
    const adminLogin = await prisma.admin.findUnique({
      where: {
        email,
      },
    });

    return adminLogin;
  };
}

 

 

이번 코드에서는 html UI 코드는 제외하였습니다. 

 

다음에 ajax를 이용해서 ui에서 회원가입을 진행시 API와 연결하는 부분을 다루어보겠습니다. 

반응형