Files
xiaoxia-saas/docs/PHASE4-DESIGN.md
T

16 KiB
Raw Blame History

Phase 4: SAAS 产品化 - 设计文档

版本:v1.0
创建时间:2026-06-17
负责人:小虾 🦐
目标完成日期:2026-07-15


📋 目标

将小虾 SaaS 从技术 Demo 升级为真正的多租户商业化产品:

  • ✅ 用户可以注册/登录/管理账号
  • ✅ 支持多租户隔离和权限控制
  • ✅ 支持订阅套餐和在线支付

🎯 核心功能模块

1️⃣ 认证与账号体系

功能列表

  • 用户注册

    • 邮箱 + 密码注册
    • 邮箱验证(发送验证链接)
    • 用户名唯一性检查
  • 用户登录

    • 邮箱/用户名 + 密码登录
    • JWT Token 签发(access_token + refresh_token)
    • 记住我(30 天有效期)
  • 密码管理

    • 忘记密码(邮件重置链接)
    • 修改密码
    • 密码强度要求(最少 8 位,包含字母+数字)
  • Session 管理

    • 刷新 Token
    • 登出(撤销 Token)
    • 查看活跃 Session(设备/IP/时间)
    • 强制登出所有设备

技术方案

密码存储

  • 使用 bcrypt 哈希密码(cost=12)
  • 不存储明文密码
  • 密码哈希存储在 User.password_hash 字段

JWT Token 设计

{
  "access_token": {
    "payload": {
      "user_id": "uuid",
      "workspace_id": "uuid",
      "role": "owner|admin|member|viewer",
      "exp": 1800  // 30 分钟过期
    }
  },
  "refresh_token": {
    "payload": {
      "user_id": "uuid",
      "session_id": "uuid",
      "exp": 2592000  // 30 天过期
    },
    "存储": "Redis (key: refresh_token:{session_id}, value: user_id)"
  }
}

Token 刷新流程

  1. 客户端检测 access_token 即将过期(剩余 < 5 分钟)
  2. 用 refresh_token 调用 /auth/refresh
  3. 验证 refresh_token 在 Redis 中存在且未过期
  4. 签发新的 access_token(可选:同时轮转 refresh_token)

邮件服务

  • SMTP 配置(支持 Gmail/阿里云企业邮箱等)
  • 邮件模板(欢迎邮件/验证邮件/密码重置)
  • 异步发送(Celery 任务)

API 设计

POST   /api/v1/auth/register          # 注册
POST   /api/v1/auth/login             # 登录
POST   /api/v1/auth/logout            # 登出
POST   /api/v1/auth/refresh           # 刷新 Token
POST   /api/v1/auth/password/forgot   # 忘记密码
POST   /api/v1/auth/password/reset    # 重置密码
POST   /api/v1/auth/password/change   # 修改密码
GET    /api/v1/auth/verify-email      # 邮箱验证
GET    /api/v1/auth/sessions          # 查看活跃 Session
DELETE /api/v1/auth/sessions/:id      # 删除指定 Session
DELETE /api/v1/auth/sessions/all      # 登出所有设备

数据模型扩展

User 实体新增字段

class User(BaseEntity):
    # 原有字段
    username: str
    email: str
    display_name: str
    
    # 新增字段
    password_hash: str              # bcrypt 哈希
    email_verified: bool = False    # 邮箱是否验证
    email_verification_token: str   # 邮箱验证令牌
    password_reset_token: str       # 密码重置令牌
    password_reset_expires_at: datetime  # 重置令牌过期时间
    last_login_at: datetime         # 最后登录时间
    last_login_ip: str              # 最后登录 IP

新增 Session 实体

class Session(BaseEntity):
    user_id: str                    # 所属用户
    refresh_token_hash: str         # refresh_token 哈希
    device_info: str                # 设备信息(User-Agent)
    ip_address: str                 # 登录 IP
    expires_at: datetime            # 过期时间
    last_active_at: datetime        # 最后活跃时间

2️⃣ 多租户权限体系

功能列表

  • Workspace 成员管理

    • 邀请成员(发送邀请邮件)
    • 移除成员
    • 转让 Workspace 所有权
  • 角色与权限

    • Owner(所有者):完全控制权
    • Admin(管理员):管理成员、项目、资产
    • Member(成员):创建/编辑自己的内容
    • Viewer(查看者):只读权限
  • 数据隔离

    • 所有资源(Project/Task/Asset)必须关联 Workspace
    • API 自动过滤非当前 Workspace 的数据
    • 防止跨 Workspace 访问

权限矩阵

操作 Owner Admin Member Viewer
查看 Workspace 信息 ✅ ✅ ✅ ✅
修改 Workspace 信息 ✅ ✅ ❌ ❌
删除 Workspace ✅ ❌ ❌ ❌
邀请成员 ✅ ✅ ❌ ❌
移除成员 ✅ ✅ ❌ ❌
修改成员角色 ✅ ✅ ❌ ❌
转让所有权 ✅ ❌ ❌ ❌
创建项目 ✅ ✅ ✅ ❌
编辑项目 ✅ ✅ 自己的 ❌
删除项目 ✅ ✅ 自己的 ❌
上传素材 ✅ ✅ ✅ ❌
查看素材 ✅ ✅ ✅ ✅
删除素材 ✅ ✅ 自己的 ❌
查看订阅/账单 ✅ ✅ ❌ ❌
修改订阅 ✅ ❌ ❌ ❌

技术方案

权限检查中间件

@require_permission("project:create")
async def create_project(request, ...):
    pass

权限装饰器实现

def require_permission(permission: str):
    def decorator(func):
        async def wrapper(request, *args, **kwargs):
            user = request.state.user
            workspace_id = request.state.workspace_id
            
            # 检查用户在当前 Workspace 的角色
            membership = get_workspace_membership(user.id, workspace_id)
            if not membership.has_permission(permission):
                raise HTTPException(403, "Permission denied")
            
            return await func(request, *args, **kwargs)
        return wrapper
    return decorator

数据隔离过滤器

# 所有查询自动加上 workspace_id 过滤
def list_projects(workspace_id: str) -> List[Project]:
    return project_repo.find_by_workspace(workspace_id)

API 设计

# Workspace 成员管理
GET    /api/v1/workspaces/:id/members          # 成员列表
POST   /api/v1/workspaces/:id/members/invite   # 邀请成员
DELETE /api/v1/workspaces/:id/members/:user_id # 移除成员
PATCH  /api/v1/workspaces/:id/members/:user_id # 修改角色
POST   /api/v1/workspaces/:id/transfer         # 转让所有权

# 邀请管理
GET    /api/v1/invitations                     # 我的邀请
POST   /api/v1/invitations/:id/accept          # 接受邀请
POST   /api/v1/invitations/:id/decline         # 拒绝邀请

数据模型扩展

新增 WorkspaceMembership 实体

class WorkspaceMembership(BaseEntity):
    workspace_id: str               # 所属 Workspace
    user_id: str                    # 成员用户
    role: WorkspaceRole             # 角色(owner/admin/member/viewer)
    invited_by_user_id: str         # 邀请人
    joined_at: datetime             # 加入时间

新增 WorkspaceInvitation 实体

class WorkspaceInvitation(BaseEntity):
    workspace_id: str               # 邀请加入的 Workspace
    email: str                      # 受邀邮箱
    role: WorkspaceRole             # 邀请角色
    invited_by_user_id: str         # 邀请人
    token: str                      # 邀请令牌
    expires_at: datetime            # 过期时间
    status: InvitationStatus        # pending/accepted/declined/expired

3️⃣ 订阅与计费体系

功能列表

  • 订阅套餐

    • 免费版:1 个 Workspace,3 个项目,10GB 存储
    • 专业版:5 个 Workspace,无限项目,100GB 存储,¥99/月
    • 企业版:无限 Workspace,无限项目,1TB 存储,专属支持,¥999/月
  • 支付功能

    • 支付宝扫码支付
    • 微信扫码支付
    • 自动续费(可选)
  • 账单管理

    • 订阅历史
    • 发票申请
    • 退款申请

技术方案

支付流程

  1. 用户选择套餐 → 创建订单
  2. 调用支付宝/微信支付 API → 生成支付二维码
  3. 用户扫码支付 → 支付平台回调我们的 webhook
  4. 验证回调签名 → 更新订单状态 → 激活订阅

订阅状态机

trial (试用) → active (有效) → expired (过期) → cancelled (取消)
                              ↓
                          grace_period (宽限期,3 天)

配额检查

  • 创建 Workspace 前检查套餐限制
  • 上传文件前检查存储空间
  • 超出配额时提示升级

API 设计

# 订阅管理
GET    /api/v1/subscriptions/plans             # 套餐列表
GET    /api/v1/subscriptions/current           # 当前订阅
POST   /api/v1/subscriptions/subscribe         # 订阅套餐
POST   /api/v1/subscriptions/cancel            # 取消订阅
POST   /api/v1/subscriptions/renew             # 续费

# 支付
POST   /api/v1/payments/create                 # 创建支付订单
GET    /api/v1/payments/:id                    # 查询订单状态
POST   /api/v1/payments/webhook/alipay         # 支付宝回调
POST   /api/v1/payments/webhook/wechat         # 微信回调

# 账单
GET    /api/v1/invoices                        # 账单列表
GET    /api/v1/invoices/:id                    # 账单详情
POST   /api/v1/invoices/:id/download           # 下载账单

数据模型

新增 Subscription 实体

class Subscription(BaseEntity):
    workspace_id: str               # 所属 Workspace
    plan: SubscriptionPlan          # 套餐(free/pro/enterprise)
    status: SubscriptionStatus      # 状态(trial/active/expired/cancelled)
    started_at: datetime            # 开始时间
    expires_at: datetime            # 到期时间
    auto_renew: bool                # 是否自动续费

新增 Payment 实体

class Payment(BaseEntity):
    workspace_id: str               # 所属 Workspace
    subscription_id: str            # 关联订阅
    amount: Decimal                 # 金额
    currency: str = "CNY"           # 货币
    payment_method: PaymentMethod   # alipay/wechat
    status: PaymentStatus           # pending/paid/failed/refunded
    transaction_id: str             # 支付平台交易号
    paid_at: datetime               # 支付时间

新增 Invoice 实体

class Invoice(BaseEntity):
    workspace_id: str               # 所属 Workspace
    payment_id: str                 # 关联支付
    invoice_number: str             # 发票号
    amount: Decimal                 # 金额
    tax_amount: Decimal             # 税额
    issued_at: datetime             # 开票时间
    pdf_url: str                    # PDF 下载地址

📐 开发规则与约定

代码规范

  1. 遵循 Clean Architecture

    • 认证逻辑在 packages/domain/auth/
    • Use Cases 在 packages/application/auth/
    • API 路由在 apps/api/app/api/routes/auth.py
  2. 安全第一

    • 所有密码必须哈希存储
    • JWT Secret 从环境变量读取,不硬编码
    • 敏感 API(修改密码/删除账号)需要二次验证
    • 所有输入必须验证和清洗
  3. 测试覆盖

    • 每个 Use Case 至少 1 个单元测试
    • 每个 API 端点至少 1 个集成测试
    • 安全相关功能(认证/权限)测试覆盖率 > 80%
  4. 日志与监控

    • 登录/登出/权限拒绝必须记录日志
    • 敏感操作(修改密码/删除账号)记录审计日志
    • 异常情况告警(大量登录失败/异常 IP)

Git 工作流

  • 每个功能模块一个分支(如 feature/auth-system)
  • 完成后合并到 main
  • 提交信息格式:feat(auth): add JWT login endpoint

部署策略

  • 认证功能先在测试环境验证
  • 灰度发布(10% 流量 → 50% → 100%)
  • 保留回滚能力(旧版本镜像保留 7 天)

📅 任务拆解与排期

Milestone 1: 认证与账号体系(7 天,2026-06-17 ~ 2026-06-23)

Day 1-2:基础设施搭建

  • JWT 工具类实现(sign/verify/refresh)
  • bcrypt 密码哈希工具
  • Redis Session 存储
  • 邮件服务封装(SMTP + 模板)
  • User 实体扩展(密码字段)

Day 3-4:核心认证功能

  • 注册 API(邮箱验证)
  • 登录 API(JWT 签发)
  • 登出 API(撤销 Token)
  • 刷新 Token API
  • 密码重置流程

Day 5-6:Session 管理

  • Session 实体与 Repository
  • 活跃 Session 列表
  • 强制登出所有设备
  • 设备信息解析(User-Agent)

Day 7:测试与文档

  • 集成测试(注册/登录/登出/刷新)
  • 安全测试(密码强度/Token 伪造)
  • API 文档更新

Milestone 2: 多租户权限体系(7 天,2026-06-24 ~ 2026-06-30)

Day 1-2:权限基础

  • WorkspaceMembership 实体与 Repository
  • WorkspaceRole 枚举与权限定义
  • 权限检查中间件
  • 数据隔离过滤器

Day 3-4:成员管理

  • 邀请成员 API
  • 接受/拒绝邀请
  • 移除成员
  • 修改成员角色
  • 转让所有权

Day 5-6:权限验证

  • 所有现有 API 加上权限检查
  • 跨 Workspace 访问防护测试
  • 权限矩阵验证

Day 7:测试与文档

  • 权限测试(各角色权限边界)
  • 数据隔离测试
  • API 文档更新

Milestone 3: 订阅与计费(7 天,2026-07-01 ~ 2026-07-07)

Day 1-2:订阅基础

  • Subscription 实体与 Repository
  • SubscriptionPlan 枚举(free/pro/enterprise)
  • 配额检查工具
  • 套餐限制中间件

Day 3-4:支付集成

  • 支付宝 SDK 集成
  • 微信支付 SDK 集成
  • 创建支付订单 API
  • 支付回调处理(webhook)

Day 5-6:账单管理

  • Invoice 实体与 Repository
  • 生成账单 PDF
  • 账单列表/下载 API
  • 订阅历史记录

Day 7:测试与文档

  • 支付流程端到端测试
  • 配额检查测试
  • API 文档更新

Milestone 4: 前端集成与收尾(7 天,2026-07-08 ~ 2026-07-14)

Day 1-2:认证 UI

  • 登录页面
  • 注册页面
  • 忘记密码页面
  • 邮箱验证提示

Day 3-4:权限 UI

  • 成员管理页面
  • 邀请成员弹窗
  • 角色选择器
  • 权限说明文档

Day 5-6:订阅 UI

  • 套餐选择页面
  • 支付二维码页面
  • 账单管理页面
  • 配额使用展示

Day 7:上线准备

  • 端到端测试
  • 性能测试(登录/权限检查)
  • 安全审计
  • 生产环境部署

🔒 安全检查清单

认证安全

  • 密码哈希使用 bcrypt,cost ≥ 12
  • JWT Secret 强度足够(≥ 32 字节随机)
  • Token 过期时间合理(access 30 分钟,refresh 30 天)
  • 防止暴力破解(登录失败 5 次锁定 15 分钟)
  • 防止用户枚举(注册/登录错误信息统一)

数据安全

  • 所有查询强制 Workspace 过滤
  • 跨 Workspace 访问返回 403,不是 404
  • 敏感字段(密码哈希)不出现在 API 响应
  • SQL 注入防护(使用 ORM,参数化查询)
  • XSS 防护(输入清洗,输出转义)

支付安全

  • 回调验证签名
  • 订单金额不信任客户端
  • 防止重放攻击(nonce + timestamp)
  • 支付密钥不出现在日志

📊 成功指标

  • 用户可以完整走通注册 → 登录 → 使用 → 续费流程
  • 权限系统无漏洞(各角色权限边界清晰)
  • 支付成功率 > 95%
  • 认证 API 响应时间 < 200ms
  • 权限检查开销 < 10ms
  • 安全测试通过(无 SQL 注入/XSS/CSRF)

📝 备注

  • 邮件服务可以先用 SMTP(Gmail/阿里云邮箱),后期再考虑 SendGrid
  • 支付回调需要公网可访问地址(备案通过后才能配置)
  • 支付功能可以先用沙箱环境测试
  • 订阅计费逻辑需要 cron 定时任务检查到期(每小时一次)

老大确认后,我就把这些任务同步到推进器里。