-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #15 from TeamBookTez/feat/login-api
Feat/login api
- Loading branch information
Showing
7 changed files
with
337 additions
and
3 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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, // 이미 존재하는 닉네임 일 때 | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; |