Commit ea537a02 by luoqi

refactor(cleanup): CORS 收口到 config + auth TTL memoize(审计 H12/A11/G6)

- main.ts CORS origins 改读 config.get('cors').origins(消除与 configuration.ts 的重复解析,
  同时救活原本无人读的 cors config 字段);行为不变
- auth.service: 4 处 parseDurationToSeconds(jwt.expiresIn) 收口为 memoized getter accessExpiresInSeconds

service tsc 通过。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
parent 4523c4ad
import 'reflect-metadata';
import { NestFactory } from '@nestjs/core';
import { Logger } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
import { apiReference } from '@scalar/nestjs-api-reference';
import { cleanupOpenApiDoc } from 'nestjs-zod';
......@@ -15,10 +16,7 @@ async function bootstrap() {
app.use(helmet({ contentSecurityPolicy: false }));
const corsOrigins = (process.env.CORS_ORIGINS ?? '')
.split(',')
.map((o) => o.trim())
.filter(Boolean);
const corsOrigins = app.get(ConfigService).getOrThrow<{ origins: string[] }>('cors').origins;
app.enableCors({
origin: corsOrigins.length > 0 ? corsOrigins : true,
credentials: false,
......
......@@ -58,6 +58,14 @@ export class AuthService {
private readonly config: ConfigService,
) {}
/** access token TTL(秒)— 进程内固定,memoize 一次(收口多处 parseDurationToSeconds) */
private _accessExpiresInSeconds?: number;
private get accessExpiresInSeconds(): number {
return (this._accessExpiresInSeconds ??= parseDurationToSeconds(
this.config.getOrThrow<string>('jwt.expiresIn'),
));
}
async exchangeToken(req: TokenExchangeRequest): Promise<TokenExchangeResponse> {
const host = await this.prisma.host.findUnique({ where: { appId: req.appId } });
if (!host || !host.active) {
......@@ -99,7 +107,7 @@ export class AuthService {
codeTtl,
);
const expiresIn = parseDurationToSeconds(this.config.getOrThrow<string>('jwt.expiresIn'));
const expiresIn = this.accessExpiresInSeconds;
return {
accessToken,
......@@ -114,7 +122,7 @@ export class AuthService {
const raw = await this.redis.getDel(CODE_PREFIX + code);
if (!raw) throw new BizError(ApiCode.AUTH_INVALID_CODE);
const parsed = JSON.parse(raw) as { accessToken: string; refreshToken: string };
const expiresIn = parseDurationToSeconds(this.config.getOrThrow<string>('jwt.expiresIn'));
const expiresIn = this.accessExpiresInSeconds;
return {
accessToken: parsed.accessToken,
refreshToken: parsed.refreshToken,
......@@ -173,7 +181,7 @@ export class AuthService {
dictionary: payload.dictionary,
});
const expiresIn = parseDurationToSeconds(this.config.getOrThrow<string>('jwt.expiresIn'));
const expiresIn = this.accessExpiresInSeconds;
return { accessToken, refreshToken: newRefreshToken, expiresIn };
}
......@@ -182,7 +190,7 @@ export class AuthService {
): Promise<string> {
return this.jwt.signAsync(payload, {
secret: this.config.getOrThrow<string>('jwt.secret'),
expiresIn: parseDurationToSeconds(this.config.getOrThrow<string>('jwt.expiresIn')),
expiresIn: this.accessExpiresInSeconds,
});
}
......@@ -313,7 +321,7 @@ export class AuthService {
role: req.role,
dictionary,
});
const expiresIn = parseDurationToSeconds(this.config.getOrThrow<string>('jwt.expiresIn'));
const expiresIn = this.accessExpiresInSeconds;
this.logger.log(
`mock-login: tenant=${req.tenant}(${preset.tenantNameZh}) role=${req.role} ` +
......
/// <reference types="next" />
/// <reference types="next/image-types/global" />
import "./.next/dev/types/routes.d.ts";
import "./.next/types/routes.d.ts";
// NOTE: This file should not be edited
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment