diff --git a/package-lock.json b/package-lock.json index 088d837..397c257 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,7 +17,7 @@ "express-async-handler": "^1.2.0", "http-status-codes": "^2.3.0", "jsonwebtoken": "^9.0.2", - "multer": "^1.4.5-lts.1", + "multer": "1.4.5-lts.1", "mysql2": "^3.10.3", "sequelize": "^6.37.3", "swagger-ui-dist": "^5.17.14", diff --git a/src/config/response.status.js b/src/config/response.status.js index eab5426..227a627 100644 --- a/src/config/response.status.js +++ b/src/config/response.status.js @@ -15,17 +15,21 @@ export const status = { PARAMETER_IS_WRONG : {status : StatusCodes.PARAMETER_IS_WRONG, "isSuccess" : false, "code": "COMMON006", "message":"잘못된 파라미터가 전달되었습니다."}, // signup err - USERID_ALREADY_EXIST: { status: StatusCodes.CONFLICT, isSuccess: false, code: "401", message: "이미 존재하는 아이디입니다." }, - EMPTY_DATA: { status: StatusCodes.CONFLICT, isSuccess: false, code: "402", message: "데이터가 비어있습니다." }, - SIGNUP_ERROR: { status: StatusCodes.CONFLICT, isSuccess: false, code: "403", message: "회원가입 에러" }, // 디테일하게 수정할 필요있음 + USERID_ALREADY_EXIST: { status: StatusCodes.UNAUTHORIZED, isSuccess: false, code: "SIGNUP001", message: "이미 존재하는 아이디입니다." }, + SIGNUP_EMPTY_DATA: { status: StatusCodes.PAYMENT_REQUIRED, isSuccess: false, code: "SIGNUP002", message: "데이터가 비어있습니다." }, + SIGNUP_ERROR: { status: StatusCodes.FORBIDDEN,isSuccess: false, code: "SIGNUP003", message: "회원가입 에러" }, // login err - USER_NOT_FOUND: { status: StatusCodes.CONFLICT, isSuccess: false, code: "401", message: "존재하지 않는 아이디입니다." }, - PASSWORD_MISMATCH: { status: StatusCodes.CONFLICT, isSuccess: false, code: "403", message: "비밀번호가 일치하지 않습니다." }, + USER_NOT_FOUND: { status: StatusCodes.UNAUTHORIZED, isSuccess: false, code: "LOGIN001", message: "존재하지 않는 아이디입니다." }, + LOGIN_EMPTY_DATA: { status: StatusCodes.PAYMENT_REQUIRED, isSuccess: false, code: "SIGNUP002", message: "데이터가 비어있습니다." }, + PASSWORD_MISMATCH: { status: StatusCodes.FORBIDDEN, isSuccess: false, code: "LOGIN002", message: "비밀번호가 일치하지 않습니다." }, // login middlewares err - TOKEN_NOT_PROVIDED: { status: StatusCodes.UNAUTHORIZED, isSuccess: false, code: "401", message: "로그인이 필요합니다." }, - TOKEN_EXPIRED: { status: StatusCodes.UNAUTHORIZED, isSuccess: false, code: "403", message: "토큰을 재발급 받아주세요." }, - INVALID_TOKEN: { status: StatusCodes.UNAUTHORIZED, isSuccess: false, code: "403", message: "유효하지 않은 토큰입니다." }, + TOKEN_NOT_PROVIDED: { status: StatusCodes.UNAUTHORIZED, isSuccess: false, code: "LOGINMIDDLEWARES001", message: "로그인이 필요합니다." }, + TOKEN_EXPIRED: { status: StatusCodes.PAYMENT_REQUIRED, isSuccess: false, code: "LOGINMIDDLEWARES002", message: "토큰을 재발급 받아주세요." }, + INVALID_TOKEN: { status: StatusCodes.FORBIDDEN, isSuccess: false, code: "LOGINMIDDLEWARES003", message: "유효하지 않은 토큰입니다." }, + // refreshToken err + REFRESH_TOKEN_NOT_PROVIDED: { status: StatusCodes.UNAUTHORIZED, isSuccess: false, code: "REFRESHTOKEN001", message: "refresh 토큰이 제공되지 않았습니다." }, + REFRESH_TOKEN_INVALID: { status: StatusCodes.PAYMENT_REQUIRED, isSuccess: false, code: "REFRESHTOKEN002", message: "유효하지 않은 refresh 토큰입니다." }, }; \ No newline at end of file diff --git a/src/domains/login/login.controller.js b/src/domains/login/login.controller.js index 8f329d5..bcbe2d5 100644 --- a/src/domains/login/login.controller.js +++ b/src/domains/login/login.controller.js @@ -8,7 +8,7 @@ export async function LoginLogic(req, res) { const { user_id, password } = req.body; if (!user_id || !password) { - return res.send(response(status.EMPTY_DATA)); + return res.send(response(status.LOGIN_EMPTY_DATA)); } const LoginData = LoginDTO(user_id, password); diff --git a/src/domains/refreshToken/refreshToken.controller.js b/src/domains/refreshToken/refreshToken.controller.js new file mode 100644 index 0000000..3938fda --- /dev/null +++ b/src/domains/refreshToken/refreshToken.controller.js @@ -0,0 +1,25 @@ +import { response } from "../../config/response.js"; +import { status } from "../../config/response.status.js"; +import { refreshTokenService } from "./refreshToken.service.js"; + +export async function refreshTokenLogic(req, res) { + try { + const token = req.cookies.refreshToken; + if (!token) { + return res.send(response(status.REFRESH_TOKEN_NOT_PROVIDED)); + } + const result = await refreshTokenService(token); + + if (!result.success) { + return res.send(response(status.REFRESH_TOKEN_INVALID)); + } + + res.cookie('accessToken', result.accessToken, { httpOnly: true, secure: false }); + res.cookie('refreshToken', result.refreshToken, { httpOnly: true, secure: false }); + + return res.send(response(status.SUCCESS)); + } catch (err) { + console.error(err); + return res.send(response(status.INTERNAL_SERVER_ERROR)); + } +} diff --git a/src/domains/refreshToken/refreshToken.service.js b/src/domains/refreshToken/refreshToken.service.js new file mode 100644 index 0000000..f9d53dc --- /dev/null +++ b/src/domains/refreshToken/refreshToken.service.js @@ -0,0 +1,24 @@ +import jwt from 'jsonwebtoken'; + +export async function refreshTokenService(token) { + try { + const decoded = jwt.verify(token,process.env.JWT_SECRET_KEY); + + const accessToken = jwt.sign({ + uuid: decoded.uuid, + }, process.env.JWT_SECRET_KEY, { + expiresIn: '5m' + }); + + const refreshToken = jwt.sign({ + uuid: decoded.uuid, + }, process.env.JWT_SECRET_KEY, { + expiresIn: '1h' + }); + + return { success: true, accessToken, refreshToken }; + } catch (err) { + console.error(err); + return { success: false, message: '토큰 인증 오류' }; + } +} diff --git a/src/domains/signup/signup.controller.js b/src/domains/signup/signup.controller.js index 869f57e..9f060d4 100644 --- a/src/domains/signup/signup.controller.js +++ b/src/domains/signup/signup.controller.js @@ -7,7 +7,7 @@ export async function SignupLogic(req, res) { const { email, user_id, password } = req.body; if (!email || !user_id || !password) { - return res.send(response(status.EMPTY_DATA)); + return res.send(response(status.SIGNUP_EMPTY_DATA)); } const signupData = createSignupDTO(user_id, password, email); diff --git a/src/index.js b/src/index.js index 5fb0ba9..4039436 100644 --- a/src/index.js +++ b/src/index.js @@ -11,6 +11,7 @@ import { response } from './config/response.js'; import { signupRouter } from './routes/signup.js'; import { loginRouter } from './routes/login.js'; import { searchRouter } from './routes/search.js'; +import { refreshTokenRouter } from './routes/refreshToken.js'; import sizeUploadRoutes from './routes/uploadsize.routes.js'; dotenv.config(); @@ -40,6 +41,8 @@ app.use("/FITple/signup",signupRouter); app.use("/FITple/login",loginRouter); app.use('/FITple/search', searchRouter); app.use('/FITple/uploadsize', sizeUploadRoutes); +app.use("/FITple/refreshToken",refreshTokenRouter); + // error handling app.use((req, res, next) => { diff --git a/src/routes/refreshToken.js b/src/routes/refreshToken.js new file mode 100644 index 0000000..8526e26 --- /dev/null +++ b/src/routes/refreshToken.js @@ -0,0 +1,6 @@ +import express from 'express'; +import { refreshTokenLogic } from '../domains/refreshToken/refreshToken.controller.js'; + +export const refreshTokenRouter = express.Router(); + +refreshTokenRouter.get('/',refreshTokenLogic); \ No newline at end of file diff --git a/src/swagger/login.swagger.yaml b/src/swagger/login.swagger.yaml index 0307926..10e8351 100644 --- a/src/swagger/login.swagger.yaml +++ b/src/swagger/login.swagger.yaml @@ -32,8 +32,8 @@ paths: type: boolean example: true code: - type: string - example: 2000 + type: number + example: 200 message: type: string example: "success!" @@ -47,7 +47,7 @@ paths: example: false code: type: string - example: 400 + example: COMMON001 message: type: string example: 잘못된 요청입니다 @@ -61,7 +61,7 @@ paths: example: false code: type: string - example: 401 + example: LOGIN001 message: type: string example: 존재하지 않는 아이디입니다. @@ -75,7 +75,7 @@ paths: example: false code: type: string - example: 402 + example: LOGIN002 message: type: string example: 데이터가 비어있습니다. @@ -89,7 +89,7 @@ paths: example: false code: type: string - example: 403 + example: LOGIN003 message: type: string example: 비밀번호가 일치하지 않습니다. @@ -103,7 +103,7 @@ paths: example: false code: type: string - example: 500 + example: COMMON000 message: type: string example: 서버 에러, 관리자에게 문의 바랍니다. \ No newline at end of file diff --git a/src/swagger/refreshToken.swagger.yaml b/src/swagger/refreshToken.swagger.yaml new file mode 100644 index 0000000..f86e632 --- /dev/null +++ b/src/swagger/refreshToken.swagger.yaml @@ -0,0 +1,77 @@ +paths: + /FITple/refreshToken: + get: + tags: + - RefreshToken + summary: 토큰 재발급 + responses: + '200': + description: 토큰 재발급 성공! + schema: + type: object + properties: + isSuccess: + type: boolean + example: true + code: + type: number + example: 200 + message: + type: string + example: "success!" + '400': + description: 잘못된 요청 + schema: + type: object + properties: + isSuccess: + type: boolean + example: false + code: + type: string + example: COMMON001 + message: + type: string + example: 잘못된 요청입니다 + '401': + description: refresh 토큰이 존재하지 않음 + schema: + type: object + properties: + isSuccess: + type: boolean + example: false + code: + type: string + example: REFRESHTOKEN001 + message: + type: string + example: refresh 토큰이 존재하지 않았습니다. + '402': + description: 유효하지 않는 refresh 토큰 + schema: + type: object + properties: + isSuccess: + type: boolean + example: false + code: + type: string + example: REFRESHTOKEN002 + message: + type: string + example: 유효하지 않은 refresh 토큰입니다. + '500': + description: 서버 에러 + schema: + type: object + properties: + isSuccess: + type: boolean + example: false + code: + type: string + example: COMMON000 + message: + type: string + example: 서버 에러, 관리자에게 문의 바랍니다. diff --git a/src/swagger/signup.swagger.yaml b/src/swagger/signup.swagger.yaml index 4ee9290..d2043b8 100644 --- a/src/swagger/signup.swagger.yaml +++ b/src/swagger/signup.swagger.yaml @@ -37,8 +37,8 @@ paths: type: boolean example: true code: - type: string - example: 2000 + type: number + example: 200 message: type: string example: "success!" @@ -53,7 +53,7 @@ paths: example: false code: type: string - example: 400 + example: COMMON001 message: type: string example: 잘못된 요청입니다 @@ -67,7 +67,7 @@ paths: example: false code: type: string - example: 401 + example: SIGNUP001 message: type: string example: 이미 존재하는 아이디입니다. @@ -81,7 +81,7 @@ paths: example: false code: type: string - example: 402 + example: SIGNUP002 message: type: string example: 데이터가 비어있습니다. @@ -95,7 +95,7 @@ paths: example: false code: type: string - example: 403 + example: SIGNUP003 message: type: string example: 회원가입 중 오류 @@ -109,7 +109,7 @@ paths: example: false code: type: string - example: 500 + example: COMMON000 message: type: string example: 서버 에러, 관리자에게 문의 바랍니다. \ No newline at end of file