Skip to content

Commit

Permalink
Merge pull request #15 from TeamBookTez/feat/login-api
Browse files Browse the repository at this point in the history
Feat/login api
  • Loading branch information
seohyun-106 authored Jan 12, 2022
2 parents b77a03b + 28ab570 commit 95844a9
Show file tree
Hide file tree
Showing 7 changed files with 337 additions and 3 deletions.
34 changes: 31 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

153 changes: 153 additions & 0 deletions src/controller/auth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
import { Request, Response } from "express";

// slack
import slack from "../others/slack/slack";

// libraries
import constant from "../library/constant";
import response from "../library/response";
import returnCode from "../library/returnCode";

// services
import authService from "../service/auth";

/**
* @회원가입
* @route POST /auth/signup
* @access public
* @err 1. 필요한 값이 없을 때
* 2. 이메일 형식이 올바르지 않을 때
* 3. 닉네임 형식이 올바르지 않을 때
* 4. 패스워드 형식이 올바르지 않을 때
* 5. 이메일이 이미 존재할 때
* 6. 닉네임이 이미 존재할 때
*/
const postSignupController = async (req: Request, res: Response) => {
try {
const resData = await authService.postSignupService(req.body);

if (resData === constant.NULL_VALUE) {
response.basicResponse(
res,
returnCode.BAD_REQUEST,
false,
"필요한 값이 없습니다."
);
} else if (resData === constant.WRONG_EMAIL_CONVENTION) {
response.basicResponse(
res,
returnCode.BAD_REQUEST,
false,
"올바르지 않은 이메일 형식 입니다."
);
} else if (resData === constant.WRONG_NICKNAME_CONVENTION) {
response.basicResponse(
res,
returnCode.BAD_REQUEST,
false,
"올바르지 않은 닉네임 형식 입니다."
);
} else if (resData === constant.WRONG_PASSWORD_CONVENTION) {
response.basicResponse(
res,
returnCode.BAD_REQUEST,
false,
"올바르지 않은 패스워드 형식 입니다."
);
} else if (resData === constant.EMAIL_ALREADY_EXIST) {
response.basicResponse(
res,
returnCode.BAD_REQUEST,
false,
"이미 존재하는 이메일 입니다."
);
} else if (resData === constant.NICKNAME_ALREADY_EXIST) {
response.basicResponse(
res,
returnCode.BAD_REQUEST,
false,
"이미 존재하는 닉네임 입니다."
);
} else {
response.tokenResponse(
res,
returnCode.CREATED,
"이동근의 북스테어즈에 온 것을 환영합니다.",
true,
resData.token
);
}
} catch (err) {
slack.slackWebhook(req, err.message);
console.error(err.message);
response.basicResponse(
res,
returnCode.INTERNAL_SERVER_ERROR,
false,
"서버 오류"
);
}
};

/**
* @로그인
* @route Post auth/login
* @access public
* @err 1. 필요한 값이 없습니다.
* 2. 존재하지 않는 이메일입니다.
* 3. 비밀번호가 일치하지 않습니다.
*/

const postLoginController = async (req: Request, res: Response) => {
try {
const { email, password } = req.body;
const data = await authService.postLoginService(email, password);

if (data === -1) {
response.basicResponse(
res,
returnCode.BAD_REQUEST,
false,
"필요한 값이 없습니다."
);
} else if (data === -2) {
response.basicResponse(
res,
returnCode.NOT_FOUND,
false,
"존재하지 않는 이메일입니다."
);
} else if (data === -3) {
response.basicResponse(
res,
returnCode.BAD_REQUEST,
false,
"비밀번호가 일치하지 않습니다."
);
} else {
const { nickname, token } = data;
response.dataResponse(
res,
returnCode.OK,
"장서현의 첫 api 소중히 다뤄주세요 💋",
true,
data
);
}
} catch (err) {
slack.slackWebhook(req, err.message);
console.error(err.message);
response.basicResponse(
res,
returnCode.INTERNAL_SERVER_ERROR,
false,
"서버 오류"
);
}
};
const authController = {
postSignupController,
postLoginController,
};

export default authController;
1 change: 1 addition & 0 deletions src/controller/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ const getTestController = async (req: Request, res: Response) => {
);
}
};

const testController = {
getTestController,
};
Expand Down
8 changes: 8 additions & 0 deletions src/library/constant.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export default {
NULL_VALUE: -1, // 필요한 값이 없을 때
WRONG_EMAIL_CONVENTION: -2, // 이메일 형식이 잘못 되었을 때
WRONG_NICKNAME_CONVENTION: -3, // 닉네임 형식이 잘못 되었을 때
WRONG_PASSWORD_CONVENTION: -4, // 비밀번호 형식이 잘못 되었을 때
EMAIL_ALREADY_EXIST: -5, // 이미 존재하는 이메일 일 때
NICKNAME_ALREADY_EXIST: -6, // 이미 존재하는 닉네임 일 때
};
8 changes: 8 additions & 0 deletions src/router/auth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import express from "express";
import authController from "../controller/auth";
const router = express.Router();

router.post("/login", authController.postLoginController);
router.post("/signup", authController.postSignupController);

module.exports = router;
1 change: 1 addition & 0 deletions src/router/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,6 @@ router.get("", async (req: Request, res: Response) => {
});

router.use("/test", require("./test"));
router.use("/auth", require("./auth"));

export default router;
135 changes: 135 additions & 0 deletions src/service/auth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
// sequelize
import sequelize, { Op } from "sequelize";
// library
import jwt from "jsonwebtoken";
import bcrypt from "bcryptjs";

import { User } from "../models";
import index from "../config";
import constant from "../library/constant";
import isEmail from "validator/lib/isEmail";

/**
* @회원가입
* @route POST /auth/signup
* @access public
* @err 1. 필요한 값이 없을 때
* 2. 이메일 형식이 올바르지 않을 때
* 3. 닉네임 형식이 올바르지 않을 때
* 4. 패스워드 형식이 올바르지 않을 때
* 5. 이메일이 이미 존재할 때
* 6. 닉네임이 이미 존재할 때
*/
const postSignupService = async ({ email, nickname, password }) => {
// 필요한 값이 존재하지 않는 경우
if (!email || !nickname || !password) {
return constant.NULL_VALUE;
}

// email 형식이 잘못되었을 때
if (!isEmail(email)) {
return constant.WRONG_EMAIL_CONVENTION;
}

// nickname 형식이 잘못되었을 때
if (
/\W/.test(nickname) ||
/_/.test(nickname) ||
nickname.length < 2 ||
nickname.length > 8
) {
return constant.WRONG_NICKNAME_CONVENTION;
}

// password 형식이 잘못되었을 때
if (
!/^(?=.*[a-zA-Z])((?=.*\d)(?=.*\W)).{8,64}$/.test(password) ||
/\s/.test(password)
) {
return constant.WRONG_PASSWORD_CONVENTION;
}

// email이 이미 존재할 때
const emailExist = await User.findAll({
where: {
email,
},
});
if (emailExist.length > 0) {
return constant.EMAIL_ALREADY_EXIST;
}

// nickname이 이미 존재할 때
const nicknameExist = await User.findAll({
where: {
nickname,
},
});

if (nicknameExist.length > 0) {
return constant.NICKNAME_ALREADY_EXIST;
}

// 새로운 유저 생성 & 토큰 발급
const salt = await bcrypt.genSalt(10);
const hashedPassword = await bcrypt.hash(password, salt);
const user = await User.create({
email,
password: hashedPassword,
nickname,
});

const payload = {
user: {
id: user.id,
},
};

const token = jwt.sign(payload, process.env.JWT_SECRET, {
expiresIn: "14d",
});
return token;
};

/**
* @로그인
* @route Post auth/login
* @access public
*/

const postLoginService = async (email: string, password: string) => {
// 요청 바디 부족
if (!email || !password) {
return -1;
}

// 존재하지 않는 이메일
const user = await User.findOne({ where: { email: email } });
if (!user) {
return -2;
}

// 비밀번호 일치 X
const isMatch = await bcrypt.compare(password, user.password);
if (!isMatch) {
return -3;
}

// 성공 시
// 토큰 만들기
const payload = {
user: {
id: user.id,
},
};
const nickname = user.nickname;
const token = jwt.sign(payload, index.jwtSecret, { expiresIn: "14d" });
return { nickname, token };
};

const authService = {
postSignupService,
postLoginService,
};

export default authService;

0 comments on commit 95844a9

Please sign in to comment.