fix(security): retire check-governance + scope /reports/dupont to session entity
- data_quality.py: remove GET /check-governance (no caller repo-wide; its entity_id param had no session auth -> cross-tenant read; duplicate of governance-check) -> the path now returns 404 - reports.py: /reports/dupont resolves the analysis target from the session account (assert_entity_slug_scope / resolve_session_slug); explicit cross-entity entity param -> 403, illegal value -> 400; the 2026-08-31 cross-entity exemption is revoked (docstring updated) - frontend: drop the checkGovernance api definition; DupontAnalysis.vue entity radio group -> read-only session entity tag, request without param - tests: TestCheckGovernanceRetired (404 x2), TestDupontSessionScope (3), TestDupont reworked to account-bound tokens (8 tests) - docs/api-verification-split.md: drop the retired row, note 334/404 -> 333/403 pytest: 10 failed / 957 passed / 1 xfailed vs HEAD baseline 10 failed / 951 passed / 1 xfailed (identical failure set -> zero regression) (cma-residual-cross-entity-cleanup-20260914)
This commit is contained in:
@@ -362,9 +362,9 @@ export const dataQualityApi = {
|
||||
logs: (params?: any) => api.get('/data-quality/logs', { params }),
|
||||
updateLog: (id: number, data: any) => api.put(`/data-quality/logs/${id}`, data),
|
||||
deleteLog: (id: number) => api.delete(`/data-quality/logs/${id}`),
|
||||
// DAMA数据治理规则检查(财务七规则)
|
||||
checkGovernance: (params?: any) => api.get('/data-quality/check-governance', { params }),
|
||||
// 财务七规则检查(最终方案:评分+7规则+实体筛选,只读幂等)
|
||||
// DAMA数据治理规则检查(财务七规则)— /check-governance 已于 2026-09-14 下线
|
||||
// (cma-residual-cross-entity-cleanup-20260914:无调用方 + entity_id 参数无会话鉴权跨租户)
|
||||
// 财务七规则检查(唯一入口:评分+7规则+实体筛选,只读幂等;实体按会话账套)
|
||||
governanceCheck: (params?: any) => api.get('/data-quality/governance-check', { params }),
|
||||
}
|
||||
|
||||
|
||||
@@ -3,13 +3,10 @@
|
||||
<div class="page-header">
|
||||
<h3 class="page-title">杜邦分析</h3>
|
||||
</div>
|
||||
<!-- 顶部控制 -->
|
||||
<!-- 顶部控制:企业只读标识(不可点)——账套由登录时选定,页内无切换入口 -->
|
||||
<div class="flex-row" style="gap:12px;margin-bottom:16px;align-items:center;">
|
||||
<span style="font-weight:600;font-size:14px;">分析对象:</span>
|
||||
<el-radio-group v-model="entity" @change="fetchDupont">
|
||||
<el-radio value="bohai">陕西博海科技(IT服务)</el-radio>
|
||||
<el-radio value="hanke">陕西酣客(白酒经销)</el-radio>
|
||||
</el-radio-group>
|
||||
<el-tag size="small" type="primary" effect="plain">{{ entityLabel }}</el-tag>
|
||||
<el-button type="primary" size="small" @click="fetchDupont" :loading="loading">刷新</el-button>
|
||||
</div>
|
||||
|
||||
@@ -116,9 +113,10 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue'
|
||||
import axios from 'axios'
|
||||
import { sessionEntityName } from '../utils/entity'
|
||||
|
||||
const loading = ref(false)
|
||||
const entity = ref('bohai')
|
||||
const entityLabel = ref(sessionEntityName())
|
||||
const data = ref<any>({})
|
||||
|
||||
const api = axios.create({ baseURL: '/api/cma', timeout: 15000 })
|
||||
@@ -151,7 +149,8 @@ function formatMoney(val: number): string {
|
||||
async function fetchDupont() {
|
||||
loading.value = true
|
||||
try {
|
||||
const r: any = await api.get('/reports/dupont', { params: { entity: entity.value } })
|
||||
// 分析对象由会话账套决定(后端按 token 解析),不再传 entity 参数
|
||||
const r: any = await api.get('/reports/dupont')
|
||||
data.value = r.data || r
|
||||
} catch (e) {
|
||||
console.error('杜邦分析加载失败:', e)
|
||||
|
||||
Reference in New Issue
Block a user