package com.mosquito.project.permission; import jakarta.persistence.*; import org.junit.jupiter.api.Test; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; import org.springframework.test.context.TestPropertySource; import java.util.List; import static org.junit.jupiter.api.Assertions.*; /** * 权限管理系统数据库Schema验证测试 * 使用JPA自动创建表,验证PRD定义的10张权限相关表 */ @DataJpaTest @org.springframework.context.annotation.Import(com.mosquito.project.config.TestCacheConfig.class) @org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase(replace = org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase.Replace.ANY) @TestPropertySource(properties = { "spring.cache.type=NONE", "spring.jpa.hibernate.ddl-auto=create-drop", "spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration,org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration" }) class PermissionSchemaVerificationTest { @PersistenceContext private EntityManager entityManager; /** * 验证表是否存在 */ private boolean tableExists(String tableName) { try { entityManager.createNativeQuery( "SELECT 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = UPPER('" + tableName + "')" ).getSingleResult(); return true; } catch (Exception e) { return false; } } /** * 获取表的所有列名 */ private List getTableColumns(String tableName) { return entityManager.createNativeQuery( "SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = UPPER('" + tableName + "') ORDER BY ORDINAL_POSITION" ).getResultList(); } // ==================== sys_role 角色表 ==================== @Test void sysRoleTableExists() { assertTrue(tableExists("sys_role"), "sys_role表应该存在"); } @Test void sysRoleTableHasRequiredColumns() { List columns = getTableColumns("sys_role"); assertTrue(columns.contains("ID"), "sys_role应有ID字段"); assertTrue(columns.contains("ROLE_CODE"), "sys_role应有ROLE_CODE字段"); assertTrue(columns.contains("ROLE_NAME"), "sys_role应有ROLE_NAME字段"); assertTrue(columns.contains("ROLE_LEVEL"), "sys_role应有ROLE_LEVEL字段"); assertTrue(columns.contains("DATA_SCOPE"), "sys_role应有DATA_SCOPE字段"); assertTrue(columns.contains("DESCRIPTION"), "sys_role应有DESCRIPTION字段"); assertTrue(columns.contains("STATUS"), "sys_role应有STATUS字段"); assertTrue(columns.contains("CREATED_BY"), "sys_role应有CREATED_BY字段"); assertTrue(columns.contains("CREATED_AT"), "sys_role应有CREATED_AT字段"); assertTrue(columns.contains("UPDATED_AT"), "sys_role应有UPDATED_AT字段"); } // ==================== sys_permission 权限表 ==================== @Test void sysPermissionTableExists() { assertTrue(tableExists("sys_permission"), "sys_permission表应该存在"); } @Test void sysPermissionTableHasRequiredColumns() { List columns = getTableColumns("sys_permission"); assertTrue(columns.contains("ID"), "sys_permission应有ID字段"); assertTrue(columns.contains("PERMISSION_CODE"), "sys_permission应有PERMISSION_CODE字段"); assertTrue(columns.contains("PERMISSION_NAME"), "sys_permission应有PERMISSION_NAME字段"); assertTrue(columns.contains("MODULE_CODE"), "sys_permission应有MODULE_CODE字段"); assertTrue(columns.contains("RESOURCE_CODE"), "sys_permission应有RESOURCE_CODE字段"); assertTrue(columns.contains("OPERATION_CODE"), "sys_permission应有OPERATION_CODE字段"); assertTrue(columns.contains("DATA_SCOPE"), "sys_permission应有DATA_SCOPE字段"); assertTrue(columns.contains("DESCRIPTION"), "sys_permission应有DESCRIPTION字段"); assertTrue(columns.contains("STATUS"), "sys_permission应有STATUS字段"); assertTrue(columns.contains("CREATED_AT"), "sys_permission应有CREATED_AT字段"); } // ==================== sys_user_role 用户角色关联表 ==================== @Test void sysUserRoleTableExists() { assertTrue(tableExists("sys_user_role"), "sys_user_role表应该存在"); } @Test void sysUserRoleTableHasRequiredColumns() { List columns = getTableColumns("sys_user_role"); assertTrue(columns.contains("ID"), "sys_user_role应有ID字段"); assertTrue(columns.contains("USER_ID"), "sys_user_role应有USER_ID字段"); assertTrue(columns.contains("ROLE_ID"), "sys_user_role应有ROLE_ID字段"); assertTrue(columns.contains("DEPARTMENT_ID"), "sys_user_role应有DEPARTMENT_ID字段"); assertTrue(columns.contains("CREATED_BY"), "sys_user_role应有CREATED_BY字段"); assertTrue(columns.contains("CREATED_AT"), "sys_user_role应有CREATED_AT字段"); } // ==================== sys_role_permission 角色权限关联表 ==================== @Test void sysRolePermissionTableExists() { assertTrue(tableExists("sys_role_permission"), "sys_role_permission表应该存在"); } @Test void sysRolePermissionTableHasRequiredColumns() { List columns = getTableColumns("sys_role_permission"); assertTrue(columns.contains("ID"), "sys_role_permission应有ID字段"); assertTrue(columns.contains("ROLE_ID"), "sys_role_permission应有ROLE_ID字段"); assertTrue(columns.contains("PERMISSION_ID"), "sys_role_permission应有PERMISSION_ID字段"); assertTrue(columns.contains("CREATED_AT"), "sys_role_permission应有CREATED_AT字段"); } // ==================== sys_department 部门表 ==================== @Test void sysDepartmentTableExists() { assertTrue(tableExists("sys_department"), "sys_department表应该存在"); } @Test void sysDepartmentTableHasRequiredColumns() { List columns = getTableColumns("sys_department"); assertTrue(columns.contains("ID"), "sys_department应有ID字段"); assertTrue(columns.contains("DEPT_NAME"), "sys_department应有DEPT_NAME字段"); assertTrue(columns.contains("PARENT_ID"), "sys_department应有PARENT_ID字段"); assertTrue(columns.contains("DEPT_CODE"), "sys_department应有DEPT_CODE字段"); assertTrue(columns.contains("LEADER_ID"), "sys_department应有LEADER_ID字段"); assertTrue(columns.contains("SORT_ORDER"), "sys_department应有SORT_ORDER字段"); assertTrue(columns.contains("STATUS"), "sys_department应有STATUS字段"); assertTrue(columns.contains("CREATED_AT"), "sys_department应有CREATED_AT字段"); } // ==================== sys_approval_flow 审批流程配置表 ==================== @Test void sysApprovalFlowTableExists() { assertTrue(tableExists("sys_approval_flow"), "sys_approval_flow表应该存在"); } @Test void sysApprovalFlowTableHasRequiredColumns() { List columns = getTableColumns("sys_approval_flow"); assertTrue(columns.contains("ID"), "sys_approval_flow应有ID字段"); assertTrue(columns.contains("FLOW_CODE"), "sys_approval_flow应有FLOW_CODE字段"); assertTrue(columns.contains("FLOW_NAME"), "sys_approval_flow应有FLOW_NAME字段"); assertTrue(columns.contains("TRIGGER_EVENT"), "sys_approval_flow应有TRIGGER_EVENT字段"); assertTrue(columns.contains("CONDITIONS"), "sys_approval_flow应有CONDITIONS字段"); assertTrue(columns.contains("NODES"), "sys_approval_flow应有NODES字段"); assertTrue(columns.contains("TIMEOUT_HOURS"), "sys_approval_flow应有TIMEOUT_HOURS字段"); assertTrue(columns.contains("TIMEOUT_ACTION"), "sys_approval_flow应有TIMEOUT_ACTION字段"); assertTrue(columns.contains("STATUS"), "sys_approval_flow应有STATUS字段"); assertTrue(columns.contains("CREATED_AT"), "sys_approval_flow应有CREATED_AT字段"); } // ==================== sys_approval_record 审批记录表 ==================== @Test void sysApprovalRecordTableExists() { assertTrue(tableExists("sys_approval_record"), "sys_approval_record表应该存在"); } @Test void sysApprovalRecordTableHasRequiredColumns() { List columns = getTableColumns("sys_approval_record"); assertTrue(columns.contains("ID"), "sys_approval_record应有ID字段"); assertTrue(columns.contains("FLOW_ID"), "sys_approval_record应有FLOW_ID字段"); assertTrue(columns.contains("BIZ_TYPE"), "sys_approval_record应有BIZ_TYPE字段"); assertTrue(columns.contains("BIZ_ID"), "sys_approval_record应有BIZ_ID字段"); assertTrue(columns.contains("CURRENT_NODE"), "sys_approval_record应有CURRENT_NODE字段"); assertTrue(columns.contains("APPLICANT_ID"), "sys_approval_record应有APPLICANT_ID字段"); assertTrue(columns.contains("STATUS"), "sys_approval_record应有STATUS字段"); assertTrue(columns.contains("CURRENT_APPROVER_ID"), "sys_approval_record应有CURRENT_APPROVER_ID字段"); assertTrue(columns.contains("CREATED_AT"), "sys_approval_record应有CREATED_AT字段"); assertTrue(columns.contains("UPDATED_AT"), "sys_approval_record应有UPDATED_AT字段"); } // ==================== sys_approval_history 审批历史表 ==================== @Test void sysApprovalHistoryTableExists() { assertTrue(tableExists("sys_approval_history"), "sys_approval_history表应该存在"); } @Test void sysApprovalHistoryTableHasRequiredColumns() { List columns = getTableColumns("sys_approval_history"); assertTrue(columns.contains("ID"), "sys_approval_history应有ID字段"); assertTrue(columns.contains("RECORD_ID"), "sys_approval_history应有RECORD_ID字段"); assertTrue(columns.contains("NODE_INDEX"), "sys_approval_history应有NODE_INDEX字段"); assertTrue(columns.contains("APPROVER_ID"), "sys_approval_history应有APPROVER_ID字段"); assertTrue(columns.contains("ACTION"), "sys_approval_history应有ACTION字段"); assertTrue(columns.contains("COMMENT"), "sys_approval_history应有COMMENT字段"); assertTrue(columns.contains("CREATED_AT"), "sys_approval_history应有CREATED_AT字段"); } // ==================== sys_permission_audit 权限审计日志表 ==================== @Test void sysPermissionAuditTableExists() { assertTrue(tableExists("sys_permission_audit"), "sys_permission_audit表应该存在"); } @Test void sysPermissionAuditTableHasRequiredColumns() { List columns = getTableColumns("sys_permission_audit"); assertTrue(columns.contains("ID"), "sys_permission_audit应有ID字段"); assertTrue(columns.contains("OPERATOR_ID"), "sys_permission_audit应有OPERATOR_ID字段"); assertTrue(columns.contains("OPERATION_TYPE"), "sys_permission_audit应有OPERATION_TYPE字段"); assertTrue(columns.contains("TARGET_TYPE"), "sys_permission_audit应有TARGET_TYPE字段"); assertTrue(columns.contains("TARGET_ID"), "sys_permission_audit应有TARGET_ID字段"); assertTrue(columns.contains("CHANGE_DETAIL"), "sys_permission_audit应有CHANGE_DETAIL字段"); assertTrue(columns.contains("IP_ADDRESS"), "sys_permission_audit应有IP_ADDRESS字段"); assertTrue(columns.contains("REASON"), "sys_permission_audit应有REASON字段"); assertTrue(columns.contains("CREATED_AT"), "sys_permission_audit应有CREATED_AT字段"); } // ==================== sys_sensitive_field 数据敏感字段配置表 ==================== @Test void sysSensitiveFieldTableExists() { assertTrue(tableExists("sys_sensitive_field"), "sys_sensitive_field表应该存在"); } @Test void sysSensitiveFieldTableHasRequiredColumns() { List columns = getTableColumns("sys_sensitive_field"); assertTrue(columns.contains("ID"), "sys_sensitive_field应有ID字段"); assertTrue(columns.contains("TABLE_NAME"), "sys_sensitive_field应有TABLE_NAME字段"); assertTrue(columns.contains("FIELD_NAME"), "sys_sensitive_field应有FIELD_NAME字段"); assertTrue(columns.contains("FIELD_TYPE"), "sys_sensitive_field应有FIELD_TYPE字段"); assertTrue(columns.contains("MASK_TYPE"), "sys_sensitive_field应有MASK_TYPE字段"); assertTrue(columns.contains("MASK_PATTERN"), "sys_sensitive_field应有MASK_PATTERN字段"); assertTrue(columns.contains("CREATED_AT"), "sys_sensitive_field应有CREATED_AT字段"); } // ==================== 全部表验证 ==================== @Test void allPermissionTablesExist() { String[] tables = { "sys_role", "sys_permission", "sys_user_role", "sys_role_permission", "sys_department", "sys_approval_flow", "sys_approval_record", "sys_approval_history", "sys_permission_audit", "sys_sensitive_field" }; for (String table : tables) { assertTrue(tableExists(table), "表 " + table + " 应该存在"); } } } // ==================== JPA实体类定义 ==================== @Entity @Table(name = "sys_role") public class SysRole { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(name = "role_code", nullable = false, unique = true, length = 50) private String roleCode; @Column(name = "role_name", nullable = false, length = 100) private String roleName; @Column(name = "role_level", nullable = false, length = 20) private String roleLevel; @Column(name = "data_scope", nullable = false, length = 20) private String dataScope; @Column(name = "description", length = 500) private String description; @Column(name = "status", length = 20) private String status; @Column(name = "created_by") private Long createdBy; @Column(name = "created_at") private java.time.LocalDateTime createdAt; @Column(name = "updated_at") private java.time.LocalDateTime updatedAt; } @Entity @Table(name = "sys_permission") public class SysPermission { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(name = "permission_code", nullable = false, unique = true, length = 100) private String permissionCode; @Column(name = "permission_name", nullable = false, length = 100) private String permissionName; @Column(name = "module_code", nullable = false, length = 50) private String moduleCode; @Column(name = "resource_code", length = 50) private String resourceCode; @Column(name = "operation_code", length = 50) private String operationCode; @Column(name = "data_scope", length = 20) private String dataScope; @Column(name = "description", length = 500) private String description; @Column(name = "status", length = 20) private String status; @Column(name = "created_at") private java.time.LocalDateTime createdAt; } @Entity @Table(name = "sys_user_role") public class SysUserRole { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(name = "user_id", nullable = false) private Long userId; @Column(name = "role_id", nullable = false) private Long roleId; @Column(name = "department_id") private Long departmentId; @Column(name = "created_by") private Long createdBy; @Column(name = "created_at") private java.time.LocalDateTime createdAt; } @Entity @Table(name = "sys_role_permission") public class SysRolePermission { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(name = "role_id", nullable = false) private Long roleId; @Column(name = "permission_id", nullable = false) private Long permissionId; @Column(name = "created_at") private java.time.LocalDateTime createdAt; } @Entity @Table(name = "sys_department") public class SysDepartment { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(name = "dept_name", nullable = false, length = 100) private String deptName; @Column(name = "parent_id") private Long parentId; @Column(name = "dept_code", length = 50) private String deptCode; @Column(name = "leader_id") private Long leaderId; @Column(name = "sort_order") private Integer sortOrder; @Column(name = "status", length = 20) private String status; @Column(name = "created_at") private java.time.LocalDateTime createdAt; } @Entity @Table(name = "sys_approval_flow") public class SysApprovalFlow { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(name = "flow_code", nullable = false, unique = true, length = 50) private String flowCode; @Column(name = "flow_name", nullable = false, length = 100) private String flowName; @Column(name = "trigger_event", nullable = false, length = 100) private String triggerEvent; @Column(name = "conditions", columnDefinition = "CLOB") private String conditions; @Column(name = "nodes", nullable = false, columnDefinition = "CLOB") private String nodes; @Column(name = "timeout_hours") private Integer timeoutHours; @Column(name = "timeout_action", length = 20) private String timeoutAction; @Column(name = "status", length = 20) private String status; @Column(name = "created_at") private java.time.LocalDateTime createdAt; } @Entity @Table(name = "sys_approval_record") public class SysApprovalRecord { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(name = "flow_id", nullable = false) private Long flowId; @Column(name = "biz_type", nullable = false, length = 50) private String bizType; @Column(name = "biz_id", nullable = false) private Long bizId; @Column(name = "current_node", nullable = false) private Integer currentNode; @Column(name = "applicant_id", nullable = false) private Long applicantId; @Column(name = "status", length = 20) private String status; @Column(name = "current_approver_id") private Long currentApproverId; @Column(name = "created_at") private java.time.LocalDateTime createdAt; @Column(name = "updated_at") private java.time.LocalDateTime updatedAt; } @Entity @Table(name = "sys_approval_history") public class SysApprovalHistory { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(name = "record_id", nullable = false) private Long recordId; @Column(name = "node_index", nullable = false) private Integer nodeIndex; @Column(name = "approver_id", nullable = false) private Long approverId; @Column(name = "action", nullable = false, length = 20) private String action; @Column(name = "comment", columnDefinition = "TEXT") private String comment; @Column(name = "created_at") private java.time.LocalDateTime createdAt; } @Entity @Table(name = "sys_permission_audit") public class SysPermissionAudit { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(name = "operator_id", nullable = false) private Long operatorId; @Column(name = "operation_type", nullable = false, length = 50) private String operationType; @Column(name = "target_type", nullable = false, length = 20) private String targetType; @Column(name = "target_id", nullable = false) private Long targetId; @Column(name = "change_detail", columnDefinition = "CLOB") private String changeDetail; @Column(name = "ip_address", length = 50) private String ipAddress; @Column(name = "reason", length = 500) private String reason; @Column(name = "created_at") private java.time.LocalDateTime createdAt; } @Entity @Table(name = "sys_sensitive_field") public class SysSensitiveField { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(name = "table_name", nullable = false, length = 50) private String tableName; @Column(name = "field_name", nullable = false, length = 50) private String fieldName; @Column(name = "field_type", nullable = false, length = 20) private String fieldType; @Column(name = "mask_type", nullable = false, length = 20) private String maskType; @Column(name = "mask_pattern", length = 50) private String maskPattern; @Column(name = "created_at") private java.time.LocalDateTime createdAt; }