admin-portal §2.3 P1 阻塞项补齐:CreateUser/UpdateUser/DeleteUser 3 RPC iam.repository/service/grpc.controller 实现 3 用户管理方法(含 bcrypt + 审计) iam.controller 新增 POST /v1/iam/users + DELETE /v1/iam/users/:id(@RequirePermission(IAM_USER_MANAGE)) iam.dto 新增 createUserSchema Zod 校验 F12 httpOnly Cookie:refresh_token 改为 httpOnly+Secure+SameSite=Strict Cookie 下发 extractRefreshToken 优先读 cookie 回退 body + buildRefreshTokenCookie/buildClearCookie
61 lines
1.7 KiB
TypeScript
61 lines
1.7 KiB
TypeScript
import { z } from "zod";
|
||
|
||
const envSchema = z.object({
|
||
// HTTP
|
||
PORT: z.string().default("3002"),
|
||
|
||
// Database
|
||
DATABASE_URL: z.string().url(),
|
||
|
||
// Redis(缓存 + token 黑名单)
|
||
REDIS_URL: z.string().url(),
|
||
|
||
// JWT RS256(president §2.15:本地文件密钥)
|
||
IAM_PRIVATE_KEY_PATH: z.string(),
|
||
IAM_PUBLIC_KEY_PATH: z.string(),
|
||
JWT_ISSUER: z.string().default("next-edu-cloud"),
|
||
JWT_AUDIENCE: z.string().default("next-edu-cloud"),
|
||
JWT_KEY_ID: z.string().default("iam-rs256-v1"),
|
||
ACCESS_TOKEN_TTL: z.string().default("15m"),
|
||
REFRESH_TOKEN_TTL_DAYS: z.string().default("7"),
|
||
|
||
// Cookie(F12 裁决:refresh_token httpOnly cookie 模式)
|
||
COOKIE_SECURE: z
|
||
.string()
|
||
.default("auto")
|
||
.transform((v) => (v === "auto" ? undefined : v === "true")),
|
||
COOKIE_DOMAIN: z.string().optional(),
|
||
|
||
// Kafka(Outbox 投递)
|
||
KAFKA_BROKERS: z.string(),
|
||
KAFKA_CLIENT_ID: z.string().default("iam-service"),
|
||
|
||
// gRPC server(I1 裁决:端口 50052)
|
||
GRPC_PORT: z.string().default("50052"),
|
||
|
||
// 可观测性
|
||
OTEL_EXPORTER_OTLP_ENDPOINT: z.string().url().optional(),
|
||
LOG_LEVEL: z
|
||
.enum(["fatal", "error", "warn", "info", "debug", "trace"])
|
||
.default("info"),
|
||
NODE_ENV: z
|
||
.enum(["development", "production", "test"])
|
||
.default("development"),
|
||
});
|
||
|
||
export type Env = z.infer<typeof envSchema>;
|
||
|
||
export function loadEnv(): Env {
|
||
const result = envSchema.safeParse(process.env);
|
||
if (!result.success) {
|
||
console.error(
|
||
"❌ Invalid environment variables:",
|
||
result.error.flatten().fieldErrors,
|
||
);
|
||
throw new Error("Invalid environment configuration");
|
||
}
|
||
return result.data;
|
||
}
|
||
|
||
export const env = loadEnv();
|