feat: 大部分注册登录功能

Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
2026-04-24 18:02:42 +08:00
parent 5ab74ad9dd
commit 5294528148
23 changed files with 858 additions and 167 deletions
+12 -20
View File
@@ -1,16 +1,18 @@
// server/api/auth/register.post.ts
import type { UserRegisterRequest, UserRegisterResult } from "#shared/types";
import type {
IUserRegisterData,
IUserRegisterRequest
} from "#shared/types";
import {
createUpstreamErrorResponse,
createErrorResponse,
createSuccessResponse,
createUpstreamErrorResponse,
newApiFetch
} from "../../utils";
} from "~~/server/utils";
/**
* 允许从请求体透传给上游的字段列表
* 只有在这里声明过的字段才会被转发,其余字段一律丢弃,防止参数污染
* 与 NewAPI 文档字段保持一致
* 允许从请求体透传给上游的字段列表
* 只有在这里声明过的字段才会被转发,其余字段一律丢弃,防止参数污染
*/
const REGISTER_FIELDS = [
"username",
@@ -18,30 +20,21 @@ const REGISTER_FIELDS = [
"email",
"verification_code",
"aff_code"
] as const satisfies ReadonlyArray<keyof UserRegisterRequest>;
] as const satisfies ReadonlyArray<keyof IUserRegisterRequest>;
/**
* POST /api/auth/register
*
* 注册流程:
* 1. 解析并校验前端传来的 JSON 请求体
* 2. 从请求体里只挑出文档允许的字段组装 payload
* 3. 通过 newApiFetch 转发到上游 NewAPI 注册接口
* 4. 将上游结果统一包装为 ApiResponse 格式返回给前端
*/
export default defineEventHandler(async (event) => {
// 读取并反序列化请求体;如果前端没有传 body,readBody 会返回 null
const requestBody = await readBody<Partial<UserRegisterRequest> | null>(
const requestBody = await readBody<Partial<IUserRegisterRequest> | null>(
event
);
// 防御性校验:请求体只能是 JSON 对象或空,不接受字符串/数字等原始值
if (requestBody !== null && typeof requestBody !== "object") {
return createErrorResponse(400, "请求体必须是 JSON 对象");
}
// 白名单过滤:只保留文档里声明的字段,且必须是字符串类型
const payload: UserRegisterRequest = {};
const payload: IUserRegisterRequest = {};
for (const field of REGISTER_FIELDS) {
const value = requestBody?.[field];
if (typeof value === "string") {
@@ -50,7 +43,7 @@ export default defineEventHandler(async (event) => {
}
try {
const result = await newApiFetch<UserRegisterResult>("/api/user/register", {
const result = await newApiFetch<IUserRegisterData>("/api/user/register", {
method: "POST",
body: payload,
headers: {
@@ -58,7 +51,6 @@ export default defineEventHandler(async (event) => {
}
});
// 上游成功
return createSuccessResponse(result, "注册成功");
} catch (error) {
return createUpstreamErrorResponse(error, "注册失败");