From 8e2e4b2156170d3899c5cecdc36abd673094b9fb Mon Sep 17 00:00:00 2001 From: likui628 <90845831+likui628@users.noreply.github.com> Date: Thu, 3 Oct 2024 22:11:10 +0800 Subject: [PATCH] Add responseMiddleware --- src/app.ts | 9 ++++++++- src/controllers/auth.ts | 23 ++++++++++++----------- src/index.ts | 18 ++++++++++++++++++ src/middlewares/index.ts | 1 + src/middlewares/response.ts | 26 ++++++++++++++++++++++++++ src/middlewares/verify-roles.ts | 10 ---------- src/types/index.ts | 6 +++++- tsconfig.json | 2 +- 8 files changed, 71 insertions(+), 24 deletions(-) create mode 100644 src/middlewares/response.ts diff --git a/src/app.ts b/src/app.ts index 40549c0..443a4df 100644 --- a/src/app.ts +++ b/src/app.ts @@ -6,7 +6,12 @@ import passport from 'passport' import cookieParser from 'cookie-parser' import routes from './routes/v1' -import { rateLimiter, errorHandler, notFound } from './middlewares' +import { + rateLimiter, + errorHandler, + notFound, + responseMiddleware, +} from './middlewares' import { jwtStrategy } from './config/passport' import morgan from './config/morgan' @@ -25,6 +30,8 @@ app.use(cors()) app.use(cookieParser()) app.use(express.json()) +app.use(responseMiddleware) + if (process.env.NODE_ENV === 'production') { app.use('/v1/auth', rateLimiter) app.use('/v1/users', rateLimiter) diff --git a/src/controllers/auth.ts b/src/controllers/auth.ts index 3c74ef6..94a125d 100644 --- a/src/controllers/auth.ts +++ b/src/controllers/auth.ts @@ -1,7 +1,8 @@ import { Request, Response } from 'express' -import { asyncHandler, errorResponse, successResponse } from '../utils' +import { asyncHandler } from '../utils' import { userService, authService, tokenService } from '../services' import { User } from '@prisma/client' +import { UserData } from '../types' async function handleTokens(user: User, res: Response) { const { token, refreshToken } = await tokenService.generateAuthTokens(user) @@ -18,7 +19,7 @@ export const register = asyncHandler(async (req: Request, res: Response) => { const user = await userService.createUser(req.body) const token = await handleTokens(user, res) - successResponse(res, { ...user, token }, 201) + res.jsonSuccess({ ...user, token }, 201) }) export const login = asyncHandler(async (req: Request, res: Response) => { @@ -26,13 +27,13 @@ export const login = asyncHandler(async (req: Request, res: Response) => { const user = await authService.loginUserWithEmailAndPassword(email, password) const token = await handleTokens(user, res) - successResponse(res, { ...user, token }, 200) + res.jsonSuccess({ ...user, token }, 200) }) export const logout = asyncHandler(async (req: Request, res: Response) => { const cookies = req.cookies if (!cookies?.refreshToken) { - return successResponse(res, null, 200) + res.jsonSuccess(undefined, 200) } const refreshToken = cookies.refreshToken as string @@ -42,7 +43,7 @@ export const logout = asyncHandler(async (req: Request, res: Response) => { httpOnly: true, secure: process.env.NODE_ENV === 'production', }) - return successResponse(res, null, 200) + res.jsonSuccess(undefined, 200) } await tokenService.deleteToken(refreshToken) @@ -50,13 +51,13 @@ export const logout = asyncHandler(async (req: Request, res: Response) => { httpOnly: true, secure: process.env.NODE_ENV === 'production', }) - return successResponse(res, null, 200) + res.jsonSuccess(undefined, 200) }) export const refresh = asyncHandler(async (req: Request, res: Response) => { const cookies = req.cookies if (!cookies?.refreshToken) { - return errorResponse(res, null, 401, 'Unauthorized') + res.jsonFail(401, 'Unauthorized') } const refreshToken = cookies.refreshToken as string res.clearCookie('refreshToken', { @@ -66,14 +67,14 @@ export const refresh = asyncHandler(async (req: Request, res: Response) => { const tokenInfo = await tokenService.verifyToken(refreshToken) if (!tokenInfo) { - return errorResponse(res, null, 401, 'Unauthorized') + res.jsonFail(401, 'Unauthorized') } const user = await userService.getUserById(tokenInfo.userId) if (!user) { - return errorResponse(res, null, 401, 'Unauthorized') + res.jsonFail(401, 'Unauthorized') } - const token = await handleTokens(user, res) - successResponse(res, { token }, 200) + const token = await handleTokens(user!, res) + res.jsonSuccess(token, 200) }) diff --git a/src/index.ts b/src/index.ts index b605343..58e832f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -6,3 +6,21 @@ const port = env.PORT || 5000 app.listen(port, () => { logger.info(`Listening to port ${port}`) }) + +import { Role, User } from '@prisma/client' + +declare module 'express-serve-static-core' { + interface CustomUser extends Express.User { + id?: User['id'] + username?: User['name'] + role?: Role + } + interface Request { + user?: CustomUser + } + + interface Response { + jsonSuccess: (data: T, statusCode?: number, message?: string) => void + jsonFail: (code: number, message?: string) => void + } +} diff --git a/src/middlewares/index.ts b/src/middlewares/index.ts index 34f8d31..18215bf 100644 --- a/src/middlewares/index.ts +++ b/src/middlewares/index.ts @@ -3,3 +3,4 @@ export * from './validate' export * from './verify-jwt' export * from './verify-roles' export * from './rate-limiter' +export * from './response' diff --git a/src/middlewares/response.ts b/src/middlewares/response.ts new file mode 100644 index 0000000..111da59 --- /dev/null +++ b/src/middlewares/response.ts @@ -0,0 +1,26 @@ +import { NextFunction, Request, Response } from 'express' + +export const responseMiddleware = ( + _req: Request, + res: Response, + next: NextFunction, +) => { + res.jsonSuccess = (data: T, code = 200, message = 'Success'): void => { + res.status(code) + res.json({ + code, + message, + data, + }) + } + + res.jsonFail = (code, message = 'Fail'): void => { + res.status(code) + res.json({ + code, + message, + }) + } + + next() +} diff --git a/src/middlewares/verify-roles.ts b/src/middlewares/verify-roles.ts index 4c0fe0e..a2eb187 100644 --- a/src/middlewares/verify-roles.ts +++ b/src/middlewares/verify-roles.ts @@ -1,17 +1,7 @@ import { NextFunction, Request, Response } from 'express' -import { Role } from '@prisma/client' import { errorResponse } from '../utils' import { roleRights } from '../config/roles' -declare global { - // eslint-disable-next-line @typescript-eslint/no-namespace - namespace Express { - interface User { - role?: Role - } - } -} - export const verifyRoles = (...requiredRights: string[]) => { return (req: Request, res: Response, next: NextFunction) => { if (requiredRights.length) { diff --git a/src/types/index.ts b/src/types/index.ts index c78026e..4ffcdd7 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -1,4 +1,4 @@ -import { Role } from '@prisma/client' +import { Role, User } from '@prisma/client' export interface Pagination { orderBy?: 'name' | 'email' | 'createdAt' | 'updatedAt' @@ -11,3 +11,7 @@ export interface QueryUsers extends Pagination { name?: string role?: Role } + +export interface UserData extends User { + token: string +} diff --git a/tsconfig.json b/tsconfig.json index a366541..7443906 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -13,6 +13,6 @@ "include": [ "./*.js", "src/**/*.ts", - "test/**/*.ts", + "test/**/*.ts" ], }