feat: migrate runtime backend to node server
This commit is contained in:
40
server-node/src/middleware/auth.ts
Normal file
40
server-node/src/middleware/auth.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
import type { NextFunction, Request, Response } from 'express';
|
||||
|
||||
import { verifyAccessToken } from '../auth/token.js';
|
||||
import type { AppConfig } from '../config.js';
|
||||
import { unauthorized } from '../errors.js';
|
||||
import { type UserRepository } from '../repositories/userRepository.js';
|
||||
|
||||
function readBearerToken(request: Request) {
|
||||
const authorization = request.header('authorization')?.trim() || '';
|
||||
if (!authorization.startsWith('Bearer ')) {
|
||||
return '';
|
||||
}
|
||||
return authorization.slice('Bearer '.length).trim();
|
||||
}
|
||||
|
||||
export function requireJwtAuth(config: AppConfig, userRepository: UserRepository) {
|
||||
return async (request: Request, _response: Response, next: NextFunction) => {
|
||||
try {
|
||||
const token = readBearerToken(request);
|
||||
if (!token) {
|
||||
throw unauthorized('缺少 Authorization Bearer Token');
|
||||
}
|
||||
|
||||
const claims = await verifyAccessToken(token, config);
|
||||
const user = userRepository.findById(claims.userId);
|
||||
if (!user) {
|
||||
throw unauthorized('用户不存在');
|
||||
}
|
||||
if (user.tokenVersion !== claims.tokenVersion) {
|
||||
throw unauthorized('登录状态已失效,请重新登录');
|
||||
}
|
||||
|
||||
request.auth = claims;
|
||||
request.userId = claims.userId;
|
||||
next();
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
};
|
||||
}
|
||||
27
server-node/src/middleware/errorHandler.ts
Normal file
27
server-node/src/middleware/errorHandler.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import type { ErrorRequestHandler } from 'express';
|
||||
|
||||
import { HttpError } from '../errors.js';
|
||||
|
||||
export const errorHandler: ErrorRequestHandler = (error, request, response, _next) => {
|
||||
const statusCode =
|
||||
error instanceof HttpError ? error.statusCode : 500;
|
||||
const message =
|
||||
error instanceof HttpError
|
||||
? error.message
|
||||
: '服务器内部错误';
|
||||
|
||||
request.log?.error(
|
||||
{
|
||||
err: error,
|
||||
request_id: request.requestId,
|
||||
user_id: request.userId ?? null,
|
||||
},
|
||||
'request failed',
|
||||
);
|
||||
|
||||
response.status(statusCode).json({
|
||||
error: {
|
||||
message,
|
||||
},
|
||||
});
|
||||
};
|
||||
8
server-node/src/middleware/requestId.ts
Normal file
8
server-node/src/middleware/requestId.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import crypto from 'node:crypto';
|
||||
|
||||
import type { RequestHandler } from 'express';
|
||||
|
||||
export const requestIdMiddleware: RequestHandler = (request, _response, next) => {
|
||||
request.requestId = request.header('x-request-id')?.trim() || crypto.randomUUID();
|
||||
next();
|
||||
};
|
||||
Reference in New Issue
Block a user