forked from xiaohei/taiji-AI-PAD
备份
This commit is contained in:
@@ -0,0 +1,48 @@
|
|||||||
|
====================================================================
|
||||||
|
Taiji AI PAD - 未被 Git 追踪的文件备份
|
||||||
|
备份时间: 2026年3月15日
|
||||||
|
====================================================================
|
||||||
|
|
||||||
|
此备份包含以下重要文件:
|
||||||
|
|
||||||
|
【环境变量配置】
|
||||||
|
- .env 主环境变量配置文件
|
||||||
|
- .env.backup 环境变量备份
|
||||||
|
|
||||||
|
【Kubernetes 密钥配置】
|
||||||
|
- k8s/secrets.yaml Kubernetes 密钥配置
|
||||||
|
- services/mcp-server/k8s/secrets.yaml MCP Server 密钥配置
|
||||||
|
|
||||||
|
【日志和配置备份】
|
||||||
|
- logs/billing_health_report.json 计费健康检查报告
|
||||||
|
- logs/quota_backup.json 配额备份
|
||||||
|
- logs/quota_fix_report.json 配额修复报告
|
||||||
|
|
||||||
|
【数据库备份】
|
||||||
|
- backups/backup_taiji_prod_20260312_035843.dump
|
||||||
|
生产数据库备份 (1.9 MB) - 2026年3月12日
|
||||||
|
|
||||||
|
====================================================================
|
||||||
|
恢复说明:
|
||||||
|
====================================================================
|
||||||
|
|
||||||
|
1. 解压备份包到项目根目录:
|
||||||
|
unzip taiji-AI-PAD-untracked-backup-20260315.zip
|
||||||
|
|
||||||
|
2. 检查并更新 .env 文件中的配置
|
||||||
|
|
||||||
|
3. 如需恢复数据库:
|
||||||
|
pg_restore -d database_name backups/backup_taiji_prod_20260312_035843.dump
|
||||||
|
|
||||||
|
4. 如需更新 Kubernetes 密钥:
|
||||||
|
kubectl apply -f k8s/secrets.yaml
|
||||||
|
|
||||||
|
====================================================================
|
||||||
|
安全提醒:
|
||||||
|
====================================================================
|
||||||
|
|
||||||
|
⚠️ 此备份包含敏感信息,请妥善保管!
|
||||||
|
⚠️ 不要将此文件上传到公开的仓库或云存储
|
||||||
|
⚠️ 建议加密存储
|
||||||
|
|
||||||
|
====================================================================
|
||||||
@@ -0,0 +1,154 @@
|
|||||||
|
# 忘记密码接口文档
|
||||||
|
|
||||||
|
## 概述
|
||||||
|
|
||||||
|
本文档描述用户侧忘记密码功能的 API 接口,供前端对接使用。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 接口列表
|
||||||
|
|
||||||
|
| 接口 | 方法 | 路径 | 说明 |
|
||||||
|
|------|------|------|------|
|
||||||
|
| 发送验证码 | POST | `/api/auth/forgot-password/send-code` | 发送密码重置验证码到邮箱 |
|
||||||
|
| 重置密码 | POST | `/api/auth/forgot-password/reset` | 验证验证码并重置密码 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. 发送密码重置验证码
|
||||||
|
|
||||||
|
### 请求
|
||||||
|
|
||||||
|
```
|
||||||
|
POST /api/auth/forgot-password/send-code
|
||||||
|
Content-Type: application/json
|
||||||
|
```
|
||||||
|
|
||||||
|
### 入参
|
||||||
|
|
||||||
|
| 字段 | 类型 | 必填 | 说明 |
|
||||||
|
|------|------|------|------|
|
||||||
|
| email | string | 是 | 注册时使用的邮箱地址 |
|
||||||
|
|
||||||
|
### 请求示例
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"email": "user@example.com"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 出参
|
||||||
|
|
||||||
|
#### 成功响应 (200)
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"success": true,
|
||||||
|
"data": null,
|
||||||
|
"message": "验证码已发送到您的邮箱,请查收"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 错误响应
|
||||||
|
|
||||||
|
| HTTP 状态码 | 错误信息 | 说明 |
|
||||||
|
|-------------|----------|------|
|
||||||
|
| 404 | 该邮箱未注册 | 邮箱不存在 |
|
||||||
|
| 429 | 请等待X秒后再重新发送验证码 | 发送频率限制(60秒内只能发送一次) |
|
||||||
|
| 500 | 验证码发送失败,请稍后重试 | 服务器错误 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. 重置密码
|
||||||
|
|
||||||
|
### 请求
|
||||||
|
|
||||||
|
```
|
||||||
|
POST /api/auth/forgot-password/reset
|
||||||
|
Content-Type: application/json
|
||||||
|
```
|
||||||
|
|
||||||
|
### 入参
|
||||||
|
|
||||||
|
| 字段 | 类型 | 必填 | 说明 |
|
||||||
|
|------|------|------|------|
|
||||||
|
| email | string | 是 | 注册时使用的邮箱地址 |
|
||||||
|
| verification_code | string | 是 | 6位数字验证码 |
|
||||||
|
| new_password | string | 是 | 新密码,至少8个字符 |
|
||||||
|
|
||||||
|
### 请求示例
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"email": "user@example.com",
|
||||||
|
"verification_code": "123456",
|
||||||
|
"new_password": "newPassword123"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 出参
|
||||||
|
|
||||||
|
#### 成功响应 (200)
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"success": true,
|
||||||
|
"data": null,
|
||||||
|
"message": "密码重置成功,请使用新密码登录"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 错误响应
|
||||||
|
|
||||||
|
| HTTP 状态码 | 错误信息 | 说明 |
|
||||||
|
|-------------|----------|------|
|
||||||
|
| 400 | 验证码错误或已过期 | 验证码无效 |
|
||||||
|
| 404 | 该邮箱未注册 | 邮箱不存在 |
|
||||||
|
| 422 | 验证错误 | 参数格式不正确(如密码少于8位) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 前端对接流程
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────┐
|
||||||
|
│ 忘记密码页面 │
|
||||||
|
└────────┬────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────┐
|
||||||
|
│ 输入邮箱地址 │
|
||||||
|
└────────┬────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────┐ POST /api/auth/forgot-password/send-code
|
||||||
|
│ 点击发送验证码 │ ──────────────────────────────────────────────►
|
||||||
|
└────────┬────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────┐
|
||||||
|
│ 输入验证码 │
|
||||||
|
│ 输入新密码 │
|
||||||
|
└────────┬────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────┐ POST /api/auth/forgot-password/reset
|
||||||
|
│ 点击重置密码 │ ──────────────────────────────────────────────►
|
||||||
|
└────────┬────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────┐
|
||||||
|
│ 跳转到登录页面 │
|
||||||
|
└─────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 注意事项
|
||||||
|
|
||||||
|
1. **验证码有效期**: 10 分钟
|
||||||
|
2. **发送频率限制**: 同一邮箱 60 秒内只能发送一次
|
||||||
|
3. **密码要求**: 至少 8 个字符
|
||||||
|
4. **验证码格式**: 6 位数字
|
||||||
|
5. **验证码使用后自动失效**: 重置成功后验证码立即失效,无法重复使用
|
||||||
@@ -161,6 +161,25 @@ spec:
|
|||||||
name: taiji-secrets
|
name: taiji-secrets
|
||||||
key: smtp-password
|
key: smtp-password
|
||||||
|
|
||||||
|
# PayPal 支付配置 (生产环境)
|
||||||
|
- name: PAYPAL_CLIENT_ID
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: taiji-secrets
|
||||||
|
key: paypal-client-id
|
||||||
|
- name: PAYPAL_CLIENT_SECRET
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: taiji-secrets
|
||||||
|
key: paypal-client-secret
|
||||||
|
- name: PAYPAL_ENVIRONMENT
|
||||||
|
value: "production"
|
||||||
|
- name: PAYPAL_WEBHOOK_ID
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: taiji-secrets
|
||||||
|
key: paypal-webhook-id
|
||||||
|
|
||||||
# 健康检查
|
# 健康检查
|
||||||
livenessProbe:
|
livenessProbe:
|
||||||
httpGet:
|
httpGet:
|
||||||
|
|||||||
@@ -50,3 +50,11 @@ stringData:
|
|||||||
# SMTP邮箱配置
|
# SMTP邮箱配置
|
||||||
# ===========================================
|
# ===========================================
|
||||||
smtp-password: "eR)8hD@1Q)3sU%2q"
|
smtp-password: "eR)8hD@1Q)3sU%2q"
|
||||||
|
|
||||||
|
# ===========================================
|
||||||
|
# PayPal 支付配置 (生产环境)
|
||||||
|
# App Name: taijiagent
|
||||||
|
# ===========================================
|
||||||
|
paypal-client-id: "AVlZsAarDjotq5n1Pu2guPDJCy5pvZiVYIOxOuejHTejNyPdGyJ0rXy_5mXiUv4M-NXYsvE1S7TCSQQV"
|
||||||
|
paypal-client-secret: "EJK7kY_gg7emiiiv3oZPJBTe4FLpqDAnpiuSi5hNl8YtaWRHpZVg9767VqZU3iXp92cQ0GYpmfYvpopG"
|
||||||
|
paypal-webhook-id: "51263380NC1182518"
|
||||||
|
|||||||
@@ -61,13 +61,14 @@ def generate_verification_code() -> str:
|
|||||||
return ''.join(random.choices(string.digits, k=VERIFICATION_CODE_LENGTH))
|
return ''.join(random.choices(string.digits, k=VERIFICATION_CODE_LENGTH))
|
||||||
|
|
||||||
|
|
||||||
async def send_verification_code(email: str, code: str) -> bool:
|
async def send_verification_code(email: str, code: str, purpose: str = "register") -> bool:
|
||||||
"""
|
"""
|
||||||
发送验证码邮件
|
发送验证码邮件
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
email: 收件人邮箱
|
email: 收件人邮箱
|
||||||
code: 验证码
|
code: 验证码
|
||||||
|
purpose: 用途,"register" 表示注册,"reset_password" 表示重置密码
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
是否发送成功
|
是否发送成功
|
||||||
@@ -81,10 +82,27 @@ async def send_verification_code(email: str, code: str) -> bool:
|
|||||||
msg = MIMEMultipart()
|
msg = MIMEMultipart()
|
||||||
msg['From'] = SMTP_EMAIL
|
msg['From'] = SMTP_EMAIL
|
||||||
msg['To'] = email
|
msg['To'] = email
|
||||||
msg['Subject'] = "Taiji AI-PAD 注册验证码"
|
|
||||||
|
|
||||||
# 邮件正文
|
# 根据用途设置不同的邮件主题和正文
|
||||||
body = f"""
|
if purpose == "reset_password":
|
||||||
|
msg['Subject'] = "Taiji AI-PAD 密码重置验证码"
|
||||||
|
body = f"""
|
||||||
|
尊敬的用户:
|
||||||
|
|
||||||
|
您正在进行密码重置操作,验证码是:{code}
|
||||||
|
|
||||||
|
验证码有效期为10分钟,请勿泄露给他人。
|
||||||
|
|
||||||
|
如果您没有进行密码重置操作,请忽略此邮件,您的账户仍然安全。
|
||||||
|
|
||||||
|
此邮件由系统自动发送,请勿回复。
|
||||||
|
|
||||||
|
---
|
||||||
|
Taiji AI-PAD 团队
|
||||||
|
"""
|
||||||
|
else:
|
||||||
|
msg['Subject'] = "Taiji AI-PAD 注册验证码"
|
||||||
|
body = f"""
|
||||||
尊敬的用户:
|
尊敬的用户:
|
||||||
|
|
||||||
您的注册验证码是:{code}
|
您的注册验证码是:{code}
|
||||||
@@ -290,12 +308,13 @@ async def verify_code(email: str, code: str) -> bool:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
async def send_and_store_verification_code(email: str) -> Optional[str]:
|
async def send_and_store_verification_code(email: str, purpose: str = "register") -> Optional[str]:
|
||||||
"""
|
"""
|
||||||
生成、发送并存储验证码
|
生成、发送并存储验证码
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
email: 邮箱地址
|
email: 邮箱地址
|
||||||
|
purpose: 用途,"register" 表示注册,"reset_password" 表示重置密码
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
验证码(如果成功),None(如果失败)
|
验证码(如果成功),None(如果失败)
|
||||||
@@ -306,11 +325,11 @@ async def send_and_store_verification_code(email: str) -> Optional[str]:
|
|||||||
# 先存储验证码(即使邮件发送失败,验证码也已存储,可以手动查看Redis)
|
# 先存储验证码(即使邮件发送失败,验证码也已存储,可以手动查看Redis)
|
||||||
store_success = await store_verification_code(email, code)
|
store_success = await store_verification_code(email, code)
|
||||||
if not store_success:
|
if not store_success:
|
||||||
logger.error("验证码存储失败,无法继续", email=email)
|
logger.error("验证码存储失败,无法继续", email=email, purpose=purpose)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# 发送邮件
|
# 发送邮件(传递 purpose 参数以使用不同的邮件模板)
|
||||||
send_success = await send_verification_code(email, code)
|
send_success = await send_verification_code(email, code, purpose=purpose)
|
||||||
|
|
||||||
# 测试模式:即使邮件发送失败也返回验证码(仅用于开发/测试环境)
|
# 测试模式:即使邮件发送失败也返回验证码(仅用于开发/测试环境)
|
||||||
test_mode = os.getenv("ENABLE_TEST_MODE", "false").lower() == "true" or os.getenv("DEBUG", "false").lower() == "true"
|
test_mode = os.getenv("ENABLE_TEST_MODE", "false").lower() == "true" or os.getenv("DEBUG", "false").lower() == "true"
|
||||||
@@ -322,6 +341,7 @@ async def send_and_store_verification_code(email: str) -> Optional[str]:
|
|||||||
"测试模式:邮件发送失败,但验证码已存储到Redis",
|
"测试模式:邮件发送失败,但验证码已存储到Redis",
|
||||||
email=email,
|
email=email,
|
||||||
verification_code=code,
|
verification_code=code,
|
||||||
|
purpose=purpose,
|
||||||
hint="验证码已存储到Redis,可通过Redis获取或查看日志(仅测试环境)"
|
hint="验证码已存储到Redis,可通过Redis获取或查看日志(仅测试环境)"
|
||||||
)
|
)
|
||||||
# 设置发送频率限制
|
# 设置发送频率限制
|
||||||
@@ -329,12 +349,25 @@ async def send_and_store_verification_code(email: str) -> Optional[str]:
|
|||||||
return code
|
return code
|
||||||
else:
|
else:
|
||||||
# 生产模式:邮件发送失败则不返回验证码
|
# 生产模式:邮件发送失败则不返回验证码
|
||||||
logger.error("邮件发送失败,验证码已存储但未发送", email=email)
|
logger.error("邮件发送失败,验证码已存储但未发送", email=email, purpose=purpose)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# 发送成功后设置频率限制
|
# 发送成功后设置频率限制
|
||||||
await set_rate_limit(email)
|
await set_rate_limit(email)
|
||||||
|
|
||||||
logger.info("验证码已发送并存储", email=email)
|
logger.info("验证码已发送并存储", email=email, purpose=purpose)
|
||||||
return code
|
return code
|
||||||
|
|
||||||
|
|
||||||
|
async def send_password_reset_code(email: str) -> Optional[str]:
|
||||||
|
"""
|
||||||
|
发送密码重置验证码(便捷函数)
|
||||||
|
|
||||||
|
Args:
|
||||||
|
email: 邮箱地址
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
验证码(如果成功),None(如果失败)
|
||||||
|
"""
|
||||||
|
return await send_and_store_verification_code(email, purpose="reset_password")
|
||||||
|
|
||||||
|
|||||||
@@ -29,11 +29,13 @@ from app.schemas import (
|
|||||||
SuccessResponse,
|
SuccessResponse,
|
||||||
TokenResponse,
|
TokenResponse,
|
||||||
PasswordChangeRequest,
|
PasswordChangeRequest,
|
||||||
|
ForgotPasswordRequest,
|
||||||
|
ResetPasswordRequest,
|
||||||
APIKeyInfo,
|
APIKeyInfo,
|
||||||
RegenerateAPIKeyResponse,
|
RegenerateAPIKeyResponse,
|
||||||
UserCreate,
|
UserCreate,
|
||||||
)
|
)
|
||||||
from app.email_verification import verify_code, send_and_store_verification_code, check_rate_limit
|
from app.email_verification import verify_code, send_and_store_verification_code, check_rate_limit, send_password_reset_code
|
||||||
from app.agent_manager_client import get_agent_manager_client, AgentManagerError
|
from app.agent_manager_client import get_agent_manager_client, AgentManagerError
|
||||||
from app.litellm_client import get_litellm_client, LiteLLMClientError
|
from app.litellm_client import get_litellm_client, LiteLLMClientError
|
||||||
from config import settings
|
from config import settings
|
||||||
@@ -904,3 +906,112 @@ async def register(req: UserCreate, db: AsyncSession = Depends(get_db)):
|
|||||||
message="注册成功"
|
message="注册成功"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/forgot-password/send-code", response_model=SuccessResponse)
|
||||||
|
async def forgot_password_send_code(
|
||||||
|
req: ForgotPasswordRequest,
|
||||||
|
db: AsyncSession = Depends(get_db)
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
忘记密码 - 发送验证码
|
||||||
|
|
||||||
|
向用户注册邮箱发送密码重置验证码。
|
||||||
|
|
||||||
|
频率限制:同一邮箱60秒内只能发送一次
|
||||||
|
|
||||||
|
请求体:
|
||||||
|
{
|
||||||
|
"email": "user@example.com"
|
||||||
|
}
|
||||||
|
|
||||||
|
响应:
|
||||||
|
- 成功:返回验证码已发送的消息
|
||||||
|
- 失败:邮箱不存在、发送频率限制等
|
||||||
|
"""
|
||||||
|
# 1. 检查发送频率限制
|
||||||
|
can_send, remaining_seconds = await check_rate_limit(req.email)
|
||||||
|
if not can_send:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_429_TOO_MANY_REQUESTS,
|
||||||
|
detail=f"请等待{remaining_seconds}秒后再重新发送验证码"
|
||||||
|
)
|
||||||
|
|
||||||
|
# 2. 检查邮箱是否存在(必须是已注册用户)
|
||||||
|
result = await db.execute(select(User).where(User.email == req.email))
|
||||||
|
user = result.scalar_one_or_none()
|
||||||
|
|
||||||
|
if not user:
|
||||||
|
# 为了安全,不直接告知邮箱不存在,但记录日志
|
||||||
|
logger.warning("忘记密码请求:邮箱不存在", email=req.email)
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND,
|
||||||
|
detail="该邮箱未注册"
|
||||||
|
)
|
||||||
|
|
||||||
|
# 3. 发送密码重置验证码(使用专门的密码重置邮件模板)
|
||||||
|
code = await send_password_reset_code(req.email)
|
||||||
|
if not code:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||||
|
detail="验证码发送失败,请稍后重试"
|
||||||
|
)
|
||||||
|
|
||||||
|
logger.info("忘记密码验证码已发送", email=req.email, user_id=str(user.id))
|
||||||
|
|
||||||
|
return SuccessResponse(
|
||||||
|
message="验证码已发送到您的邮箱,请查收"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/forgot-password/reset", response_model=SuccessResponse)
|
||||||
|
async def forgot_password_reset(
|
||||||
|
req: ResetPasswordRequest,
|
||||||
|
db: AsyncSession = Depends(get_db)
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
忘记密码 - 重置密码
|
||||||
|
|
||||||
|
验证邮箱验证码并重置密码。
|
||||||
|
|
||||||
|
请求体:
|
||||||
|
{
|
||||||
|
"email": "user@example.com",
|
||||||
|
"verification_code": "123456",
|
||||||
|
"new_password": "newPassword123"
|
||||||
|
}
|
||||||
|
|
||||||
|
响应:
|
||||||
|
- 成功:密码重置成功
|
||||||
|
- 失败:验证码错误、邮箱不存在等
|
||||||
|
"""
|
||||||
|
# 1. 检查邮箱是否存在
|
||||||
|
result = await db.execute(select(User).where(User.email == req.email))
|
||||||
|
user = result.scalar_one_or_none()
|
||||||
|
|
||||||
|
if not user:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND,
|
||||||
|
detail="该邮箱未注册"
|
||||||
|
)
|
||||||
|
|
||||||
|
# 2. 验证验证码
|
||||||
|
is_valid = await verify_code(req.email, req.verification_code)
|
||||||
|
if not is_valid:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_400_BAD_REQUEST,
|
||||||
|
detail="验证码错误或已过期"
|
||||||
|
)
|
||||||
|
|
||||||
|
# 3. 更新密码
|
||||||
|
new_hash = get_password_hash(req.new_password)
|
||||||
|
user.password_hash = new_hash
|
||||||
|
user.hashed_password = new_hash # 兼容旧字段
|
||||||
|
|
||||||
|
await db.commit()
|
||||||
|
|
||||||
|
logger.info("密码重置成功", email=req.email, user_id=str(user.id))
|
||||||
|
|
||||||
|
return SuccessResponse(
|
||||||
|
message="密码重置成功,请使用新密码登录"
|
||||||
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -51,6 +51,18 @@ class PasswordChangeRequest(BaseModel):
|
|||||||
new_password: str
|
new_password: str
|
||||||
|
|
||||||
|
|
||||||
|
class ForgotPasswordRequest(BaseModel):
|
||||||
|
"""忘记密码 - 发送验证码请求"""
|
||||||
|
email: EmailStr = Field(..., description="注册时使用的邮箱地址")
|
||||||
|
|
||||||
|
|
||||||
|
class ResetPasswordRequest(BaseModel):
|
||||||
|
"""忘记密码 - 重置密码请求"""
|
||||||
|
email: EmailStr = Field(..., description="注册时使用的邮箱地址")
|
||||||
|
verification_code: str = Field(..., min_length=6, max_length=6, description="邮箱验证码,6位数字")
|
||||||
|
new_password: str = Field(..., min_length=8, description="新密码,至少8个字符")
|
||||||
|
|
||||||
|
|
||||||
class UserCreate(BaseModel):
|
class UserCreate(BaseModel):
|
||||||
"""创建用户请求(自由注册)"""
|
"""创建用户请求(自由注册)"""
|
||||||
username: str = Field(..., min_length=3, max_length=50, description="用户名,3-50个字符")
|
username: str = Field(..., min_length=3, max_length=50, description="用户名,3-50个字符")
|
||||||
|
|||||||
@@ -0,0 +1,230 @@
|
|||||||
|
# MCP-Server 第一阶段状态报告
|
||||||
|
|
||||||
|
> 文档版本:v1.0
|
||||||
|
> 更新日期:2026-03-19
|
||||||
|
> 状态:第一阶段(底座和主链路)基本完成
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 一、第一阶段目标
|
||||||
|
|
||||||
|
第一阶段的核心目标是搭建 **"底座和主链路"**,为整个 AI Agent 平台提供基础能力支撑:
|
||||||
|
|
||||||
|
1. **多角色用户体系**:支持租户、渠道、管理员等多种角色的登录和权限管理
|
||||||
|
2. **Agent 全生命周期管理**:支持平台 Agent 和自定义 Agent 的创建、启动、停止、删除
|
||||||
|
3. **计费主链路**:支持 Agent 运行时长计费和模型 Token 调用计费
|
||||||
|
4. **资源配额管理**:支持余额管理、配额分配、预警通知
|
||||||
|
5. **模型网关集成**:与 LiteLLM 集成,支持多模型供应商接入
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 二、已完成项
|
||||||
|
|
||||||
|
### 2.1 用户与权限管理 ✅
|
||||||
|
|
||||||
|
| 功能 | 状态 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| 统一登录 | ✅ 完成 | 支持租户、渠道、管理员通过同一入口登录 |
|
||||||
|
| 用户注册 | ✅ 完成 | 支持邮箱注册(需验证码) |
|
||||||
|
| 角色权限 | ✅ 完成 | 支持 user、channel_admin、billing_admin、operations_admin、admin、super_admin 等角色 |
|
||||||
|
| API Key 管理 | ✅ 完成 | 支持创建、列出、删除 API Key,用于开发者集成 |
|
||||||
|
| Token 刷新 | ✅ 完成 | 支持 Access Token 过期后通过 Refresh Token 刷新 |
|
||||||
|
| 登出功能 | ✅ 完成 | 支持主动登出,Token 立即失效 |
|
||||||
|
|
||||||
|
### 2.2 渠道管理 ✅
|
||||||
|
|
||||||
|
| 功能 | 状态 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| 渠道创建 | ✅ 完成 | 管理员可创建渠道合作伙伴 |
|
||||||
|
| 渠道登录 | ✅ 完成 | 渠道管理员独立登录入口 |
|
||||||
|
| 租户管理 | ✅ 完成 | 渠道可创建和管理下属租户 |
|
||||||
|
| 资源分配 | ✅ 完成 | 渠道可将平台 Agent 和模型配额分配给租户 |
|
||||||
|
| 佣金配置 | ✅ 完成 | 支持配置渠道佣金比例 |
|
||||||
|
| 授信额度 | ✅ 完成 | 支持配置渠道授信额度 |
|
||||||
|
|
||||||
|
### 2.3 Agent 管理 ✅
|
||||||
|
|
||||||
|
| 功能 | 状态 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| 模板列表 | ✅ 完成 | 获取所有可用的 Agent 模板(平台模板 + 自定义模板) |
|
||||||
|
| 平台 Agent | ✅ 完成 | 预定义的 Agent 类型,无需配置即可使用 |
|
||||||
|
| 自定义 Agent | ✅ 完成 | 用户可配置环境变量创建自定义 Agent |
|
||||||
|
| Agent 创建 | ✅ 完成 | 创建 Agent 并自动部署到 Kubernetes |
|
||||||
|
| Agent 状态查询 | ✅ 完成 | 查询 Agent 运行状态、Pod 信息 |
|
||||||
|
| Agent 删除 | ✅ 完成 | 删除 Agent 并清理 Kubernetes 资源 |
|
||||||
|
| 健康检查 | ✅ 完成 | 监控 Agent 健康状态 |
|
||||||
|
|
||||||
|
### 2.4 工具管理 ✅
|
||||||
|
|
||||||
|
| 功能 | 状态 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| 模板工具 | ✅ 完成 | 基于 Agent 模板创建的工具(如 MySQL、PostgreSQL) |
|
||||||
|
| API 工具 | ✅ 完成 | 自定义 API 调用配置 |
|
||||||
|
| 外部数据工具 | ✅ 完成 | 用户上传工具配置,自动生成 Pydantic 工具文件 |
|
||||||
|
| 工具集 | ✅ 完成 | 将多个工具组合成工具集,方便部署 |
|
||||||
|
|
||||||
|
### 2.5 计费系统 ✅
|
||||||
|
|
||||||
|
| 功能 | 状态 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| EU 计费单位 | ✅ 完成 | 1 EU = 1 美元,统一计费单位 |
|
||||||
|
| Agent 运行时计费 | ✅ 完成 | 按 Agent 运行时长和资源使用量计费 |
|
||||||
|
| 模型 Token 计费 | ✅ 完成 | 按模型调用的 Token 数量计费(通过 LiteLLM) |
|
||||||
|
| 余额管理 | ✅ 完成 | 支持查询余额、充值、扣款 |
|
||||||
|
| 授信额度 | ✅ 完成 | 支持配置用户授信额度,余额不足时可透支 |
|
||||||
|
| PayPal 充值 | ✅ 完成 | 支持通过 PayPal 进行充值 |
|
||||||
|
| 计费记录查询 | ✅ 完成 | 支持按时间、Agent、模型等维度查询计费记录 |
|
||||||
|
|
||||||
|
### 2.6 配额管理 ✅
|
||||||
|
|
||||||
|
| 功能 | 状态 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| 平台 Agent 配额 | ✅ 完成 | 管理员分配给渠道,渠道分配给租户 |
|
||||||
|
| 自定义 Agent 配额 | ✅ 完成 | CPU/内存配额管理 |
|
||||||
|
| 模型配额 | ✅ 完成 | RPM(每分钟请求数)/ TPM(每分钟 Token 数)限制 |
|
||||||
|
| 配额预警 | ✅ 完成 | 余额低于阈值时自动预警 |
|
||||||
|
| 速率限制 | ✅ 完成 | 防止 API 滥用 |
|
||||||
|
|
||||||
|
### 2.7 模型供应商管理 ✅
|
||||||
|
|
||||||
|
| 功能 | 状态 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| 供应商创建 | ✅ 完成 | 管理员可添加模型供应商(OpenAI、Azure、Anthropic 等) |
|
||||||
|
| 模型列表 | ✅ 完成 | 获取 LiteLLM 中配置的所有可用模型 |
|
||||||
|
| 供应商授权 | ✅ 完成 | 管理员授权渠道使用特定供应商 |
|
||||||
|
| 健康检查 | ✅ 完成 | 监控供应商 API 可用性 |
|
||||||
|
|
||||||
|
### 2.8 监控与统计 ✅
|
||||||
|
|
||||||
|
| 功能 | 状态 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| 系统健康检查 | ✅ 完成 | 检查数据库、微服务状态 |
|
||||||
|
| 租户仪表盘 | ✅ 完成 | 展示 EU 消耗、模型使用、API 调用统计 |
|
||||||
|
| 全局 API 统计 | ✅ 完成 | 总调用次数、今日调用、成功/失败统计 |
|
||||||
|
| 审计日志 | ✅ 完成 | 记录关键操作日志 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 三、未完成项
|
||||||
|
|
||||||
|
### 3.1 Agent 运维功能
|
||||||
|
|
||||||
|
| 功能 | 状态 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| Agent 扩缩容 | ❌ 未实现 | 动态调整 Agent 副本数量 |
|
||||||
|
| Agent 日志查看 | ❌ 未实现 | 查看 Agent 运行日志 |
|
||||||
|
| Agent 重启 | ❌ 未实现 | 重启异常的 Agent |
|
||||||
|
|
||||||
|
### 3.2 前端集成待确认
|
||||||
|
|
||||||
|
| 功能 | 状态 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| 工作流编排 | ⚠️ 待确认 | 多 Agent 串联执行(最多 3 个节点) |
|
||||||
|
| 实时消息推送 | ⚠️ 待确认 | WebSocket 实时通知 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 四、当前遗留问题
|
||||||
|
|
||||||
|
### 4.1 功能完整性
|
||||||
|
|
||||||
|
| 问题 | 严重程度 | 说明 |
|
||||||
|
|------|----------|------|
|
||||||
|
| 邮箱验证服务 | 中 | 注册需要邮箱验证码,但邮件发送服务未配置 |
|
||||||
|
| 周期性计费任务 | 中 | 需要配置定时任务触发周期性计费 |
|
||||||
|
| Agent 停止计费 | 中 | 需确认 Agent 删除时计费是否正确结算 |
|
||||||
|
|
||||||
|
### 4.2 安全相关
|
||||||
|
|
||||||
|
| 问题 | 严重程度 | 说明 |
|
||||||
|
|------|----------|------|
|
||||||
|
| 默认密钥配置 | 高 | 生产环境必须通过环境变量覆盖默认密钥 |
|
||||||
|
|
||||||
|
### 4.3 数据清理
|
||||||
|
|
||||||
|
| 问题 | 严重程度 | 说明 |
|
||||||
|
|------|----------|------|
|
||||||
|
| 废弃数据表 | 低 | 旧版计费表已废弃,可在后续版本清理 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 五、系统架构概览
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────────────────┐
|
||||||
|
│ 前端应用 │
|
||||||
|
│ (租户端 / 渠道端 / 管理端) │
|
||||||
|
└───────────────────────────┬─────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────────────────────────────────────┐
|
||||||
|
│ MCP-Server │
|
||||||
|
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
|
||||||
|
│ │ 用户认证 │ │ Agent管理 │ │ 计费系统 │ │
|
||||||
|
│ │ 权限控制 │ │ 工具管理 │ │ 配额管理 │ │
|
||||||
|
│ └─────────────┘ └─────────────┘ └─────────────┘ │
|
||||||
|
└───────────────────────────┬─────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
┌───────────────┼───────────────┐
|
||||||
|
▼ ▼ ▼
|
||||||
|
┌───────────────┐ ┌───────────────┐ ┌───────────────┐
|
||||||
|
│ Agent Manager │ │ LiteLLM │ │ PostgreSQL │
|
||||||
|
│ (K8s Pods) │ │ Gateway │ │ + Redis │
|
||||||
|
└───────────────┘ └───────────────┘ └───────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 六、下一阶段建议
|
||||||
|
|
||||||
|
### 6.1 优先级高
|
||||||
|
|
||||||
|
1. **Agent 运维功能**:实现扩缩容、日志查看、重启功能
|
||||||
|
2. **邮件服务配置**:完成邮箱验证功能
|
||||||
|
3. **周期性计费**:配置定时任务确保计费准确
|
||||||
|
|
||||||
|
### 6.2 优先级中
|
||||||
|
|
||||||
|
1. **工作流编排**:确认前端需求后实现多 Agent 串联
|
||||||
|
2. **实时通知**:确认前端需求后实现 WebSocket 推送
|
||||||
|
|
||||||
|
### 6.3 优先级低
|
||||||
|
|
||||||
|
1. **数据清理**:清理废弃的数据表
|
||||||
|
2. **性能优化**:根据实际负载优化查询性能
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 七、核心业务流程
|
||||||
|
|
||||||
|
### 7.1 租户使用 Agent 流程
|
||||||
|
|
||||||
|
```
|
||||||
|
1. 租户登录 → 2. 查看可用 Agent 模板 → 3. 创建 Agent
|
||||||
|
↓
|
||||||
|
4. Agent 部署到 K8s ← 5. 系统检查配额 ← 6. 系统检查余额
|
||||||
|
↓
|
||||||
|
7. Agent 运行 → 8. 系统记录计费 → 9. 定期扣款
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7.2 渠道分配资源流程
|
||||||
|
|
||||||
|
```
|
||||||
|
1. 渠道申请资源 → 2. 管理员审批 → 3. 分配配额给渠道
|
||||||
|
↓
|
||||||
|
4. 渠道创建租户 → 5. 渠道分配配额给租户 → 6. 租户使用资源
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7.3 计费流程
|
||||||
|
|
||||||
|
```
|
||||||
|
Agent 运行时计费:
|
||||||
|
Agent 启动 → 记录开始时间 → Agent 停止 → 计算时长 → 计算费用 → 扣款
|
||||||
|
|
||||||
|
模型 Token 计费:
|
||||||
|
调用模型 → LiteLLM 处理 → 回调通知 → 记录 Token 用量 → 计算费用 → 扣款
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*文档结束*
|
||||||
Reference in New Issue
Block a user