feat(connection): 支持生产连接多项保护策略

- 新增数据编辑、结构编辑、脚本执行和数据导入四类连接级保护配置
- 升级生产连接保护弹窗为多选卡片,并修复选项对齐与勾选态显示
- 按保护类型收口 QueryEditor、DataGrid、表设计、导入与同步目标入口
- 后端统一拦截 SQL 或 Mongo 写操作、结果编辑、结构变更和导入写入
- AI 本地工具与 RPC 执行链路透传连接保护配置并复用后端守卫
- 补充多语言文案、定向测试与需求追踪记录
This commit is contained in:
Syngnat
2026-06-23 17:42:54 +08:00
parent b0a9a995fb
commit adacf0b5c5
35 changed files with 1184 additions and 160 deletions

View File

@@ -3116,6 +3116,48 @@ describe('QueryEditor external SQL save', () => {
expect(tableSuggestion.detail).not.toContain('Table (analytics)');
});
it('deduplicates Oracle-style database qualified table completion labels when schema matches the qualifier', async () => {
storeState.languagePreference = 'zh-CN';
setCurrentLanguage('zh-CN');
storeState.connections[0].config.type = 'oracle';
storeState.connections[0].config.database = 'ORCLPDB1';
editorState.value = 'select * from sbdev.AA';
autoFetchState.visible = true;
backendApp.DBGetDatabases.mockResolvedValueOnce({
success: true,
data: [{ Database: 'ORCLPDB1' }, { Database: 'sbdev' }],
});
backendApp.DBGetTables.mockImplementation(async (_config: any, dbName: string) => {
if (String(dbName || '').toLowerCase() === 'sbdev') {
return { success: true, data: [{ Table: 'SBDEV.AAA3_NJ' }] };
}
return { success: true, data: [] };
});
backendApp.DBGetAllColumns.mockResolvedValue({ success: true, data: [] });
await act(async () => {
create(<QueryEditor tab={createTab({ query: editorState.value, dbName: 'ORCLPDB1' })} />);
});
await act(async () => {
await Promise.resolve();
await Promise.resolve();
});
const completionProvider = editorState.providers[0];
expect(completionProvider).toBeTruthy();
const completionItems = await completionProvider.provideCompletionItems(
editorState.editor.getModel(),
{ lineNumber: 1, column: editorState.value.length + 1 },
);
const tableSuggestion = completionItems?.suggestions?.find((item: any) => item?.label === 'AAA3_NJ');
expect(tableSuggestion).toBeTruthy();
expect(tableSuggestion.insertText).toBe('AAA3_NJ');
expect(tableSuggestion.detail).toContain('表 (sbdev)');
expect(completionItems?.suggestions?.some((item: any) => item?.label === 'sbdev.SBDEV.AAA3_NJ')).toBe(false);
});
it('localizes schema-qualified table completion detail in zh-CN while preserving the raw database and schema names', async () => {
storeState.languagePreference = 'zh-CN';
setCurrentLanguage('zh-CN');