diff --git a/crates/erp-plugin/src/dynamic_table.rs b/crates/erp-plugin/src/dynamic_table.rs index 1dd4bf7..7fd5010 100644 --- a/crates/erp-plugin/src/dynamic_table.rs +++ b/crates/erp-plugin/src/dynamic_table.rs @@ -1019,6 +1019,7 @@ mod tests { ], indexes: vec![], relations: vec![], + data_scope: None, }; let sql = DynamicTableManager::build_create_table_sql("erp_crm", &entity); @@ -1060,6 +1061,7 @@ mod tests { }], indexes: vec![], relations: vec![], + data_scope: None, }; let sql = DynamicTableManager::build_create_table_sql("erp_crm", &entity); diff --git a/crates/erp-plugin/src/manifest.rs b/crates/erp-plugin/src/manifest.rs index 56d6d0e..740eb2b 100644 --- a/crates/erp-plugin/src/manifest.rs +++ b/crates/erp-plugin/src/manifest.rs @@ -45,6 +45,8 @@ pub struct PluginEntity { pub indexes: Vec, #[serde(default)] pub relations: Vec, + #[serde(default)] + pub data_scope: Option, // 是否启用行级数据权限 } /// 字段校验规则 @@ -79,6 +81,8 @@ pub struct PluginField { pub validation: Option, // 字段校验规则 #[serde(default)] pub no_cycle: Option, // 禁止循环引用 + #[serde(default)] + pub scope_role: Option, // 标记为数据权限的"所有者"字段 } /// 字段类型 @@ -145,6 +149,7 @@ impl PluginField { ref_entity: None, validation: None, no_cycle: None, + scope_role: None, } } } @@ -272,6 +277,8 @@ pub struct PluginPermission { pub name: String, #[serde(default)] pub description: String, + #[serde(default)] + pub data_scope_levels: Option>, // 支持的数据范围等级 } /// 从 TOML 字符串解析插件清单 @@ -746,4 +753,48 @@ on_delete = "cascade" assert_eq!(entity.relations[0].foreign_key, "customer_id"); assert!(matches!(entity.relations[0].on_delete, OnDeleteStrategy::Cascade)); } + + #[test] + fn parse_entity_with_data_scope() { + let toml = r#" +[metadata] +id = "test" +name = "Test" +version = "0.1.0" + +[schema] +[[schema.entities]] +name = "customer" +display_name = "客户" +data_scope = true + +[[schema.entities.fields]] +name = "owner_id" +field_type = "uuid" +display_name = "负责人" +scope_role = "owner" +"#; + let manifest = parse_manifest(toml).unwrap(); + let entity = &manifest.schema.unwrap().entities[0]; + assert_eq!(entity.data_scope, Some(true)); + assert_eq!(entity.fields[0].scope_role.as_deref(), Some("owner")); + } + + #[test] + fn parse_permission_with_data_scope_levels() { + let toml = r#" +[metadata] +id = "test" +name = "Test" +version = "0.1.0" + +[[permissions]] +code = "customer.list" +name = "查看客户" +data_scope_levels = ["self", "department", "department_tree", "all"] +"#; + let manifest = parse_manifest(toml).unwrap(); + let perm = &manifest.permissions.unwrap()[0]; + assert_eq!(perm.data_scope_levels.as_ref().unwrap().len(), 4); + } }