Files
Inbox/Go项目实战/用户模块/01_实体关系图.md
2025-12-11 07:24:36 +08:00

112 lines
5.1 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.

---
tags: []
aliases:
- ER 图
date created: 星期二, 十二月 9日 2025, 10:45:43 晚上
date modified: 星期二, 十二月 9日 2025, 10:58:01 晚上
---
# ER 图
**设计思路分析:**
1. **RBAC 模型选择:** 为了满足“银行级权限控制”及“企业级样板间”的扩展性要求,我采用了标准的 **RBAC Level 1 (Flat RBAC)** 变体。虽然当前只有 3 个固定角色,但使用 **多对多 (Many-to-Many)** 的关联表 (`user_roles`) 能够支持未来某用户既是 "Editor" 又是 "TechLeader" 的混合权限场景,避免后续重构。
2. **双令牌机制落地:** 专门设计了 `refresh_tokens` 表。JWT 的 Access Token 是无状态的(不入库),但 Refresh Token 必须入库以实现“吊销”、“防重放”和“设备管理”功能。
3. **软删除与审计:** 所有核心表(`users`, `roles`)均继承了 Base Model包含 `deleted_at` 字段。
---
## 📊 阶段二:概念验证 (Conceptual Modeling - ER Diagram)
```mermaid
erDiagram
%% ---------------------------------------------------------
%% 1. 用户核心表 (Users)
%% 核心聚合根,包含认证凭证与个人资料
%% ---------------------------------------------------------
users {
bigint id PK "主键"
string username "用户名, unique, not null"
string password_hash "Argon2/Bcrypt 哈希值, not null"
string nickname "用户昵称 (Profile)"
string avatar_url "头像链接 (Profile)"
string bio "个人简介 (Profile)"
smallint status "状态: 1=Active, 0=Banned"
timestamptz created_at "创建时间"
timestamptz updated_at "更新时间"
timestamptz deleted_at "软删除时间 (Soft Delete)"
}
%% ---------------------------------------------------------
%% 2. 角色表 (Roles)
%% 存储 Admin, Editor, Subscriber 等定义
%% ---------------------------------------------------------
roles {
bigint id PK "主键"
string code "角色编码 (e.g. 'admin'), unique"
string name "角色显示名称 (e.g. '超级管理员')"
string description "备注"
timestamptz created_at
timestamptz updated_at
timestamptz deleted_at
}
%% ---------------------------------------------------------
%% 3. 用户-角色关联表 (User Roles)
%% 中间表,实现 RBAC 多对多关系
%% ---------------------------------------------------------
user_roles {
bigint user_id FK "关联 users.id"
bigint role_id FK "关联 roles.id"
timestamptz created_at
}
%% ---------------------------------------------------------
%% 4. 刷新令牌表 (Refresh Tokens)
%% 用于双令牌机制的续期与风控
%% ---------------------------------------------------------
refresh_tokens {
bigint id PK "主键"
bigint user_id FK "关联 users.id"
string token_hash "Refresh Token 的哈希值 (安全考虑不存明文)"
string family_id "令牌家族ID (用于检测重用/Rotation)"
string parent_token_id "父令牌ID (用于溯源)"
boolean is_revoked "是否已撤销 (黑名单机制)"
timestamptz expires_at "过期时间 (7天)"
timestamptz created_at
}
%% ---------------------------------------------------------
%% 关系定义 (Relationships)
%% ---------------------------------------------------------
%% 一个用户可以拥有多个 Refresh Token (多设备登录)
users ||--o{ refresh_tokens : "has_many (sessions)"
%% 一个用户可以拥有多个角色 (扩展性设计)
users ||--o{ user_roles : "assigned_to"
%% 一个角色可以包含多个用户
roles ||--o{ user_roles : "includes"
```
---
## 🔑 关键关系业务含义说明
1. **Users `||--o{` Refresh Tokens (1 对 多):**
- **业务含义:** 一个用户可以在多个设备手机、PC同时登录。
- **风控逻辑:** 当用户执行“修改密码”或“严重违规封号”时,后端会根据 `user_id` 批量将该用户下的所有 `is_revoked` 设为 `true`,从而实现**强制下线**。
- **令牌轮转:** `family_id``parent_token_id` 用于检测令牌复用攻击。如果一个旧的 RT 被使用,系统可以根据 `family_id` 级联作废整个令牌链。
2. **Users `}|--|{` Roles (多 对 多,通过 `user_roles`):**
- **业务含义:** 虽然 PRD 定义了三个层级,但物理模型采用“多对多”设计是架构上的**防御性编程**。
- **场景:** 如果未来需要赋予某个 Editor 临时的 Admin 权限,或者创建一个 "SuperSubscriber"(付费会员),我们只需在 `user_roles` 插入一条记录,而无需修改表结构。
3. **Users 表的混合设计:**
- **决策:** 我没有将 `Profile` (昵称/头像) 拆分为独立表。
- **理由:** 遵循“勿增实体”原则。在当前 V1 阶段Profile 字段较少(仅 3 个),且在列表页展示时(如“评论列表”)属于高频连表查询。合并不仅减少了 JOIN 开销,也简化了 GORM 的模型编写。