-- 数据权限模块 — RBAC 侧表结构 -- 设计文档:E:\oms0414\docs\数据权限设计.md -- 与 user / role / organization 同库;表名小写,与 Fake.Rbac 风格一致 -- 执行前请确认已存在 RBAC 基础表 -- --------------------------------------------------------------------------- -- 1. 用户组织权限 -- --------------------------------------------------------------------------- CREATE TABLE IF NOT EXISTS `user_org_perm` ( `Id` CHAR(36) NOT NULL COMMENT '主键 GUID', `UserId` CHAR(36) NOT NULL COMMENT 'FK user.Id', `OrganizationId` CHAR(36) NOT NULL COMMENT 'FK organization.Id', `OrgScope` TINYINT NOT NULL DEFAULT 2 COMMENT '1=仅本级 2=本级+所有下级', `EffectiveTime` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '生效时间', `ExpireTime` DATETIME NULL COMMENT '过期时间,NULL=永久', `IsTemporary` TINYINT NOT NULL DEFAULT 0 COMMENT '是否临时授权:0否 1是', `IsDeleted` TINYINT NOT NULL DEFAULT 0, `CreateUserId` INT NOT NULL DEFAULT 0, `CreateTime` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, `UpdateUserId` INT NULL, `UpdateTime` DATETIME NULL, PRIMARY KEY (`Id`), KEY `idx_user_org_perm_user` (`UserId`, `IsDeleted`), KEY `idx_user_org_perm_org` (`OrganizationId`), KEY `idx_user_org_perm_expire` (`ExpireTime`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户组织数据权限'; -- --------------------------------------------------------------------------- -- 2. 角色组织权限(角色继承 / 模板绑定) -- --------------------------------------------------------------------------- CREATE TABLE IF NOT EXISTS `role_org_perm` ( `Id` CHAR(36) NOT NULL, `RoleId` CHAR(36) NOT NULL COMMENT 'FK role.Id', `OrganizationId` CHAR(36) NOT NULL, `OrgScope` TINYINT NOT NULL DEFAULT 2, `IsDeleted` TINYINT NOT NULL DEFAULT 0, `CreateUserId` INT NOT NULL DEFAULT 0, `CreateTime` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, `UpdateUserId` INT NULL, `UpdateTime` DATETIME NULL, PRIMARY KEY (`Id`), UNIQUE KEY `uk_role_org_perm` (`RoleId`, `OrganizationId`, `IsDeleted`), KEY `idx_role_org_perm_role` (`RoleId`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='角色组织数据权限'; -- --------------------------------------------------------------------------- -- 3. 数据范围(个人/小组/部门/组织树/全局) -- --------------------------------------------------------------------------- CREATE TABLE IF NOT EXISTS `role_data_scope` ( `Id` CHAR(36) NOT NULL, `RoleId` CHAR(36) NOT NULL, `DataScope` TINYINT NOT NULL COMMENT '1个人 2小组 3部门 4组织树 5全局', `DataResourceCode` VARCHAR(32) NULL COMMENT 'NULL=全局默认;Order/Customer/Recharge 等', `IsDeleted` TINYINT NOT NULL DEFAULT 0, `CreateUserId` INT NOT NULL DEFAULT 0, `CreateTime` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, `UpdateUserId` INT NULL, `UpdateTime` DATETIME NULL, PRIMARY KEY (`Id`), UNIQUE KEY `uk_role_data_scope` (`RoleId`, `DataResourceCode`, `IsDeleted`), KEY `idx_role_data_scope_role` (`RoleId`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='角色数据范围'; CREATE TABLE IF NOT EXISTS `user_data_scope` ( `Id` CHAR(36) NOT NULL, `UserId` CHAR(36) NOT NULL, `DataScope` TINYINT NOT NULL, `DataResourceCode` VARCHAR(32) NULL, `EffectiveTime` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, `ExpireTime` DATETIME NULL, `IsTemporary` TINYINT NOT NULL DEFAULT 0, `IsDeleted` TINYINT NOT NULL DEFAULT 0, `CreateUserId` INT NOT NULL DEFAULT 0, `CreateTime` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, `UpdateUserId` INT NULL, `UpdateTime` DATETIME NULL, PRIMARY KEY (`Id`), UNIQUE KEY `uk_user_data_scope` (`UserId`, `DataResourceCode`, `IsDeleted`), KEY `idx_user_data_scope_user` (`UserId`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户数据范围(覆盖角色默认)'; -- --------------------------------------------------------------------------- -- 4. 业务维度 -- --------------------------------------------------------------------------- CREATE TABLE IF NOT EXISTS `role_biz_perm` ( `Id` CHAR(36) NOT NULL, `RoleId` CHAR(36) NOT NULL, `BizType` VARCHAR(32) NOT NULL COMMENT 'product_line/kpi_area/customer_group/warehouse/region', `BizId` VARCHAR(64) NOT NULL COMMENT '业务主键字符串', `BizName` VARCHAR(128) NULL COMMENT '冗余展示名', `IsDeleted` TINYINT NOT NULL DEFAULT 0, `CreateUserId` INT NOT NULL DEFAULT 0, `CreateTime` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`Id`), KEY `idx_role_biz_perm_role` (`RoleId`, `BizType`), KEY `idx_role_biz_perm_biz` (`BizType`, `BizId`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='角色业务维度权限'; CREATE TABLE IF NOT EXISTS `user_biz_perm` ( `Id` CHAR(36) NOT NULL, `UserId` CHAR(36) NOT NULL, `BizType` VARCHAR(32) NOT NULL, `BizId` VARCHAR(64) NOT NULL, `BizName` VARCHAR(128) NULL, `EffectiveTime` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, `ExpireTime` DATETIME NULL, `IsTemporary` TINYINT NOT NULL DEFAULT 0, `IsDeleted` TINYINT NOT NULL DEFAULT 0, `CreateUserId` INT NOT NULL DEFAULT 0, `CreateTime` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`Id`), KEY `idx_user_biz_perm_user` (`UserId`, `BizType`), KEY `idx_user_biz_perm_biz` (`BizType`, `BizId`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户业务维度权限'; -- --------------------------------------------------------------------------- -- 5. 密级 -- --------------------------------------------------------------------------- CREATE TABLE IF NOT EXISTS `role_secret_perm` ( `Id` CHAR(36) NOT NULL, `RoleId` CHAR(36) NOT NULL, `SecretLevel` TINYINT NOT NULL COMMENT '1公开 2内部 3机密 4绝密', `DataResourceCode` VARCHAR(32) NULL, `IsDeleted` TINYINT NOT NULL DEFAULT 0, `CreateUserId` INT NOT NULL DEFAULT 0, `CreateTime` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`Id`), KEY `idx_role_secret_perm_role` (`RoleId`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='角色密级权限'; CREATE TABLE IF NOT EXISTS `user_secret_perm` ( `Id` CHAR(36) NOT NULL, `UserId` CHAR(36) NOT NULL, `SecretLevel` TINYINT NOT NULL, `DataResourceCode` VARCHAR(32) NULL, `EffectiveTime` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, `ExpireTime` DATETIME NULL, `IsTemporary` TINYINT NOT NULL DEFAULT 0, `IsDeleted` TINYINT NOT NULL DEFAULT 0, `CreateUserId` INT NOT NULL DEFAULT 0, `CreateTime` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`Id`), KEY `idx_user_secret_perm_user` (`UserId`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户密级权限'; -- --------------------------------------------------------------------------- -- 6. 自定义过滤规则(JSON AST,禁止存 SQL) -- --------------------------------------------------------------------------- CREATE TABLE IF NOT EXISTS `role_filter_rule` ( `Id` CHAR(36) NOT NULL, `RoleId` CHAR(36) NOT NULL, `DataResourceCode` VARCHAR(32) NOT NULL, `FilterContent` JSON NOT NULL COMMENT '过滤条件 AST', `FilterHash` CHAR(64) NOT NULL COMMENT 'SHA256(FilterContent)', `IsDeleted` TINYINT NOT NULL DEFAULT 0, `CreateUserId` INT NOT NULL DEFAULT 0, `CreateTime` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, `UpdateUserId` INT NULL, `UpdateTime` DATETIME NULL, PRIMARY KEY (`Id`), UNIQUE KEY `uk_role_filter_rule` (`RoleId`, `DataResourceCode`, `IsDeleted`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='角色自定义过滤'; CREATE TABLE IF NOT EXISTS `user_filter_rule` ( `Id` CHAR(36) NOT NULL, `UserId` CHAR(36) NOT NULL, `DataResourceCode` VARCHAR(32) NOT NULL, `FilterContent` JSON NOT NULL, `FilterHash` CHAR(64) NOT NULL, `EffectiveTime` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, `ExpireTime` DATETIME NULL, `IsTemporary` TINYINT NOT NULL DEFAULT 0, `IsDeleted` TINYINT NOT NULL DEFAULT 0, `CreateUserId` INT NOT NULL DEFAULT 0, `CreateTime` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, `UpdateUserId` INT NULL, `UpdateTime` DATETIME NULL, PRIMARY KEY (`Id`), UNIQUE KEY `uk_user_filter_rule` (`UserId`, `DataResourceCode`, `IsDeleted`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户自定义过滤'; -- --------------------------------------------------------------------------- -- 7. 数据资源注册(模块接入清单) -- --------------------------------------------------------------------------- CREATE TABLE IF NOT EXISTS `data_resource` ( `Id` CHAR(36) NOT NULL, `Code` VARCHAR(32) NOT NULL COMMENT 'Order/Customer/Recharge/ChannelProduct/Xhs', `Name` VARCHAR(64) NOT NULL, `Description` VARCHAR(256) NULL, `MainTable` VARCHAR(64) NULL COMMENT '主表名,如 t_order', `OrgField` VARCHAR(64) NULL COMMENT '组织字段名', `OwnerField` VARCHAR(64) NULL COMMENT '负责人字段名', `SecretLevelField` VARCHAR(64) NULL DEFAULT 'SecretLevel', `IsEnabled` TINYINT NOT NULL DEFAULT 1, `SortOrder` INT NOT NULL DEFAULT 0, `IsDeleted` TINYINT NOT NULL DEFAULT 0, `CreateTime` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`Id`), UNIQUE KEY `uk_data_resource_code` (`Code`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='数据权限资源注册'; -- --------------------------------------------------------------------------- -- 8. 字段脱敏配置 -- --------------------------------------------------------------------------- CREATE TABLE IF NOT EXISTS `data_perm_field_mask` ( `Id` CHAR(36) NOT NULL, `DataResourceCode` VARCHAR(32) NOT NULL, `FieldName` VARCHAR(64) NOT NULL COMMENT 'DTO/表字段名', `SecretLevel` TINYINT NOT NULL COMMENT '达到此密级才脱敏', `MaskType` VARCHAR(32) NOT NULL DEFAULT 'partial' COMMENT 'partial/full/hide', `MaskPattern` VARCHAR(128) NULL COMMENT '如 phone: 3,4 保留首尾', `IsEnabled` TINYINT NOT NULL DEFAULT 1, `IsDeleted` TINYINT NOT NULL DEFAULT 0, `CreateTime` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`Id`), UNIQUE KEY `uk_field_mask` (`DataResourceCode`, `FieldName`, `IsDeleted`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='字段级脱敏配置'; -- --------------------------------------------------------------------------- -- 9. 权限模板 -- --------------------------------------------------------------------------- CREATE TABLE IF NOT EXISTS `data_perm_template` ( `Id` CHAR(36) NOT NULL, `Name` VARCHAR(64) NOT NULL, `Code` VARCHAR(32) NOT NULL COMMENT '模板编码,如 SalesStaff', `Description` VARCHAR(256) NULL, `RoleCode` VARCHAR(64) NULL COMMENT '可选绑定 RBAC role.Code,分配角色时自动套用', `IsBuiltIn` TINYINT NOT NULL DEFAULT 0 COMMENT '内置模板不可删', `IsDeleted` TINYINT NOT NULL DEFAULT 0, `CreateUserId` INT NOT NULL DEFAULT 0, `CreateTime` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, `UpdateUserId` INT NULL, `UpdateTime` DATETIME NULL, PRIMARY KEY (`Id`), UNIQUE KEY `uk_data_perm_template_code` (`Code`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='数据权限模板'; CREATE TABLE IF NOT EXISTS `data_perm_template_item` ( `Id` CHAR(36) NOT NULL, `TemplateId` CHAR(36) NOT NULL, `DimensionType` VARCHAR(32) NOT NULL COMMENT 'org/data_scope/biz/secret/filter', `ItemContent` JSON NOT NULL COMMENT '维度配置 JSON', `SortOrder` INT NOT NULL DEFAULT 0, `IsDeleted` TINYINT NOT NULL DEFAULT 0, PRIMARY KEY (`Id`), KEY `idx_template_item_tpl` (`TemplateId`, `DimensionType`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='数据权限模板明细'; -- --------------------------------------------------------------------------- -- 10. 审计 -- --------------------------------------------------------------------------- CREATE TABLE IF NOT EXISTS `data_perm_change_log` ( `Id` BIGINT NOT NULL AUTO_INCREMENT, `TargetType` VARCHAR(16) NOT NULL COMMENT 'user/role/template', `TargetId` CHAR(36) NOT NULL, `Action` VARCHAR(16) NOT NULL COMMENT 'create/update/delete/apply_template', `BeforeJson` JSON NULL, `AfterJson` JSON NULL, `OperatorUserId` CHAR(36) NOT NULL COMMENT '操作人 user.Id', `OperatorMapId` INT NULL COMMENT '操作人 mapId', `CreateTime` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`Id`), KEY `idx_perm_change_target` (`TargetType`, `TargetId`, `CreateTime`), KEY `idx_perm_change_operator` (`OperatorUserId`, `CreateTime`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='数据权限配置变更日志'; CREATE TABLE IF NOT EXISTS `data_perm_access_log` ( `Id` BIGINT NOT NULL AUTO_INCREMENT, `UserId` CHAR(36) NOT NULL, `MapId` INT NULL, `DataResourceCode` VARCHAR(32) NOT NULL, `ApiPath` VARCHAR(256) NOT NULL, `HttpMethod` VARCHAR(8) NOT NULL DEFAULT 'GET', `AppliedScopeJson` JSON NULL COMMENT '生效五维快照', `RowCount` INT NULL COMMENT '返回行数', `ElapsedMs` INT NULL, `ClientIp` VARCHAR(64) NULL, `CreateTime` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`Id`), KEY `idx_perm_access_user_time` (`UserId`, `CreateTime`), KEY `idx_perm_access_resource` (`DataResourceCode`, `CreateTime`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='数据权限访问审计(可采样)'; -- --------------------------------------------------------------------------- -- 11. 种子:数据资源注册 -- --------------------------------------------------------------------------- INSERT INTO `data_resource` (`Id`, `Code`, `Name`, `Description`, `MainTable`, `OrgField`, `OwnerField`, `SortOrder`) VALUES ('da300001-0000-4000-8000-000000000001', 'Order', '订单', '运营后台订单查询', 't_order', 'OrganizationId', 'CreateUserId', 10), ('da300001-0000-4000-8000-000000000002', 'Customer', '客户', '客户资料列表', 't_customer', 'OrganizationId', 'Salesman', 20), ('da300001-0000-4000-8000-000000000003', 'Recharge', '充值', '充值审核列表', 't_recharge_record', NULL, 'CreateUserId', 30), ('da300001-0000-4000-8000-000000000004', 'ChannelProduct', '销售产品', '渠道产品配置', 't_sales_product', NULL, NULL, 40), ('da300001-0000-4000-8000-000000000005', 'Xhs', '小红书', '小红书模块', NULL, NULL, NULL, 50) ON DUPLICATE KEY UPDATE `Name` = VALUES(`Name`), `Description` = VALUES(`Description`), `MainTable` = VALUES(`MainTable`), `OrgField` = VALUES(`OrgField`), `OwnerField` = VALUES(`OwnerField`); -- --------------------------------------------------------------------------- -- 12. 种子:内置权限模板(明细需按环境组织 Id 调整后再 apply) -- --------------------------------------------------------------------------- INSERT INTO `data_perm_template` (`Id`, `Name`, `Code`, `Description`, `RoleCode`, `IsBuiltIn`, `CreateUserId`, `CreateTime`) VALUES ('da000001-0000-4000-8000-000000000001', '普通销售', 'SalesStaff', '个人级+指定产品线+密级1-2', NULL, 1, 0, NOW()), ('da000001-0000-4000-8000-000000000002', '销售主管', 'SalesSupervisor', '部门级+全部产品线+密级1-3', NULL, 1, 0, NOW()), ('da000001-0000-4000-8000-000000000003', '分公司经理', 'BranchManager', '组织树级+密级1-3', NULL, 1, 0, NOW()), ('da000001-0000-4000-8000-000000000004', '总部产品经理', 'ProductManager', '全局级+单产品线+密级1-2', NULL, 1, 0, NOW()), ('da000001-0000-4000-8000-000000000005', '财务专员', 'FinanceStaff', '组织树级+密级含3-4', NULL, 1, 0, NOW()), ('da000001-0000-4000-8000-000000000006', '客服专员', 'CsStaff', '个人级+密级1-2', NULL, 1, 0, NOW()) ON DUPLICATE KEY UPDATE `Name` = VALUES(`Name`), `Description` = VALUES(`Description`); INSERT INTO `data_perm_template_item` (`Id`, `TemplateId`, `DimensionType`, `ItemContent`, `SortOrder`) VALUES -- 普通销售 ('da200001-0000-4000-8000-000000000011', 'da000001-0000-4000-8000-000000000001', 'data_scope', '{"dataScope":1,"dataResourceCode":null}', 1), ('da200001-0000-4000-8000-000000000012', 'da000001-0000-4000-8000-000000000001', 'secret', '{"secretLevels":[1,2]}', 2), -- 销售主管 ('da200001-0000-4000-8000-000000000021', 'da000001-0000-4000-8000-000000000002', 'data_scope', '{"dataScope":3,"dataResourceCode":null}', 1), ('da200001-0000-4000-8000-000000000022', 'da000001-0000-4000-8000-000000000002', 'secret', '{"secretLevels":[1,2,3]}', 2), -- 分公司经理 ('da200001-0000-4000-8000-000000000031', 'da000001-0000-4000-8000-000000000003', 'data_scope', '{"dataScope":4,"dataResourceCode":null}', 1), ('da200001-0000-4000-8000-000000000032', 'da000001-0000-4000-8000-000000000003', 'secret', '{"secretLevels":[1,2,3]}', 2), -- 总部产品经理 ('da200001-0000-4000-8000-000000000041', 'da000001-0000-4000-8000-000000000004', 'data_scope', '{"dataScope":5,"dataResourceCode":null}', 1), ('da200001-0000-4000-8000-000000000042', 'da000001-0000-4000-8000-000000000004', 'secret', '{"secretLevels":[1,2]}', 2), -- 财务专员 ('da200001-0000-4000-8000-000000000051', 'da000001-0000-4000-8000-000000000005', 'data_scope', '{"dataScope":4,"dataResourceCode":null}', 1), ('da200001-0000-4000-8000-000000000052', 'da000001-0000-4000-8000-000000000005', 'secret', '{"secretLevels":[1,2,3,4]}', 2), -- 客服专员 ('da200001-0000-4000-8000-000000000061', 'da000001-0000-4000-8000-000000000006', 'data_scope', '{"dataScope":1,"dataResourceCode":null}', 1), ('da200001-0000-4000-8000-000000000062', 'da000001-0000-4000-8000-000000000006', 'secret', '{"secretLevels":[1,2]}', 2) ON DUPLICATE KEY UPDATE `ItemContent` = VALUES(`ItemContent`), `SortOrder` = VALUES(`SortOrder`); -- --------------------------------------------------------------------------- -- 13. 种子:字段脱敏(Customer / Order) -- --------------------------------------------------------------------------- INSERT INTO `data_perm_field_mask` (`Id`, `DataResourceCode`, `FieldName`, `SecretLevel`, `MaskType`, `MaskPattern`) VALUES ('fa000001-0000-4000-8000-000000000001', 'Customer', 'Phone', 4, 'partial', 'phone'), ('fa000001-0000-4000-8000-000000000002', 'Customer', 'Email', 4, 'partial', 'email'), ('fa000001-0000-4000-8000-000000000003', 'Customer', 'Password', 1, 'hide', NULL), ('fa000001-0000-4000-8000-000000000004', 'Order', 'PayableAmount', 3, 'hide', NULL), ('fa000001-0000-4000-8000-000000000005', 'Order', 'CostAmount', 3, 'hide', NULL), ('fa000001-0000-4000-8000-000000000006', 'Order', 'ProfitAmount', 4, 'hide', NULL) ON DUPLICATE KEY UPDATE `SecretLevel` = VALUES(`SecretLevel`), `MaskType` = VALUES(`MaskType`);