Files
SMANAGE/SAAS_ARCHITECTURE.md
TermiNexus 966ef66b08 docs(arch): 同步UserRole/角色作用域数据模型描述(关联表为准)
UserRole遗留字段(DeptUUID/WorkgroupUUID/RoleType)已删除,部门/工作组归属与成员类型全走关联表
2026-08-28 15:34:36 +08:00

276 lines
15 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# SAAS 架构概览
> 面向技术决策会议的架构说明文档。本文档聚焦 SAAS 多租户-公司-部门-用户-角色架构设计、当前实现状态与未来发展方向。
---
## 1. 项目定位
**GVS-DSDK** 是一套面向中小企业(SMB)的 SAAS 化企业管理平台,包含:
- **多租户 SAAS 框架**:支持租户入驻、审核、隔离
- **企业资源管理(GERP)**:组织、角色、权限、菜单、工单、资产、文档
- **三大业务引擎**:分佣引擎、支付网关、统计引擎
- **分布式通信底座(MSYNC)**:服务注册、发现、分布式事务
## 2. 技术栈
| 层 | 技术 |
|---|---|
| 后端框架 | Django 4.2+ / DRF / SimpleJWT |
| 异步任务 | Celery + Redis(可降级同步) |
| 实时通信 | Socket.IO(python-socketio) |
| 数据库 | MySQL 5.7+(7 库分库路由) |
| 缓存 | Redis(可降级 locmem) |
| 安全 | bcrypt / AES-256-GCM / JWT |
| 前端 | 原生 HTML/JS + 自研 NeoUI/GERPUI 组件 |
| 部署 | Gunicorn + Nginx 反向代理 |
## 3. 双包架构
```
┌─────────────────────────────────────────────────────┐
│ d:\SMANAGE(项目根) │
│ │
│ ┌──────────────────────┐ ┌──────────────────────┐│
│ │ gvsds │ │ gvsdsdk ││
│ │ 主服务器(业务层) │◄─┤ 分布式 SDK(薄封装)││
│ │ - Django 项目 │ │ - 协议契约层 ││
│ │ - 14 个业务 App │ │ - 惰性加载 ││
│ │ - 完整业务实现 │ │ - PascalCase 协议 ││
│ └──────────────────────┘ └──────────────────────┘│
│ ▲ ▲ │
│ │ │ │
│ ┌──────────────────────┐ ┌──────────────────────┐│
│ │ ATestCServer │ │ TempLate/ ││
│ │ 子服务器示例 │ │ 前端模板资源 ││
│ │ 通过 SDK 接入 │ │ GERP/AKS/MSOC 等 ││
│ └──────────────────────┘ └──────────────────────┘│
└─────────────────────────────────────────────────────┘
```
### 3.1 `gvsds` — 主服务器
- 14 个 Django App:`core / gerp / ugm / crb / invite / ccgo / sve / t4 / mc / doc / api / msync / payment / commission / stats`
- 7 库分库路由:`Users / GerpCore / Plans / Tasks / T4PC / Document / Minecraft`
- 6 个自定义中间件:IP 过滤、域名注入、当前角色注入、服务认证、攻击检测、错误日志
### 3.2 `gvsdsdk` — 分布式 SDK / 通用 SAAS 服务层
- **服务层**:从薄封装演进为**通用 SAAS 服务层**——`RoleManager / AuthManager / AdminUserManager / TenantManager / CompanyManager / DepartmentManager / MessageManager / MenuManager / WorkOrderManager / InventoryManager / AssetManager / AuditManager / OrderManager / StatsManager / UserService` 等,gvsds 视图层通过它们访问数据(裸 ORM 已基本消除)
- **惰性加载(PEP 562)**:130+ 符号按需 import
- **双类导出**:自有实现(无 Django 依赖,子服务器可用)+ 服务端实现(依赖 Django ORM)
- **msync 原生实现(1.1.0)**:通信底座已从 `gvsds.apps.msync` 整体迁入 `gvsdsdk/msync`(models/registry/ogm/transaction/auth + Django 集成层),可脱离 gvsds 独立部署(屏蔽 gvsds 后全模块独立导入验证通过)
- **引擎**:`CommissionEngine`(分佣)、`PaymentManager`(支付)、`OrderManager`(订单状态机)、`StatsManager`(统计)、`TransactionManager`(分布式事务)
### 3.3 主从通信机制
- **版本校验**:启动时 `gvsdsdk.check_min_version('1.1.0')`,主从必须一致(版本兼容矩阵见 `gvsdsdk/VERSION_MATRIX.md`)
- **Socket.IO 协议**:20+ 事件,全程 PascalCase 字段
- **支付网关自动注册**:`gvsdsdk/apps.py` 的 `ready()` 钩子
---
## 4. SAAS 多租户架构(核心)
### 4.1 组织四层架构
```
┌──────────────────────────────────────────────────────────┐
│ 第 4 层:鉴权规则层(运行时) │
│ 操作权限 (RBAC) 数据权限 (ABAC + RoleScope) │
├──────────────────────────────────────────────────────────┤
│ 第 3 层:角色权限载体层 │
│ Role + UserRole + RolePermission │
├──────────────────────────────────────────────────────────┤
│ 第 2 层:岗位模板层(初始化快照) │
│ PositionTemplate + PositionTemplatePermission │
│ CopyToRole 一次性复制,后续独立演进 │
├──────────────────────────────────────────────────────────┤
│ 第 1 层:组织人事层 │
│ Tenant → Company → Department │
│ UserDept(员工-部门多对多) │
│ Position(人事职务标签,与权限解耦) │
│ Workgroup(跨部门工作组) Shop(商铺,归公司) │
└──────────────────────────────────────────────────────────┘
```
### 4.2 数据模型核心表(共 17 张 SAAS 表)
| 分类 | 表名 | 职责 |
|---|---|---|
| **租户** | `Tenant` | 多租户根,含审核状态/到期时间 |
| **组织** | `Company` / `CompanyInfo` / `Department` / `Workgroup` | 公司树/工商信息/部门树/跨部门组 |
| **用户** | `User` / `UserAvatar` / `User2FA` / `UserPending2FA` / `UserLoginLog` / `AccountActivation` / `Password` / `UserIDCard` | 用户身份与认证 |
| **角色权限** | `Role` / `Permission` / `UserRole` / `RolePermission` | RBAC 核心 |
| **岗位模板** | `PositionTemplate` / `PositionTemplatePermission` | 权限初始化快照 |
| **人事标签** | `Position` | 职务标签(与权限解耦) |
| **商铺** | `Shop` / `RoleShop` | 多商铺体系 |
| **ABAC** | `UserABAC` | 属性访问控制(补充) |
| **审计** | `AuditLog` / `AbnormalUserLog` | 操作审计 + 攻击溯源 |
### 4.3 关键设计决策
#### (1) Position 与权限**完全解耦**
- 人事职务标签(`Position`)仅用于人事管理,**不直接绑定权限**
- 调岗/升职只修改 `Position`,权限只通过 `UserRole → RolePermission → Permission` 走
- 规避了业界常见错误:把职务直接绑权限导致调岗时权限树重算
#### (2) PositionTemplate 的"快照复制"机制
- 模板 → 角色 = **一次性复制**(`CopyToRole`),复制后两者无运行时绑定
- 模板调整只影响**之后新建**的角色,已有角色不被动变更
- 避免了"模板改一个字段,全员权限突然变了"的运维灾难
#### (3) UserRole 实体化 + 关联表(部门/工作组多对多)
`UserRole` 是"用户↔角色"的**实体化中间表**(联合唯一:同一用户+同一角色仅一行):
- **权限分配**:User ↔ Role 多对多(`UserRoleUUID` 作为全局唯一关联实体)
- **组织归属**:不再放 UserRole 上,改走关联表(多对多):
- `UserRoleDepartment`:(用户-角色对) ↔ 部门(`UserRoleUUID + DeptUUID`)
- `UserRoleWorkgroup`:(用户-角色对) ↔ 工作组(`UserRoleUUID + WorkgroupUUID`)
- **成员类型**:`RoleType`(0=成员 / 1=负责人/组长)冗余在关联表,**按部门/工作组区分**
**优势**:一个用户-角色对可同时挂多个部门/工作组,且在不同部门可分别标注成员/负责人
**注意**:UserRole 上的遗留字段(`DeptUUID / WorkgroupUUID / RoleType`)已废弃删除(见 gvsdsdk 0002 迁移),
全部语义以关联表为准。
#### (4) 角色作用域四档数据权限(`RoleScope`)
| 类型 | 判定条件 | 可见范围 |
|---|---|---|
| `admin` | IsSuperuser/IsStaff 或 `admin:super` 权限 | 全公司 |
| `dept_manager` | `UserRoleDepartment.RoleType=1`(按当前公司过滤,可多部门) | 本部门成员 |
| `workgroup_lead` | `UserRoleWorkgroup.RoleType=1`(按当前公司过滤,可多工作组) | 本工作组成员 |
| `member` | 其他 | 仅自己 |
### 4.4 运行时鉴权流程
```
HTTP Request
│
├─► JWTAuthentication → User 实例
├─► CurrentRoleMiddleware → request.current_role (Role)
├─► DomainMiddleware → request.current_company_uuid
│
├──► 操作权限校验:PermissionVerifier(permission, attrs, user, request)
│ ├─ ABAC:UserABAC.HierarchicalPermissionIdentifiers ∋ attr?
│ └─ RBAC:RolePermission(角色)→Permission.PermCode ∋ attr?
│ (含请求级缓存,消除 N+1)
│
└──► 数据权限校验:RoleScope.GetUserScope(request)
└─ ApplyScopeToQueryset(qs, scope, table_name)
按 admin/dept_manager/workgroup_lead/member 差异化过滤
```
### 4.5 主键设计
- 全程使用 `BINARY(16)` UUID 主键
- 优势:分布式生成、无 ID 冲突、不暴露顺序信息
- 代价:InnoDB 聚簇索引无序,写入有页分裂开销(可考虑改 UUIDv7)
---
## 5. 三大业务引擎
### 5.1 分佣引擎(`CommissionEngine`)
| 策略 | Type | 说明 |
|---|---|---|
| `PercentageStrategy` | `percentage` | 比例分账,支持保底/封顶 |
| `FixedStrategy` | `fixed` | 固定金额 |
| `TieredStrategy` | `tiered` | 阶梯分账 |
| `RemainderStrategy` | `remainder` | 剩余归平台 |
| `WithdrawalFeeStrategy` | `withdrawal_fee` | 提现手续费 |
支持:规则配置 → 触发分佣 → 预结算 → 邀请链分佣 → 查询统计
### 5.2 支付网关(`PaymentManager`)
| 渠道 | 支付方式 | 转账 |
|---|---|---|
| 微信支付 | JSAPI/Native/H5/小程序 | 支持 |
| 支付宝 | APP/H5/Native | 支持 |
| 银行卡 | APP/H5/Native | 仅 bank 类型 |
支持:网关配置 → 支付/查询/退款/转账 → 回调处理
### 5.3 统计引擎(`stats`)
- Celery 定时任务:每日重置 / 每月重置 / 排行榜构建 / 过期清理
- 按角色差异化仪表盘
---
## 6. 当前实现状态
### 6.1 已完成
- ✅ 14 个业务 App 完整实现
- ✅ 多租户入驻审核工作流
- ✅ RBAC + ABAC 混合鉴权
- ✅ 分佣引擎 + 支付网关 + 统计引擎
- ✅ MSYNC 分布式通信(注册/发现/OGM/Saga 事务)
- ✅ 文件分片上传 + 资产管理
- ✅ 操作审计日志 + 攻击检测
- ✅ **服务层化迁移(P0/P1/P2 全部完成,2026-08-07)**:role_scope 数据权限底座、form_service 角色/用户链路、菜单/工单/消息/物品/背包/文档/文件资产、25 个 ViewSet queryset、form_service 通用增删改落库、doc 视图/统计任务/审计清理等全部收敛到 gvsdsdk(详见项目记忆「服务层化迁移进度」);invite/sve/t4/ccgo 已定性为业务定制留在 gvsds(与 CRB/MC 同边界)
### 6.2 已知技术债
| 优先级 | 问题 | 影响 |
|---|---|---|
| ~~高~~ | ~~Role/Permission 模型双份定义~~:✅ 已收敛(2026-08-10)——gvsds 各 app 模型统一 `from gvsdsdk.models import`,SDK 为唯一模型源 | — |
| 高 | 部分表(User/Dept/Workgroup/Shop)无 TenantUUID | 跨租户查询需 JOIN,删除租户困难(待迁移脚本补列回填) |
| 中 | ABAC 实现本质是 RBAC(字符串集合) | 已文档更正为"属性标识符补充层",真 ABAC 重构列入中期规划 |
| 中 | 数据权限硬编码 `if table_name == 'X'` | 违反开闭原则 |
| 中 | 缺乏软删除机制 | 误删不可恢复 |
| ~~中~~ | ~~stats 双轨~~:✅ 已统一(2026-08-07)——`StatEngine`(gvsds/apps/stats/manager.py)已删除,编排方法全部并入 gvsdsdk `StatsManager`,视图/Celery 任务统一走 SDK | — |
| 低 | UUID 主键无序导致索引膨胀 | 大数据量写入性能下降 |
---
## 7. 未来发展方向(会议讨论建议项)
### 7.1 短期(1-3 个月)
1. ~~统一 Role/Permission 模型~~:✅ 已收敛(2026-08-10)——视图层统一经 gvsdsdk Manager 访问,模型层 gvsds 统一从 gvsdsdk import,双份定义消除
2. **补全 TenantUUID 字段**:所有租户语义表直接打 `TenantUUID`,简化跨租户查询与租户删除
3. **数据权限策略化**:用策略模式替代 `if table_name == 'X'`,每个模型注册自己的 `ScopeFilter`
4. ~~更新根 README.md~~:✅ 已反映当前 Django 架构
5. ~~统一 stats 双轨实现~~:✅ 已收敛——`StatEngine` 删除,`StatsManager` 补齐编排方法(DefineMetric/GenerateDailyRanking/QueryRanking/RunScheduledResets/BuildRankings 等),视图与 Celery 任务统一经 gvsdsdk 访问
### 7.2 中期(3-6 个月)
1. **重构 ABAC 为真正的属性访问控制**:支持时间/IP/资源所有者/字段级权限
2. **引入软删除机制**:`DeletedAt` + `DeletedByUUID`,配合审计日志实现数据恢复
3. **支付网关扩展**:增加 PayPal/Stripe 适配(出海场景)
4. **租户配额管理**:用户数/数据量/API 调用次数配额
### 7.3 长期(6+ 个月)
1. **拆分协议层**:把 gvsdsdk 拆为 `gvsds-protocol`(纯协议)+ `gvsds-business`(业务能力),主从各自依赖
2. **改用 UUIDv7 或 Snowflake**:解决主键无序问题
3. **多区域部署**:基于 MSYNC 实现跨地域多活
4. **微服务化拆分**:gerp/payment/commission/stats 可独立部署
---
## 8. 关键架构原则
1. **PascalCase 全链路一致**:从数据库字段 → Python 类 → Socket.IO 事件 → 前端,无转换层
2. **优雅降级**:Redis/Celery/网关依赖缺失时自动降级,开发环境零依赖启动
3. **配置外置**:`app.ini` + `secrets.ini` + 环境变量三层配置,支持 12-factor 部署
4. **薄封装 SDK**:协议契约层与业务实现层分离,主从可独立演进
5. **Position 与权限解耦**:人事标签不绑权限,避免调岗重算
---
## 9. 联系与维护
- **主仓库**:`d:\SMANAGE`
- **SDK 包**:`gvsdsdk/`(pyproject.toml v1.0.0)
- **子服务器示例**:`ATestCServer/`
- **设计文档**:`docs/commission_engine.md` / `docs/payment_gateway.md` / `docs/stats_engine.md`
---
**本架构文档用于技术决策会议参考,详细 API 与字段定义见 [gvsdsdk/API.md](file:///d:/SMANAGE/gvsdsdk/API.md) 与 [gvsdsdk/README.md](file:///d:/SMANAGE/gvsdsdk/README.md)。**