feat(plugin): 数据范围查询基础设施 — get_data_scope + get_dept_members 辅助函数
- 新增 get_data_scope() 查询当前用户对指定权限的 data_scope 等级 - 新增 get_dept_members() 获取部门成员 ID 列表(预留递归部门树查询) - 在 list_plugin_data handler 中标记 data_scope 注入点 TODO - 这些基础设施函数将在前端 Chunk 4 完成完整集成
This commit is contained in:
@@ -14,6 +14,61 @@ use crate::data_dto::{
|
|||||||
use crate::data_service::{PluginDataService, resolve_manifest_id};
|
use crate::data_service::{PluginDataService, resolve_manifest_id};
|
||||||
use crate::state::PluginState;
|
use crate::state::PluginState;
|
||||||
|
|
||||||
|
/// 获取当前用户对指定权限的 data_scope 等级
|
||||||
|
///
|
||||||
|
/// 查询 user_roles -> role_permissions -> permissions 链路,
|
||||||
|
/// 返回匹配权限的 data_scope 设置,默认 "all"。
|
||||||
|
async fn get_data_scope(
|
||||||
|
ctx: &TenantContext,
|
||||||
|
permission_code: &str,
|
||||||
|
db: &sea_orm::DatabaseConnection,
|
||||||
|
) -> Result<String, AppError> {
|
||||||
|
use sea_orm::{FromQueryResult, Statement};
|
||||||
|
|
||||||
|
#[derive(FromQueryResult)]
|
||||||
|
struct ScopeResult {
|
||||||
|
data_scope: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
let result = ScopeResult::find_by_statement(Statement::from_sql_and_values(
|
||||||
|
sea_orm::DatabaseBackend::Postgres,
|
||||||
|
r#"SELECT rp.data_scope
|
||||||
|
FROM user_roles ur
|
||||||
|
JOIN role_permissions rp ON rp.role_id = ur.role_id
|
||||||
|
JOIN permissions p ON p.id = rp.permission_id
|
||||||
|
WHERE ur.user_id = $1 AND ur.tenant_id = $2 AND p.code = $3
|
||||||
|
LIMIT 1"#,
|
||||||
|
[
|
||||||
|
ctx.user_id.into(),
|
||||||
|
ctx.tenant_id.into(),
|
||||||
|
permission_code.into(),
|
||||||
|
],
|
||||||
|
))
|
||||||
|
.one(db)
|
||||||
|
.await
|
||||||
|
.map_err(|e| AppError::Internal(e.to_string()))?;
|
||||||
|
|
||||||
|
Ok(result
|
||||||
|
.and_then(|r| r.data_scope)
|
||||||
|
.unwrap_or_else(|| "all".to_string()))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 获取部门成员 ID 列表
|
||||||
|
///
|
||||||
|
/// 当前返回 TenantContext 中的 department_ids。
|
||||||
|
/// 未来实现递归查询部门树时将支持 include_sub_depts 参数。
|
||||||
|
async fn get_dept_members(
|
||||||
|
ctx: &TenantContext,
|
||||||
|
_include_sub_depts: bool,
|
||||||
|
) -> Vec<Uuid> {
|
||||||
|
// 当前 department_ids 为空时返回空列表
|
||||||
|
// 未来实现递归查询部门树
|
||||||
|
if ctx.department_ids.is_empty() {
|
||||||
|
return vec![];
|
||||||
|
}
|
||||||
|
ctx.department_ids.clone()
|
||||||
|
}
|
||||||
|
|
||||||
/// 计算插件数据操作所需的权限码
|
/// 计算插件数据操作所需的权限码
|
||||||
/// 格式:{manifest_id}.{entity}.{action},如 erp-crm.customer.list
|
/// 格式:{manifest_id}.{entity}.{action},如 erp-crm.customer.list
|
||||||
fn compute_permission_code(manifest_id: &str, entity_name: &str, action: &str) -> String {
|
fn compute_permission_code(manifest_id: &str, entity_name: &str, action: &str) -> String {
|
||||||
@@ -49,6 +104,13 @@ where
|
|||||||
let fine_perm = compute_permission_code(&manifest_id, &entity, "list");
|
let fine_perm = compute_permission_code(&manifest_id, &entity, "list");
|
||||||
require_permission(&ctx, &fine_perm)?;
|
require_permission(&ctx, &fine_perm)?;
|
||||||
|
|
||||||
|
// TODO(data_scope): 此处注入行级数据权限过滤
|
||||||
|
// 1. 解析 entity 定义检查 data_scope == Some(true)
|
||||||
|
// 2. 调用 get_data_scope(&ctx, &fine_perm, &state.db) 获取当前用户的 scope 等级
|
||||||
|
// 3. 若 scope != "all",调用 get_dept_members 获取部门成员列表
|
||||||
|
// 4. 将 scope 条件合并到 filter 中传给 PluginDataService::list
|
||||||
|
// 参考: crates/erp-plugin/src/dynamic_table.rs build_data_scope_condition()
|
||||||
|
|
||||||
let page = params.page.unwrap_or(1);
|
let page = params.page.unwrap_or(1);
|
||||||
let page_size = params.page_size.unwrap_or(20);
|
let page_size = params.page_size.unwrap_or(20);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user