Files
whale-town-end/docs/api/api-documentation.md
moyin 85d488a508 docs: 重构文档结构和组织
- 重新组织docs目录结构,按功能模块分类
- 新增deployment和development目录
- 更新API文档结构
- 添加客户端README文档
- 移除过时的文档文件
2025-12-24 18:04:14 +08:00

50 KiB
Raw Blame History

Pixel Game Server API接口文档

概述

本文档描述了像素游戏服务器的完整API接口包括用户认证、管理员后台、应用状态等功能。

基础URL: http://localhost:3000
API文档地址: http://localhost:3000/api-docs
项目名称: Pixel Game Server
版本: 1.0.0

通用响应格式

所有API接口都遵循统一的响应格式

{
  "success": boolean,
  "data": object | null,
  "message": string,
  "error_code": string | null
}

字段说明

  • success: 请求是否成功
  • data: 响应数据(成功时返回)
  • message: 响应消息
  • error_code: 错误代码(失败时返回)

接口分类

1. 应用状态接口 (App)

  • GET / - 获取应用状态

2. 用户认证接口 (Auth)

  • POST /auth/login - 用户登录
  • POST /auth/register - 用户注册
  • POST /auth/github - GitHub OAuth登录
  • POST /auth/forgot-password - 发送密码重置验证码
  • POST /auth/reset-password - 重置密码
  • PUT /auth/change-password - 修改密码
  • POST /auth/send-email-verification - 发送邮箱验证码
  • POST /auth/verify-email - 验证邮箱验证码
  • POST /auth/resend-email-verification - 重新发送邮箱验证码
  • POST /auth/debug-verification-code - 调试验证码信息(开发环境)

3. 管理员接口 (Admin)

  • POST /admin/auth/login - 管理员登录
  • GET /admin/users - 获取用户列表
  • GET /admin/users/:id - 获取用户详情
  • POST /admin/users/:id/reset-password - 重置用户密码
  • GET /admin/logs/runtime - 获取运行日志
  • GET /admin/logs/archive - 下载日志压缩包

4. 用户管理接口 (User Management)

  • PUT /admin/users/:id/status - 修改用户状态
  • POST /admin/users/batch-status - 批量修改用户状态
  • GET /admin/users/status-stats - 获取用户状态统计

接口列表

应用状态接口

1. 获取应用状态

接口地址: GET /

功能描述: 返回应用的基本运行状态信息,用于健康检查和监控

请求参数

响应示例

成功响应 (200):

{
  "service": "Pixel Game Server",
  "version": "1.0.0",
  "status": "running",
  "timestamp": "2025-12-23T10:00:00.000Z",
  "uptime": 3600,
  "environment": "development",
  "storage_mode": "memory"
}
字段名 类型 说明
service string 服务名称
version string 服务版本
status string 运行状态 (running/starting/stopping/error)
timestamp string 当前时间戳
uptime number 运行时间(秒)
environment string 运行环境 (development/production/test)
storage_mode string 存储模式 (database/memory)

用户认证接口

1. 用户登录

接口地址: POST /auth/login

功能描述: 用户登录,支持用户名、邮箱或手机号登录

请求参数

{
  "identifier": "testuser",
  "password": "password123"
}
参数名 类型 必填 说明
identifier string 登录标识符,支持用户名、邮箱或手机号
password string 用户密码

响应示例

成功响应 (200):

{
  "success": true,
  "data": {
    "user": {
      "id": "1",
      "username": "testuser",
      "nickname": "测试用户",
      "email": "test@example.com",
      "phone": "+8613800138000",
      "avatar_url": "https://example.com/avatar.jpg",
      "role": 1,
      "created_at": "2025-12-17T10:00:00.000Z"
    },
    "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "is_new_user": false,
    "message": "登录成功"
  },
  "message": "登录成功"
}

失败响应 (401):

{
  "success": false,
  "message": "用户名或密码错误",
  "error_code": "LOGIN_FAILED"
}

2. 用户注册

接口地址: POST /auth/register

功能描述: 创建新用户账户

请求参数

{
  "username": "testuser",
  "password": "password123",
  "nickname": "测试用户",
  "email": "test@example.com",
  "phone": "+8613800138000"
}
参数名 类型 必填 说明
username string 用户名只能包含字母、数字和下划线长度1-50字符
password string 密码必须包含字母和数字长度8-128字符
nickname string 用户昵称长度1-50字符
email string 邮箱地址
phone string 手机号码

响应示例

成功响应 (201):

{
  "success": true,
  "data": {
    "user": {
      "id": "2",
      "username": "testuser",
      "nickname": "测试用户",
      "email": "test@example.com",
      "phone": "+8613800138000",
      "avatar_url": null,
      "role": 1,
      "created_at": "2025-12-17T10:00:00.000Z"
    },
    "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "is_new_user": true,
    "message": "注册成功"
  },
  "message": "注册成功"
}

失败响应 (409):

{
  "success": false,
  "message": "用户名已存在",
  "error_code": "REGISTER_FAILED"
}

3. GitHub OAuth登录

接口地址: POST /auth/github

功能描述: 使用GitHub账户登录或注册

请求参数

{
  "github_id": "12345678",
  "username": "octocat",
  "nickname": "The Octocat",
  "email": "octocat@github.com",
  "avatar_url": "https://github.com/images/error/octocat_happy.gif"
}
参数名 类型 必填 说明
github_id string GitHub用户ID
username string GitHub用户名
nickname string GitHub显示名称
email string GitHub邮箱地址
avatar_url string GitHub头像URL

响应示例

成功响应 (200):

{
  "success": true,
  "data": {
    "user": {
      "id": "3",
      "username": "octocat",
      "nickname": "The Octocat",
      "email": "octocat@github.com",
      "phone": null,
      "avatar_url": "https://github.com/images/error/octocat_happy.gif",
      "role": 1,
      "created_at": "2025-12-17T10:00:00.000Z"
    },
    "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "is_new_user": true,
    "message": "GitHub账户绑定成功"
  },
  "message": "GitHub账户绑定成功"
}

4. 发送密码重置验证码

接口地址: POST /auth/forgot-password

功能描述: 向用户邮箱或手机发送密码重置验证码

请求参数

{
  "identifier": "test@example.com"
}
参数名 类型 必填 说明
identifier string 邮箱或手机号

响应示例

成功响应 (200):

{
  "success": true,
  "data": {
    "verification_code": "123456"
  },
  "message": "验证码已发送,请查收"
}

注意: 实际应用中不应返回验证码,这里仅用于演示。

5. 重置密码

接口地址: POST /auth/reset-password

功能描述: 使用验证码重置用户密码

请求参数

{
  "identifier": "test@example.com",
  "verification_code": "123456",
  "new_password": "newpassword123"
}
参数名 类型 必填 说明
identifier string 邮箱或手机号
verification_code string 6位数字验证码
new_password string 新密码必须包含字母和数字长度8-128字符

响应示例

成功响应 (200):

{
  "success": true,
  "message": "密码重置成功"
}

6. 修改密码

接口地址: PUT /auth/change-password

功能描述: 用户修改自己的密码(需要提供旧密码)

请求参数

{
  "user_id": "1",
  "old_password": "oldpassword123",
  "new_password": "newpassword123"
}
参数名 类型 必填 说明
user_id string 用户ID实际应用中应从JWT令牌中获取
old_password string 当前密码
new_password string 新密码必须包含字母和数字长度8-128字符

响应示例

成功响应 (200):

{
  "success": true,
  "message": "密码修改成功"
}

7. 发送邮箱验证码

接口地址: POST /auth/send-email-verification

功能描述: 向指定邮箱发送验证码,用于注册时的邮箱验证

请求参数

{
  "email": "test@example.com"
}
参数名 类型 必填 说明
email string 邮箱地址

响应示例

成功响应 (200):

{
  "success": true,
  "data": {
    "verification_code": "123456",
    "is_test_mode": false
  },
  "message": "验证码已发送,请查收"
}

测试模式响应 (206):

{
  "success": false,
  "data": {
    "verification_code": "059174",
    "is_test_mode": true
  },
  "message": "⚠️ 测试模式:验证码已生成但未真实发送。请在控制台查看验证码,或配置邮件服务以启用真实发送。",
  "error_code": "TEST_MODE_ONLY"
}

8. 验证邮箱验证码

接口地址: POST /auth/verify-email

功能描述: 使用验证码验证邮箱

请求参数

{
  "email": "test@example.com",
  "verification_code": "123456"
}
参数名 类型 必填 说明
email string 邮箱地址
verification_code string 6位数字验证码

响应示例

成功响应 (200):

{
  "success": true,
  "message": "邮箱验证成功"
}

9. 重新发送邮箱验证码

接口地址: POST /auth/resend-email-verification

功能描述: 重新向指定邮箱发送验证码

请求参数

{
  "email": "test@example.com"
}
参数名 类型 必填 说明
email string 邮箱地址

响应示例

成功响应 (200):

{
  "success": true,
  "data": {
    "verification_code": "123456",
    "is_test_mode": false
  },
  "message": "验证码已重新发送,请查收"
}

10. 调试验证码信息

接口地址: POST /auth/debug-verification-code

功能描述: 获取验证码的详细调试信息(仅开发环境使用)

请求参数

{
  "email": "test@example.com"
}
参数名 类型 必填 说明
email string 邮箱地址

响应示例

成功响应 (200):

{
  "success": true,
  "data": {
    "email": "test@example.com",
    "verification_code": "123456",
    "expires_at": "2025-12-23T10:15:00.000Z",
    "created_at": "2025-12-23T10:00:00.000Z"
  },
  "message": "调试信息获取成功"
}

管理员接口

注意:所有管理员接口都需要在 Header 中携带 Authorization: Bearer <token>,且用户角色必须为管理员 (role=9)。

1. 管理员登录

接口地址: POST /admin/auth/login

功能描述: 管理员登录,仅允许 role=9 的账户登录后台

请求参数

{
  "identifier": "admin",
  "password": "Admin123456"
}
参数名 类型 必填 说明
identifier string 登录标识符(用户名/邮箱/手机号)
password string 密码

响应示例

成功响应 (200):

{
  "success": true,
  "data": {
    "admin": {
      "id": "1",
      "username": "admin",
      "nickname": "管理员",
      "role": 9
    },
    "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "expires_at": 1766102400000
  },
  "message": "管理员登录成功"
}

2. 获取用户列表

接口地址: GET /admin/users

功能描述: 分页获取所有注册用户列表

请求参数

参数名 类型 必填 说明
limit number 每页数量默认100
offset number 偏移量默认0

响应示例

成功响应 (200):

{
  "success": true,
  "data": {
    "users": [
      {
        "id": "1",
        "username": "user1",
        "nickname": "小明",
        "email": "user1@example.com",
        "email_verified": false,
        "phone": "+8613800138000",
        "avatar_url": "https://example.com/avatar.png",
        "role": 1,
        "created_at": "2025-12-19T00:00:00.000Z",
        "updated_at": "2025-12-19T00:00:00.000Z"
      }
    ],
    "limit": 100,
    "offset": 0
  },
  "message": "用户列表获取成功"
}

3. 获取用户详情

接口地址: GET /admin/users/:id

功能描述: 获取指定用户的详细信息

请求参数

参数名 类型 必填 说明
id string 用户ID路径参数

响应示例

成功响应 (200):

{
  "success": true,
  "data": {
    "user": {
      "id": "1",
      "username": "user1",
      "nickname": "小明",
      "email": "user1@example.com",
      "email_verified": false,
      "phone": "+8613800138000",
      "avatar_url": "https://example.com/avatar.png",
      "role": 1,
      "created_at": "2025-12-19T00:00:00.000Z",
      "updated_at": "2025-12-19T00:00:00.000Z"
    }
  },
  "message": "用户信息获取成功"
}

4. 重置用户密码

接口地址: POST /admin/users/:id/reset-password

功能描述: 管理员强制重置指定用户的密码

请求参数

参数名 类型 必填 说明
id string 用户ID路径参数
new_password string 新密码至少8位包含字母和数字
{
  "new_password": "NewPass1234"
}

响应示例

成功响应 (200):

{
  "success": true,
  "message": "密码重置成功"
}

5. 获取运行日志

接口地址: GET /admin/logs/runtime

功能描述: 从 logs/ 目录读取最近的日志行

请求参数

参数名 类型 必填 说明
lines number 返回行数默认200最大2000

响应示例

成功响应 (200):

{
  "success": true,
  "data": {
    "file": "dev.log",
    "updated_at": "2025-12-19T19:10:15.000Z",
    "lines": [
      "[2025-12-19 19:10:15] INFO: Server started",
      "[2025-12-19 19:10:16] INFO: Database connected"
    ]
  },
  "message": "运行日志获取成功"
}

6. 下载日志压缩包

接口地址: GET /admin/logs/archive

功能描述: 将 logs/ 目录打包为 tar.gz 并下载

请求参数

响应示例

成功响应 (200):

  • Content-Type: application/gzip
  • Content-Disposition: attachment; filename="logs-2025-12-23T10-00-00-000Z.tar.gz"
  • 返回二进制流tar.gz 文件)

用户管理接口

注意:所有用户管理接口都需要管理员权限,需要在 Header 中携带 Authorization: Bearer <token>

1. 修改用户状态

接口地址: PUT /admin/users/:id/status

功能描述: 管理员修改指定用户的账户状态,支持激活、锁定、禁用等操作

请求参数

参数名 类型 必填 说明
id string 用户ID路径参数
status string 用户状态枚举值
reason string 修改原因
{
  "status": "locked",
  "reason": "用户违反社区规定"
}

用户状态枚举值:

  • active - 正常状态,可以正常使用
  • inactive - 未激活,需要邮箱验证
  • locked - 已锁定,临时禁用
  • banned - 已禁用,管理员操作
  • deleted - 已删除,软删除状态
  • pending - 待审核,需要管理员审核

响应示例

成功响应 (200):

{
  "success": true,
  "data": {
    "user": {
      "id": "1",
      "username": "testuser",
      "nickname": "测试用户",
      "status": "locked",
      "status_description": "已锁定",
      "updated_at": "2025-12-24T10:00:00.000Z"
    },
    "reason": "用户违反社区规定"
  },
  "message": "用户状态修改成功"
}

2. 批量修改用户状态

接口地址: POST /admin/users/batch-status

功能描述: 管理员批量修改多个用户的账户状态

请求参数

{
  "user_ids": ["1", "2", "3"],
  "status": "locked",
  "reason": "批量处理违规用户"
}
参数名 类型 必填 说明
user_ids array 用户ID列表1-100个
status string 用户状态枚举值
reason string 批量修改原因

响应示例

成功响应 (200):

{
  "success": true,
  "data": {
    "result": {
      "success_users": [
        {
          "id": "1",
          "username": "user1",
          "nickname": "用户1",
          "status": "locked",
          "status_description": "已锁定",
          "updated_at": "2025-12-24T10:00:00.000Z"
        }
      ],
      "failed_users": [
        {
          "user_id": "999",
          "error": "用户不存在"
        }
      ],
      "success_count": 1,
      "failed_count": 1,
      "total_count": 2
    },
    "reason": "批量处理违规用户"
  },
  "message": "批量用户状态修改完成成功1失败1"
}

3. 获取用户状态统计

接口地址: GET /admin/users/status-stats

功能描述: 获取各种用户状态的数量统计信息

请求参数

响应示例

成功响应 (200):

{
  "success": true,
  "data": {
    "stats": {
      "active": 1250,
      "inactive": 45,
      "locked": 12,
      "banned": 8,
      "deleted": 3,
      "pending": 15,
      "total": 1333
    },
    "timestamp": "2025-12-24T10:00:00.000Z"
  },
  "message": "用户状态统计获取成功"
}

## 测试指南和边界条件

### 🧪 **前端测试建议**

为了确保前端应用的稳定性,建议对以下场景进行全面测试:

#### **1. 用户认证测试**

##### **注册功能测试**
```javascript
// 正常注册流程
const testNormalRegister = async () => {
  // 1. 发送邮箱验证码
  const codeResponse = await sendEmailVerification('test@example.com');
  
  // 2. 使用验证码注册
  const registerResponse = await register({
    username: 'testuser123',
    password: 'Test123456',
    nickname: '测试用户',
    email: 'test@example.com',
    email_verification_code: codeResponse.data.verification_code
  });
  
  expect(registerResponse.success).toBe(true);
  expect(registerResponse.data.user.username).toBe('testuser123');
  expect(registerResponse.data.access_token).toBeDefined();
};

// 边界条件测试
const testRegisterEdgeCases = async () => {
  // 密码强度测试
  await expectError(register({
    username: 'test',
    password: '123',  // 太短
    nickname: '测试'
  }), 'REGISTER_FAILED');
  
  // 用户名重复测试
  await expectError(register({
    username: 'existinguser',  // 已存在
    password: 'Test123456',
    nickname: '测试'
  }), 'REGISTER_FAILED');
  
  // 邮箱验证码错误测试
  await expectError(register({
    username: 'newuser',
    password: 'Test123456',
    nickname: '测试',
    email: 'test@example.com',
    email_verification_code: '000000'  // 错误验证码
  }), 'REGISTER_FAILED');
};
登录功能测试
// 多种登录方式测试
const testLoginMethods = async () => {
  // 用户名登录
  await testLogin('testuser', 'password123');
  
  // 邮箱登录
  await testLogin('test@example.com', 'password123');
  
  // 手机号登录(如果支持)
  await testLogin('+8613800138000', 'password123');
};

// 登录失败场景测试
const testLoginFailures = async () => {
  // 用户不存在
  await expectError(login('nonexistent', 'password'), 'LOGIN_FAILED');
  
  // 密码错误
  await expectError(login('testuser', 'wrongpassword'), 'LOGIN_FAILED');
  
  // 账户被锁定
  await expectError(login('lockeduser', 'password'), 'LOGIN_FAILED');
};

2. 验证码功能测试

验证码生成和验证
// 验证码频率限制测试
const testVerificationRateLimit = async () => {
  const email = 'test@example.com';
  
  // 第一次发送 - 应该成功
  const response1 = await sendEmailVerification(email);
  expect(response1.success).toBe(true);
  
  // 立即再次发送 - 应该被限制
  await expectError(
    sendEmailVerification(email), 
    'TOO_MANY_REQUESTS',
    429
  );
  
  // 等待冷却时间后再次发送
  await sleep(60000); // 等待1分钟
  const response2 = await sendEmailVerification(email);
  expect(response2.success).toBe(true);
};

// 验证码尝试次数限制测试
const testVerificationAttempts = async () => {
  const email = 'test@example.com';
  const response = await sendEmailVerification(email);
  const correctCode = response.data.verification_code;
  
  // 错误尝试3次
  for (let i = 0; i < 3; i++) {
    await expectError(
      verifyEmail(email, '000000'), 
      'VERIFICATION_FAILED'
    );
  }
  
  // 第4次尝试即使验证码正确也应该失败
  await expectError(
    verifyEmail(email, correctCode), 
    'VERIFICATION_FAILED'
  );
};

3. 管理员功能测试

权限验证测试
// 管理员登录测试
const testAdminLogin = async () => {
  // 正确的管理员凭据
  const response = await adminLogin('admin', 'Admin123456');
  expect(response.success).toBe(true);
  expect(response.data.admin.role).toBe(9);
  
  // 普通用户尝试管理员登录
  await expectError(
    adminLogin('normaluser', 'password'), 
    'ADMIN_LOGIN_FAILED',
    403
  );
};

// 管理员操作权限测试
const testAdminOperations = async () => {
  const adminToken = await getAdminToken();
  
  // 有效token的操作
  const users = await getUserList(adminToken);
  expect(users.success).toBe(true);
  
  // 无效token的操作
  await expectError(
    getUserList('invalid_token'), 
    'UNAUTHORIZED',
    401
  );
  
  // 普通用户token的操作
  const userToken = await getUserToken();
  await expectError(
    getUserList(userToken), 
    'FORBIDDEN',
    403
  );
};

4. 用户状态管理测试

状态变更测试
// 用户状态修改测试
const testUserStatusUpdate = async () => {
  const adminToken = await getAdminToken();
  const userId = '1';
  
  // 锁定用户
  const lockResponse = await updateUserStatus(adminToken, userId, {
    status: 'locked',
    reason: '违反社区规定'
  });
  expect(lockResponse.success).toBe(true);
  expect(lockResponse.data.user.status).toBe('locked');
  
  // 被锁定用户尝试登录
  await expectError(
    login('lockeduser', 'password'), 
    'LOGIN_FAILED',
    403
  );
  
  // 恢复用户状态
  await updateUserStatus(adminToken, userId, {
    status: 'active',
    reason: '恢复正常'
  });
};

// 批量状态修改测试
const testBatchStatusUpdate = async () => {
  const adminToken = await getAdminToken();
  
  const response = await batchUpdateUserStatus(adminToken, {
    user_ids: ['1', '2', '999'], // 包含不存在的用户ID
    status: 'locked',
    reason: '批量处理'
  });
  
  expect(response.success).toBe(true);
  expect(response.data.result.success_count).toBe(2);
  expect(response.data.result.failed_count).toBe(1);
  expect(response.data.result.failed_users[0].user_id).toBe('999');
};

5. 安全功能测试

频率限制测试
// 登录频率限制测试
const testLoginRateLimit = async () => {
  // 快速连续登录尝试
  for (let i = 0; i < 3; i++) {
    try {
      await login('testuser', 'wrongpassword');
    } catch (error) {
      if (error.status === 429) {
        expect(error.message).toContain('Too Many Requests');
        break;
      }
    }
  }
};

// 维护模式测试
const testMaintenanceMode = async () => {
  // 模拟维护模式开启
  // 所有请求都应该返回503
  await expectError(
    getAppStatus(), 
    'SERVICE_UNAVAILABLE',
    503
  );
};

6. 错误处理测试

网络错误处理
// 超时处理测试
const testTimeout = async () => {
  // 模拟长时间操作
  await expectError(
    slowOperation(), 
    'REQUEST_TIMEOUT',
    408
  );
};

// 内容类型验证测试
const testContentType = async () => {
  // 错误的Content-Type
  await expectError(
    fetch('/auth/login', {
      method: 'POST',
      headers: { 'Content-Type': 'text/plain' },
      body: 'invalid data'
    }),
    'UNSUPPORTED_MEDIA_TYPE',
    415
  );
};

📋 测试检查清单

功能测试

  • 用户注册(正常流程)
  • 用户注册(邮箱验证流程)
  • 用户登录(用户名/邮箱/手机号)
  • GitHub OAuth登录
  • 密码重置流程
  • 密码修改功能
  • 邮箱验证码发送和验证
  • 管理员登录
  • 用户列表查询
  • 用户详情查询
  • 用户密码重置(管理员)
  • 用户状态管理
  • 批量用户状态修改
  • 用户状态统计
  • 运行日志查询
  • 日志文件下载

边界条件测试

  • 密码强度验证(太短、太简单)
  • 用户名格式验证(特殊字符、长度)
  • 邮箱格式验证
  • 验证码格式验证非6位数字
  • 用户名重复检查
  • 邮箱重复检查
  • 不存在用户的操作
  • 无效验证码验证
  • 过期验证码验证
  • 验证码尝试次数限制

安全测试

  • 频率限制(登录、发送验证码)
  • 权限验证(管理员接口)
  • Token有效性验证
  • 用户状态检查(锁定、禁用用户登录)
  • 维护模式功能
  • 内容类型验证
  • 请求超时处理

错误处理测试

  • 网络连接错误
  • 服务器内部错误500
  • 请求超时408
  • 频率限制429
  • 权限不足403
  • 资源不存在404
  • 参数验证错误400
  • 维护模式503

🔧 测试工具推荐

API测试工具

  • Postman: 手动API测试和文档
  • Insomnia: 轻量级API客户端
  • curl: 命令行测试
  • HTTPie: 用户友好的命令行工具

自动化测试框架

  • Jest: JavaScript测试框架
  • Cypress: 端到端测试
  • Playwright: 现代Web测试
  • Supertest: Node.js HTTP测试

测试脚本示例

项目提供了现成的测试脚本:

  • test-api.ps1 - Windows PowerShell测试脚本
  • test-api.sh - Linux/macOS Bash测试脚本

运行测试脚本:

# Windows
.\test-api.ps1

# Linux/macOS
./test-api.sh

# 自定义参数
.\test-api.ps1 -BaseUrl "http://localhost:3000" -TestEmail "custom@example.com"

📊 测试数据管理

测试环境配置

  • 内存模式: 数据重启后清空,适合快速测试
  • 数据库模式: 数据持久化,适合完整功能测试
  • 测试模式: 邮件不真实发送,验证码在响应中返回

测试数据清理

// 清理测试数据
const cleanupTestData = async () => {
  // 删除测试用户
  await deleteTestUsers();
  
  // 清理Redis验证码
  await clearVerificationCodes();
  
  // 重置计数器
  await resetRateLimitCounters();
};

⚠️ 测试注意事项

  1. 频率限制: 测试时注意API频率限制避免被限制
  2. 测试隔离: 每个测试用例使用独立的测试数据
  3. 异步操作: 注意验证码生成和验证的时序
  4. 错误恢复: 测试失败后要清理测试数据
  5. 环境差异: 开发、测试、生产环境的配置差异
  6. 数据一致性: 并发测试时注意数据竞争条件

🚀 性能测试建议

负载测试场景

  • 并发用户注册
  • 高频验证码发送
  • 大量用户同时登录
  • 管理员批量操作
  • 日志文件下载

性能指标

  • 响应时间 < 2秒正常操作
  • 吞吐量 > 100 req/s
  • 错误率 < 1%
  • 内存使用稳定
  • CPU使用率 < 80%

通用错误代码

错误代码 HTTP状态码 说明 触发条件
LOGIN_FAILED 401 登录失败 用户名不存在、密码错误、账户被锁定
REGISTER_FAILED 400/409 注册失败 用户名已存在、密码强度不足、验证码错误
GITHUB_OAUTH_FAILED 401 GitHub OAuth失败 GitHub认证信息无效
SEND_CODE_FAILED 400 发送验证码失败 邮箱格式错误、发送服务异常
RESET_PASSWORD_FAILED 400 重置密码失败 验证码无效、密码强度不足
CHANGE_PASSWORD_FAILED 400 修改密码失败 旧密码错误、新密码强度不足
TEST_MODE_ONLY 206 测试模式 邮件服务未配置,验证码未真实发送

管理员相关错误代码

错误代码 HTTP状态码 说明 触发条件
ADMIN_LOGIN_FAILED 401/403 管理员登录失败 非管理员用户、凭据错误
ADMIN_USERS_FAILED 500 获取用户列表失败 数据库查询异常
ADMIN_OPERATION_FAILED 400/500 管理员操作失败 参数错误、系统异常

用户状态相关错误代码

错误代码 HTTP状态码 说明 触发条件
USER_STATUS_UPDATE_FAILED 400/404 用户状态修改失败 用户不存在、状态值无效
BATCH_USER_STATUS_UPDATE_FAILED 400 批量用户状态修改失败 用户ID列表为空、状态值无效
USER_STATUS_STATS_FAILED 500 用户状态统计失败 数据库查询异常

安全相关错误代码

错误代码 HTTP状态码 说明 触发条件
SERVICE_UNAVAILABLE 503 系统维护中 维护模式开启
TOO_MANY_REQUESTS 429 请求过于频繁 触发频率限制
REQUEST_TIMEOUT 408 请求超时 操作执行时间过长
UNSUPPORTED_MEDIA_TYPE 415 不支持的媒体类型 Content-Type不正确
UNAUTHORIZED 401 未授权 Token无效或过期
FORBIDDEN 403 权限不足 非管理员访问管理员接口

验证码相关错误代码

错误代码 HTTP状态码 说明 触发条件
VERIFICATION_CODE_EXPIRED 400 验证码已过期 验证码超过有效期5分钟
VERIFICATION_CODE_INVALID 400 验证码无效 验证码格式错误或不存在
VERIFICATION_CODE_ATTEMPTS_EXCEEDED 400 验证码尝试次数过多 错误尝试超过3次
VERIFICATION_CODE_RATE_LIMITED 429 验证码发送频率限制 1分钟内重复发送
VERIFICATION_CODE_HOURLY_LIMIT 429 验证码每小时限制 1小时内发送超过5次

详细错误响应格式

标准错误响应

{
  "success": false,
  "message": "具体错误描述",
  "error_code": "ERROR_CODE",
  "timestamp": "2025-12-24T10:00:00.000Z"
}

验证错误响应

{
  "success": false,
  "message": "参数验证失败",
  "error_code": "VALIDATION_FAILED",
  "errors": [
    {
      "field": "password",
      "message": "密码长度至少8位"
    },
    {
      "field": "email",
      "message": "邮箱格式不正确"
    }
  ]
}

频率限制错误响应

{
  "success": false,
  "message": "请求过于频繁,请稍后再试",
  "error_code": "TOO_MANY_REQUESTS",
  "retry_after": 60,
  "limit_info": {
    "limit": 5,
    "remaining": 0,
    "reset_time": "2025-12-24T10:01:00.000Z"
  }
}

维护模式错误响应

{
  "success": false,
  "message": "系统正在维护中,请稍后再试",
  "error_code": "SERVICE_UNAVAILABLE",
  "maintenance_info": {
    "start_time": "2025-12-24T10:00:00.000Z",
    "estimated_end_time": "2025-12-24T12:00:00.000Z",
    "retry_after": 1800,
    "reason": "系统升级维护"
  }
}

数据验证规则

用户名规则

  • 长度1-50字符
  • 格式:只能包含字母、数字和下划线
  • 正则表达式:^[a-zA-Z0-9_]+$

密码规则

  • 长度8-128字符
  • 格式:必须包含字母和数字
  • 正则表达式:^(?=.*[a-zA-Z])(?=.*\d)

验证码规则

  • 长度6位数字
  • 正则表达式:^\d{6}$
  • 有效期通常为5-15分钟

邮箱规则

  • 格式:符合标准邮箱格式
  • 验证:支持邮箱验证码验证

管理员权限

  • 角色role=9 为管理员
  • 认证:需要 JWT Token
  • 权限:可管理所有用户数据

使用示例

JavaScript/TypeScript 示例

// 获取应用状态
const statusResponse = await fetch('http://localhost:3000/');
const statusData = await statusResponse.json();
console.log('服务状态:', statusData.status);

// 用户登录
const loginResponse = await fetch('http://localhost:3000/auth/login', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    identifier: 'testuser',
    password: 'password123'
  })
});

const loginData = await loginResponse.json();
if (loginData.success) {
  const token = loginData.data.access_token;
  // 保存token用于后续请求
  localStorage.setItem('token', token);
}

// 用户注册(带邮箱验证)
// 1. 先发送邮箱验证码
const sendCodeResponse = await fetch('http://localhost:3000/auth/send-email-verification', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    email: 'newuser@example.com'
  })
});

// 2. 用户输入验证码后进行注册
const registerResponse = await fetch('http://localhost:3000/auth/register', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    username: 'newuser',
    password: 'password123',
    nickname: '新用户',
    email: 'newuser@example.com',
    email_verification_code: '123456'
  })
});

// 管理员登录
const adminLoginResponse = await fetch('http://localhost:3000/admin/auth/login', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    identifier: 'admin',
    password: 'Admin123456'
  })
});

const adminData = await adminLoginResponse.json();
if (adminData.success) {
  const adminToken = adminData.data.access_token;
  
  // 获取用户列表
  const usersResponse = await fetch('http://localhost:3000/admin/users?limit=10&offset=0', {
    headers: {
      'Authorization': `Bearer ${adminToken}`
    }
  });
  
  const usersData = await usersResponse.json();
  console.log('用户列表:', usersData.data.users);
}

cURL 示例

# 获取应用状态
curl -X GET http://localhost:3000/

# 用户登录
curl -X POST http://localhost:3000/auth/login \
  -H "Content-Type: application/json" \
  -d '{
    "identifier": "testuser",
    "password": "password123"
  }'

# 发送邮箱验证码
curl -X POST http://localhost:3000/auth/send-email-verification \
  -H "Content-Type: application/json" \
  -d '{
    "email": "newuser@example.com"
  }'

# 用户注册
curl -X POST http://localhost:3000/auth/register \
  -H "Content-Type: application/json" \
  -d '{
    "username": "newuser",
    "password": "password123",
    "nickname": "新用户",
    "email": "newuser@example.com",
    "email_verification_code": "123456"
  }'

# 管理员登录
curl -X POST http://localhost:3000/admin/auth/login \
  -H "Content-Type: application/json" \
  -d '{
    "identifier": "admin",
    "password": "Admin123456"
  }'

# 获取用户列表需要管理员Token
curl -X GET "http://localhost:3000/admin/users?limit=10&offset=0" \
  -H "Authorization: Bearer YOUR_ADMIN_TOKEN"

# 重置用户密码
curl -X POST http://localhost:3000/admin/users/1/reset-password \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_ADMIN_TOKEN" \
  -d '{
    "new_password": "NewPass1234"
  }'

# 获取运行日志
curl -X GET "http://localhost:3000/admin/logs/runtime?lines=100" \
  -H "Authorization: Bearer YOUR_ADMIN_TOKEN"

# 下载日志压缩包
curl -X GET http://localhost:3000/admin/logs/archive \
  -H "Authorization: Bearer YOUR_ADMIN_TOKEN" \
  -o logs.tar.gz

安全特性

1. 频率限制 (Rate Limiting)

系统实现了基于IP地址的频率限制防止恶意攻击和滥用

限制策略

接口类型 限制规则 时间窗口 说明
登录接口 2次/分钟 60秒 防止暴力破解
管理员操作 10次/分钟 60秒 限制管理员操作频率
一般接口 100次/分钟 60秒 防止接口滥用

响应示例

当触发频率限制时,返回 429 Too Many Requests

{
  "statusCode": 429,
  "message": "ThrottlerException: Too Many Requests",
  "error": "Too Many Requests"
}

2. 维护模式 (Maintenance Mode)

系统支持维护模式,在系统升级或维护期间暂停服务:

启用方式

设置环境变量:

MAINTENANCE_MODE=true
MAINTENANCE_START_TIME=2025-12-24T10:00:00.000Z
MAINTENANCE_END_TIME=2025-12-24T12:00:00.000Z
MAINTENANCE_REASON=系统升级维护
MAINTENANCE_RETRY_AFTER=1800

响应示例

维护模式下所有请求返回 503 Service Unavailable

{
  "success": false,
  "message": "系统正在维护中,请稍后再试",
  "error_code": "SERVICE_UNAVAILABLE",
  "maintenance_info": {
    "start_time": "2025-12-24T10:00:00.000Z",
    "estimated_end_time": "2025-12-24T12:00:00.000Z",
    "retry_after": 1800,
    "reason": "系统升级维护"
  }
}

3. 内容类型验证 (Content Type Validation)

系统验证POST/PUT请求的Content-Type头

支持的内容类型

  • application/json - JSON数据
  • application/x-www-form-urlencoded - 表单数据
  • multipart/form-data - 文件上传

响应示例

不支持的内容类型返回 415 Unsupported Media Type

{
  "statusCode": 415,
  "message": "不支持的媒体类型",
  "error": "Unsupported Media Type"
}

4. 请求超时控制 (Request Timeout)

系统为不同类型的操作设置了超时限制:

超时配置

操作类型 超时时间 说明
普通操作 30秒 一般API请求
数据库查询 60秒 复杂查询操作
慢操作 120秒 批量处理等耗时操作

响应示例

请求超时返回 408 Request Timeout

{
  "statusCode": 408,
  "message": "请求超时",
  "error": "Request Timeout"
}

5. 用户状态管理 (User Status Management)

系统支持细粒度的用户状态控制:

用户状态枚举

状态值 状态名称 说明
active 正常 用户可以正常使用所有功能
inactive 未激活 新注册用户,需要邮箱验证
locked 锁定 临时锁定,可以解锁
banned 禁用 永久禁用,需要管理员处理
deleted 删除 软删除状态,数据保留
pending 待审核 需要管理员审核激活

状态检查

登录时系统会检查用户状态:

  • active: 正常登录
  • inactive: 提示需要邮箱验证
  • locked: 返回账户锁定错误
  • banned: 返回账户禁用错误
  • deleted: 返回账户不存在错误
  • pending: 返回账户待审核错误

6. 安全最佳实践

JWT Token 安全

  • Token 有效期8小时
  • 使用 HS256 算法签名
  • 包含用户ID、角色等关键信息
  • 建议在客户端安全存储

密码安全

  • 使用 bcrypt 加密存储
  • 支持密码强度验证
  • 不在日志中记录明文密码
  • 支持密码重置功能

API 安全

  • 所有管理员接口需要身份验证
  • 支持跨域资源共享 (CORS)
  • 实现请求日志记录
  • 敏感信息自动脱敏

注意事项

  1. 安全性: 实际应用中应使用HTTPS协议
  2. 令牌: 示例中的access_token是JWT格式需要妥善保存
  3. 验证码:
    • 实际应用中不应在响应中返回验证码
    • 测试模式下会在控制台显示验证码
    • 验证码有效期通常为5-15分钟
  4. 用户ID: 修改密码接口中的user_id应从JWT令牌中获取而不是从请求体中传递
  5. 错误处理: 建议在客户端实现适当的错误处理和用户提示
  6. 限流: 建议对登录、注册等接口实施限流策略
  7. 管理员权限:
    • 管理员接口需要 role=9 的用户权限
    • 需要在请求头中携带有效的JWT Token
    • Token格式Authorization: Bearer <token>
  8. 存储模式:
    • 数据库模式数据持久化存储在MySQL
    • 内存模式:数据存储在内存中,重启后丢失
  9. 邮箱验证:
    • 注册时如果提供邮箱,需要先获取验证码
    • 支持重新发送验证码功能
    • 调试接口仅用于开发环境

常见测试场景

🔍 前端开发者必测场景

1. 用户注册完整流程

// 场景:新用户完整注册流程
const testCompleteRegistration = async () => {
  const email = 'newuser@example.com';
  
  // Step 1: 发送邮箱验证码
  const codeResponse = await fetch('/auth/send-email-verification', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ email })
  });
  
  expect(codeResponse.status).toBe(206); // 测试模式
  const codeData = await codeResponse.json();
  expect(codeData.success).toBe(false);
  expect(codeData.error_code).toBe('TEST_MODE_ONLY');
  
  // Step 2: 使用验证码注册
  const registerResponse = await fetch('/auth/register', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      username: 'newuser123',
      password: 'SecurePass123',
      nickname: '新用户',
      email: email,
      email_verification_code: codeData.data.verification_code
    })
  });
  
  expect(registerResponse.status).toBe(201);
  const registerData = await registerResponse.json();
  expect(registerData.success).toBe(true);
  expect(registerData.data.access_token).toBeDefined();
};

2. 登录失败处理

// 场景:各种登录失败情况
const testLoginFailures = async () => {
  // 用户不存在
  const response1 = await fetch('/auth/login', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      identifier: 'nonexistent',
      password: 'password123'
    })
  });
  
  expect(response1.status).toBe(200); // 业务错误返回200
  const data1 = await response1.json();
  expect(data1.success).toBe(false);
  expect(data1.error_code).toBe('LOGIN_FAILED');
  
  // 密码错误
  const response2 = await fetch('/auth/login', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      identifier: 'existinguser',
      password: 'wrongpassword'
    })
  });
  
  expect(response2.status).toBe(200);
  const data2 = await response2.json();
  expect(data2.success).toBe(false);
  expect(data2.error_code).toBe('LOGIN_FAILED');
};

3. 频率限制测试

// 场景:验证码发送频率限制
const testRateLimit = async () => {
  const email = 'test@example.com';
  
  // 第一次发送 - 成功
  const response1 = await fetch('/auth/send-email-verification', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ email })
  });
  expect(response1.status).toBe(206); // 测试模式
  
  // 立即再次发送 - 被限制
  const response2 = await fetch('/auth/send-email-verification', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ email })
  });
  expect(response2.status).toBe(429);
  
  const data2 = await response2.json();
  expect(data2.message).toContain('请等待');
};

4. 管理员权限测试

// 场景:管理员权限验证
const testAdminPermissions = async () => {
  // 普通用户尝试访问管理员接口
  const userToken = 'user_token_here';
  
  const response = await fetch('/admin/users', {
    headers: { 'Authorization': `Bearer ${userToken}` }
  });
  
  expect(response.status).toBe(403);
  
  // 无效token访问
  const response2 = await fetch('/admin/users', {
    headers: { 'Authorization': 'Bearer invalid_token' }
  });
  
  expect(response2.status).toBe(401);
  
  // 正确的管理员token
  const adminToken = await getAdminToken();
  const response3 = await fetch('/admin/users', {
    headers: { 'Authorization': `Bearer ${adminToken}` }
  });
  
  expect(response3.status).toBe(200);
};

5. 用户状态影响登录

// 场景:不同用户状态的登录测试
const testUserStatusLogin = async () => {
  // 正常用户登录
  const activeResponse = await login('activeuser', 'password');
  expect(activeResponse.success).toBe(true);
  
  // 锁定用户登录
  const lockedResponse = await login('lockeduser', 'password');
  expect(lockedResponse.success).toBe(false);
  expect(lockedResponse.message).toContain('锁定');
  
  // 禁用用户登录
  const bannedResponse = await login('banneduser', 'password');
  expect(bannedResponse.success).toBe(false);
  expect(bannedResponse.message).toContain('禁用');
};

📝 边界条件测试清单

输入验证测试

  • 空字符串输入
  • 超长字符串输入(用户名>50字符
  • 特殊字符输入SQL注入尝试
  • 无效邮箱格式
  • 弱密码少于8位、纯数字、纯字母
  • 无效验证码格式非6位数字

状态边界测试

  • 验证码过期边界5分钟
  • 验证码尝试次数边界3次
  • 频率限制边界1分钟、1小时
  • Token过期边界8小时
  • 用户状态变更后的立即登录

并发测试

  • 同时发送多个验证码请求
  • 同时使用相同验证码验证
  • 并发用户注册相同用户名
  • 并发管理员操作同一用户

🚨 错误恢复测试

网络异常处理

// 场景:网络中断恢复
const testNetworkRecovery = async () => {
  // 模拟网络中断
  mockNetworkError();
  
  try {
    await login('testuser', 'password');
    fail('应该抛出网络错误');
  } catch (error) {
    expect(error.message).toContain('网络');
  }
  
  // 恢复网络
  restoreNetwork();
  
  // 重试应该成功
  const response = await login('testuser', 'password');
  expect(response.success).toBe(true);
};

服务降级测试

// 场景:邮件服务不可用时的降级
const testEmailServiceDegradation = async () => {
  // 邮件服务不可用时,应该返回测试模式
  const response = await fetch('/auth/send-email-verification', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ email: 'test@example.com' })
  });
  
  expect(response.status).toBe(206);
  const data = await response.json();
  expect(data.error_code).toBe('TEST_MODE_ONLY');
  expect(data.data.is_test_mode).toBe(true);
};

🔧 自动化测试脚本

快速冒烟测试

#!/bin/bash
# 快速验证所有关键接口

BASE_URL="http://localhost:3000"

echo "🚀 开始API冒烟测试..."

# 1. 应用状态检查
echo "1. 检查应用状态..."
curl -f "$BASE_URL/" > /dev/null || exit 1

# 2. 验证码发送
echo "2. 测试验证码发送..."
RESPONSE=$(curl -s -X POST "$BASE_URL/auth/send-email-verification" \
  -H "Content-Type: application/json" \
  -d '{"email":"test@example.com"}')

CODE=$(echo "$RESPONSE" | jq -r '.data.verification_code')
if [ "$CODE" = "null" ]; then
  echo "❌ 验证码发送失败"
  exit 1
fi

# 3. 用户注册
echo "3. 测试用户注册..."
USERNAME="smoketest_$(date +%s)"
curl -f -X POST "$BASE_URL/auth/register" \
  -H "Content-Type: application/json" \
  -d "{\"username\":\"$USERNAME\",\"password\":\"Test123456\",\"nickname\":\"冒烟测试\",\"email\":\"test@example.com\",\"email_verification_code\":\"$CODE\"}" > /dev/null || exit 1

# 4. 用户登录
echo "4. 测试用户登录..."
curl -f -X POST "$BASE_URL/auth/login" \
  -H "Content-Type: application/json" \
  -d "{\"identifier\":\"$USERNAME\",\"password\":\"Test123456\"}" > /dev/null || exit 1

echo "✅ 冒烟测试通过!"

性能基准测试

#!/bin/bash
# 简单的性能基准测试

echo "📊 开始性能基准测试..."

# 并发登录测试
echo "测试并发登录性能..."
ab -n 100 -c 10 -T 'application/json' -p login_data.json http://localhost:3000/auth/login

# 验证码发送性能测试
echo "测试验证码发送性能..."
ab -n 50 -c 5 -T 'application/json' -p email_data.json http://localhost:3000/auth/send-email-verification

echo "📈 性能测试完成,请查看上述结果"

💡 测试技巧和建议

1. 测试数据管理

  • 使用时间戳生成唯一的测试用户名
  • 测试完成后清理测试数据
  • 使用专门的测试邮箱域名

2. 异步操作处理

  • 验证码生成后立即使用,避免过期
  • 注意频率限制的时间窗口
  • 使用适当的等待时间

3. 错误场景覆盖

  • 测试所有可能的HTTP状态码
  • 验证错误消息的准确性
  • 测试错误恢复机制

4. 安全测试

  • 尝试SQL注入和XSS攻击
  • 测试权限绕过
  • 验证敏感信息不泄露

这些测试场景和边界条件将帮助前端开发者进行全面的API测试确保应用的稳定性和安全性。

  • v1.0.0 (2025-12-24):
    • 完整的API文档更新
      • 重新整理接口分类,将用户管理接口独立分类
      • 确保文档与实际运行的服务完全一致
      • 验证所有接口的请求参数和响应格式
    • 应用状态接口 (1个)
      • GET / - 获取应用状态
    • 用户认证接口 (10个)
      • 用户登录、注册、GitHub OAuth
      • 密码重置和修改功能
      • 邮箱验证相关接口
      • 调试验证码接口
    • 管理员接口 (6个)
      • 管理员登录和用户管理
      • 用户列表和详情查询
      • 密码重置功能
      • 日志管理和下载
    • 用户管理接口 (3个)
      • 用户状态管理 (active/inactive/locked/banned/deleted/pending)
      • 单个用户状态修改接口
      • 批量用户状态修改接口
      • 用户状态统计接口
    • 安全增强功能
      • 频率限制中间件 (Rate Limiting)
      • 维护模式中间件 (Maintenance Mode)
      • 内容类型验证中间件 (Content Type Validation)
      • 请求超时拦截器 (Request Timeout)
      • 用户状态检查和权限控制
    • 总计接口数量: 20个API接口
    • 完善错误代码和使用示例
    • 修复路由冲突问题
    • 确保文档与实际测试效果一致