# 用户管理模块需求文档(历史拆分稿) **模块**: 用户管理(User Management) **版本**: v1.0 (MVP) **创建日期**: 2024-12-12 **状态**: 🟠 已拆分(请以拆分后的基础设施文档为准) **最近更新**: 2025-12-17 > 重要说明:本文部分“表结构/字段”源自早期探索版本(存在 `users.authId` 等设计)。 > 当前项目已确定:**直接使用 Supabase Auth 的 `auth.users.id` 作为全系统用户主键**,业务侧仅维护 `public.profiles` 扩展信息; > 因此本文的“领域模型”将逐步改写为以 `profiles.id = auth.users.id` 为基准。 > 本文已拆分为以下文档(后续新增/变更请更新这些文档): > - 身份与访问控制(IAM):`docs/requirements/iam.md` > - 组织与岗位:`docs/requirements/organization.md` > - 数据范围与数据权限:`docs/requirements/data-permission.md` > - 审计日志:`docs/requirements/audit.md` --- ## 目录 1. [概述](#概述) 2. [问题陈述](#问题陈述) 3. [涉及角色](#涉及角色) 4. [MVP 范围](#mvp-范围) 5. [领域模型](#领域模型) 6. [用例列表](#用例列表) 7. [业务规则](#业务规则) 8. [非功能性需求](#非功能性需求) 9. [范围外功能](#范围外功能) 10. [下一阶段计划](#下一阶段计划) --- ## 概述 用户管理模块是 campus-hub-next 平台的基础模块,负责用户注册、认证、个人信息管理以及管理端用户管理功能。本模块基于 Supabase Auth 实现身份验证,采用 RBAC(基于角色的访问控制)权限模型。 ### 目标 - 提供便捷的用户注册和登录流程 - 支持用户自主管理个人信息 - 为管理员提供用户管理后台 - 建立完善的权限控制体系 - 为后续业务模块提供统一的用户身份基础 --- ## 问题陈述 ### 当前痛点 1. **无用户系统**: 平台需要用户身份认证体系,作为所有业务模块的基础 2. **注册审核需求**: 学校需要对新注册用户进行审核,防止非本校人员注册 3. **学号管理**: 需要将用户与学号强关联,确保一个学号只能注册一个账号 4. **权限控制**: 不同角色用户需要有不同的访问权限和操作权限 5. **用户管理**: 管理员需要统一的用户管理后台 ### 解决方案 - 基于 Supabase Auth 实现用户注册、登录、会话管理 - 提供可配置的注册审核开关 - 实现学号唯一性约束和验证 - 基于 RBAC 实现细粒度权限控制 - 提供管理端用户列表、详情查看、状态管理功能 --- ## 涉及角色 ### 1. 普通用户(User) **角色代码**: `user` **职责**: - 注册账号 - 登录/登出系统 - 查看和修改个人信息 - 使用平台各业务功能(资源分享、预约等) **权限示例**: - `campus:resource:view` - 查看课程资源 - `campus:facility:view` - 查看功能房 - `campus:library:view` - 查看数字图书 ### 2. 管理员(Admin) **角色代码**: `admin` **职责**: - 管理用户(查看列表、详情、状态管理) - 审核新注册用户 - 为用户分配角色和权限(下一阶段) - 查看用户统计数据(下一阶段) **权限示例**: - `campus:user:manage` - 用户管理 - `campus:user:approve` - 审核用户(下一阶段) - `campus:user:assign_role` - 分配角色(下一阶段) - 继承普通用户的所有权限 ### 3. 超级管理员(Super Admin) **角色代码**: `super_admin` **职责**: - 拥有系统最高权限 - 管理其他管理员 - 系统配置管理 **权限示例**: - `campus:*:*` - 所有权限(通配符) - 不可被其他管理员禁用或删除 --- ## MVP 范围 ### 必须实现的功能 #### 前台功能(Portal - 面向普通用户) 1. **用户注册** - 邮箱 + 密码注册 - 填写姓名和学号 - 学号必须为 16 位数字,全局唯一 - 根据注册审核开关,注册后状态为 `active` 或 `pending_approval` 2. **用户登录** - 邮箱 + 密码登录 - 返回 JWT token(access token + refresh token) - 登录成功后跳转到首页 3. **用户登出** - 清除本地 token - 注销 Supabase 会话 4. **个人信息查看** - 查看当前用户的完整信息 - 显示姓名、邮箱、学号、头像、角色、权限等 5. **个人信息修改** - 修改姓名 - 修改学号(需验证唯一性) - 修改用户名 - 上传/更换头像 #### 后台功能(Console - 面向管理员) 1. **用户列表** - 分页显示所有用户 - 支持按姓名、邮箱、学号搜索 - 支持按状态筛选(激活、停用、封禁、待审核) - 支持按角色筛选 - 支持排序(按创建时间、姓名、邮箱) 2. **用户详情** - 查看指定用户的完整信息 - 显示用户的角色和权限列表 - 显示用户的登录记录(登录次数、最后登录时间) 3. **用户状态管理** - 激活账号(`active`) - 停用账号(`disabled`) - 封禁账号(`banned`) - 审核通过(`pending_approval` → `active`) - 填写操作理由(可选,建议填写) ### 核心约束 1. 学号必须为精确 16 位数字 2. 学号全局唯一,不允许重复 3. 密码至少 8 位,包含字母和数字 4. 新注册用户默认分配 `user` 角色 5. 只有 `admin` 和 `super_admin` 可访问后台 6. 管理员不能修改自己的账号状态 7. 管理员不能修改超级管理员的状态 --- ## 领域模型 ### 核心实体 #### 1. Profile(用户扩展信息) 说明:用户身份与邮箱等敏感字段由 Supabase Auth 的 `auth.users` 管理;本表仅存放业务扩展字段。 **表名**: `profiles` **属性**: | 字段 | 类型 | 必填 | 唯一 | 说明 | |-----|------|------|------|------| | id | UUID | 是 | 是 | 用户主键(= `auth.users.id`) | | name | string | 是 | 否 | 真实姓名 | | username | string | 否 | 是 | 用户名(可选,全局唯一) | | studentId | string(16) | 是 | 是 | 学号(16 位数字,全局唯一) | | avatarUrl | string | 否 | 否 | 头像 URL(可选) | | status | enum | 是 | 否 | 账号状态(业务侧) | | createdAt | timestamp | 是 | 否 | 创建时间 | | updatedAt | timestamp | 是 | 否 | 更新时间 | | lastLoginAt | timestamp | 否 | 否 | 最后登录时间(可选) | **Auth 字段来源**(不在 `profiles` 冗余存储): - `email`:`auth.users.email` **状态枚举** (`status`): - `active` - 正常激活 - `disabled` - 已停用 - `banned` - 已封禁 - `pending_approval` - 等待审核 - `pending_email_verification` - 等待邮箱验证(可选) **索引**: - `id` (主键) - `studentId` (唯一索引) - `username` (唯一索引,可选) - `status` (普通索引) - `createdAt` (普通索引) #### 2. Role(角色) **表名**: `roles` **属性**: | 字段 | 类型 | 必填 | 唯一 | 说明 | |-----|------|------|------|------| | id | UUID | 是 | 是 | 角色主键 | | code | string | 是 | 是 | 角色代码(如 user, admin) | | name | string | 是 | 否 | 角色名称 | | category | enum | 是 | 否 | 角色类别 | | scope | enum | 是 | 否 | 作用范围 | | description | string | 否 | 否 | 角色描述 | | createdAt | timestamp | 是 | 否 | 创建时间 | | updatedAt | timestamp | 是 | 否 | 更新时间 | **类别枚举** (`category`): - `system` - 系统角色(用户、管理员等) - `department` - 部门角色(某个部门的管理员) - `major` - 专业角色(某个专业的负责人) - `custom` - 自定义角色 **作用范围** (`scope`): - `global` - 全局角色 - `department` - 部门级角色 - `major` - 专业级角色 #### 3. Permission(权限) **表名**: `permissions` **属性**: | 字段 | 类型 | 必填 | 唯一 | 说明 | |-----|------|------|------|------| | id | UUID | 是 | 是 | 权限主键 | | code | string | 是 | 是 | 权限代码(如 campus:user:manage) | | module | string | 是 | 否 | 所属模块 | | action | string | 是 | 否 | 操作类型 | | description | string | 否 | 否 | 权限描述 | | createdAt | timestamp | 是 | 否 | 创建时间 | **权限命名规范**: - 格式: `campus::` - 示例: `campus:user:manage`, `campus:resource:publish` - 支持通配符: `campus:*:*`(所有权限) #### 4. UserRole(用户-角色关联) **表名**: `user_roles` **属性**: | 字段 | 类型 | 必填 | 唯一 | 说明 | |-----|------|------|------|------| | id | UUID | 是 | 是 | 关联主键 | | userId | UUID | 是 | 否 | 用户 ID(外键) | | roleId | UUID | 是 | 否 | 角色 ID(外键) | | departmentId | UUID | 否 | 否 | 部门 ID(用于部门级角色) | | grantedAt | timestamp | 是 | 否 | 授予时间 | | grantedBy | UUID | 否 | 否 | 授予人 ID | **约束**: - 唯一约束: `(userId, roleId, departmentId)` - 外键: `userId` → `profiles.id`(= `auth.users.id`) - 外键: `roleId` → `roles.id` #### 5. RolePermission(角色-权限关联) **表名**: `role_permissions` **属性**: | 字段 | 类型 | 必填 | 唯一 | 说明 | |-----|------|------|------|------| | id | UUID | 是 | 是 | 关联主键 | | roleId | UUID | 是 | 否 | 角色 ID(外键) | | permissionId | UUID | 是 | 否 | 权限 ID(外键) | | createdAt | timestamp | 是 | 否 | 创建时间 | **约束**: - 唯一约束: `(roleId, permissionId)` - 外键: `roleId` → `roles.id` - 外键: `permissionId` → `permissions.id` ### 实体关系 ``` Profile ──< UserRole >── Role ↓ RolePermission ↓ Permission ``` **说明**: 1. 一个用户可以拥有多个角色(多对多) 2. 一个角色可以拥有多个权限(多对多) 3. 用户的最终权限 = 所有角色的权限的并集 4. 支持部门级/专业级角色(通过 `departmentId` 区分作用范围) --- ## 用例列表 ### 前台用例(Portal) #### UC-01: 用户注册 **作为**: 新用户 **在哪**: 注册页面 (`/auth/signup`) **做什么**: 填写邮箱、密码、姓名、学号并提交注册 **为了什么**: 创建账号并使用平台功能 **前置条件**: - 用户未登录 **主流程**: 1. 用户访问注册页面 2. 填写邮箱、密码、姓名、学号 3. 点击"注册"按钮 4. 系统验证输入(格式、学号唯一性) 5. 调用 `POST /api/auth/signup` 接口 6. 根据注册审核开关: - **开关开启**: 显示"注册成功,等待审核"提示,状态为 `pending_approval` - **开关关闭**: 显示"注册成功"提示,状态为 `active`,自动跳转到登录页 **异常流程**: - 邮箱已存在: 提示"该邮箱已被注册" - 学号已存在: 提示"该学号已被注册" - 学号格式错误: 提示"学号必须为16位数字" - 密码不符合要求: 提示"密码至少8位,包含字母和数字" #### UC-02: 用户登录 **作为**: 已注册用户 **在哪**: 登录页面 (`/auth/signin`) **做什么**: 使用邮箱和密码登录系统 **为了什么**: 访问个人信息和使用平台功能 **前置条件**: - 用户已注册且状态为 `active` **主流程**: 1. 用户访问登录页面 2. 输入邮箱和密码 3. 点击"登录"按钮 4. 调用 `POST /api/auth/signin` 接口 5. 系统验证凭证 6. 返回 JWT token 并保存到本地存储 7. 跳转到首页 **异常流程**: - 邮箱或密码错误: 提示"邮箱或密码错误" - 账号等待审核: 提示"账号等待审核中,请耐心等待" - 账号已停用: 提示"账号已被停用,请联系管理员" - 账号已封禁: 提示"账号已被封禁" #### UC-03: 查看个人信息 **作为**: 已登录用户 **在哪**: 个人中心页面 (`/profile`) **做什么**: 查看自己的详细信息 **为了什么**: 了解账号状态和个人资料 **前置条件**: - 用户已登录 **主流程**: 1. 用户访问个人中心页面 2. 调用 `GET /api/me/profile` 接口 3. 显示用户信息: - 基本信息: 姓名、邮箱、学号、用户名 - 账号状态 - 头像 - 角色列表 - 权限列表 - 注册时间、最后登录时间 #### UC-04: 修改个人信息 **作为**: 已登录用户 **在哪**: 个人信息编辑页面 (`/profile/edit`) **做什么**: 修改姓名、学号、用户名或头像 **为了什么**: 更新个人资料 **前置条件**: - 用户已登录 **主流程**: 1. 用户访问个人信息编辑页面 2. 当前信息预填到表单 3. 用户修改需要更新的字段 4. 点击"保存"按钮 5. 调用 `PATCH /api/me/profile` 接口 6. 系统验证(学号唯一性等) 7. 更新成功,显示提示信息 **异常流程**: - 学号已被其他用户使用: 提示"该学号已被使用" - 学号格式错误: 提示"学号必须为16位数字" - 用户名已被使用: 提示"该用户名已被使用" #### UC-05: 用户登出 **作为**: 已登录用户 **在哪**: 任意页面的用户菜单 **做什么**: 点击"登出"按钮 **为了什么**: 退出当前登录会话 **前置条件**: - 用户已登录 **主流程**: 1. 用户点击"登出"按钮 2. 调用 `POST /api/auth/signout` 接口 3. 清除本地 token 4. 跳转到登录页 --- ### 后台用例(Console) #### UC-06: 查看用户列表 **作为**: 管理员 **在哪**: 用户管理页面 (`/console/users`) **做什么**: 查看所有用户的列表,支持搜索和筛选 **为了什么**: 管理和监控用户账号 **前置条件**: - 管理员已登录 - 拥有 `campus:user:manage` 权限或 `admin`/`super_admin` 角色 **主流程**: 1. 管理员访问用户管理页面 2. 调用 `GET /api/console/users` 接口(带分页参数) 3. 显示用户列表表格: - 列: 姓名、邮箱、学号、状态、角色、创建时间、最后登录时间 - 支持分页(每页 20 条) - 支持搜索(按姓名、邮箱、学号) - 支持筛选(按状态、角色) - 支持排序(按创建时间、姓名、邮箱) **扩展流程**: - 点击某行: 跳转到用户详情页面 - 使用搜索框: 实时筛选符合条件的用户 - 切换状态筛选: 只显示指定状态的用户 #### UC-07: 查看用户详情 **作为**: 管理员 **在哪**: 用户详情页面 (`/console/users/:id`) **做什么**: 查看指定用户的完整信息 **为了什么**: 了解用户详细情况并进行管理操作 **前置条件**: - 管理员已登录 - 拥有 `campus:user:manage` 权限 **主流程**: 1. 管理员从用户列表点击某个用户 2. 调用 `GET /api/console/users/:id` 接口 3. 显示用户完整信息: - 基本信息区域: 姓名、邮箱、学号、用户名、头像 - 账号状态区域: 当前状态、创建时间、更新时间 - 角色与权限区域: 角色列表、权限列表 - 登录记录区域: 登录次数、最后登录时间、最后登录 IP - 操作按钮区域: 修改状态、分配角色(下一阶段) #### UC-08: 更新用户状态 **作为**: 管理员 **在哪**: 用户详情页面或用户列表 **做什么**: 修改用户账号状态(激活、停用、封禁等) **为了什么**: 管理用户的访问权限 **前置条件**: - 管理员已登录 - 拥有 `campus:user:manage` 权限 - 目标用户不是管理员自己 - 目标用户不是超级管理员(或当前管理员是超级管理员) **主流程**: 1. 管理员在用户详情页或列表点击"修改状态" 2. 弹出状态选择对话框 3. 选择目标状态(激活、停用、封禁) 4. 填写操作理由(可选,建议填写) 5. 点击"确认"按钮 6. 调用 `PATCH /api/console/users/:id/status` 接口 7. 更新成功,显示提示信息 8. 刷新用户信息 **异常流程**: - 试图修改自己的状态: 提示"不能修改自己的账号状态" - 非超管试图修改超管: 提示"无权限修改超级管理员的状态" #### UC-09: 审核新注册用户(注册审核开启时) **作为**: 管理员 **在哪**: 用户管理页面 **做什么**: 审核状态为"等待审核"的新注册用户 **为了什么**: 控制用户注册,防止非本校人员注册 **前置条件**: - 管理员已登录 - 系统启用了注册审核开关 - 存在状态为 `pending_approval` 的用户 **主流程**: 1. 管理员在用户列表筛选"等待审核"状态 2. 查看待审核用户列表 3. 点击某个用户查看详情 4. 确认用户信息(姓名、学号、邮箱等) 5. 选择操作: - **通过审核**: 调用 `PATCH /api/console/users/:id/status`,状态改为 `active` - **拒绝审核**: 调用 `PATCH /api/console/users/:id/status`,状态改为 `disabled` 6. 填写审核理由 7. 确认操作 8. 系统更新用户状态 9. 用户收到通知(下一阶段) --- ## 业务规则 ### 1. 注册规则 - **学号验证**: 必须为精确 16 位数字,格式 `^[0-9]{16}$` - **学号唯一性**: 每个学号只能注册一个账号 - **邮箱唯一性**: 每个邮箱只能注册一个账号 - **密码复杂度**: 至少 8 位,包含字母和数字 - **默认角色**: 所有新用户默认分配 `user` 角色 - **注册审核**: - 审核开关**开启**: 新用户状态为 `pending_approval`,需管理员审核 - 审核开关**关闭**: 新用户状态为 `active`,可直接登录 ### 2. 登录规则 - **凭证验证**: 使用邮箱和密码登录 - **状态检查**: 只有状态为 `active` 的用户可以登录 - **Token 有效期**: - Access Token: 1 小时 - Refresh Token: 7 天 - **登录记录**: 记录最后登录时间和登录 IP(可选) ### 3. 权限规则 - **权限继承**: 用户的权限 = 所有角色的权限并集 - **权限匹配**: 支持通配符匹配(`campus:*:*` 匹配所有权限) - **权限缓存**: 权限信息缓存 5 分钟,减少数据库查询 - **后台访问**: 需要 `campus:user:manage` 权限或 `admin`/`super_admin` 角色 ### 4. 状态流转规则 ``` pending_approval → active (管理员审核通过) → disabled (管理员拒绝) active → disabled (管理员停用) → banned (管理员封禁) disabled → active (管理员恢复) → banned (管理员封禁) banned → active (管理员解封) ``` ### 5. 管理员操作规则 - **自我限制**: 管理员不能修改自己的账号状态 - **超管保护**: 只有超级管理员可以修改其他管理员的状态 - **操作记录**: 所有管理操作应记录操作人和操作理由(用于审计) --- ## 非功能性需求 ### 1. 性能要求 - 用户登录响应时间 < 500ms - 用户列表查询响应时间 < 1s(1000 条记录以内) - 权限查询使用缓存,避免频繁数据库查询 - 支持 1000+ 并发用户同时在线 ### 2. 安全要求 - 密码使用 bcrypt 或 Supabase Auth 内置加密存储 - JWT Token 使用 HMAC-SHA256 签名 - 敏感操作(修改状态等)记录审计日志 - 防止 SQL 注入(使用 Drizzle ORM 参数化查询) - 防止 XSS 攻击(前端输出转义) ### 3. 可用性要求 - 系统可用性 ≥ 99.5% - 数据库每日自动备份 - 关键错误有友好的用户提示信息 ### 4. 可维护性要求 - 代码遵循 TypeScript 严格模式 - 所有 API 有完整文档 - 关键业务逻辑有注释说明 - Service/Repository 分层架构,易于测试和维护 --- ## 范围外功能 以下功能**不在 MVP 范围内**,计划在下一阶段实现: 1. **密码重置**: 通过邮件重置密码 2. **邮箱验证**: 新用户注册后需验证邮箱 3. **角色分配**: 管理员为用户分配/移除角色 4. **权限分配**: 管理员为用户分配/移除权限 5. **批量操作**: 批量修改用户状态、批量分配角色 6. **用户导入**: 从 Excel/CSV 批量导入用户 7. **用户统计**: 用户注册趋势、活跃度统计 8. **登录历史**: 详细的登录记录列表 9. **操作审计**: 管理员操作日志查询 10. **高级搜索**: 按部门、专业、注册时间段等多维度筛选 11. **用户标签**: 为用户打标签(如"活跃用户"、"VIP"等) 12. **通知功能**: 账号状态变更时通知用户 --- ## 下一阶段计划 ### Phase 2: 增强功能 **优先级 P1(高)**: 1. 密码重置功能 2. 角色与权限分配 3. 用户状态变更通知 **优先级 P2(中)**: 4. 用户导入/导出 5. 操作审计日志 6. 用户统计报表 **优先级 P3(低)**: 7. 邮箱验证(如 Supabase Auth 支持方便) 8. 高级搜索与筛选 9. 用户标签系统 ### Phase 3: 集成与优化 1. 与其他模块集成(资源分享、功能房预约等) 2. SSO 单点登录(如需要) 3. 性能优化(权限缓存策略、查询优化) 4. 安全加固(登录限流、异常登录检测) --- *说明:本文为历史拆分稿,已由 `docs/requirements/iam.md` / `organization.md` / `data-permission.md` / `audit.md` 替代,不再作为单一事实来源。*