Files
whale-town-end/docs/api/api-documentation.md
moyin d59e9531e2 fix(docs): 修正API文档中的错误码和验证码说明
- 修正验证码登录错误码:VERIFICATION_CODE_INVALID -> VERIFICATION_CODE_LOGIN_FAILED
- 修正发送登录验证码错误码:USER_NOT_FOUND -> SEND_LOGIN_CODE_FAILED
- 添加验证码登录相关错误码到错误码表格
- 完善验证码使用说明和注意事项
- 确保文档与实际API响应完全一致
2025-12-25 16:04:34 +08:00

2329 lines
58 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Pixel Game Server API接口文档
## 概述
本文档描述了像素游戏服务器的完整API接口包括用户认证、管理员后台、应用状态等功能。
**基础URL**: `http://localhost:3000`
**API文档地址**: `http://localhost:3000/api-docs`
**项目名称**: Pixel Game Server
**版本**: 1.0.0
## 通用响应格式
所有API接口都遵循统一的响应格式
```json
{
"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/verification-code-login` - 验证码登录
- `POST /auth/send-login-verification-code` - 发送登录验证码
- `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` - 调试验证码信息(开发环境)
- `POST /auth/debug-clear-throttle` - 清除限流记录(开发环境)
### 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):
```json
{
"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`
**功能描述**: 用户登录,支持用户名、邮箱或手机号登录
#### 请求参数
```json
{
"identifier": "testuser",
"password": "password123"
}
```
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| identifier | string | 是 | 登录标识符,支持用户名、邮箱或手机号 |
| password | string | 是 | 用户密码 |
#### 响应示例
**成功响应** (200):
```json
{
"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):
```json
{
"success": false,
"message": "用户名或密码错误",
"error_code": "LOGIN_FAILED"
}
```
#### 1.1 验证码登录
**接口地址**: `POST /auth/verification-code-login`
**功能描述**: 使用邮箱或手机号和验证码进行登录,无需密码
#### 请求参数
```json
{
"identifier": "test@example.com",
"verification_code": "123456"
}
```
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| identifier | string | 是 | 登录标识符(邮箱或手机号) |
| verification_code | string | 是 | 6位数字验证码 |
#### 响应示例
**成功响应** (200):
```json
{
"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):
```json
{
"success": false,
"message": "验证码错误或已过期",
"error_code": "VERIFICATION_CODE_LOGIN_FAILED"
}
```
**可能的错误码**:
- `VERIFICATION_CODE_LOGIN_FAILED`: 验证码错误或已过期
- `USER_NOT_FOUND`: 用户不存在
- `EMAIL_NOT_VERIFIED`: 邮箱未验证(邮箱登录时)
- `INVALID_IDENTIFIER`: 无效的邮箱或手机号格式
#### 1.2 发送登录验证码
**接口地址**: `POST /auth/send-login-verification-code`
**功能描述**: 向用户邮箱或手机发送登录验证码
#### 请求参数
```json
{
"identifier": "test@example.com"
}
```
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| identifier | string | 是 | 邮箱或手机号 |
#### 响应示例
**成功响应** (200):
```json
{
"success": true,
"message": "验证码发送成功",
"data": {
"sent_to": "test@example.com",
"expires_in": 300
}
}
```
**测试模式响应** (206):
```json
{
"success": false,
"message": "测试模式:验证码已生成但未真实发送",
"error_code": "TEST_MODE_ONLY",
"data": {
"verification_code": "123456",
"sent_to": "test@example.com",
"expires_in": 300,
"is_test_mode": true
}
}
```
**失败响应** (404):
```json
{
"success": false,
"message": "用户不存在",
"error_code": "SEND_LOGIN_CODE_FAILED"
}
```
#### 2. 用户注册
**接口地址**: `POST /auth/register`
**功能描述**: 创建新用户账户
**重要说明**
- 如果提供邮箱,必须先调用发送验证码接口获取验证码
- 注册时会按以下顺序进行检查:
1. 首先检查用户名是否已存在
2. 检查邮箱是否已存在(如果提供)
3. 检查手机号是否已存在(如果提供)
4. 最后验证邮箱验证码(如果提供邮箱)
- 这样确保验证码不会因为用户已存在而被无效消费
- 注册成功返回201失败返回400
#### 请求参数
```json
{
"username": "testuser",
"password": "password123",
"nickname": "测试用户",
"email": "test@example.com",
"email_verification_code": "123456"
}
```
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| username | string | 是 | 用户名只能包含字母、数字和下划线长度1-50字符 |
| password | string | 是 | 密码必须包含字母和数字长度8-128字符 |
| nickname | string | 是 | 用户昵称长度1-50字符 |
| email | string | 否 | 邮箱地址(如果提供,必须先获取验证码) |
| phone | string | 否 | 手机号码 |
| email_verification_code | string | 条件必填 | 邮箱验证码,提供邮箱时必填 |
#### 响应示例
**成功响应** (201):
```json
{
"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": "注册成功"
}
```
**失败响应** (400):
**用户名已存在**:
```json
{
"success": false,
"message": "用户名已存在",
"error_code": "REGISTER_FAILED"
}
```
**邮箱已存在**:
```json
{
"success": false,
"message": "邮箱已存在",
"error_code": "REGISTER_FAILED"
}
```
**手机号已存在**:
```json
{
"success": false,
"message": "手机号已存在",
"error_code": "REGISTER_FAILED"
}
```
**邮箱验证码相关错误**:
```json
{
"success": false,
"message": "提供邮箱时必须提供邮箱验证码",
"error_code": "REGISTER_FAILED"
}
```
**频率限制响应** (429):
```json
{
"success": false,
"message": "注册请求过于频繁请5分钟后再试",
"error_code": "TOO_MANY_REQUESTS",
"throttle_info": {
"limit": 10,
"window_seconds": 300,
"current_requests": 10,
"reset_time": "2025-12-24T11:26:41.136Z"
}
}
```
#### 3. GitHub OAuth登录
**接口地址**: `POST /auth/github`
**功能描述**: 使用GitHub账户登录或注册
#### 请求参数
```json
{
"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):
```json
{
"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`
**功能描述**: 向用户邮箱或手机发送密码重置验证码
#### 请求参数
```json
{
"identifier": "test@example.com"
}
```
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| identifier | string | 是 | 邮箱或手机号 |
#### 响应示例
**成功响应** (200):
```json
{
"success": true,
"data": {
"verification_code": "123456"
},
"message": "验证码已发送,请查收"
}
```
**注意**: 实际应用中不应返回验证码,这里仅用于演示。
#### 5. 重置密码
**接口地址**: `POST /auth/reset-password`
**功能描述**: 使用验证码重置用户密码
#### 请求参数
```json
{
"identifier": "test@example.com",
"verification_code": "123456",
"new_password": "newpassword123"
}
```
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| identifier | string | 是 | 邮箱或手机号 |
| verification_code | string | 是 | 6位数字验证码 |
| new_password | string | 是 | 新密码必须包含字母和数字长度8-128字符 |
#### 响应示例
**成功响应** (200):
```json
{
"success": true,
"message": "密码重置成功"
}
```
#### 6. 修改密码
**接口地址**: `PUT /auth/change-password`
**功能描述**: 用户修改自己的密码(需要提供旧密码)
#### 请求参数
```json
{
"user_id": "1",
"old_password": "oldpassword123",
"new_password": "newpassword123"
}
```
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| user_id | string | 是 | 用户ID实际应用中应从JWT令牌中获取 |
| old_password | string | 是 | 当前密码 |
| new_password | string | 是 | 新密码必须包含字母和数字长度8-128字符 |
#### 响应示例
**成功响应** (200):
```json
{
"success": true,
"message": "密码修改成功"
}
```
#### 7. 发送邮箱验证码
**接口地址**: `POST /auth/send-email-verification`
**功能描述**: 向指定邮箱发送验证码,用于注册时的邮箱验证
#### 请求参数
```json
{
"email": "test@example.com"
}
```
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| email | string | 是 | 邮箱地址 |
#### 响应示例
**成功响应** (200):
```json
{
"success": true,
"data": {
"verification_code": "123456",
"is_test_mode": false
},
"message": "验证码已发送,请查收"
}
```
**测试模式响应** (206):
```json
{
"success": false,
"data": {
"verification_code": "059174",
"is_test_mode": true
},
"message": "⚠️ 测试模式:验证码已生成但未真实发送。请在控制台查看验证码,或配置邮件服务以启用真实发送。",
"error_code": "TEST_MODE_ONLY"
}
```
#### 8. 验证邮箱验证码
**接口地址**: `POST /auth/verify-email`
**功能描述**: 使用验证码验证邮箱
#### 请求参数
```json
{
"email": "test@example.com",
"verification_code": "123456"
}
```
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| email | string | 是 | 邮箱地址 |
| verification_code | string | 是 | 6位数字验证码 |
#### 响应示例
**成功响应** (200):
```json
{
"success": true,
"message": "邮箱验证成功"
}
```
#### 9. 重新发送邮箱验证码
**接口地址**: `POST /auth/resend-email-verification`
**功能描述**: 重新向指定邮箱发送验证码
#### 请求参数
```json
{
"email": "test@example.com"
}
```
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| email | string | 是 | 邮箱地址 |
#### 响应示例
**成功响应** (200):
```json
{
"success": true,
"data": {
"verification_code": "123456",
"is_test_mode": false
},
"message": "验证码已重新发送,请查收"
}
```
#### 10. 调试验证码信息
**接口地址**: `POST /auth/debug-verification-code`
**功能描述**: 获取验证码的详细调试信息(仅开发环境使用)
#### 请求参数
```json
{
"email": "test@example.com"
}
```
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| email | string | 是 | 邮箱地址 |
#### 响应示例
**成功响应** (200):
```json
{
"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": "调试信息获取成功"
}
```
#### 11. 清除限流记录
**接口地址**: `POST /auth/debug-clear-throttle`
**功能描述**: 清除所有限流记录(仅开发环境使用)
**注意**: 此接口用于开发测试清除所有IP的频率限制记录
#### 请求参数
#### 响应示例
**成功响应** (200):
```json
{
"success": true,
"message": "限流记录已清除"
}
```
### 管理员接口
**注意**:所有管理员接口都需要在 Header 中携带 `Authorization: Bearer <token>`,且用户角色必须为管理员 (role=9)。
#### 1. 管理员登录
**接口地址**: `POST /admin/auth/login`
**功能描述**: 管理员登录,仅允许 role=9 的账户登录后台
#### 请求参数
```json
{
"identifier": "admin",
"password": "Admin123456"
}
```
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| identifier | string | 是 | 登录标识符(用户名/邮箱/手机号) |
| password | string | 是 | 密码 |
#### 响应示例
**成功响应** (200):
```json
{
"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):
```json
{
"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):
```json
{
"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位包含字母和数字 |
```json
{
"new_password": "NewPass1234"
}
```
#### 响应示例
**成功响应** (200):
```json
{
"success": true,
"message": "密码重置成功"
}
```
#### 5. 获取运行日志
**接口地址**: `GET /admin/logs/runtime`
**功能描述**: 从 logs/ 目录读取最近的日志行
#### 请求参数
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| lines | number | 否 | 返回行数默认200最大2000 |
#### 响应示例
**成功响应** (200):
```json
{
"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 | 否 | 修改原因 |
```json
{
"status": "locked",
"reason": "用户违反社区规定"
}
```
**用户状态枚举值:**
- `active` - 正常状态,可以正常使用
- `inactive` - 未激活,需要邮箱验证
- `locked` - 已锁定,临时禁用
- `banned` - 已禁用,管理员操作
- `deleted` - 已删除,软删除状态
- `pending` - 待审核,需要管理员审核
#### 响应示例
**成功响应** (200):
```json
{
"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`
**功能描述**: 管理员批量修改多个用户的账户状态
#### 请求参数
```json
{
"user_ids": ["1", "2", "3"],
"status": "locked",
"reason": "批量处理违规用户"
}
```
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| user_ids | array | 是 | 用户ID列表1-100个 |
| status | string | 是 | 用户状态枚举值 |
| reason | string | 否 | 批量修改原因 |
#### 响应示例
**成功响应** (200):
```json
{
"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):
```json
{
"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');
};
```
##### **登录功能测试**
```javascript
// 多种登录方式测试
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. 验证码功能测试**
##### **验证码生成和验证**
```javascript
// 验证码频率限制测试
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. 管理员功能测试**
##### **权限验证测试**
```javascript
// 管理员登录测试
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. 用户状态管理测试**
##### **状态变更测试**
```javascript
// 用户状态修改测试
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. 安全功能测试**
##### **频率限制测试**
```javascript
// 登录频率限制测试
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. 错误处理测试**
##### **网络错误处理**
```javascript
// 超时处理测试
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测试脚本
运行测试脚本:
```bash
# Windows
.\test-api.ps1
# Linux/macOS
./test-api.sh
# 自定义参数
.\test-api.ps1 -BaseUrl "http://localhost:3000" -TestEmail "custom@example.com"
```
### 📊 **测试数据管理**
#### **测试环境配置**
- **内存模式**: 数据重启后清空,适合快速测试
- **数据库模式**: 数据持久化,适合完整功能测试
- **测试模式**: 邮件不真实发送,验证码在响应中返回
#### **测试数据清理**
```javascript
// 清理测试数据
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_LOGIN_FAILED | 401 | 验证码登录失败 | 验证码错误、已过期或用户邮箱未验证 |
| SEND_LOGIN_CODE_FAILED | 400/404 | 发送登录验证码失败 | 用户不存在或发送服务异常 |
| VERIFICATION_CODE_ATTEMPTS_EXCEEDED | 400 | 验证码尝试次数过多 | 错误尝试超过3次 |
| VERIFICATION_CODE_RATE_LIMITED | 429 | 验证码发送频率限制 | 1分钟内重复发送 |
| VERIFICATION_CODE_HOURLY_LIMIT | 429 | 验证码每小时限制 | 1小时内发送超过5次 |
### **详细错误响应格式**
#### **标准错误响应**
```json
{
"success": false,
"message": "具体错误描述",
"error_code": "ERROR_CODE",
"timestamp": "2025-12-24T10:00:00.000Z"
}
```
#### **验证错误响应**
```json
{
"success": false,
"message": "参数验证失败",
"error_code": "VALIDATION_FAILED",
"errors": [
{
"field": "password",
"message": "密码长度至少8位"
},
{
"field": "email",
"message": "邮箱格式不正确"
}
]
}
```
#### **频率限制错误响应**
```json
{
"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"
}
}
```
#### **维护模式错误响应**
```json
{
"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 示例
```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 示例
```bash
# 获取应用状态
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-login-verification-code \
-H "Content-Type: application/json" \
-d '{
"identifier": "test@example.com"
}'
# 验证码登录
curl -X POST http://localhost:3000/auth/verification-code-login \
-H "Content-Type: application/json" \
-d '{
"identifier": "test@example.com",
"verification_code": "123456"
}'
# 发送邮箱验证码
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地址的频率限制防止恶意攻击和滥用
#### 限制策略
| 接口类型 | 限制规则 | 时间窗口 | 说明 |
|----------|----------|----------|------|
| 登录接口 | 5次/分钟 | 60秒 | 防止暴力破解 |
| 注册接口 | 10次/5分钟 | 300秒 | 防止批量注册(开发环境已放宽) |
| 发送验证码 | 1次/分钟 | 60秒 | 防止验证码滥发 |
| 密码重置 | 3次/小时 | 3600秒 | 限制密码重置频率 |
| 管理员操作 | 10次/分钟 | 60秒 | 限制管理员操作频率 |
| 一般接口 | 30次/分钟 | 60秒 | 通用API限制 | 100次/分钟 | 60秒 | 防止接口滥用 |
#### 响应示例
当触发频率限制时,返回 **429 Too Many Requests**
```json
{
"success": false,
"message": "注册请求过于频繁请5分钟后再试",
"error_code": "TOO_MANY_REQUESTS",
"throttle_info": {
"limit": 10,
"window_seconds": 300,
"current_requests": 10,
"reset_time": "2025-12-24T11:26:41.136Z"
}
}
```
**重要说明**
- 频率限制基于IP地址
- 超过限制后需要等待到重置时间才能再次请求
- 开发环境下注册接口限制已放宽至10次/5分钟
### 2. 维护模式 (Maintenance Mode)
系统支持维护模式,在系统升级或维护期间暂停服务:
#### 启用方式
设置环境变量:
```bash
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**
```json
{
"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**
```json
{
"statusCode": 415,
"message": "不支持的媒体类型",
"error": "Unsupported Media Type"
}
```
### 4. 请求超时控制 (Request Timeout)
系统为不同类型的操作设置了超时限制:
#### 超时配置
| 操作类型 | 超时时间 | 说明 |
|----------|----------|------|
| 普通操作 | 30秒 | 一般API请求 |
| 数据库查询 | 60秒 | 复杂查询操作 |
| 慢操作 | 120秒 | 批量处理等耗时操作 |
#### 响应示例
请求超时返回 **408 Request Timeout**
```json
{
"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分钟
- 验证码登录要求邮箱已验证email_verified=true
- 调试接口:`POST /auth/debug-verification-code` 可获取验证码详情
4. **用户ID**: 修改密码接口中的user_id应从JWT令牌中获取而不是从请求体中传递
5. **错误处理**: 建议在客户端实现适当的错误处理和用户提示
6. **限流**: 建议对登录、注册等接口实施限流策略
7. **管理员权限**:
- 管理员接口需要 role=9 的用户权限
- 需要在请求头中携带有效的JWT Token
- Token格式`Authorization: Bearer <token>`
8. **存储模式**:
- 数据库模式数据持久化存储在MySQL
- 内存模式:数据存储在内存中,重启后丢失
9. **邮箱验证**:
- 注册时如果提供邮箱,需要先获取验证码
- 支持重新发送验证码功能
- 调试接口仅用于开发环境
10. **验证码登录**:
- 验证码登录需要用户邮箱已验证
- 支持邮箱和手机号两种方式
- 验证码类型为 `login_verification`
- 与注册验证码是不同的验证码类型
## 常见测试场景
### 🔍 **前端开发者必测场景**
#### **1. 用户注册完整流程**
```javascript
// 场景:新用户完整注册流程
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. 验证码登录完整流程**
```javascript
// 场景:验证码登录完整流程
const testVerificationCodeLogin = async () => {
const email = 'test@example.com';
// Step 1: 发送登录验证码
const codeResponse = await fetch('/auth/send-login-verification-code', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ identifier: 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 loginResponse = await fetch('/auth/verification-code-login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
identifier: email,
verification_code: codeData.data.verification_code
})
});
expect(loginResponse.status).toBe(200);
const loginData = await loginResponse.json();
expect(loginData.success).toBe(true);
expect(loginData.data.access_token).toBeDefined();
};
```
#### **3. 登录失败处理**
```javascript
// 场景:各种登录失败情况
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');
};
```
#### **4. 频率限制测试**
```javascript
// 场景:验证码发送频率限制
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('请等待');
};
```
#### **5. 管理员权限测试**
```javascript
// 场景:管理员权限验证
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);
};
```
#### **6. 用户状态影响登录**
```javascript
// 场景:不同用户状态的登录测试
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小时
- [ ] 用户状态变更后的立即登录
#### **并发测试**
- [ ] 同时发送多个验证码请求
- [ ] 同时使用相同验证码验证
- [ ] 并发用户注册相同用户名
- [ ] 并发管理员操作同一用户
### 🚨 **错误恢复测试**
#### **网络异常处理**
```javascript
// 场景:网络中断恢复
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);
};
```
#### **服务降级测试**
```javascript
// 场景:邮件服务不可用时的降级
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);
};
```
### 🔧 **自动化测试脚本**
#### **快速冒烟测试**
```bash
#!/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 "✅ 冒烟测试通过!"
```
#### **性能基准测试**
```bash
#!/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文档更新**
- 重新整理接口分类,将用户管理接口独立分类
- 确保文档与实际运行的服务完全一致
- 验证所有接口的请求参数和响应格式
- **修复HTTP状态码问题**:所有接口现在根据业务结果返回正确状态码
- **更新限流配置**注册接口限制调整为10次/5分钟开发环境
- **应用状态接口** (1个)
- `GET /` - 获取应用状态
- **用户认证接口** (13个)
- 用户登录、注册、GitHub OAuth
- 密码重置和修改功能
- 邮箱验证相关接口
- 调试验证码接口
- **新增**:清除限流记录接口(开发环境)
- **管理员接口** (6个)
- 管理员登录和用户管理
- 用户列表和详情查询
- 密码重置功能
- 日志管理和下载
- **用户管理接口** (3个)
- 用户状态管理 (active/inactive/locked/banned/deleted/pending)
- 单个用户状态修改接口
- 批量用户状态修改接口
- 用户状态统计接口
- **安全增强功能**
- 频率限制中间件 (Rate Limiting) - 已调整配置
- 维护模式中间件 (Maintenance Mode)
- 内容类型验证中间件 (Content Type Validation)
- 请求超时拦截器 (Request Timeout)
- 用户状态检查和权限控制
- **修复**HTTP状态码现在正确反映业务执行结果
- **总计接口数量**: 23个API接口
- 完善错误代码和使用示例
- 修复路由冲突问题
- 确保文档与实际测试效果一致
- **重要修复**:解决了业务失败但返回成功状态码的问题