186 lines
9.8 KiB
Markdown
186 lines
9.8 KiB
Markdown
# 实现计划:Weibo-HotSign 多用户签到系统
|
||
|
||
## 概述
|
||
|
||
按照自底向上的顺序实现:先构建共享基础层,再逐步实现各微服务。每个阶段包含核心实现和对应的测试任务。
|
||
|
||
## Tasks
|
||
|
||
- [x] 1. 创建共享模块 (shared/)
|
||
- [x] 1.1 创建 `backend/shared/` 包结构和共享配置
|
||
- 创建 `shared/__init__.py`、`shared/config.py`
|
||
- 配置项包括 DATABASE_URL、REDIS_URL、JWT_SECRET_KEY、COOKIE_ENCRYPTION_KEY
|
||
- 使用 pydantic-settings 从环境变量加载
|
||
- _Requirements: 10.1, 10.2_
|
||
- [x] 1.2 创建共享 ORM 模型和数据库连接管理
|
||
- 创建 `shared/models/base.py`:AsyncEngine、AsyncSessionLocal、Base、get_db()
|
||
- 创建 `shared/models/user.py`:User 模型(含 accounts relationship)
|
||
- 创建 `shared/models/account.py`:Account 模型(含 tasks、signin_logs relationship)
|
||
- 创建 `shared/models/task.py`:Task 模型
|
||
- 创建 `shared/models/signin_log.py`:SigninLog 模型
|
||
- 所有模型与 `init-db.sql` 中的表结构对齐
|
||
- _Requirements: 10.1, 10.2, 10.3_
|
||
- [x] 1.3 实现 Cookie 加密/解密工具 (`shared/crypto.py`)
|
||
- 使用 pycryptodome 实现 AES-256-GCM 加密/解密
|
||
- `encrypt_cookie(plaintext, key) -> (ciphertext_b64, iv_b64)`
|
||
- `decrypt_cookie(ciphertext_b64, iv_b64, key) -> plaintext`
|
||
- 密钥从环境变量 COOKIE_ENCRYPTION_KEY 派生(使用 SHA-256 哈希为32字节)
|
||
- _Requirements: 3.1, 3.2, 10.4_
|
||
- [ ]* 1.4 编写 Cookie 加密 Round-trip 属性测试
|
||
- **Property 1: Cookie 加密 Round-trip**
|
||
- 使用 hypothesis 生成随机字符串,验证 encrypt 后 decrypt 还原
|
||
- **Validates: Requirements 3.1, 3.2, 3.3**
|
||
- [x] 1.5 实现统一响应格式工具 (`shared/response.py`)
|
||
- `success_response(data, message)` 返回标准成功格式
|
||
- `error_response(message, code, details, status_code)` 返回标准错误格式
|
||
- _Requirements: 9.1, 9.2_
|
||
|
||
- [x] 2. 重构 Auth_Service(Token 刷新机制)
|
||
- [x] 2.1 重构 Auth_Service 使用 shared 模块
|
||
- 修改 `auth_service/app/main.py` 导入 shared models 和 get_db
|
||
- 删除 `auth_service/app/models/database.py` 中的重复 User 模型定义
|
||
- 更新 `auth_service/app/services/auth_service.py` 使用 shared User 模型
|
||
- _Requirements: 10.3_
|
||
- [x] 2.2 实现 Refresh Token 机制
|
||
- 在 `auth_service/app/utils/security.py` 中添加 `create_refresh_token()` 和 `verify_refresh_token()`
|
||
- Refresh Token 使用 Redis 存储(key: `refresh_token:{hash}`, value: `user_id`, TTL: 7天)
|
||
- 登录接口返回 access_token + refresh_token
|
||
- 实现 `/auth/refresh` 端点:验证旧 token → 删除旧 token → 生成新 token 对(Token Rotation)
|
||
- 更新 `auth_service/app/schemas/user.py` 添加 RefreshToken 相关 schema
|
||
- _Requirements: 1.3, 1.5, 1.6_
|
||
- [x] 2.3 为 Auth_Service 所有响应应用统一格式
|
||
- 注册、登录、刷新、获取用户信息接口使用 `shared/response.py` 格式化响应
|
||
- 注册全局异常处理器(HTTPException、RequestValidationError)
|
||
- _Requirements: 9.1, 9.2, 9.3, 9.4_
|
||
- [ ]* 2.4 编写认证流程属性测试
|
||
- **Property 2: 用户注册后可登录获取信息**
|
||
- **Property 3: 用户名/邮箱唯一性约束**
|
||
- **Property 4: 无效凭证登录拒绝**
|
||
- **Property 5: Refresh Token 轮换**
|
||
- **Property 6: 弱密码拒绝**
|
||
- **Validates: Requirements 1.1-1.8**
|
||
|
||
- [x] 3. Checkpoint - 确保共享模块和认证服务测试通过
|
||
- 运行所有测试,确认 shared 模块和 auth_service 工作正常
|
||
- 如有问题请向用户确认
|
||
|
||
- [x] 4. 实现 API_Service(账号管理)
|
||
- [x] 4.1 创建 API_Service 基础结构
|
||
- 创建 `api_service/app/__init__.py`、`main.py`、`config.py`、`dependencies.py`
|
||
- `main.py`:FastAPI 应用,注册 CORS、全局异常处理器、路由
|
||
- `dependencies.py`:JWT 认证依赖(`get_current_user`),复用 shared 的 JWT 验证逻辑
|
||
- _Requirements: 2.8, 9.1, 9.2, 9.3, 9.4_
|
||
- [x] 4.2 实现微博账号 CRUD 路由
|
||
- 创建 `api_service/app/schemas/account.py`:AccountCreate、AccountUpdate、AccountResponse
|
||
- 创建 `api_service/app/routers/accounts.py`:
|
||
- `POST /api/v1/accounts`:加密 Cookie 后存储,状态初始化为 "pending"
|
||
- `GET /api/v1/accounts`:返回当前用户的账号列表(不含 Cookie 明文)
|
||
- `GET /api/v1/accounts/{id}`:返回账号详情
|
||
- `PUT /api/v1/accounts/{id}`:更新备注或 Cookie(更新 Cookie 时重新加密)
|
||
- `DELETE /api/v1/accounts/{id}`:删除账号(级联删除 tasks 和 logs)
|
||
- 所有接口验证资源归属(user_id 匹配)
|
||
- _Requirements: 2.1-2.8_
|
||
- [ ]* 4.3 编写账号管理属性测试
|
||
- **Property 7: 账号创建与列表一致性**
|
||
- **Property 8: 账号详情 Round-trip**
|
||
- **Property 9: 账号更新反映**
|
||
- **Property 10: 账号删除级联**
|
||
- **Property 11: 跨用户资源隔离**
|
||
- **Property 12: 受保护接口认证要求**
|
||
- **Validates: Requirements 2.1-2.8, 4.6, 8.5, 8.4, 9.4**
|
||
|
||
- [-] 5. 实现 API_Service(任务配置)
|
||
- [x] 5.1 实现签到任务 CRUD 路由
|
||
- 创建 `api_service/app/schemas/task.py`:TaskCreate、TaskUpdate、TaskResponse
|
||
- 创建 `api_service/app/routers/tasks.py`:
|
||
- `POST /api/v1/accounts/{id}/tasks`:验证 Cron 表达式有效性,创建任务
|
||
- `GET /api/v1/accounts/{id}/tasks`:获取账号的任务列表
|
||
- `PUT /api/v1/tasks/{id}`:更新任务(启用/禁用)
|
||
- `DELETE /api/v1/tasks/{id}`:删除任务
|
||
- 使用 `croniter` 库验证 Cron 表达式
|
||
- 任务创建/更新/删除时通过 Redis pub/sub 通知 Task_Scheduler
|
||
- _Requirements: 4.1-4.6_
|
||
- [ ]* 5.2 编写任务配置属性测试
|
||
- **Property 13: 有效 Cron 表达式创建任务**
|
||
- **Property 14: 无效 Cron 表达式拒绝**
|
||
- **Property 15: 任务启用/禁用切换**
|
||
- **Property 16: 任务删除**
|
||
- **Validates: Requirements 4.1-4.6**
|
||
|
||
- [x] 6. 实现 API_Service(签到日志查询)
|
||
- [x] 6.1 实现签到日志查询路由
|
||
- 创建 `api_service/app/schemas/signin_log.py`:SigninLogResponse、PaginatedResponse
|
||
- 创建 `api_service/app/routers/signin_logs.py`:
|
||
- `GET /api/v1/accounts/{id}/signin-logs`:支持分页(page, size)和状态过滤(status)
|
||
- 返回按 `signed_at` 降序排列的日志
|
||
- 返回总记录数用于前端分页
|
||
- 验证账号归属权限
|
||
- _Requirements: 8.1-8.5_
|
||
- [ ]* 6.2 编写签到日志查询属性测试
|
||
- **Property 23: 签到日志时间倒序**
|
||
- **Property 24: 签到日志分页**
|
||
- **Property 25: 签到日志状态过滤**
|
||
- **Validates: Requirements 8.1-8.3**
|
||
|
||
- [ ] 7. Checkpoint - 确保 API_Service 所有测试通过
|
||
- 运行所有测试,确认账号管理、任务配置、日志查询功能正常
|
||
- 如有问题请向用户确认
|
||
|
||
- [ ] 8. 重构 Task_Scheduler(真实数据库交互)
|
||
- [ ] 8.1 重构 Task_Scheduler 使用 shared 模块
|
||
- 修改 `task_scheduler/app/celery_app.py` 导入 shared models
|
||
- 实现 `load_scheduled_tasks()`:从 DB 查询 `is_enabled=True` 的 Task,动态注册到 Celery Beat
|
||
- 实现 Redis pub/sub 监听:接收任务变更通知,动态更新调度
|
||
- 替换 `signin_tasks.py` 中的 mock 账号列表为真实 DB 查询
|
||
- _Requirements: 5.1, 5.2, 5.3_
|
||
- [ ] 8.2 实现分布式锁和重试机制
|
||
- 使用 Redis SETNX 实现分布式锁,防止同一任务重复调度
|
||
- 配置 Celery 任务重试:`max_retries=3`、`default_retry_delay=60`
|
||
- _Requirements: 5.4, 5.5_
|
||
- [ ]* 8.3 编写调度器属性测试
|
||
- **Property 17: 调度器加载已启用任务**
|
||
- **Property 18: 分布式锁防重复调度**
|
||
- **Validates: Requirements 5.1, 5.5**
|
||
|
||
- [ ] 9. 重构 Signin_Executor(真实数据库交互)
|
||
- [ ] 9.1 重构 Signin_Executor 使用 shared 模块
|
||
- 修改 `signin_service.py` 中的 `_get_account_info()` 从 DB 查询真实 Account 数据
|
||
- 修改 `weibo_client.py` 中的 `_decrypt_cookies()` 使用 `shared/crypto.py`
|
||
- 实现签到结果写入 `signin_logs` 表(替代 mock)
|
||
- 实现 Cookie 失效时更新 `account.status = "invalid_cookie"`
|
||
- _Requirements: 6.1, 6.2, 6.4, 6.5_
|
||
- [ ] 9.2 实现反爬虫防护模块
|
||
- 实现随机延迟函数:返回 `[min, max]` 范围内的随机值
|
||
- 实现 User-Agent 轮换:从预定义列表中随机选择
|
||
- 实现代理池集成:调用 proxy pool 服务获取代理,不可用时降级为直连
|
||
- _Requirements: 7.1, 7.2, 7.3, 7.4_
|
||
- [ ]* 9.3 编写签到执行属性测试
|
||
- **Property 19: 签到结果持久化**
|
||
- **Property 20: Cookie 失效时更新账号状态**
|
||
- **Property 21: 随机延迟范围**
|
||
- **Property 22: User-Agent 来源**
|
||
- **Validates: Requirements 6.1, 6.4, 6.5, 7.1, 7.2**
|
||
|
||
- [ ] 10. 更新 Dockerfile 和集成配置
|
||
- [ ] 10.1 更新 `backend/Dockerfile`
|
||
- 在每个构建阶段添加 `COPY shared/ ./shared/`
|
||
- 确保 shared 模块在所有服务容器中可用
|
||
- _Requirements: 10.1, 10.3_
|
||
- [ ] 10.2 更新 `backend/requirements.txt`
|
||
- 添加 `croniter`(Cron 表达式解析)
|
||
- 添加 `hypothesis`(属性测试)
|
||
- 添加 `pytest`、`pytest-asyncio`(测试框架)
|
||
- 确认 `pycryptodome`、`redis`、`celery` 等已存在
|
||
|
||
- [ ] 11. 最终 Checkpoint - 全量测试
|
||
- 运行所有单元测试和属性测试
|
||
- 验证各服务可独立启动
|
||
- 如有问题请向用户确认
|
||
|
||
## 备注
|
||
|
||
- 标记 `*` 的任务为可选测试任务,可跳过以加快 MVP 进度
|
||
- 每个任务引用了具体的需求编号以确保可追溯性
|
||
- 属性测试使用 `hypothesis` 库,每个测试至少运行 100 次迭代
|
||
- Checkpoint 任务用于阶段性验证,确保增量开发的正确性
|