diff --git a/README.md b/README.md index ad8b357..a3e6753 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ ### 环境要求 - [Godot Engine 4.5+](https://godotengine.org/download) -- Python 3.7+ (用于API测试) +- Python 3.7+ (用于API测试和Web服务器) ### 运行项目 ```bash @@ -29,6 +29,19 @@ cd whale-town python tests/api/simple_api_test.py ``` +### Web版本部署 +```bash +# Windows用户 +scripts\build_web.bat # 导出Web版本 +scripts\serve_web.bat # 启动本地测试服务器 + +# Linux/macOS用户 +./scripts/build_web.sh # 导出Web版本 +./scripts/serve_web.sh # 启动本地测试服务器 +``` + +详细部署指南请查看: [Web部署完整指南](docs/web_deployment_guide.md) + ## 🏗️ 项目架构 ### 核心设计理念 @@ -52,6 +65,10 @@ whaleTown/ ├── 📝 scripts/ # 业务逻辑脚本 │ ├── scenes/ # 场景脚本 │ ├── network/ # 网络相关 +│ ├── build_web.bat # Windows Web导出脚本 +│ ├── build_web.sh # Linux/macOS Web导出脚本 +│ ├── serve_web.bat # Windows 本地服务器 +│ ├── serve_web.sh # Linux/macOS 本地服务器 │ └── ui/ # UI组件脚本 ├── 🧩 module/ # 可复用模块 │ ├── UI/ # UI组件模块 @@ -82,6 +99,8 @@ whaleTown/ └── 📚 docs/ # 项目文档 ├── auth/ # 认证相关文档 ├── api-documentation.md # API接口文档 + ├── web_deployment_guide.md # Web部署完整指南 + ├── web_deployment_changelog.md # Web部署更新日志 ├── project_structure.md # 项目结构说明 ├── naming_convention.md # 命名规范 ├── code_comment_guide.md # 代码注释规范 @@ -117,6 +136,13 @@ EventSystem.connect_event("player_died", _on_player_died) - **GitHub OAuth** - 第三方登录集成 - **错误处理** - 完整的错误提示和频率限制 +### 🌐 Web版本部署 +- **自动化导出** - 一键导出Web版本 +- **本地测试服务器** - 内置HTTP服务器用于测试 +- **生产环境配置** - 完整的服务器配置指南 +- **跨平台支持** - Windows、Linux、macOS全平台支持 +- **性能优化** - 资源压缩和加载优化 + ### 🎮 游戏功能 - **主场景** - 游戏主界面和菜单系统 - **认证场景** - 完整的登录注册界面 @@ -164,6 +190,7 @@ git commit -m "docs:更新项目文档" - 📝 [命名规范](docs/naming_convention.md) - 详细的命名规则 - 💬 [代码注释规范](docs/code_comment_guide.md) - 注释标准和AI辅助指南 - 🔀 [Git提交规范](docs/git_commit_guide.md) - 提交信息标准 +- 🌐 [Web部署指南](docs/web_deployment_guide.md) - 完整的Web部署文档 ### API和测试文档 - 🔌 [API接口文档](docs/api-documentation.md) - 完整的API说明和测试指南 diff --git a/docs/api-documentation.md b/docs/api-documentation.md index 3d9b792..7d09f9a 100644 --- a/docs/api-documentation.md +++ b/docs/api-documentation.md @@ -1,114 +1,92 @@ -# Pixel Game Server API接口文档 +# Pixel Game Server API 文档 -## 概述 +**版本**: 1.1.1 +**更新时间**: 2025-12-25 -本文档描述了像素游戏服务器的完整API接口,包括用户认证、管理员后台、应用状态等功能。 +## 🚨 后端对前端的提示与注意点 -**基础URL**: `http://localhost:3000` -**API文档地址**: `http://localhost:3000/api-docs` -**项目名称**: Pixel Game Server -**版本**: 1.0.0 +### 重要提醒 +1. **邮箱冲突检测**: 发送邮箱验证码前会检查邮箱是否已被注册,已注册邮箱返回409状态码 +2. **HTTP状态码**: 所有接口根据业务结果返回正确状态码(409冲突、400参数错误、401认证失败等) +3. **验证码有效期**: 所有验证码有效期为5分钟 +4. **频率限制**: 验证码发送限制1次/分钟,注册限制10次/5分钟 +5. **测试模式**: 开发环境下邮件服务返回206状态码,验证码在响应中返回 +6. **冷却时间自动清除**: 注册、密码重置、验证码登录成功后会自动清除验证码冷却时间,方便后续操作 -## 通用响应格式 +### 错误处理规范 +- **409 Conflict**: 资源冲突(用户名、邮箱已存在) +- **400 Bad Request**: 参数错误、验证码错误 +- **401 Unauthorized**: 认证失败、密码错误 +- **429 Too Many Requests**: 频率限制 +- **206 Partial Content**: 测试模式(验证码未真实发送) -所有API接口都遵循统一的响应格式: +### 前端开发建议 +1. 根据HTTP状态码进行错误处理,不要只依赖success字段 +2. 邮箱注册流程:先发送验证码 → 检查409冲突 → 使用验证码注册 +3. 测试模式下验证码在响应中返回,生产环境需用户查收邮件 +4. 实现重试机制处理429频率限制错误 +5. 注册/重置密码成功后,验证码冷却时间会自动清除,可立即发送新验证码 -```json -{ - "success": boolean, - "data": object | null, - "message": string, - "error_code": string | null -} -``` +--- -### 字段说明 +## 📋 API接口列表 -- `success`: 请求是否成功 -- `data`: 响应数据(成功时返回) -- `message`: 响应消息 -- `error_code`: 错误代码(失败时返回) - -## 接口分类 - -### 1. 应用状态接口 (App) +### 应用状态接口 - `GET /` - 获取应用状态 -### 2. 用户认证接口 (Auth) +### 用户认证接口 - `POST /auth/login` - 用户登录 - `POST /auth/register` - 用户注册 - `POST /auth/github` - GitHub OAuth登录 +- `POST /auth/verification-code-login` - 验证码登录 +- `POST /auth/send-login-verification-code` - 发送登录验证码 - `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` - 下载日志压缩包 +- `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` - 获取用户状态统计 -## 接口列表 +--- -### 应用状态接口 +## 🧪 API接口详细说明与测试用例 +### 1. 获取应用状态 -#### 1. 获取应用状态 +**接口**: `GET /` -**接口地址**: `GET /` - -**功能描述**: 返回应用的基本运行状态信息,用于健康检查和监控 - -#### 请求参数 - -无 - -#### 响应示例 - -**成功响应** (200): +#### 成功响应 (200) ```json { "service": "Pixel Game Server", - "version": "1.0.0", + "version": "1.1.1", "status": "running", - "timestamp": "2025-12-23T10:00:00.000Z", - "uptime": 3600, + "timestamp": "2025-12-25T10:27:44.352Z", + "uptime": 8, "environment": "development", - "storage_mode": "memory" + "storage_mode": "database" } ``` -| 字段名 | 类型 | 说明 | -|--------|------|------| -| service | string | 服务名称 | -| version | string | 服务版本 | -| status | string | 运行状态 (running/starting/stopping/error) | -| timestamp | string | 当前时间戳 | -| uptime | number | 运行时间(秒) | -| environment | string | 运行环境 (development/production/test) | -| storage_mode | string | 存储模式 (database/memory) | +--- -### 用户认证接口 +### 2. 用户登录 -#### 1. 用户登录 - -**接口地址**: `POST /auth/login` - -**功能描述**: 用户登录,支持用户名、邮箱或手机号登录 - -#### 请求参数 +**接口**: `POST /auth/login` +#### 请求体 ```json { "identifier": "testuser", @@ -116,14 +94,7 @@ } ``` -| 参数名 | 类型 | 必填 | 说明 | -|--------|------|------|------| -| identifier | string | 是 | 登录标识符,支持用户名、邮箱或手机号 | -| password | string | 是 | 用户密码 | - -#### 响应示例 - -**成功响应** (200): +#### 成功响应 (200) ```json { "success": true, @@ -133,13 +104,12 @@ "username": "testuser", "nickname": "测试用户", "email": "test@example.com", - "phone": "+8613800138000", - "avatar_url": "https://example.com/avatar.jpg", + "phone": null, + "avatar_url": null, "role": 1, "created_at": "2025-12-17T10:00:00.000Z" }, "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", - "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "is_new_user": false, "message": "登录成功" }, @@ -147,60 +117,61 @@ } ``` -**失败响应** (401): +#### 认证失败响应 (401) ```json { "success": false, - "message": "用户名或密码错误", + "message": "用户名、邮箱或手机号不存在", "error_code": "LOGIN_FAILED" } ``` -#### 2. 用户注册 - -**接口地址**: `POST /auth/register` - -**功能描述**: 创建新用户账户 - -**重要说明**: -- 如果提供邮箱,必须先调用发送验证码接口获取验证码 -- 验证码验证失败会返回400状态码,而不是201 -- 注册成功返回201,失败返回400 - -#### 请求参数 - +#### 密码错误响应 (401) ```json { - "username": "testuser", + "success": false, + "message": "密码错误", + "error_code": "LOGIN_FAILED" +} +``` + +--- + +### 3. 用户注册 + +**接口**: `POST /auth/register` + +#### 请求体(无邮箱) +```json +{ + "username": "newuser", "password": "password123", - "nickname": "测试用户", - "email": "test@example.com", + "nickname": "新用户" +} +``` + +#### 请求体(带邮箱验证) +```json +{ + "username": "newuser", + "password": "password123", + "nickname": "新用户", + "email": "newuser@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): +#### 成功响应 (201) ```json { "success": true, "data": { "user": { "id": "2", - "username": "testuser", - "nickname": "测试用户", - "email": "test@example.com", - "phone": "+8613800138000", + "username": "newuser", + "nickname": "新用户", + "email": "newuser@example.com", + "phone": null, "avatar_url": null, "role": 1, "created_at": "2025-12-17T10:00:00.000Z" @@ -213,38 +184,310 @@ } ``` -**失败响应** (400): +#### 用户名冲突响应 (409) ```json { "success": false, - "message": "提供邮箱时必须提供邮箱验证码", + "message": "用户名已存在", "error_code": "REGISTER_FAILED" } ``` -**频率限制响应** (429): +#### 邮箱冲突响应 (409) ```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" - } + "message": "邮箱已存在", + "error_code": "REGISTER_FAILED" } ``` -#### 3. GitHub OAuth登录 +#### 验证码错误响应 (400) +```json +{ + "success": false, + "message": "验证码不存在或已过期", + "error_code": "REGISTER_FAILED" +} +``` -**接口地址**: `POST /auth/github` +--- -**功能描述**: 使用GitHub账户登录或注册 +### 4. 发送邮箱验证码 -#### 请求参数 +**接口**: `POST /auth/send-email-verification` +#### 请求体 +```json +{ + "email": "test@example.com" +} +``` + +#### 成功响应 (200) - 生产环境 +```json +{ + "success": true, + "data": { + "is_test_mode": false + }, + "message": "验证码已发送,请查收邮件" +} +``` + +#### 测试模式响应 (206) - 开发环境 +```json +{ + "success": false, + "data": { + "verification_code": "123456", + "is_test_mode": true + }, + "message": "⚠️ 测试模式:验证码已生成但未真实发送。请在控制台查看验证码,或配置邮件服务以启用真实发送。", + "error_code": "TEST_MODE_ONLY" +} +``` + +#### 邮箱冲突响应 (409) +```json +{ + "success": false, + "message": "邮箱已被注册,请使用其他邮箱或直接登录", + "error_code": "SEND_EMAIL_VERIFICATION_FAILED" +} +``` + +#### 频率限制响应 (429) +```json +{ + "success": false, + "message": "验证码发送过于频繁,请1分钟后再试", + "error_code": "TOO_MANY_REQUESTS", + "throttle_info": { + "limit": 1, + "window_seconds": 60, + "current_requests": 1, + "reset_time": "2025-12-25T10:07:37.056Z" + } +} +``` +--- + +### 5. 验证码登录 + +**接口**: `POST /auth/verification-code-login` + +#### 请求体 +```json +{ + "identifier": "test@example.com", + "verification_code": "123456" +} +``` + +#### 成功响应 (200) +```json +{ + "success": true, + "data": { + "user": { + "id": "1", + "username": "testuser", + "nickname": "测试用户", + "email": "test@example.com", + "phone": null, + "avatar_url": null, + "role": 1, + "created_at": "2025-12-17T10:00:00.000Z" + }, + "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", + "is_new_user": false, + "message": "验证码登录成功" + }, + "message": "验证码登录成功" +} +``` + +#### 验证码错误响应 (401) +```json +{ + "success": false, + "message": "验证码验证失败", + "error_code": "VERIFICATION_CODE_LOGIN_FAILED" +} +``` + +#### 用户不存在响应 (404) +```json +{ + "success": false, + "message": "用户不存在,请先注册账户", + "error_code": "VERIFICATION_CODE_LOGIN_FAILED" +} +``` + +--- + +### 6. 发送登录验证码 + +**接口**: `POST /auth/send-login-verification-code` + +#### 请求体 +```json +{ + "identifier": "test@example.com" +} +``` + +#### 成功响应 (200) - 生产环境 +```json +{ + "success": true, + "data": { + "is_test_mode": false + }, + "message": "验证码已发送,请查收" +} +``` + +#### 测试模式响应 (206) - 开发环境 +```json +{ + "success": false, + "data": { + "verification_code": "654321", + "is_test_mode": true + }, + "message": "⚠️ 测试模式:验证码已生成但未真实发送。请在控制台查看验证码,或配置邮件服务以启用真实发送。", + "error_code": "TEST_MODE_ONLY" +} +``` + +#### 用户不存在响应 (404) +```json +{ + "success": false, + "message": "用户不存在", + "error_code": "SEND_LOGIN_CODE_FAILED" +} +``` + +--- + +### 7. 发送密码重置验证码 + +**接口**: `POST /auth/forgot-password` + +#### 请求体 +```json +{ + "identifier": "test@example.com" +} +``` + +#### 成功响应 (200) - 生产环境 +```json +{ + "success": true, + "data": { + "is_test_mode": false + }, + "message": "验证码已发送,请查收" +} +``` + +#### 测试模式响应 (206) - 开发环境 +```json +{ + "success": false, + "data": { + "verification_code": "789012", + "is_test_mode": true + }, + "message": "⚠️ 测试模式:验证码已生成但未真实发送。请在控制台查看验证码,或配置邮件服务以启用真实发送。", + "error_code": "TEST_MODE_ONLY" +} +``` + +#### 用户不存在响应 (404) +```json +{ + "success": false, + "message": "用户不存在", + "error_code": "SEND_CODE_FAILED" +} +``` + +--- + +### 8. 重置密码 + +**接口**: `POST /auth/reset-password` + +#### 请求体 +```json +{ + "identifier": "test@example.com", + "verification_code": "789012", + "new_password": "newpassword123" +} +``` + +#### 成功响应 (200) +```json +{ + "success": true, + "message": "密码重置成功" +} +``` + +#### 验证码错误响应 (400) +```json +{ + "success": false, + "message": "验证码验证失败", + "error_code": "RESET_PASSWORD_FAILED" +} +``` + +--- + +### 9. 修改密码 + +**接口**: `PUT /auth/change-password` + +#### 请求体 +```json +{ + "user_id": "1", + "old_password": "oldpassword123", + "new_password": "newpassword123" +} +``` + +#### 成功响应 (200) +```json +{ + "success": true, + "message": "密码修改成功" +} +``` + +#### 旧密码错误响应 (401) +```json +{ + "success": false, + "message": "旧密码错误", + "error_code": "CHANGE_PASSWORD_FAILED" +} +``` +--- + +### 10. GitHub OAuth登录 + +**接口**: `POST /auth/github` + +#### 请求体 ```json { "github_id": "12345678", @@ -255,17 +498,7 @@ } ``` -| 参数名 | 类型 | 必填 | 说明 | -|--------|------|------|------| -| github_id | string | 是 | GitHub用户ID | -| username | string | 是 | GitHub用户名 | -| nickname | string | 是 | GitHub显示名称 | -| email | string | 否 | GitHub邮箱地址 | -| avatar_url | string | 否 | GitHub头像URL | - -#### 响应示例 - -**成功响应** (200): +#### 成功响应 (200) - 已存在用户 ```json { "success": true, @@ -281,6 +514,29 @@ "created_at": "2025-12-17T10:00:00.000Z" }, "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", + "is_new_user": false, + "message": "GitHub登录成功" + }, + "message": "GitHub登录成功" +} +``` + +#### 成功响应 (200) - 新用户注册 +```json +{ + "success": true, + "data": { + "user": { + "id": "4", + "username": "octocat_1", + "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账户绑定成功" }, @@ -288,156 +544,13 @@ } ``` -#### 4. 发送密码重置验证码 +--- -**接口地址**: `POST /auth/forgot-password` +### 11. 验证邮箱验证码 -**功能描述**: 向用户邮箱或手机发送密码重置验证码 - -#### 请求参数 - -```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` - -**功能描述**: 使用验证码验证邮箱 - -#### 请求参数 +**接口**: `POST /auth/verify-email` +#### 请求体 ```json { "email": "test@example.com", @@ -445,14 +558,7 @@ } ``` -| 参数名 | 类型 | 必填 | 说明 | -|--------|------|------|------| -| email | string | 是 | 邮箱地址 | -| verification_code | string | 是 | 6位数字验证码 | - -#### 响应示例 - -**成功响应** (200): +#### 成功响应 (200) ```json { "success": true, @@ -460,121 +566,76 @@ } ``` -#### 9. 重新发送邮箱验证码 +#### 验证码错误响应 (400) +```json +{ + "success": false, + "message": "验证码错误", + "error_code": "EMAIL_VERIFICATION_FAILED" +} +``` -**接口地址**: `POST /auth/resend-email-verification` +--- -**功能描述**: 重新向指定邮箱发送验证码 +### 12. 重新发送邮箱验证码 -#### 请求参数 +**接口**: `POST /auth/resend-email-verification` +#### 请求体 ```json { "email": "test@example.com" } ``` -| 参数名 | 类型 | 必填 | 说明 | -|--------|------|------|------| -| email | string | 是 | 邮箱地址 | - -#### 响应示例 - -**成功响应** (200): +#### 成功响应 (200) - 生产环境 ```json { "success": true, "data": { - "verification_code": "123456", "is_test_mode": false }, - "message": "验证码已重新发送,请查收" + "message": "验证码已重新发送,请查收邮件" } ``` -#### 10. 调试验证码信息 - -**接口地址**: `POST /auth/debug-verification-code` - -**功能描述**: 获取验证码的详细调试信息(仅开发环境使用) - -#### 请求参数 - +#### 测试模式响应 (206) - 开发环境 ```json { - "email": "test@example.com" -} -``` - -| 参数名 | 类型 | 必填 | 说明 | -|--------|------|------|------| -| email | string | 是 | 邮箱地址 | - -#### 响应示例 - -**成功响应** (200): -```json -{ - "success": true, + "success": false, "data": { - "email": "test@example.com", - "verification_code": "123456", - "expires_at": "2025-12-23T10:15:00.000Z", - "created_at": "2025-12-23T10:00:00.000Z" + "verification_code": "456789", + "is_test_mode": true }, - "message": "调试信息获取成功" + "message": "⚠️ 测试模式:验证码已生成但未真实发送。请在控制台查看验证码,或配置邮件服务以启用真实发送。", + "error_code": "TEST_MODE_ONLY" } ``` -#### 11. 清除限流记录 - -**接口地址**: `POST /auth/debug-clear-throttle` - -**功能描述**: 清除所有限流记录(仅开发环境使用) - -**注意**: 此接口用于开发测试,清除所有IP的频率限制记录 - -#### 请求参数 - -无 - -#### 响应示例 - -**成功响应** (200): +#### 邮箱已验证响应 (400) ```json { - "success": true, - "message": "限流记录已清除" + "success": false, + "message": "邮箱已验证,无需重复验证", + "error_code": "RESEND_EMAIL_VERIFICATION_FAILED" } ``` -### 管理员接口 +--- -**注意**:所有管理员接口都需要在 Header 中携带 `Authorization: Bearer `,且用户角色必须为管理员 (role=9)。 +### 13. 管理员登录 -#### 1. 管理员登录 - -**接口地址**: `POST /admin/auth/login` - -**功能描述**: 管理员登录,仅允许 role=9 的账户登录后台 - -#### 请求参数 +**接口**: `POST /admin/auth/login` +#### 请求体 ```json { - "identifier": "admin", + "username": "admin", "password": "Admin123456" } ``` -| 参数名 | 类型 | 必填 | 说明 | -|--------|------|------|------| -| identifier | string | 是 | 登录标识符(用户名/邮箱/手机号) | -| password | string | 是 | 密码 | - -#### 响应示例 - -**成功响应** (200): +#### 成功响应 (200) ```json { "success": true, @@ -583,31 +644,45 @@ "id": "1", "username": "admin", "nickname": "管理员", - "role": 9 + "role": 0 }, "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", - "expires_at": 1766102400000 + "expires_in": 28800, + "message": "管理员登录成功" }, "message": "管理员登录成功" } ``` -#### 2. 获取用户列表 +#### 认证失败响应 (401) +```json +{ + "success": false, + "message": "用户名或密码错误", + "error_code": "ADMIN_LOGIN_FAILED" +} +``` -**接口地址**: `GET /admin/users` +#### 权限不足响应 (403) +```json +{ + "success": false, + "message": "权限不足,需要管理员权限", + "error_code": "ADMIN_LOGIN_FAILED" +} +``` +--- -**功能描述**: 分页获取所有注册用户列表 +### 14. 获取用户列表 -#### 请求参数 +**接口**: `GET /admin/users` -| 参数名 | 类型 | 必填 | 说明 | -|--------|------|------|------| -| limit | number | 否 | 每页数量,默认100 | -| offset | number | 否 | 偏移量,默认0 | +#### 查询参数 +- `page`: 页码(可选,默认1) +- `limit`: 每页数量(可选,默认10) +- `status`: 用户状态筛选(可选) -#### 响应示例 - -**成功响应** (200): +#### 成功响应 (200) ```json { "success": true, @@ -615,172 +690,35 @@ "users": [ { "id": "1", - "username": "user1", - "nickname": "小明", - "email": "user1@example.com", - "email_verified": false, - "phone": "+8613800138000", - "avatar_url": "https://example.com/avatar.png", + "username": "testuser", + "nickname": "测试用户", + "email": "test@example.com", + "phone": null, "role": 1, - "created_at": "2025-12-19T00:00:00.000Z", - "updated_at": "2025-12-19T00:00:00.000Z" + "status": "active", + "email_verified": true, + "created_at": "2025-12-17T10:00:00.000Z", + "updated_at": "2025-12-17T10:00:00.000Z" } ], - "limit": 100, - "offset": 0 + "pagination": { + "page": 1, + "limit": 10, + "total": 1, + "pages": 1 + } }, "message": "用户列表获取成功" } ``` -#### 3. 获取用户详情 +--- -**接口地址**: `GET /admin/users/:id` +### 15. 获取用户详情 -**功能描述**: 获取指定用户的详细信息 +**接口**: `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 `。 - -#### 1. 修改用户状态 - -**接口地址**: `PUT /admin/users/:id/status` - -**功能描述**: 管理员修改指定用户的账户状态,支持激活、锁定、禁用等操作 - -#### 请求参数 - -| 参数名 | 类型 | 必填 | 说明 | -|--------|------|------|------| -| id | string | 是 | 用户ID(路径参数) | -| status | string | 是 | 用户状态枚举值 | -| reason | string | 否 | 修改原因 | - -```json -{ - "status": "locked", - "reason": "用户违反社区规定" -} -``` - -**用户状态枚举值:** -- `active` - 正常状态,可以正常使用 -- `inactive` - 未激活,需要邮箱验证 -- `locked` - 已锁定,临时禁用 -- `banned` - 已禁用,管理员操作 -- `deleted` - 已删除,软删除状态 -- `pending` - 待审核,需要管理员审核 - -#### 响应示例 - -**成功响应** (200): +#### 成功响应 (200) ```json { "success": true, @@ -789,1328 +727,237 @@ "id": "1", "username": "testuser", "nickname": "测试用户", + "email": "test@example.com", + "phone": null, + "role": 1, + "status": "active", + "email_verified": true, + "github_id": null, + "avatar_url": null, + "created_at": "2025-12-17T10:00:00.000Z", + "updated_at": "2025-12-17T10:00:00.000Z" + } + }, + "message": "用户详情获取成功" +} +``` + +#### 用户不存在响应 (404) +```json +{ + "success": false, + "message": "用户不存在", + "error_code": "USER_NOT_FOUND" +} +``` + +--- + +### 16. 管理员重置用户密码 + +**接口**: `POST /admin/users/:id/reset-password` + +#### 请求体 +```json +{ + "new_password": "newpassword123" +} +``` + +#### 成功响应 (200) +```json +{ + "success": true, + "message": "用户密码重置成功" +} +``` + +#### 用户不存在响应 (404) +```json +{ + "success": false, + "message": "用户不存在", + "error_code": "USER_NOT_FOUND" +} +``` + +--- + +### 17. 修改用户状态 + +**接口**: `PUT /admin/users/:id/status` + +#### 请求体 +```json +{ + "status": "locked", + "reason": "违规操作" +} +``` + +#### 成功响应 (200) +```json +{ + "success": true, + "data": { + "user": { + "id": "1", + "username": "testuser", "status": "locked", - "status_description": "已锁定", - "updated_at": "2025-12-24T10:00:00.000Z" - }, - "reason": "用户违反社区规定" + "updated_at": "2025-12-17T10:00:00.000Z" + } }, "message": "用户状态修改成功" } ``` -#### 2. 批量修改用户状态 - -**接口地址**: `POST /admin/users/batch-status` - -**功能描述**: 管理员批量修改多个用户的账户状态 - -#### 请求参数 - +#### 状态值无效响应 (400) ```json { - "user_ids": ["1", "2", "3"], - "status": "locked", - "reason": "批量处理违规用户" + "success": false, + "message": "无效的用户状态值", + "error_code": "USER_STATUS_UPDATE_FAILED" } ``` -| 参数名 | 类型 | 必填 | 说明 | -|--------|------|------|------| -| user_ids | array | 是 | 用户ID列表(1-100个) | -| status | string | 是 | 用户状态枚举值 | -| reason | string | 否 | 批量修改原因 | +--- -#### 响应示例 +### 18. 批量修改用户状态 -**成功响应** (200): +**接口**: `POST /admin/users/batch-status` + +#### 请求体 +```json +{ + "user_ids": ["1", "2", "3"], + "status": "active", + "reason": "批量激活" +} +``` + +#### 成功响应 (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": "批量处理违规用户" + "updated_count": 3, + "failed_count": 0, + "results": [ + { + "user_id": "1", + "success": true, + "new_status": "active" + }, + { + "user_id": "2", + "success": true, + "new_status": "active" + }, + { + "user_id": "3", + "success": true, + "new_status": "active" + } + ] }, - "message": "批量用户状态修改完成,成功:1,失败:1" + "message": "批量状态修改完成" } ``` -#### 3. 获取用户状态统计 +--- -**接口地址**: `GET /admin/users/status-stats` +### 19. 获取用户状态统计 -**功能描述**: 获取各种用户状态的数量统计信息 +**接口**: `GET /admin/users/status-stats` -#### 请求参数 - -无 - -#### 响应示例 - -**成功响应** (200): +#### 成功响应 (200) ```json { "success": true, "data": { "stats": { - "active": 1250, - "inactive": 45, - "locked": 12, - "banned": 8, - "deleted": 3, - "pending": 15, - "total": 1333 + "active": 15, + "inactive": 3, + "locked": 2, + "banned": 1, + "deleted": 0, + "pending": 5 }, - "timestamp": "2025-12-24T10:00:00.000Z" + "total": 26 }, "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'); -}; +### 20. 获取运行时日志 + +**接口**: `GET /admin/logs/runtime` + +#### 查询参数 +- `lines`: 日志行数(可选,默认100) +- `level`: 日志级别(可选) + +#### 成功响应 (200) +```json +{ + "success": true, + "data": { + "logs": [ + "[2025-12-25 18:27:35] LOG [NestApplication] Nest application successfully started", + "[2025-12-25 18:27:35] LOG [RouterExplorer] Mapped {/, GET} route" + ], + "total_lines": 2, + "timestamp": "2025-12-25T10:27:44.352Z" + }, + "message": "运行时日志获取成功" +} ``` -#### **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); -}; +### 21. 获取归档日志 -// 验证码尝试次数限制测试 -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' - ); -}; -``` +**接口**: `GET /admin/logs/archive` -#### **3. 管理员功能测试** +#### 查询参数 +- `date`: 日期(YYYY-MM-DD格式,可选) +- `download`: 是否下载(可选) -##### **权限验证测试** -```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; +#### 成功响应 (200) +```json +{ + "success": true, + "data": { + "files": [ + { + "filename": "app-2025-12-24.log", + "size": 1024, + "created_at": "2025-12-24T00:00:00.000Z" } - } - } -}; - -// 维护模式测试 -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_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', + ], + "total_files": 1 }, - 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); + "message": "归档日志列表获取成功" } ``` -### 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" - }' +### v1.1.2 (2025-12-25) +- **验证码冷却优化**: 注册、密码重置、验证码登录成功后自动清除验证码冷却时间 +- **用户体验提升**: 成功操作后可立即发送新的验证码,无需等待冷却时间 +- **代码健壮性**: 冷却时间清除失败不影响主要业务流程 -# 发送邮箱验证码 -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-15分钟 -4. **用户ID**: 修改密码接口中的user_id应从JWT令牌中获取,而不是从请求体中传递 -5. **错误处理**: 建议在客户端实现适当的错误处理和用户提示 -6. **限流**: 建议对登录、注册等接口实施限流策略 -7. **管理员权限**: - - 管理员接口需要 role=9 的用户权限 - - 需要在请求头中携带有效的JWT Token - - Token格式:`Authorization: Bearer ` -8. **存储模式**: - - 数据库模式:数据持久化存储在MySQL - - 内存模式:数据存储在内存中,重启后丢失 -9. **邮箱验证**: - - 注册时如果提供邮箱,需要先获取验证码 - - 支持重新发送验证码功能 - - 调试接口仅用于开发环境 - -## 常见测试场景 - -### 🔍 **前端开发者必测场景** - -#### **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 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. 频率限制测试** -```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('请等待'); -}; -``` - -#### **4. 管理员权限测试** -```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); -}; -``` - -#### **5. 用户状态影响登录** -```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 /` - 获取应用状态 - - **用户认证接口** (11个) - - 用户登录、注册、GitHub OAuth - - 密码重置和修改功能 - - 邮箱验证相关接口 - - 调试验证码接口 - - **新增**:清除限流记录接口(开发环境) - - **管理员接口** (6个) - - 管理员登录和用户管理 - - 用户列表和详情查询 - - 密码重置功能 - - 日志管理和下载 - - **用户管理接口** (3个) - - 用户状态管理 (active/inactive/locked/banned/deleted/pending) - - 单个用户状态修改接口 - - 批量用户状态修改接口 - - 用户状态统计接口 - - **安全增强功能** - - 频率限制中间件 (Rate Limiting) - 已调整配置 - - 维护模式中间件 (Maintenance Mode) - - 内容类型验证中间件 (Content Type Validation) - - 请求超时拦截器 (Request Timeout) - - 用户状态检查和权限控制 - - **修复**:HTTP状态码现在正确反映业务执行结果 - - **总计接口数量**: 21个API接口 - - 完善错误代码和使用示例 - - 修复路由冲突问题 - - 确保文档与实际测试效果一致 - - **重要修复**:解决了业务失败但返回成功状态码的问题 +### v1.1.1 (2025-12-25) +- **邮箱冲突检测优化**: 发送邮箱验证码前检查邮箱是否已被注册 +- **用户体验提升**: 避免向已注册邮箱发送无用验证码 +- **错误处理改进**: 返回409 Conflict状态码和明确错误信息 +### v1.1.0 (2025-12-25) +- **新增验证码登录功能**: 支持邮箱验证码登录 +- **HTTP状态码修复**: 所有接口返回正确的业务状态码 +- **完善错误处理**: 统一错误响应格式和错误代码 \ No newline at end of file