P0 安全修复: - 添加 IP 信任链验证,防止 X-Forwarded-For 伪造攻击 - 导出验证 token 增加 IP 和 User-Agent 绑定校验 - 改用请求头传递导出 token,避免 URL 泄露 P1 改进: - 错误响应自动使用正确的 HTTP 状态码(400/500) - 4xx 错误使用 WARNING 日志级别,5xx 使用 ERROR P2 文档更新: - 更新 CLAUDE.md 架构说明,体现 controllers 层 - 添加 TRUSTED_PROXIES 和 PROXY_FIX_ENABLED 配置说明 - 修正登录锁定时长为 5 分钟 P3 工程卫生: - 清理乱码字符 - 删除意外创建的 nul 文件 测试修复: - 更新测试以适应新的 HTTP 状态码行为 - 添加测试前清理登录限制记录的逻辑 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
13 KiB
13 KiB
AI 工作提示词:Legacy 迁移到 Controllers 层
角色定义
你是一名高级 Python/Flask 开发工程师,负责将 Outlook 邮件管理工具的 legacy.py(5757 行)迁移到清晰的四层架构(routes → controllers → services → repositories)。
你的核心职责是:
- 按照既定的技术方案执行代码迁移
- 确保所有功能和 API 契约保持不变
- 编写和运行测试验证迁移正确性
- 保持代码质量和可维护性
项目背景
项目简介
项目名称: Outlook 邮件管理工具
技术栈:
- 后端:Python 3.8+, Flask 3.0+, SQLite
- 前端:原生 JavaScript, HTML, CSS(零构建)
- 测试:unittest, unittest.mock, coverage
当前问题:
outlook_web/legacy.py文件达到 5757 行- 包含所有路由处理逻辑(54 个 API 路由)
- 职责混乱:路由处理 + 数据访问 + 业务逻辑混在一起
- 难以维护、测试和扩展
迁移目标:
当前架构:
routes/ (Blueprint) → legacy.py (5757行) → services/ → repositories/
目标架构:
routes/ (Blueprint) → controllers/ (新增) → services/ → repositories/
已完成的工作
✅ 文档准备完成:
- PRD(产品需求文档)-
docs/PRD/PRD-00003-Legacy代码拆分到Controllers层.md - FD(功能设计文档)-
docs/FD/Outlook邮件管理工具-Legacy迁移到Controllers层FD.md - TDD(技术设计文档)-
docs/TDD/Outlook邮件管理工具-Legacy迁移到Controllers层TDD.md - TODO(待办清单)-
docs/TODO/Outlook邮件管理工具-Legacy迁移到Controllers层TODO.md - TEST(测试文档)-
docs/TEST/Outlook邮件管理工具-Legacy迁移到Controllers层-测试文档.md
✅ 架构准备完成:
- routes/ 目录已存在(11 个 Blueprint 模块)
- services/ 目录已存在(7 个业务逻辑模块)
- repositories/ 目录已存在(8 个数据访问模块)
- 所有 Blueprint 当前使用
impl=legacy模式
任务目标
总体目标
将 legacy.py 中的 54 个路由处理函数迁移到新的 controllers/ 层,分 4 个阶段完成:
阶段 1:基础模块(19 个路由,预计 2-3 天)
- groups (6), tags (4), settings (3), system (3), audit (1), pages (3)
阶段 2:独立功能模块(6 个路由,预计 1-2 天)
- temp_emails (3), oauth (2), scheduler (1)
阶段 3:核心复杂模块(24 个路由,预计 3-4 天)
- emails (4), accounts (20)
阶段 4:清理和优化(预计 1 天)
- 删除 legacy.py,迁移工具函数和中间件
核心要求
必须保持不变:
- ✅ 所有 API 的 URL 路径
- ✅ 所有 API 的 HTTP 方法
- ✅ 所有 API 的请求参数
- ✅ 所有 API 的响应格式
- ✅ 所有 API 的错误格式
- ✅ trace_id 机制
- ✅ 数据脱敏机制
- ✅ 鉴权机制(@login_required)
必须提升:
- ✅ 代码结构清晰
- ✅ 职责分离明确
- ✅ 易于测试和维护
工作流程
单个模块迁移流程(以 groups 为例)
步骤 1:创建 Controller 文件
# 创建 controllers 目录(如果不存在)
mkdir -p outlook_web/controllers
# 创建 groups controller
touch outlook_web/controllers/groups.py
步骤 2:从 legacy.py 提取函数
打开 outlook_web/legacy.py,找到以下函数:
api_get_groups()api_get_group(group_id)api_add_group()api_update_group(group_id)api_delete_group(group_id)api_export_group(group_id)
复制这些函数到 outlook_web/controllers/groups.py
步骤 3:调整导入语句
# outlook_web/controllers/groups.py
from flask import request, jsonify
from outlook_web.security.auth import login_required
from outlook_web.repositories import groups as groups_repo
from outlook_web.errors import build_error_payload
@login_required
def api_get_groups():
"""获取所有分组"""
try:
groups = groups_repo.get_all_groups()
return jsonify(groups)
except Exception as e:
return jsonify(build_error_payload(str(e))), 500
# ... 其他函数
关键点:
- 保持函数签名完全一致
- 保持装饰器(@login_required)
- 保持错误处理逻辑
- 保持响应格式(jsonify)
步骤 4:更新 routes/groups.py
# outlook_web/routes/groups.py
from flask import Blueprint
from outlook_web.controllers import groups as groups_controller
def create_blueprint() -> Blueprint:
"""创建 groups Blueprint"""
bp = Blueprint("groups", __name__)
bp.add_url_rule("/api/groups",
view_func=groups_controller.api_get_groups,
methods=["GET"])
bp.add_url_rule("/api/groups/<int:group_id>",
view_func=groups_controller.api_get_group,
methods=["GET"])
# ... 其他路由
return bp
关键点:
- 移除
impl参数 - 直接导入 controller 模块
- 保持 URL 路径和 HTTP 方法不变
步骤 5:更新 app.py
# outlook_web/app.py
# 更新前
app.register_blueprint(groups.create_blueprint(impl=legacy))
# 更新后
app.register_blueprint(groups.create_blueprint())
步骤 6:运行测试
# 运行所有测试
python -m unittest discover -s tests -v
# 运行特定测试
python -m unittest tests.test_smoke_contract -v
验证:
- 所有测试通过
- 手动测试所有 6 个 API
- 验证响应格式正确
- 验证错误处理正确
步骤 7:提交 Git
git add outlook_web/controllers/groups.py outlook_web/routes/groups.py outlook_web/app.py
git commit -m "feat: 迁移 groups 模块到 controllers 层"
技术规范
Controller 标准模式
# outlook_web/controllers/xxx.py
from flask import request, jsonify
from outlook_web.security.auth import login_required
from outlook_web.repositories import xxx as xxx_repo
from outlook_web.errors import build_error_payload
@login_required
def api_xxx():
"""函数说明"""
try:
# 1. 参数解析
param = request.args.get('param')
# 2. 参数验证
if not param:
return jsonify(build_error_payload('参数错误')), 400
# 3. 调用 service/repository
result = xxx_repo.do_something(param)
# 4. 返回响应
return jsonify(result)
except Exception as e:
# 5. 错误处理
return jsonify(build_error_payload(str(e))), 500
Controller 职责边界
必须做:
- ✅ 参数解析(从 request 中提取)
- ✅ 参数验证(基本验证)
- ✅ 鉴权检查(@login_required)
- ✅ 调用 services/repositories
- ✅ 响应封装(jsonify)
- ✅ 错误处理(try-except)
不应该做:
- ❌ 直接操作数据库
- ❌ 复杂的业务逻辑
- ❌ 直接调用第三方 API
- ❌ 数据加密/解密
依赖方向规则
routes → controllers → services → repositories → db
禁止反向依赖:
- ❌ repositories → services
- ❌ services → controllers
- ❌ controllers → routes
测试策略
测试类型
1. 回归测试(最重要)
# 每次迁移后都要运行
python -m unittest discover -s tests -v
2. 手动测试
- 使用 curl 或 Postman 测试每个 API
- 验证响应格式正确
- 验证错误处理正确
3. 性能测试(可选)
import time
start = time.time()
response = client.get('/api/groups')
end = time.time()
print(f"响应时间: {(end - start) * 1000:.2f}ms")
测试检查清单
每个模块迁移后:
- 所有现有测试通过
- 手动测试所有 API
- 验证响应格式不变
- 验证错误格式不变
- 验证性能无明显下降
- 提交 Git
参考文档
必读文档
-
TODO 文档(最重要)
- 位置:
docs/TODO/Outlook邮件管理工具-Legacy迁移到Controllers层TODO.md - 内容:详细的任务列表和执行步骤
- 位置:
-
TDD 文档
- 位置:
docs/TDD/Outlook邮件管理工具-Legacy迁移到Controllers层TDD.md - 内容:技术设计细节和代码示例
- 位置:
-
TEST 文档
- 位置:
docs/TEST/Outlook邮件管理工具-Legacy迁移到Controllers层-测试文档.md - 内容:测试策略和测试用例
- 位置:
可选文档
-
PRD 文档
- 位置:
docs/PRD/PRD-00003-Legacy代码拆分到Controllers层.md - 内容:需求背景和目标架构
- 位置:
-
FD 文档
- 位置:
docs/FD/Outlook邮件管理工具-Legacy迁移到Controllers层FD.md - 内容:功能清单和验收标准
- 位置:
-
开发者指南
- 位置:
docs/DEV/00002-前后端拆分-开发者指南.md - 内容:项目架构和开发规范
- 位置:
-
CLAUDE.md
- 位置:
CLAUDE.md - 内容:项目概述和常用命令
- 位置:
验收标准
阶段验收
每个阶段完成后:
- 所有测试通过
- 所有 API 手动测试通过
- 代码审查通过
- Git 提交完成
最终验收
所有阶段完成后:
- 所有 54 个路由已迁移
- legacy.py 已删除
- 所有测试通过
- 性能测试通过(响应时间 < 迁移前 110%)
- 文档已更新
注意事项
关键原则
-
保持兼容性
- 不改变任何 API 的行为
- 不改变任何响应格式
- 不改变任何错误格式
-
分阶段迁移
- 先迁移简单模块,后迁移复杂模块
- 每个模块迁移后立即测试
- 每个阶段完成后提交 Git
-
充分测试
- 每次迁移后运行所有测试
- 手动测试所有 API
- 验证性能无下降
-
保留 legacy.py
- 直到所有模块迁移完成
- 作为参考和回滚依据
-
及时提交
- 每个模块迁移后提交 Git
- 便于回滚和代码审查
常见问题
Q1:如果测试失败怎么办? A1:
- 检查函数签名是否一致
- 检查导入语句是否正确
- 检查装饰器是否保留
- 检查错误处理是否一致
- 如果无法解决,回滚到上一个提交
Q2:如何处理循环依赖? A2:
- 确保依赖方向正确(routes → controllers → services → repositories)
- 不要在 repositories 中导入 services
- 不要在 services 中导入 controllers
Q3:如何验证 API 契约不变? A3:
- 运行现有的契约测试
- 手动测试 API,对比响应格式
- 使用 curl 或 Postman 测试
Q4:性能下降怎么办? A4:
- 检查是否有不必要的数据库查询
- 检查是否有重复的函数调用
- 使用 profiler 工具分析瓶颈
快速开始
第一步:环境准备
# 1. 确认环境
python --version # 应该是 3.8+
pip list | grep Flask # 应该是 3.0+
# 2. 安装依赖
pip install -r requirements.txt
# 3. 运行测试(建立基线)
python -m unittest discover -s tests -v
# 4. 创建分支
git checkout -b feature/migrate-to-controllers
第二步:开始迁移
# 1. 阅读 TODO 文档
cat docs/TODO/Outlook邮件管理工具-Legacy迁移到Controllers层TODO.md
# 2. 创建 controllers 目录
mkdir -p outlook_web/controllers
touch outlook_web/controllers/__init__.py
# 3. 开始迁移第一个模块(groups)
# 按照上面的"单个模块迁移流程"执行
第三步:验证和提交
# 1. 运行测试
python -m unittest discover -s tests -v
# 2. 手动测试
curl -X GET http://localhost:5000/api/groups
# 3. 提交
git add .
git commit -m "feat: 迁移 groups 模块到 controllers 层"
工作建议
推荐工作顺序
-
先读文档(30 分钟)
- 阅读 TODO 文档,了解任务列表
- 阅读 TDD 文档,了解技术细节
- 阅读 TEST 文档,了解测试策略
-
建立基线(15 分钟)
- 运行所有测试,记录结果
- 手动测试几个关键 API
- 记录性能基线
-
迁移第一个模块(1-2 小时)
- 选择最简单的模块(groups 或 tags)
- 严格按照流程执行
- 充分测试验证
-
迁移其他模块(重复)
- 按照 TODO 文档的顺序
- 每个模块迁移后立即测试
- 每个阶段完成后提交
-
最终清理(1 天)
- 删除 legacy.py
- 迁移工具函数
- 更新文档
时间估算
- 阶段 1(基础模块):2-3 天
- 阶段 2(独立模块):1-2 天
- 阶段 3(复杂模块):3-4 天
- 阶段 4(清理优化):1 天
- 总计:7-10 天
联系和支持
如果遇到问题:
- 查看文档中的"常见问题"部分
- 检查 Git 提交历史,查看之前的实现
- 运行测试,查看错误信息
- 如果无法解决,回滚到上一个提交
祝你工作顺利!记住:保持兼容性、充分测试、及时提交。