feat(plugin): 集成过滤查询/排序/搜索到 REST API,添加数据校验和 searchable 索引
- data_dto: PluginDataListParams 新增 filter/sort_by/sort_order - data_service: list 方法支持 filter/search/sort 参数,自动提取 searchable 字段 - data_service: create/update 添加 required 字段校验 - data_service: 新增 resolve_entity_fields 和 validate_data 辅助函数 - data_handler: 权限检查从硬编码改为动态计算 plugin_id.entity.action - dynamic_table: searchable 字段自动创建 B-tree 索引
This commit is contained in:
@@ -11,6 +11,16 @@ use crate::data_dto::{CreatePluginDataReq, PluginDataListParams, PluginDataResp,
|
||||
use crate::data_service::PluginDataService;
|
||||
use crate::state::PluginState;
|
||||
|
||||
/// 计算插件数据操作所需的权限码
|
||||
/// 格式:{plugin_id}.{entity}.{action},如 crm.customer.list
|
||||
fn compute_permission_code(plugin_id: &str, entity_name: &str, action: &str) -> String {
|
||||
let action_suffix = match action {
|
||||
"list" | "get" => "list",
|
||||
_ => "manage",
|
||||
};
|
||||
format!("{}.{}.{}", plugin_id, entity_name, action_suffix)
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
get,
|
||||
path = "/api/v1/plugins/{plugin_id}/{entity}",
|
||||
@@ -32,11 +42,21 @@ where
|
||||
PluginState: FromRef<S>,
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "plugin.list")?;
|
||||
// 动态权限检查:先尝试精细权限,回退到通用权限
|
||||
let fine_perm = compute_permission_code(&plugin_id.to_string(), &entity, "list");
|
||||
if require_permission(&ctx, &fine_perm).is_err() {
|
||||
require_permission(&ctx, "plugin.list")?;
|
||||
}
|
||||
|
||||
let page = params.page.unwrap_or(1);
|
||||
let page_size = params.page_size.unwrap_or(20);
|
||||
|
||||
// 解析 filter JSON
|
||||
let filter: Option<serde_json::Value> = params
|
||||
.filter
|
||||
.as_ref()
|
||||
.and_then(|f| serde_json::from_str(f).ok());
|
||||
|
||||
let (items, total) = PluginDataService::list(
|
||||
plugin_id,
|
||||
&entity,
|
||||
@@ -44,6 +64,10 @@ where
|
||||
page,
|
||||
page_size,
|
||||
&state.db,
|
||||
filter,
|
||||
params.search,
|
||||
params.sort_by,
|
||||
params.sort_order,
|
||||
)
|
||||
.await?;
|
||||
|
||||
@@ -77,7 +101,10 @@ where
|
||||
PluginState: FromRef<S>,
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "plugin.admin")?;
|
||||
let fine_perm = compute_permission_code(&plugin_id.to_string(), &entity, "create");
|
||||
if require_permission(&ctx, &fine_perm).is_err() {
|
||||
require_permission(&ctx, "plugin.admin")?;
|
||||
}
|
||||
|
||||
let result = PluginDataService::create(
|
||||
plugin_id,
|
||||
@@ -112,7 +139,10 @@ where
|
||||
PluginState: FromRef<S>,
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "plugin.list")?;
|
||||
let fine_perm = compute_permission_code(&plugin_id.to_string(), &entity, "get");
|
||||
if require_permission(&ctx, &fine_perm).is_err() {
|
||||
require_permission(&ctx, "plugin.list")?;
|
||||
}
|
||||
|
||||
let result =
|
||||
PluginDataService::get_by_id(plugin_id, &entity, id, ctx.tenant_id, &state.db).await?;
|
||||
@@ -141,7 +171,10 @@ where
|
||||
PluginState: FromRef<S>,
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "plugin.admin")?;
|
||||
let fine_perm = compute_permission_code(&plugin_id.to_string(), &entity, "update");
|
||||
if require_permission(&ctx, &fine_perm).is_err() {
|
||||
require_permission(&ctx, "plugin.admin")?;
|
||||
}
|
||||
|
||||
let result = PluginDataService::update(
|
||||
plugin_id,
|
||||
@@ -178,7 +211,10 @@ where
|
||||
PluginState: FromRef<S>,
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "plugin.admin")?;
|
||||
let fine_perm = compute_permission_code(&plugin_id.to_string(), &entity, "delete");
|
||||
if require_permission(&ctx, &fine_perm).is_err() {
|
||||
require_permission(&ctx, "plugin.admin")?;
|
||||
}
|
||||
|
||||
PluginDataService::delete(
|
||||
plugin_id,
|
||||
|
||||
Reference in New Issue
Block a user