-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feat/login api #15
Feat/login api #15
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
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); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
||
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; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 변수 선언부는 불필요하니 지워주는게 좋을것 같아요 |
||
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, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 프리티어 적용 확인해 주시면 감사합니다 |
||
postLoginController, | ||
}; | ||
|
||
export default authController; |
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, // 이미 존재하는 닉네임 일 때 | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import express from "express"; | ||
import authController from "../controller/auth"; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. import 시엔 항상 주석으로 description을 달아주세요! |
||
const router = express.Router(); | ||
|
||
router.post("/login", authController.postLoginController); | ||
router.post("/signup", authController.postSignupController); | ||
|
||
module.exports = router; |
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"; | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. import 주석 확인! |
||
/** | ||
* @회원가입 | ||
* @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, | ||
}, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. find 쿼리시에는 항상 is_delete 를 포함하여 where절을 걸어주세요 |
||
}); | ||
if (emailExist.length > 0) { | ||
return constant.EMAIL_ALREADY_EXIST; | ||
} | ||
|
||
// nickname이 이미 존재할 때 | ||
const nicknameExist = await User.findAll({ | ||
where: { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. where절에 is_delete 걸어주세요! |
||
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 } }); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. where절 is_delete 걸어주세요! |
||
if (!user) { | ||
return -2; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. constant library 적용! |
||
} | ||
|
||
// 비밀번호 일치 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; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
파라미터로 req.body 한번에 보내도록 통일하겠습니다!