ether-docs/02-DESIGN/detail/DETAIL-AUTH.md

46 KiB
Raw Blame History

身份与权限域 - 详细设计

文档版本: v1.0 生成日期: 2026-05-18 数据来源: module-auth 实际代码 + REVERSE-AUTH.md 对照需求: 05-AUTH.md


一、功能点清单

功能ID 功能名称 优先级 实现状态 对应需求ID
AUTH-001 用户登录 P0 已实现 05-AUTH-001
AUTH-002 用户登出 P0 已实现 05-AUTH-002
AUTH-003 获取当前用户 P0 已实现 05-AUTH-003
AUTH-004 Token刷新 P0 已实现 05-AUTH-004
AUTH-005 用户CRUD P0 已实现 05-AUTH-010
AUTH-006 修改密码 P0 已实现 05-AUTH-011
AUTH-007 分配用户角色 P0 已实现 05-AUTH-020
AUTH-008 用户项目关联 P1 已实现 05-AUTH-030
AUTH-009 企业员工管理 P1 已实现 05-AUTH-012
AUTH-010 角色CRUD P0 已实现 05-AUTH-020
AUTH-011 角色权限分配 P0 已实现 05-AUTH-021
AUTH-012 按项目查询角色 P1 已实现 05-AUTH-022
AUTH-013 权限CRUD P0 已实现 05-AUTH-025
AUTH-014 按类型查询权限 P1 已实现 05-AUTH-026
AUTH-015 菜单权限查询 P1 已实现 05-AUTH-027
AUTH-016 部门树管理 P1 已实现 05-AUTH-040
AUTH-017 部门成员查询 P1 已实现 05-AUTH-041
AUTH-018 项目成员管理 P0 已实现 05-AUTH-030
AUTH-019 登录失败锁定 P0 已实现 05-AUTH-005
AUTH-020 密码强度校验 P0 已实现 05-AUTH-006
AUTH-021 弱密码检测 P1 已实现 05-AUTH-007
AUTH-022 审计日志查询 P1 已实现 05-AUTH-050
AUTH-023 审计日志统计 P2 已实现 05-AUTH-051
AUTH-024 系统配置管理 P1 已实现 05-AUTH-060
AUTH-025 数据访问授权 P2 已实现(@Deprecated) 05-AUTH-035
AUTH-026 住户认证流程 P1 已实现 05-AUTH-015
AUTH-027 住户房屋绑定 P1 已实现 05-AUTH-016
AUTH-028 项目员工角色分配 P1 已实现 05-AUTH-031

二、数据结构设计

2.1 实体定义

2.1.1 User用户

表名: auth_user

字段名 类型 约束 说明
id UUID PK, 自动生成 用户唯一标识符
username VARCHAR(50) NOT NULL, UNIQUE, 正则^[a-zA-Z0-9_]+$, 3-50位 登录用户名
password VARCHAR(255) NOT NULL, @JsonIgnore BCrypt加密密码
salt VARCHAR @JsonIgnore 密码盐值BCrypt模式下冗余
realName VARCHAR(50) 真实姓名
phone VARCHAR(20) 正则^1[3-9]\d{9}$ 手机号码
email VARCHAR(100) @Email 电子邮箱
avatar VARCHAR 头像URL
status VARCHAR(20) NOT NULL, 默认ACTIVE, @Enumerated(STRING) 用户状态枚举
userType VARCHAR(20) NOT NULL 用户类型ENTERPRISE/PROJECT_STAFF/RESIDENT/CUSTOMER
deptId UUID 所属部门ID
lastLoginTime LocalDateTime 最后登录时间
lastLoginIp VARCHAR 最后登录IP
createdAt LocalDateTime NOT NULL, @PrePersist自动填充 创建时间
updatedAt LocalDateTime NOT NULL, @PreUpdate自动填充 更新时间
createdBy UUID 创建人ID

索引:

  • auth_user_username_key → username (UNIQUE)

关系:

  • roles → M2M → Role通过 auth_user_role 中间表LAZY加载

中间表: auth_user_role

字段名 类型 约束 说明
user_id UUID FK → auth_user, fk_auth_user_role_user 用户ID
role_id UUID FK → auth_role, fk_auth_user_role_role 角色ID

2.1.2 Role角色

表名: auth_role

字段名 类型 约束 说明
id UUID PK, 自动生成 角色唯一标识符
code VARCHAR(50) NOT NULL, UNIQUE, 正则^[a-zA-Z0-9_]+$, 2-50位 角色代码
name VARCHAR(50) NOT NULL, 2-50位 角色名称
description VARCHAR(200) 角色描述
type VARCHAR(20) NOT NULL, @Enumerated(STRING) 角色类型枚举
dataScope VARCHAR(20) 默认SELF, @Enumerated(STRING) 数据范围枚举
projectId UUID columnDefinition=uuid 所属项目IDNULL=系统级)
status VARCHAR(20) NOT NULL, 默认ENABLED, @Enumerated(STRING) 角色状态枚举
createdAt LocalDateTime NOT NULL, @PrePersist自动填充 创建时间
updatedAt LocalDateTime NOT NULL, @PreUpdate自动填充 更新时间

索引:

  • auth_role_code_key → code (UNIQUE)

关系:

  • permissions → M2M → Permission通过 auth_role_permission 中间表LAZY加载

中间表: auth_role_permission

字段名 类型 约束 说明
role_id UUID FK → auth_role, fk_auth_role_permission_role 角色ID
permission_id UUID FK → auth_permission, fk_auth_role_permission_permission 权限ID

2.1.3 Permission权限

表名: auth_permission

字段名 类型 约束 说明
id UUID PK, 自动生成 权限唯一标识符
code VARCHAR(100) NOT NULL, UNIQUE, 正则^[a-zA-Z0-9_:]+$, 2-100位 权限代码,格式module:resource:action
name VARCHAR(100) NOT NULL, 2-100位 权限名称
type VARCHAR(20) 权限类型MENU/BUTTON/API
resource VARCHAR(50) 资源路径API类型
method VARCHAR(50) HTTP方法API类型
description VARCHAR(200) 权限描述
parentCode VARCHAR(50) 父权限代码(树形结构)
path VARCHAR(200) 路由路径(菜单类型)
component VARCHAR(200) 组件路径(菜单类型)
icon VARCHAR(100) 图标名称(菜单类型)
sortOrder Integer 排序序号
visible Boolean NOT NULL, 默认true 是否可见
createdAt LocalDateTime @PrePersist自动填充 创建时间
updatedAt LocalDateTime @PreUpdate自动填充 更新时间

索引:

  • auth_permission_code_key → code (UNIQUE)

关系:

  • roles → M2M → Role通过 auth_role_permission 中间表LAZY加载@JsonIgnoreProperties避免循环序列化

2.1.4 Dept部门

表名: dept

字段名 类型 约束 说明
id UUID PK, 自动生成 部门唯一标识符
parentId UUID 上级部门IDNULL=顶级)
deptName VARCHAR(100) NOT NULL 部门名称
deptType VARCHAR(20) 默认"ADMIN" 部门类型
leaderId UUID 部门负责人ID
sortOrder Integer 排序序号
status VARCHAR(20) 默认"ACTIVE" 状态ACTIVE/DISABLED
createdAt LocalDateTime @PrePersist自动填充 创建时间
updatedAt LocalDateTime @PreUpdate自动填充 更新时间
createdBy UUID column: created_by 创建人ID
updatedBy UUID column: updated_by 更新人ID

关系:

  • 自引用树形结构parentId → Dept.id

2.1.5 AuditLog审计日志

表名: sys_audit_log

字段名 类型 约束 说明
id UUID PK, 自动生成 日志ID
userId UUID column: user_id 操作用户ID
username VARCHAR(64) NOT NULL 操作用户名
operation VARCHAR(128) NOT NULL 操作描述
module VARCHAR(64) NOT NULL 模块标识
action VARCHAR(64) NOT NULL, @Enumerated(STRING) 操作类型枚举
targetType VARCHAR(64) 目标类型
targetId VARCHAR(64) 目标ID
content VARCHAR(2000) 操作内容
params LONGVARCHAR(5000) 请求参数
result LONGVARCHAR(5000) 操作结果
ipAddress VARCHAR(64) column: ip_address IP地址
userAgent VARCHAR(512) 用户代理
requestUrl VARCHAR(512) column: request_url 请求URL
requestMethod VARCHAR(16) column: request_method 请求方法
executionTimeMs Integer column: execution_time_ms 执行耗时(ms)
status VARCHAR(16) 默认SUCCESS, @Enumerated(STRING) 状态枚举
errorMsg VARCHAR(2000) column: error_msg 错误信息
createdAt LocalDateTime NOT NULL, @CreationTimestamp, 不可更新 创建时间
tenantId UUID column: tenant_id 租户ID

索引:

  • idx_audit_log_created_at → createdAt
  • idx_audit_log_user_id → userId
  • idx_audit_log_module → module
  • idx_audit_log_action → action
  • idx_al_user_createdat → userId, createdAt DESC

2.1.6 EnterpriseUser企业员工

表名: enterprise_user

字段名 类型 约束 说明
userId UUID PK, FK → auth_user 用户ID共享主键
employeeNo VARCHAR(50) 员工工号
deptId UUID 部门ID
position VARCHAR(50) 职位
entryDate LocalDate 入职日期
userCategory VARCHAR(50) 员工类别ENTERPRISE/MANAGEMENT

关系:

  • user → @OneToOne → User@MapsId共享主键

2.1.7 ProjectStaff项目员工

表名: project_staff

字段名 类型 约束 说明
id UUID PK, 自动生成 主键ID
userId UUID FK → auth_user, insertable=false, updatable=false 用户ID
projectId UUID column: project_id 所属项目ID
deptId UUID column: dept_id 所属部门ID
staffType VARCHAR(50) 员工类型SECURITY/CLEANING/GARDEN/MAINTENANCE/CUSTOMER_SERVICE/GENERAL
shiftType VARCHAR(20) 班次类型DAY/NIGHT/ROTATION
leaderId UUID 班组长ID
assignmentStatus VARCHAR(20) 在岗状态ASSIGNED/ON_LEAVE/TRANSFERRED
createdAt LocalDateTime column: created_at, 不可更新 创建时间
updatedAt LocalDateTime column: updated_at 更新时间

关系:

  • user → @OneToOne → UserFK: fk_project_staff_user
  • staffRoles → @OneToMany → ProjectStaffRolemappedBy="staff", CASCADE=ALL, orphanRemoval=true

2.1.8 ProjectStaffRole项目员工角色

表名: project_staff_role

字段名 类型 约束 说明
id UUID PK, 自动生成 主键ID
staff_id UUID FK → project_staff, NOT NULL 关联项目员工
role_id UUID FK → auth_role, NOT NULL 关联角色
createdAt LocalDateTime column: created_at, @PrePersist自动填充 创建时间

关系:

  • staff → @ManyToOne(LAZY) → ProjectStaff
  • role → @ManyToOne(EAGER) → Role

2.1.9 Resident住户

表名: resident

字段名 类型 约束 说明
userId UUID PK, FK → auth_user 用户ID共享主键
idCard VARCHAR(18) @JsonIgnore 身份证号码
residentType VARCHAR(20) 住户类型OWNER/FAMILY/TENANT
verificationStatus VARCHAR(20) 认证状态UNVERIFIED/PENDING/VERIFIED/REJECTED
verifiedAt LocalDateTime 认证时间
verifiedBy UUID 认证人ID
createdAt LocalDateTime NOT NULL, @PrePersist自动填充 创建时间
updatedAt LocalDateTime NOT NULL, @PreUpdate自动填充 更新时间
createdBy UUID column: created_by 创建人ID
updatedBy UUID column: updated_by 更新人ID

关系:

  • user → @OneToOne → User@MapsId共享主键

2.1.10 Space房屋空间

表名: space

字段名 类型 约束 说明
id UUID PK, 自动生成 空间ID
projectId UUID column: project_id 所属项目ID
building VARCHAR(50) 楼栋
unit VARCHAR(50) 单元
roomNo VARCHAR(50) 房号
spaceType VARCHAR(20) 房屋类型RESIDENTIAL/COMMERCIAL
floor Integer 楼层
unitArea BigDecimal 建筑面积(㎡)
status VARCHAR(20) 状态

2.1.11 ResidentSpace住户-房屋关联)

表名: resident_space

字段名 类型 约束 说明
id UUID PK, 自动生成 关联记录ID
userId UUID NOT NULL, column: user_id 用户ID
spaceId UUID NOT NULL, column: space_id 房屋ID
relationType VARCHAR(20) 关系类型OWNER/FAMILY/TENANT
bindingStatus VARCHAR(20) 绑定状态PENDING/ACTIVE/EXPIRED/CANCELLED
startDate LocalDate 生效日期
endDate LocalDate 失效日期NULL=永久)

2.1.12 UserProject用户-项目关联)

表名: user_project

字段名 类型 约束 说明
id UUID PK, 自动生成 关联记录ID
userId UUID NOT NULL, column: user_id 用户ID
projectId UUID NOT NULL, column: project_id 项目ID
roleInProject VARCHAR NOT NULL, 默认"member", column: role_in_project 项目中角色leader/member/viewer
joinedAt LocalDateTime NOT NULL, 默认当前时间, column: joined_at 加入时间

2.1.13 SysConfig系统配置

表名: sys_config

字段名 类型 约束 说明
id UUID PK, 自动生成 配置项ID
configKey VARCHAR(128) NOT NULL, UNIQUE, column: config_key 配置键
configValue VARCHAR(5000) column: config_value 配置值
description VARCHAR(256) 配置描述
createdAt LocalDateTime NOT NULL, @CreationTimestamp, 不可更新 创建时间
updatedAt LocalDateTime NOT NULL, @UpdateTimestamp 更新时间

2.1.14 DataAccess数据访问授权@Deprecated

表名: biz_data_access

字段名 类型 约束 说明
id UUID PK, 自动生成 授权记录ID
dataType VARCHAR NOT NULL, column: data_type 数据类型
dataId UUID NOT NULL, column: data_id 数据ID
accessType VARCHAR NOT NULL, column: access_type 访问者类型
accessId UUID NOT NULL, column: access_id 访问者ID
accessLevel VARCHAR NOT NULL, 默认"read", column: access_level 访问级别
grantedBy UUID column: granted_by 授权人ID
grantedAt LocalDateTime NOT NULL, 默认当前时间, column: granted_at 授权时间

注意: DataAccess 实体及对应控制器已标记 @Deprecated后续版本将移除。


2.2 枚举定义

UserStatus

描述
ACTIVE 正常
LOCKED 锁定
DISABLED 禁用

RoleType

描述
SYSTEM 系统级,可访问所有项目数据
PROJECT 项目级,仅可访问指定项目数据
DEPARTMENT 部门级,仅可访问本部门数据

DataScope

描述
ALL 全部数据
PROJECT 本项目数据
DEPARTMENT 本部门数据
SELF 仅本人数据

RoleStatus

描述
ENABLED 启用
DISABLED 禁用

DeptType

描述
ADMIN 行政管理
ENGINEERING 工程部
SECURITY 安保部
CS 客服部
CLEANING 保洁部

ActionType

描述
CREATE 创建
UPDATE 修改
DELETE 删除
QUERY 查询
VIEW 查看
LOGIN 登录
LOGOUT 登出
EXPORT 导出
IMPORT 导入
ASSIGN 分配
REVOKE 撤销

2.3 ER关系图Mermaid

erDiagram
    User ||--o{ Role : "auth_user_role M2M"
    Role ||--o{ Permission : "auth_role_permission M2M"
    User ||--|| EnterpriseUser : "共享主键 1:1"
    User ||--|| ProjectStaff : "FK 1:1"
    User ||--|| Resident : "共享主键 1:1"
    ProjectStaff ||--o{ ProjectStaffRole : "1:N 级联删除"
    ProjectStaffRole }o--|| Role : "N:1 EAGER"
    Resident ||--o{ ResidentSpace : "1:N"
    ResidentSpace }o--|| Space : "N:1"
    User ||--o{ UserProject : "1:N"
    UserProject }o--|| Project : "N:1"

    Dept ||--o{ Dept : "自引用树形 parentId"

    AuditLog {
        UUID id PK
        UUID userId
        String username
        String operation
        String module
        String action
        String targetType
        String targetId
        String status
    }

    SysConfig {
        UUID id PK
        String configKey UK
        String configValue
    }

    DataAccess {
        UUID id PK
        String dataType
        UUID dataId
        String accessType
        UUID accessId
        String accessLevel
    }

三、API设计

3.1 AuthController -- 认证管理

基础路径: /api/auth

编号 方法 路径 说明 请求参数 响应格式 权限要求 例外情况
AUTH-API-001 POST /login 用户登录 Body: {username: String(3-50), password: String(8-128)} {code, data: {token, userId, username, realName, roles}} 无(公开) 用户名不存在; 密码错误; 账户锁定; 账户禁用; 登录失败超5次锁定10分钟
AUTH-API-002 POST /logout 用户登出 Header: Authorization: Bearer {token} {code, data: null} 已登录 Token无效
AUTH-API-003 GET /me 获取当前用户 Header: Authorization: Bearer {token} {code, data: {username}} 已登录 Token缺失; Token无效
AUTH-API-004 POST /refresh 刷新Token Header: Authorization: Bearer {token} {code, data: {token}} 已登录 Token缺失; Token无效; Token已过期

登录响应详细格式:

{
  "code": 200,
  "data": {
    "token": "eyJhbGciOiJIUzI1NiJ9...",
    "userId": "uuid",
    "username": "admin",
    "realName": "管理员",
    "roles": ["SYSTEM_ADMIN", "PROJECT_MANAGER"]
  }
}

3.2 UserController -- 用户管理

基础路径: /api/auth/users

编号 方法 路径 说明 请求参数 响应格式 权限要求 例外情况
USER-API-001 GET / 分页查询用户列表 page(int, 默认0), size(int, 默认10) {code, data: {content: [User], totalElements, totalPages, ...}} 已登录 分页参数越界
USER-API-002 GET /{id} 根据ID获取用户 id(UUID, Path) {code, data: User} 已登录 用户不存在
USER-API-003 POST / 创建用户 Body: User实体 {code, data: User} 管理员 用户名已存在; 字段校验失败
USER-API-004 PUT /{id} 更新用户 id(UUID, Path), Body: User实体 {code, data: User} 管理员 用户不存在; 用户名冲突
USER-API-005 DELETE /{id} 删除用户 id(UUID, Path) {code, data: null} 管理员 用户不存在; 用户有关联数据
USER-API-006 PUT /{id}/password 修改密码 id(UUID, Path), Body: {oldPassword: String(8-128), newPassword: String(8-128)} {code, data: null} 本人或管理员 原密码错误; 新密码强度不足; 新密码为弱密码
USER-API-007 POST /{id}/roles 分配角色 id(UUID, Path), Body: [roleId1, roleId2, ...] {code, data: null} 管理员 用户不存在; 角色ID不存在; 分配数量超限
USER-API-008 GET /{id}/projects 获取用户项目列表 id(UUID, Path) {code, data: [UserProject]} 已登录 用户不存在
USER-API-009 POST /{id}/projects 添加用户到项目 id(UUID, Path), Body: {projectId: UUID, roleInProject: String} {code, data: null} 管理员 用户不存在; 项目不存在; 已在该项目中
USER-API-010 DELETE /{id}/projects/{projectId} 从项目移除用户 id(UUID, Path), projectId(UUID, Path) {code, data: null} 管理员 关联不存在
USER-API-011 GET /enterprise 获取企业员工列表 {code, data: [UserVO]} 已登录

UserVO格式:

{
  "id": "uuid",
  "username": "zhangsan",
  "realName": "张三",
  "phone": "13800138000",
  "email": "zhangsan@example.com",
  "avatar": "url",
  "status": "ACTIVE",
  "userType": "ENTERPRISE",
  "deptId": "uuid"
}

3.3 RoleController -- 角色管理

基础路径: /api/auth/roles

编号 方法 路径 说明 请求参数 响应格式 权限要求 例外情况
ROLE-API-001 GET / 分页查询角色列表 page(int, 默认0), size(int, 默认10) {code, data: Page<Role>} 已登录 分页参数越界
ROLE-API-002 GET /{id} 根据ID获取角色 id(UUID, Path) {code, data: Role} 已登录 角色不存在
ROLE-API-003 GET /project/{projectId} 根据项目ID查询角色 projectId(UUID, Path) {code, data: [Role]} 已登录 项目不存在
ROLE-API-004 POST / 创建角色 Body: Role实体 {code, data: Role} 管理员 角色代码已存在; 字段校验失败
ROLE-API-005 PUT /{id} 更新角色 id(UUID, Path), Body: Role实体 {code, data: Role} 管理员 角色不存在; 角色代码冲突
ROLE-API-006 DELETE /{id} 删除角色 id(UUID, Path) {code, data: null} 管理员 角色不存在; 角色已分配给用户
ROLE-API-007 POST /{id}/permissions 为角色分配权限 id(UUID, Path), Body: [permissionId1, permissionId2, ...] {code, data: null} 管理员 角色不存在; 权限ID不存在
ROLE-API-008 GET /{id}/permissions 获取角色权限列表 id(UUID, Path) {code, data: [Permission]} 已登录 角色不存在
ROLE-API-009 GET /{id}/users 获取拥有某角色的用户 id(UUID, Path) {code, data: [User]} 已登录 角色不存在

3.4 PermissionController -- 权限管理

基础路径: /api/auth/permissions

编号 方法 路径 说明 请求参数 响应格式 权限要求 例外情况
PERM-API-001 GET / 分页查询权限列表 page(int, 默认0), size(int, 默认10) {code, data: Page<Permission>} 已登录 分页参数越界
PERM-API-002 GET /{id} 根据ID获取权限 id(UUID, Path) {code, data: Permission} 已登录 权限不存在
PERM-API-003 GET /type/{type} 根据类型查询权限 type(String, Path): MENU/BUTTON/API {code, data: [Permission]} 已登录 无效类型
PERM-API-004 GET /menus 查询所有菜单权限 {code, data: [Permission]} 已登录
PERM-API-005 POST / 创建权限 Body: Permission实体 {code, data: Permission} 管理员 权限代码已存在; 字段校验失败
PERM-API-006 PUT /{id} 更新权限 id(UUID, Path), Body: Permission实体 {code, data: Permission} 管理员 权限不存在; 权限代码冲突
PERM-API-007 DELETE /{id} 删除权限 id(UUID, Path) {code, data: null} 管理员 权限不存在; 权限已分配给角色

3.5 DeptController -- 部门管理

基础路径: /api/auth/depts

编号 方法 路径 说明 请求参数 响应格式 权限要求 例外情况
DEPT-API-001 GET /tree 获取部门树 {code, data: [DeptVO]} 已登录
DEPT-API-002 GET / 获取所有启用部门 {code, data: [Dept]} 已登录
DEPT-API-003 GET /{id} 根据ID获取部门 id(UUID, Path) {code, data: Dept} 已登录 部门不存在
DEPT-API-004 POST / 创建部门 Body: DeptDTO {deptName, parentId, deptType, leaderId, sortOrder} {code, data: Dept} 管理员 父部门不存在; 字段校验失败
DEPT-API-005 PUT /{id} 更新部门 id(UUID, Path), Body: DeptDTO {code, data: Dept} 管理员 部门不存在; 形成环
DEPT-API-006 DELETE /{id} 删除部门 id(UUID, Path) {code, data: null} 管理员 部门不存在; 有子部门; 部门下有用户
DEPT-API-007 GET /{deptId}/members 获取部门成员 deptId(UUID, Path) {code, data: [UserVO]} 已登录 部门不存在
DEPT-API-008 GET /by-type/{deptType} 根据类型查询部门 deptType(String, Path): ADMIN/ENGINEERING/SECURITY/CS/CLEANING {code, data: [Dept]} 已登录 无效类型

DeptVO格式:

{
  "id": "uuid",
  "parentId": "uuid",
  "deptName": "工程部",
  "deptType": "ENGINEERING",
  "leaderId": "uuid",
  "sortOrder": 1,
  "status": "ACTIVE",
  "children": [DeptVO, DeptVO, ...]
}

3.6 ProjectMemberController -- 项目成员管理

基础路径: /api/auth/projects

编号 方法 路径 说明 请求参数 响应格式 权限要求 例外情况
PMM-API-001 GET /{projectId}/members 查询项目成员列表 projectId(UUID, Path), page(int, 默认0), size(int, 默认20) {code, data: PageResponse<ProjectMemberVO>} 已登录 项目不存在
PMM-API-002 GET /{projectId}/available-members 获取可添加成员 projectId(UUID, Path), search(String, 可选) {code, data: [UserVO]} 已登录 项目不存在
PMM-API-003 POST /{projectId}/members 添加项目成员 projectId(UUID, Path), Body: AddProjectMemberDTO {userId, staffType, roleIds} {code, data: null} 项目管理员 用户不存在; 项目不存在; 用户已是成员
PMM-API-004 DELETE /{projectId}/members/{userId} 移除项目成员 projectId(UUID, Path), userId(UUID, Path) {code, data: null} 项目管理员 成员不存在

ProjectMemberVO格式:

{
  "id": "uuid",
  "userId": "uuid",
  "username": "zhangsan",
  "realName": "张三",
  "staffType": "SECURITY",
  "shiftType": "DAY",
  "assignmentStatus": "ASSIGNED",
  "roles": [
    {"id": "uuid", "code": "SECURITY_GUARD", "name": "保安"}
  ]
}

3.7 DataAccessController -- 数据访问授权 @Deprecated

基础路径: /api/data-access

编号 方法 路径 说明 请求参数 响应格式 权限要求 例外情况
DA-API-001 POST / 授予数据访问权限 Body: DataAccessRequest {dataType, dataId, accessType, accessId, accessLevel} {code, data: null} 已登录 未登录(401); 字段校验失败
DA-API-002 DELETE /{id} 撤销数据访问权限 id(UUID, Path) {code, data: null} 已登录 记录不存在
DA-API-003 GET / 查询数据访问记录 dataType(String), dataId(UUID) {code, data: [DataAccess]} 已登录 参数缺失

注意: 此控制器所有端点已标记 @Deprecated后续版本将移除。


3.8 AuditLogController -- 审计日志

基础路径: /api/audit-logs

编号 方法 路径 说明 请求参数 响应格式 权限要求 例外情况
AUDIT-API-001 GET / 分页查询审计日志 page(int, 默认0), size(int, 默认10), module(String, 可选), action(String, 可选), username(String, 可选), startDate(DateTime, 可选), endDate(DateTime, 可选) {code, data: Page<AuditLog>} 管理员 查询范围超30天自动截断
AUDIT-API-002 GET /modules 获取模块列表 {code, data: [{value, label}]} 管理员
AUDIT-API-003 GET /actions 获取操作类型列表 {code, data: [{value, label}]} 管理员
AUDIT-API-004 GET /stats 获取最近30天日志统计 {code, data: {total, retentionDays, description}} 管理员

模块列表固定值: USER(用户管理), ROLE(角色管理), PERMISSION(权限管理), PROJECT(项目管理), AUTH(登录认证)


3.9 SysConfigController -- 系统配置

基础路径: /api/config

编号 方法 路径 说明 请求参数 响应格式 权限要求 例外情况
CFG-API-001 GET / 获取所有配置项 {code, data: {key1: value1, key2: value2}} 管理员
CFG-API-002 GET /{configKey} 根据键获取配置 configKey(String, Path) {code, data: SysConfig} 管理员 配置键不存在
CFG-API-003 PUT /{configKey} 更新单个配置 configKey(String, Path), Body: {configValue: String(NotBlank)} {code, data: SysConfig} 管理员 配置键不存在; 配置值为空
CFG-API-004 PUT / 批量更新配置 Body: {key1: value1, key2: value2} {code, data: {key1: value1, key2: value2}} 管理员 配置键不存在

四、业务规则

4.1 RBAC权限模型角色-权限-用户关联规则)

模型结构: User <--M2M--> Role <--M2M--> Permission

双层角色分配:

  1. 用户直接角色: 通过 auth_user_role 中间表关联

    • 用户创建时分配
    • 通过 UserController.assignRoles 接口分配
    • 覆盖模式:新分配的角色列表完全替换旧列表
  2. 项目员工角色: 通过 ProjectStaffRole 关联

    • 项目成员管理时分配
    • 覆盖模式:先删除旧角色,再添加新角色
    • 级联删除:删除 ProjectStaff 时自动删除其所有 ProjectStaffRole

登录时角色收集规则:

用户所有角色 = 用户直接角色(auth_user_role)  项目员工角色(ProjectStaffRole → Role)

角色类型与数据范围对应关系:

角色类型 说明 默认数据范围 projectId
SYSTEM 系统级角色,跨项目 ALL NULL
PROJECT 项目级角色,绑定特定项目 PROJECT 非NULL
DEPARTMENT 部门级角色 DEPARTMENT NULL

角色分配约束:

  • 角色分配数量受 BatchOperationValidator.validateAssignmentSize() 限制
  • 分配不存在的角色ID将抛出异常
  • 角色状态为 DISABLED 时不应分配给用户(需业务层校验)

4.2 数据范围控制ALL/PROJECT/DEPARTMENT/SELF的SQL过滤规则

四级数据范围:

数据范围 编码 说明 SQL过滤规则
全部 ALL 可查看所有数据 不做数据过滤
项目 PROJECT 仅可查看所属项目数据 WHERE project_id IN (用户可访问的项目ID列表)
部门 DEPARTMENT 仅可查看本部门数据 WHERE project_id IN (...) AND dept_id = 用户部门ID
本人 SELF 仅可查看本人数据 WHERE assigned_to = 当前用户ID OR created_by = 当前用户ID

DataScopeService 核心方法:

方法 说明 返回值
canAccessAllData() 检查角色集中是否有ALL范围 Boolean
isSelfScopeOnly() 检查是否所有角色都是SELF范围 Boolean
getPermittedProjectIds() 获取用户可访问的项目ID列表 List<UUID>

项目上下文传递机制:

  1. 前端请求携带 X-Project-ID Header
  2. ProjectContextInterceptor 拦截器设置 ThreadLocal
  3. 业务层通过 DataScopeService 过滤数据

4.3 JWT认证流程登录→Token生成→验证→刷新→登出

Token生成:

  • 算法: HMAC-SHA256
  • Claims: userId(subject), username, roles列表
  • 过期时间: 可配置默认86400000ms = 24小时
  • 密钥: 配置项 jwt.secret

完整认证流程:

1. 登录 POST /api/auth/login
   ├── 检查登录锁定(Redis: login:attempt:{username})
   ├── 查询用户(含角色, LAZY加载)
   ├── 验证密码(BCrypt.matches)
   ├── 检查用户状态(LOCKED/DISABLED → 拒绝)
   ├── 收集角色(直接角色 + 项目员工角色)
   ├── 生成JWT Token
   ├── 清除登录失败计数
   ├── 更新lastLoginTime/lastLoginIp
   └── 返回 {token, userId, username, realName, roles}

2. 请求认证
   ├── Header: Authorization: Bearer {token}
   ├── JwtTokenProvider.validateToken() 验证签名和过期
   └── 解析 userId / username / roles

3. Token刷新 POST /api/auth/refresh
   ├── 验证当前Token有效
   ├── 检查Token未过期
   ├── 生成新Token
   └── 返回 {token}

4. 登出 POST /api/auth/logout
   └── 客户端清除Token服务端无状态

4.4 密码策略BCrypt/强度校验/弱密码检测/登录锁定)

加密算法: BCryptSpring Security PasswordEncoder

密码强度校验规则(可配置,前缀 password.*:

规则 配置键 默认值 说明
最小长度 password.minLength 8 最小长度
最大长度 password.maxLength 20 最大长度
需要大写字母 password.requireUppercase true 至少1个大写字母
需要小写字母 password.requireLowercase true 至少1个小写字母
需要数字 password.requireDigit true 至少1个数字
需要特殊字符 password.requireSpecial true 至少1个特殊字符

弱密码黑名单: password, 123456, admin, qwerty, letmein, welcome, monkey, dragon

旧密码兼容策略:

  • 检测非BCrypt格式密码MD5/SHA-1等
  • 非BCrypt密码强制返回 matches=false
  • 用户需通过修改密码流程重置为BCrypt格式

登录失败锁定机制基于Redis:

参数 默认值 说明
maxAttempts 5 最大失败次数
lockoutDurationMinutes 10 锁定时长(分钟)
Key格式 login:attempt:{username} Redis Key

锁定流程:

  1. 每次失败: increment计数首次设置TTL
  2. 达到上限(5次): isLockedOut返回true拒绝登录
  3. 登录成功: 清除计数
  4. 手动解锁: unlock方法清除Key

4.5 项目成员管理(添加/移除/角色分配/在岗状态变更)

添加项目成员流程:

  1. 接收 AddProjectMemberDTO: {userId, staffType, roleIds}
  2. 创建/更新 ProjectStaff 记录(设定员工类型、分配状态=ASSIGNED
  3. 覆盖模式更新角色: 先删除旧 ProjectStaffRole再添加新 ProjectStaffRole
  4. 创建 UserProject 关联记录

移除项目成员流程:

  1. 删除 ProjectStaff 记录(级联删除 ProjectStaffRole
  2. 删除 UserProject 关联记录

在岗状态变更:

  • ASSIGNED: 已分配(正常在岗)
  • ON_LEAVE: 请假(临时离岗)
  • TRANSFERRED: 已调离(永久离岗)

员工类型:

  • SECURITY(保安), CLEANING(保洁), GARDEN(绿化), MAINTENANCE(维修), CUSTOMER_SERVICE(客服), GENERAL(普通员工)

班次类型:

  • DAY(白班), NIGHT(夜班), ROTATION(轮班)

4.6 住户认证流程(申请→审核→通过/拒绝→房屋绑定)

认证状态流转:

UNVERIFIED(未认证) → PENDING(待审核) → VERIFIED(已认证)
                                      → REJECTED(已拒绝) → PENDING(重新申请)

认证流程:

  1. 住户注册账号verificationStatus = UNVERIFIED
  2. 住户提交认证申请身份证、住户类型verificationStatus = PENDING
  3. 管理员审核:
    • 通过: verificationStatus = VERIFIED, 记录 verifiedAt/verifiedBy
    • 拒绝: verificationStatus = REJECTED

房屋绑定流程:

  1. 住户认证通过后,创建 ResidentSpace 关联
  2. 关联字段: userId, spaceId, relationType(OWNER/FAMILY/TENANT)
  3. 绑定状态: PENDING(待生效) → ACTIVE(生效中) → EXPIRED(已过期) / CANCELLED(已取消)
  4. 支持生效/失效日期: startDate / endDateNULL=永久)

五、执行约束

5.1 用户名唯一性约束

  • 数据库约束: auth_user.username 列 UNIQUE
  • 校验规则: 正则 ^[a-zA-Z0-9_]+$长度3-50位
  • 违反后果: 创建/更新用户时抛出 DataIntegrityViolationException
  • 处理方式: 业务层先查询是否存在相同用户名,存在则抛出 BusinessException

5.2 角色代码唯一性约束

  • 数据库约束: auth_role.code 列 UNIQUE
  • 校验规则: 正则 ^[a-zA-Z0-9_]+$长度2-50位
  • 违反后果: 创建/更新角色时抛出 DataIntegrityViolationException
  • 处理方式: 业务层先查询是否存在相同角色代码,存在则抛出 BusinessException

5.3 权限代码唯一性约束

  • 数据库约束: auth_permission.code 列 UNIQUE
  • 校验规则: 正则 ^[a-zA-Z0-9_:]+$长度2-100位格式 module:resource:action
  • 违反后果: 创建/更新权限时抛出 DataIntegrityViolationException
  • 处理方式: 业务层先查询是否存在相同权限代码,存在则抛出 BusinessException

5.4 部门树完整性约束(不能形成环)

  • 约束说明: 部门通过 parentId 自引用形成树形结构,更新 parentId 时不能形成环路
  • 校验方式: 业务层在更新 parentId 时,沿 parentId 链向上遍历,检查是否会回到当前节点
  • 违反后果: 抛出 BusinessException提示"不能将部门设置为其子部门的下级"
  • 附加约束: 删除部门时,必须先删除或移动其所有子部门

5.5 密码强度约束

  • 最小长度: 8位
  • 最大长度: 20位业务层校验/ 128位API层校验
  • 必须包含: 大写字母、小写字母、数字、特殊字符各至少1个
  • 弱密码检测: 不允许使用黑名单中的密码
  • 违反后果: 修改密码时抛出 BusinessException提示具体不满足的规则

六、权限控制

6.1 API端点权限矩阵

控制器 端点 所需角色 数据范围过滤
AuthController POST /login 公开(无需认证)
AuthController POST /logout 已登录用户
AuthController GET /me 已登录用户 SELF
AuthController POST /refresh 已登录用户
UserController GET / 管理员 ALL/PROJECT/DEPARTMENT/SELF
UserController GET /{id} 管理员 同上
UserController POST / 管理员(SYSTEM级)
UserController PUT /{id} 管理员 同上
UserController DELETE /{id} 管理员(SYSTEM级)
UserController PUT /{id}/password 本人或管理员 SELF
UserController POST /{id}/roles 管理员(SYSTEM级)
UserController GET /{id}/projects 已登录用户 SELF
UserController POST /{id}/projects 管理员(PROJECT级)
UserController DELETE /{id}/projects/{projectId} 管理员(PROJECT级)
UserController GET /enterprise 已登录用户 ALL/PROJECT
RoleController GET / 已登录用户 ALL/PROJECT
RoleController GET /{id} 已登录用户 同上
RoleController GET /project/{projectId} 已登录用户 PROJECT
RoleController POST / 管理员(SYSTEM级)
RoleController PUT /{id} 管理员(SYSTEM级)
RoleController DELETE /{id} 管理员(SYSTEM级)
RoleController POST /{id}/permissions 管理员(SYSTEM级)
RoleController GET /{id}/permissions 已登录用户 同上
RoleController GET /{id}/users 已登录用户 同上
PermissionController GET / 已登录用户 ALL
PermissionController GET /{id} 已登录用户 ALL
PermissionController GET /type/{type} 已登录用户 ALL
PermissionController GET /menus 已登录用户 SELF(按角色过滤)
PermissionController POST / 管理员(SYSTEM级)
PermissionController PUT /{id} 管理员(SYSTEM级)
PermissionController DELETE /{id} 管理员(SYSTEM级)
DeptController GET /tree 已登录用户 ALL
DeptController GET / 已登录用户 ALL
DeptController GET /{id} 已登录用户 ALL
DeptController POST / 管理员(SYSTEM级)
DeptController PUT /{id} 管理员(SYSTEM级)
DeptController DELETE /{id} 管理员(SYSTEM级)
DeptController GET /{deptId}/members 已登录用户 DEPARTMENT
DeptController GET /by-type/{deptType} 已登录用户 ALL
ProjectMemberController GET /{projectId}/members 项目成员 PROJECT
ProjectMemberController GET /{projectId}/available-members 项目管理员 PROJECT
ProjectMemberController POST /{projectId}/members 项目管理员 PROJECT
ProjectMemberController DELETE /{projectId}/members/{userId} 项目管理员 PROJECT
DataAccessController POST / 已登录用户(@Deprecated)
DataAccessController DELETE /{id} 已登录用户(@Deprecated)
DataAccessController GET / 已登录用户(@Deprecated)
AuditLogController GET / 管理员(SYSTEM级) ALL
AuditLogController GET /modules 管理员(SYSTEM级)
AuditLogController GET /actions 管理员(SYSTEM级)
AuditLogController GET /stats 管理员(SYSTEM级) ALL
SysConfigController GET / 管理员(SYSTEM级) ALL
SysConfigController GET /{configKey} 管理员(SYSTEM级) ALL
SysConfigController PUT /{configKey} 管理员(SYSTEM级)
SysConfigController PUT / 管理员(SYSTEM级)

6.2 数据范围过滤规则

操作类型 ALL范围 PROJECT范围 DEPARTMENT范围 SELF范围
查询用户列表 全部用户 本项目成员 本部门用户 仅本人
查询角色列表 全部角色 本项目角色 - -
查询审计日志 全部日志 本项目日志 本部门日志 本人操作日志
查询部门成员 全部 本项目部门成员 本部门成员 -

七、例外情况处理

7.1 用户相关例外

例外场景 错误码 错误信息 处理方式
用户名已存在 409 "用户名{username}已存在" 创建/更新前查询,存在则拒绝
用户不存在 404 "用户不存在" findById返回空时抛出
密码错误 401 "用户名或密码错误" BCrypt.matches返回false
账户锁定 423 "账户已锁定,请{minutes}分钟后重试" 检查Redis锁定状态
账户禁用 403 "账户已被禁用" 检查UserStatus.DISABLED
原密码错误 400 "原密码不正确" 修改密码时验证
新密码强度不足 400 "密码必须包含大写字母、小写字母、数字和特殊字符长度8-20位" 密码策略校验
新密码为弱密码 400 "该密码过于简单,请使用更复杂的密码" 弱密码黑名单检测
手机号格式错误 400 "手机号格式不正确" 正则校验
邮箱格式错误 400 "邮箱格式不正确" @Email校验
删除有关联数据的用户 400 "该用户存在关联数据,无法删除" 检查UserProject/ProjectStaff等关联

7.2 角色相关例外

例外场景 错误码 错误信息 处理方式
角色代码已存在 409 "角色代码{code}已存在" 创建/更新前查询
角色不存在 404 "角色不存在" findById返回空时抛出
删除已分配的角色 400 "该角色已分配给用户,无法删除" 检查auth_user_role关联
角色代码格式错误 400 "角色代码只能包含字母、数字和下划线" 正则校验

7.3 权限相关例外

例外场景 错误码 错误信息 处理方式
权限代码已存在 409 "权限代码{code}已存在" 创建/更新前查询
权限不存在 404 "权限不存在" findById返回空时抛出
删除已分配的权限 400 "该权限已分配给角色,无法删除" 检查auth_role_permission关联
权限代码格式错误 400 "权限代码只能包含字母、数字、冒号和下划线" 正则校验

7.4 部门相关例外

例外场景 错误码 错误信息 处理方式
部门不存在 404 "部门不存在" getById返回空时返回error
有子部门不能删除 400 "该部门存在子部门,无法删除" 检查子部门数量
部门下有用户不能删除 400 "该部门下存在用户,无法删除" 检查部门成员
部门树形成环 400 "不能将部门设置为其子部门的下级" 遍历parentId链检查
父部门不存在 400 "上级部门不存在" 创建/更新时校验parentId

7.5 认证相关例外

例外场景 错误码 错误信息 处理方式
Token缺失 401 "未授权" Authorization Header为空
Token无效 401 "Token无效" JWT签名验证失败
Token已过期 401 "Token已过期" JWT过期时间检查
登录失败超限 423 "登录失败次数过多,账户已锁定{minutes}分钟" Redis计数检查
用户名不存在 401 "用户名或密码错误" 不暴露具体原因

7.6 项目成员相关例外

例外场景 错误码 错误信息 处理方式
用户已是项目成员 409 "该用户已是项目成员" 检查ProjectStaff存在性
项目成员不存在 404 "项目成员不存在" 删除时校验
角色ID不存在 400 "角色ID{id}不存在" 分配角色时校验

7.7 系统配置相关例外

例外场景 错误码 错误信息 处理方式
配置键不存在 404 "配置项{key}不存在" 查询时校验
配置值为空 400 "配置值不能为空" @NotBlank校验

7.8 审计日志相关例外

例外场景 错误码 错误信息 处理方式
查询范围超30天 200(自动截断) 无(自动截断起始时间) 强制限制查询窗口
分页参数过大 200(自动修正) 无(使用getSafeSize修正) PaginationValidator校验