46 KiB
身份与权限域 - 详细设计
文档版本: 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}$ |
手机号码 |
| VARCHAR(100) | 电子邮箱 | ||
| 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 | 所属项目ID(NULL=系统级) |
| 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 | 上级部门ID(NULL=顶级) | |
| 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→ createdAtidx_audit_log_user_id→ userIdidx_audit_log_module→ moduleidx_audit_log_action→ actionidx_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 → User(FK: fk_project_staff_user)staffRoles→ @OneToMany → ProjectStaffRole(mappedBy="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) → ProjectStaffrole→ @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
双层角色分配:
-
用户直接角色: 通过
auth_user_role中间表关联- 用户创建时分配
- 通过
UserController.assignRoles接口分配 - 覆盖模式:新分配的角色列表完全替换旧列表
-
项目员工角色: 通过
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> |
项目上下文传递机制:
- 前端请求携带
X-Project-IDHeader ProjectContextInterceptor拦截器设置 ThreadLocal- 业务层通过 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/强度校验/弱密码检测/登录锁定)
加密算法: BCrypt(Spring 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 |
锁定流程:
- 每次失败: increment计数,首次设置TTL
- 达到上限(5次): isLockedOut返回true,拒绝登录
- 登录成功: 清除计数
- 手动解锁: unlock方法清除Key
4.5 项目成员管理(添加/移除/角色分配/在岗状态变更)
添加项目成员流程:
- 接收 AddProjectMemberDTO:
{userId, staffType, roleIds} - 创建/更新 ProjectStaff 记录(设定员工类型、分配状态=ASSIGNED)
- 覆盖模式更新角色: 先删除旧 ProjectStaffRole,再添加新 ProjectStaffRole
- 创建 UserProject 关联记录
移除项目成员流程:
- 删除 ProjectStaff 记录(级联删除 ProjectStaffRole)
- 删除 UserProject 关联记录
在岗状态变更:
- ASSIGNED: 已分配(正常在岗)
- ON_LEAVE: 请假(临时离岗)
- TRANSFERRED: 已调离(永久离岗)
员工类型:
- SECURITY(保安), CLEANING(保洁), GARDEN(绿化), MAINTENANCE(维修), CUSTOMER_SERVICE(客服), GENERAL(普通员工)
班次类型:
- DAY(白班), NIGHT(夜班), ROTATION(轮班)
4.6 住户认证流程(申请→审核→通过/拒绝→房屋绑定)
认证状态流转:
UNVERIFIED(未认证) → PENDING(待审核) → VERIFIED(已认证)
→ REJECTED(已拒绝) → PENDING(重新申请)
认证流程:
- 住户注册账号,verificationStatus = UNVERIFIED
- 住户提交认证申请(身份证、住户类型),verificationStatus = PENDING
- 管理员审核:
- 通过: verificationStatus = VERIFIED, 记录 verifiedAt/verifiedBy
- 拒绝: verificationStatus = REJECTED
房屋绑定流程:
- 住户认证通过后,创建 ResidentSpace 关联
- 关联字段: userId, spaceId, relationType(OWNER/FAMILY/TENANT)
- 绑定状态: PENDING(待生效) → ACTIVE(生效中) → EXPIRED(已过期) / CANCELLED(已取消)
- 支持生效/失效日期: startDate / endDate(NULL=永久)
五、执行约束
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校验 |