mirror of
https://github.com/Syngnat/GoNavi.git
synced 2026-06-28 09:21:38 +08:00
🐛 fix(driver): 明确JDBC Jar导入限制并补充Kingbase指引
- 后端在驱动包选择与本地导入前拦截 JDBC Jar,并返回替代说明 - 驱动管理统一改为“导入驱动包”,补充不支持 JDBC Jar 的提示 - 自定义连接补充 kingbase8 等驱动别名与 Go 驱动说明 - 新增后端与前端回归测试 Refs #317
This commit is contained in:
@@ -12,6 +12,7 @@ import {
|
||||
} from '../utils/connectionModalPresentation';
|
||||
import { resolveConnectionSecretDraft } from '../utils/connectionSecretDraft';
|
||||
import { getCustomConnectionDsnValidationMessage } from '../utils/customConnectionDsn';
|
||||
import { CUSTOM_CONNECTION_DRIVER_HELP } from '../utils/driverImportGuidance';
|
||||
import { applyNoAutoCapAttributes, noAutoCapInputProps } from '../utils/inputAutoCap';
|
||||
import { DBGetDatabases, GetDriverStatusList, MongoDiscoverMembers, TestConnection, RedisConnect, SelectDatabaseFile, SelectSSHKeyFile } from '../../wailsjs/go/app/App';
|
||||
import { ConnectionConfig, MongoMemberInfo, SavedConnection } from '../types';
|
||||
@@ -2163,7 +2164,7 @@ const ConnectionModal: React.FC<{
|
||||
|
||||
{isCustom ? (
|
||||
<>
|
||||
<Form.Item name="driver" label="驱动名称 (Driver Name)" rules={[{ required: true, message: '请输入驱动名称' }]} help="已支持: mysql, postgres, sqlite, oracle, dm, kingbase">
|
||||
<Form.Item name="driver" label="驱动名称 (Driver Name)" rules={[{ required: true, message: '请输入驱动名称' }]} help={CUSTOM_CONNECTION_DRIVER_HELP}>
|
||||
<Input {...noAutoCapInputProps} placeholder="例如: mysql, postgres" />
|
||||
</Form.Item>
|
||||
<Form.Item name="dsn" label="连接字符串 (DSN)" rules={[createCustomDsnRule()]}>
|
||||
|
||||
@@ -4,6 +4,11 @@ import { DeleteOutlined, DownloadOutlined, FileSearchOutlined, FolderOpenOutline
|
||||
import { EventsOn } from '../../wailsjs/runtime/runtime';
|
||||
import { useStore } from '../store';
|
||||
import { normalizeOpacityForPlatform, resolveAppearanceValues } from '../utils/appearance';
|
||||
import {
|
||||
DRIVER_LOCAL_IMPORT_BUTTON_LABEL,
|
||||
DRIVER_LOCAL_IMPORT_DIRECTORY_HELP,
|
||||
DRIVER_LOCAL_IMPORT_SINGLE_FILE_HELP,
|
||||
} from '../utils/driverImportGuidance';
|
||||
import {
|
||||
CheckDriverNetworkStatus,
|
||||
DownloadDriverPackage,
|
||||
@@ -1171,7 +1176,7 @@ const DriverManagerModal: React.FC<{ open: boolean; onClose: () => void; onOpenG
|
||||
loading={loadingLocal}
|
||||
onClick={() => installDriverFromLocalFile(row)}
|
||||
>
|
||||
本地导入
|
||||
{DRIVER_LOCAL_IMPORT_BUTTON_LABEL}
|
||||
</Button>
|
||||
<Button
|
||||
type={hasLogs ? 'default' : 'text'}
|
||||
@@ -1373,8 +1378,8 @@ const DriverManagerModal: React.FC<{ open: boolean; onClose: () => void; onOpenG
|
||||
children: (
|
||||
<Space direction="vertical" size={6} style={{ width: '100%' }}>
|
||||
<Text type="secondary">自动下载和手动导入的驱动都会落盘到以下目录;后续版本升级可重复复用已下载驱动。</Text>
|
||||
<Text type="secondary">如果应用内下载链路失败,可先手动下载驱动包到该目录,再使用“本地导入”或“导入驱动目录”完成安装。</Text>
|
||||
<Text type="secondary">行内“本地导入”仅用于单个驱动文件/总包(如 `mariadb-driver-agent`、`mariadb-driver-agent.exe`、`GoNavi-DriverAgents.zip`);批量导入请使用上方“导入驱动目录”。</Text>
|
||||
<Text type="secondary">{DRIVER_LOCAL_IMPORT_DIRECTORY_HELP}</Text>
|
||||
<Text type="secondary">{DRIVER_LOCAL_IMPORT_SINGLE_FILE_HELP}</Text>
|
||||
<Paragraph copyable={{ text: downloadDir || '-' }} style={{ marginBottom: 0 }}>
|
||||
驱动根目录:{downloadDir || '-'}
|
||||
</Paragraph>
|
||||
|
||||
22
frontend/src/utils/driverImportGuidance.test.ts
Normal file
22
frontend/src/utils/driverImportGuidance.test.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
|
||||
import {
|
||||
CUSTOM_CONNECTION_DRIVER_HELP,
|
||||
DRIVER_LOCAL_IMPORT_BUTTON_LABEL,
|
||||
DRIVER_LOCAL_IMPORT_DIRECTORY_HELP,
|
||||
DRIVER_LOCAL_IMPORT_SINGLE_FILE_HELP,
|
||||
} from './driverImportGuidance';
|
||||
|
||||
describe('driver import guidance', () => {
|
||||
it('keeps local import copy focused on driver packages instead of JDBC jars', () => {
|
||||
expect(DRIVER_LOCAL_IMPORT_BUTTON_LABEL).toBe('导入驱动包');
|
||||
expect(DRIVER_LOCAL_IMPORT_DIRECTORY_HELP).toContain('导入驱动目录');
|
||||
expect(DRIVER_LOCAL_IMPORT_SINGLE_FILE_HELP).toContain('JDBC Jar');
|
||||
});
|
||||
|
||||
it('documents custom driver aliases for kingbase and related fallbacks', () => {
|
||||
expect(CUSTOM_CONNECTION_DRIVER_HELP).toContain('kingbase8');
|
||||
expect(CUSTOM_CONNECTION_DRIVER_HELP).toContain('pgx');
|
||||
expect(CUSTOM_CONNECTION_DRIVER_HELP).toContain('JDBC Jar');
|
||||
});
|
||||
});
|
||||
10
frontend/src/utils/driverImportGuidance.ts
Normal file
10
frontend/src/utils/driverImportGuidance.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
export const DRIVER_LOCAL_IMPORT_BUTTON_LABEL = '导入驱动包';
|
||||
|
||||
export const DRIVER_LOCAL_IMPORT_DIRECTORY_HELP =
|
||||
'如果应用内下载链路失败,可先手动下载驱动包到该目录,再使用“导入驱动包”或“导入驱动目录”完成安装。';
|
||||
|
||||
export const DRIVER_LOCAL_IMPORT_SINGLE_FILE_HELP =
|
||||
'行内“导入驱动包”仅用于单个驱动文件/总包(如 `mariadb-driver-agent`、`mariadb-driver-agent.exe`、`GoNavi-DriverAgents.zip`),不支持直接导入 JDBC Jar;批量导入请使用上方“导入驱动目录”。';
|
||||
|
||||
export const CUSTOM_CONNECTION_DRIVER_HELP =
|
||||
'已支持: mysql, postgres, sqlite, oracle, dm, kingbase;别名支持 postgresql/pgx、dm8、kingbase8/kingbasees/kingbasev8。当前不支持通过 JDBC Jar 扩展驱动。';
|
||||
@@ -486,6 +486,17 @@ func (a *App) SelectDriverDownloadDirectory(currentDir string) connection.QueryR
|
||||
}
|
||||
}
|
||||
|
||||
func validateLocalDriverPackagePath(path string) error {
|
||||
pathText := strings.TrimSpace(path)
|
||||
if pathText == "" {
|
||||
return nil
|
||||
}
|
||||
if strings.EqualFold(filepath.Ext(pathText), ".jar") {
|
||||
return fmt.Errorf("当前驱动管理不支持直接导入 JDBC Jar。GoNavi 使用 Go 驱动与可选 driver-agent;请改用驱动包/驱动目录,如需连接人大金仓请优先使用“Kingbase”连接类型,或在自定义连接中填写 kingbase / kingbase8")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *App) SelectDriverPackageFile(currentPath string) connection.QueryResult {
|
||||
defaultDir := strings.TrimSpace(currentPath)
|
||||
if defaultDir == "" {
|
||||
@@ -501,7 +512,7 @@ func (a *App) SelectDriverPackageFile(currentPath string) connection.QueryResult
|
||||
}
|
||||
|
||||
selection, err := runtime.OpenFileDialog(a.ctx, runtime.OpenDialogOptions{
|
||||
Title: "选择驱动包文件",
|
||||
Title: "选择驱动包文件(非 JDBC Jar)",
|
||||
DefaultDirectory: defaultDir,
|
||||
})
|
||||
if err != nil {
|
||||
@@ -514,6 +525,9 @@ func (a *App) SelectDriverPackageFile(currentPath string) connection.QueryResult
|
||||
if abs, err := filepath.Abs(selection); err == nil {
|
||||
selection = abs
|
||||
}
|
||||
if err := validateLocalDriverPackagePath(selection); err != nil {
|
||||
return connection.QueryResult{Success: false, Message: err.Error()}
|
||||
}
|
||||
return connection.QueryResult{Success: true, Data: map[string]interface{}{"path": selection}}
|
||||
}
|
||||
|
||||
@@ -900,6 +914,9 @@ func (a *App) InstallLocalDriverPackage(driverType string, filePath string, down
|
||||
if definition.BuiltIn {
|
||||
return connection.QueryResult{Success: false, Message: "内置驱动无需安装扩展包"}
|
||||
}
|
||||
if err := validateLocalDriverPackagePath(filePath); err != nil {
|
||||
return connection.QueryResult{Success: false, Message: err.Error()}
|
||||
}
|
||||
if err := ensureOptionalDriverBuildAvailable(definition); err != nil {
|
||||
return connection.QueryResult{Success: false, Message: err.Error()}
|
||||
}
|
||||
|
||||
37
internal/app/methods_driver_local_import_test.go
Normal file
37
internal/app/methods_driver_local_import_test.go
Normal file
@@ -0,0 +1,37 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestValidateLocalDriverPackagePathRejectsJdbcJar(t *testing.T) {
|
||||
err := validateLocalDriverPackagePath(filepath.Join("tmp", "kingbase8.JAR"))
|
||||
if err == nil {
|
||||
t.Fatal("expected JDBC jar path to be rejected")
|
||||
}
|
||||
if !strings.Contains(err.Error(), "JDBC Jar") {
|
||||
t.Fatalf("expected JDBC jar hint, got %q", err.Error())
|
||||
}
|
||||
if err := validateLocalDriverPackagePath(filepath.Join("tmp", "kingbase-driver-agent.zip")); err != nil {
|
||||
t.Fatalf("expected zip package to stay supported, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestInstallLocalDriverPackageRejectsJdbcJarBeforeBuildChecks(t *testing.T) {
|
||||
jarPath := filepath.Join(t.TempDir(), "kingbase8.jar")
|
||||
if err := os.WriteFile(jarPath, []byte("fake-jar"), 0o644); err != nil {
|
||||
t.Fatalf("write temp jar: %v", err)
|
||||
}
|
||||
|
||||
app := &App{}
|
||||
result := app.InstallLocalDriverPackage("kingbase", jarPath, t.TempDir(), "")
|
||||
if result.Success {
|
||||
t.Fatal("expected local jar import to fail")
|
||||
}
|
||||
if !strings.Contains(result.Message, "JDBC Jar") {
|
||||
t.Fatalf("expected JDBC jar guidance, got %q", result.Message)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user