fix: 审计修复 — ErrorBoundary 接入 + data_scope 全端点接线 + inventory.wasm
1. H1: App.tsx 接入 ErrorBoundary 包裹 Suspense,防止页面渲染错误导致白屏 2. H2: data_scope 行级权限扩展到 count/aggregate/timeseries 端点, 所有数据查询操作现在都受 data_scope 过滤 3. M3: 进销存插件 WASM 编译部署到 apps/web/public/inventory.wasm
This commit is contained in:
BIN
apps/web/public/inventory.wasm
Normal file
BIN
apps/web/public/inventory.wasm
Normal file
Binary file not shown.
@@ -4,6 +4,7 @@ import { ConfigProvider, theme as antdTheme, Spin } from 'antd';
|
||||
import zhCN from 'antd/locale/zh_CN';
|
||||
import MainLayout from './layouts/MainLayout';
|
||||
import Login from './pages/Login';
|
||||
import { ErrorBoundary } from './components/ErrorBoundary';
|
||||
import { useAuthStore } from './stores/auth';
|
||||
import { useAppStore } from './stores/app';
|
||||
|
||||
@@ -133,6 +134,7 @@ export default function App() {
|
||||
element={
|
||||
<PrivateRoute>
|
||||
<MainLayout>
|
||||
<ErrorBoundary>
|
||||
<Suspense fallback={<div style={{ display: 'flex', justifyContent: 'center', padding: 100 }}><Spin size="large" /></div>}>
|
||||
<Routes>
|
||||
<Route path="/" element={<Home />} />
|
||||
@@ -151,6 +153,7 @@ export default function App() {
|
||||
<Route path="/plugins/:pluginId/:entityName" element={<PluginCRUDPage />} />
|
||||
</Routes>
|
||||
</Suspense>
|
||||
</ErrorBoundary>
|
||||
</MainLayout>
|
||||
</PrivateRoute>
|
||||
}
|
||||
|
||||
@@ -527,6 +527,7 @@ impl PluginDataService {
|
||||
db: &sea_orm::DatabaseConnection,
|
||||
filter: Option<serde_json::Value>,
|
||||
search: Option<String>,
|
||||
scope: Option<DataScopeParams>,
|
||||
) -> AppResult<u64> {
|
||||
let info = resolve_entity_info(plugin_id, entity_name, tenant_id, db).await?;
|
||||
|
||||
@@ -543,7 +544,7 @@ impl PluginDataService {
|
||||
}
|
||||
};
|
||||
|
||||
let (sql, values) = DynamicTableManager::build_filtered_count_sql(
|
||||
let (mut sql, mut values) = DynamicTableManager::build_filtered_count_sql(
|
||||
&info.table_name,
|
||||
tenant_id,
|
||||
filter,
|
||||
@@ -551,6 +552,13 @@ impl PluginDataService {
|
||||
)
|
||||
.map_err(|e| AppError::Validation(e))?;
|
||||
|
||||
// 合并数据权限条件
|
||||
let scope_condition = build_scope_sql(&scope, &info.generated_fields);
|
||||
if !scope_condition.0.is_empty() {
|
||||
sql = merge_scope_condition(sql, &scope_condition);
|
||||
values.extend(scope_condition.1);
|
||||
}
|
||||
|
||||
#[derive(FromQueryResult)]
|
||||
struct CountResult {
|
||||
count: i64,
|
||||
@@ -578,10 +586,11 @@ impl PluginDataService {
|
||||
db: &sea_orm::DatabaseConnection,
|
||||
group_by_field: &str,
|
||||
filter: Option<serde_json::Value>,
|
||||
scope: Option<DataScopeParams>,
|
||||
) -> AppResult<Vec<(String, i64)>> {
|
||||
let info = resolve_entity_info(plugin_id, entity_name, tenant_id, db).await?;
|
||||
|
||||
let (sql, values) = DynamicTableManager::build_aggregate_sql(
|
||||
let (mut sql, mut values) = DynamicTableManager::build_aggregate_sql(
|
||||
&info.table_name,
|
||||
tenant_id,
|
||||
group_by_field,
|
||||
@@ -589,6 +598,13 @@ impl PluginDataService {
|
||||
)
|
||||
.map_err(|e| AppError::Validation(e))?;
|
||||
|
||||
// 合并数据权限条件
|
||||
let scope_condition = build_scope_sql(&scope, &info.generated_fields);
|
||||
if !scope_condition.0.is_empty() {
|
||||
sql = merge_scope_condition(sql, &scope_condition);
|
||||
values.extend(scope_condition.1);
|
||||
}
|
||||
|
||||
#[derive(FromQueryResult)]
|
||||
struct AggRow {
|
||||
key: Option<String>,
|
||||
@@ -621,7 +637,7 @@ impl PluginDataService {
|
||||
filter: Option<serde_json::Value>,
|
||||
) -> AppResult<Vec<(String, i64)>> {
|
||||
// TODO: 未来版本添加 Redis 缓存层
|
||||
Self::aggregate(plugin_id, entity_name, tenant_id, db, group_by_field, filter).await
|
||||
Self::aggregate(plugin_id, entity_name, tenant_id, db, group_by_field, filter, None).await
|
||||
}
|
||||
|
||||
/// 时间序列聚合 — 按时间字段截断为 day/week/month 统计计数
|
||||
@@ -634,10 +650,11 @@ impl PluginDataService {
|
||||
time_grain: &str,
|
||||
start: Option<String>,
|
||||
end: Option<String>,
|
||||
scope: Option<DataScopeParams>,
|
||||
) -> AppResult<Vec<crate::data_dto::TimeseriesItem>> {
|
||||
let info = resolve_entity_info(plugin_id, entity_name, tenant_id, db).await?;
|
||||
|
||||
let (sql, values) = DynamicTableManager::build_timeseries_sql(
|
||||
let (mut sql, mut values) = DynamicTableManager::build_timeseries_sql(
|
||||
&info.table_name,
|
||||
tenant_id,
|
||||
time_field,
|
||||
@@ -647,6 +664,13 @@ impl PluginDataService {
|
||||
)
|
||||
.map_err(|e| AppError::Validation(e))?;
|
||||
|
||||
// 合并数据权限条件
|
||||
let scope_condition = build_scope_sql(&scope, &info.generated_fields);
|
||||
if !scope_condition.0.is_empty() {
|
||||
sql = merge_scope_condition(sql, &scope_condition);
|
||||
values.extend(scope_condition.1);
|
||||
}
|
||||
|
||||
#[derive(FromQueryResult)]
|
||||
struct TsRow {
|
||||
period: Option<String>,
|
||||
|
||||
@@ -390,6 +390,11 @@ where
|
||||
let fine_perm = compute_permission_code(&manifest_id, &entity, "list");
|
||||
require_permission(&ctx, &fine_perm)?;
|
||||
|
||||
// 解析数据权限范围
|
||||
let scope = resolve_data_scope(
|
||||
&ctx, &manifest_id, &entity, &fine_perm, &state.db,
|
||||
).await?;
|
||||
|
||||
// 解析 filter JSON
|
||||
let filter: Option<serde_json::Value> = params
|
||||
.filter
|
||||
@@ -403,6 +408,7 @@ where
|
||||
&state.db,
|
||||
filter,
|
||||
params.search,
|
||||
scope,
|
||||
)
|
||||
.await?;
|
||||
|
||||
@@ -434,6 +440,11 @@ where
|
||||
let fine_perm = compute_permission_code(&manifest_id, &entity, "list");
|
||||
require_permission(&ctx, &fine_perm)?;
|
||||
|
||||
// 解析数据权限范围
|
||||
let scope = resolve_data_scope(
|
||||
&ctx, &manifest_id, &entity, &fine_perm, &state.db,
|
||||
).await?;
|
||||
|
||||
// 解析 filter JSON
|
||||
let filter: Option<serde_json::Value> = params
|
||||
.filter
|
||||
@@ -447,6 +458,7 @@ where
|
||||
&state.db,
|
||||
¶ms.group_by,
|
||||
filter,
|
||||
scope,
|
||||
)
|
||||
.await?;
|
||||
|
||||
@@ -483,6 +495,11 @@ where
|
||||
let fine_perm = compute_permission_code(&manifest_id, &entity, "list");
|
||||
require_permission(&ctx, &fine_perm)?;
|
||||
|
||||
// 解析数据权限范围
|
||||
let scope = resolve_data_scope(
|
||||
&ctx, &manifest_id, &entity, &fine_perm, &state.db,
|
||||
).await?;
|
||||
|
||||
let result = PluginDataService::timeseries(
|
||||
plugin_id,
|
||||
&entity,
|
||||
@@ -492,6 +509,7 @@ where
|
||||
¶ms.time_grain,
|
||||
params.start,
|
||||
params.end,
|
||||
scope,
|
||||
)
|
||||
.await?;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user