Files
MyGoNavi/internal/app/connection_readonly_test.go
Syngnat 88434e77a9 feat(elasticsearch): 新增 REST 控制台并完善安全执行链
- 复用查询页提供 ES 控制台、模板、AI 辅助及原始与表格结果
- 新增统一解析分类、危险确认、连接保护和受控 REST 执行
- 扩展 driver agent、版本适配、Wails 绑定、多语言与文档
- 修复完整回归中发现的跨平台和前端基线用例问题

Refs #782
2026-08-01 14:58:12 +08:00

86 lines
3.5 KiB
Go

package app
import (
"strings"
"testing"
"GoNavi-Wails/internal/connection"
"GoNavi-Wails/shared/i18n"
)
func TestSupportsConnectionReadOnlyMode(t *testing.T) {
if !supportsConnectionReadOnlyMode(connection.ConnectionConfig{Type: "postgres"}) {
t.Fatal("postgres should support connection-level production guard")
}
if !supportsConnectionReadOnlyMode(connection.ConnectionConfig{Type: "mongodb"}) {
t.Fatal("mongodb should support connection-level production guard")
}
if !supportsConnectionReadOnlyMode(connection.ConnectionConfig{Type: "nacos"}) {
t.Fatal("nacos should support connection-level production guard")
}
if !supportsConnectionReadOnlyMode(connection.ConnectionConfig{Type: "elasticsearch"}) {
t.Fatal("elasticsearch should support connection-level production guard")
}
if supportsConnectionReadOnlyMode(connection.ConnectionConfig{Type: "redis"}) {
t.Fatal("redis should not support connection-level production guard")
}
}
func TestEnsureReadOnlyConnectionAllowsQuery(t *testing.T) {
sqlConfig := connection.ConnectionConfig{Type: "postgres", ReadOnly: true}
if err := ensureConnectionAllowsQuery(sqlConfig, "SELECT * FROM users"); err != nil {
t.Fatalf("read-only postgres connection should allow select: %v", err)
}
if err := ensureConnectionAllowsQuery(sqlConfig, "UPDATE users SET name = 'next'"); err == nil {
t.Fatal("read-only postgres connection should block update")
}
mongoConfig := connection.ConnectionConfig{Type: "mongodb", ReadOnly: true}
if err := ensureConnectionAllowsQuery(mongoConfig, `{"find":"users","filter":{"active":true}}`); err != nil {
t.Fatalf("read-only mongodb connection should allow find: %v", err)
}
if err := ensureConnectionAllowsQuery(mongoConfig, `{"delete":"users","deletes":[{"q":{"active":false},"limit":0}]}`); err == nil {
t.Fatal("read-only mongodb connection should block delete")
}
}
func TestEnsureReadOnlyConnectionAllowsAction(t *testing.T) {
setDefaultAppLanguage(i18n.LanguageEnUS)
t.Cleanup(func() {
setDefaultAppLanguage(i18n.LanguageEnUS)
})
config := connection.ConnectionConfig{Type: "postgres", ReadOnly: true}
err := ensureConnectionAllowsStructureEdit(config, "connection.backend.action.drop_database")
if err == nil {
t.Fatal("read-only connection should block mutating actions")
}
if !strings.Contains(err.Error(), defaultAppText("connection.backend.action.drop_database", nil)) {
t.Fatalf("blocked action message should include action label, got %q", err.Error())
}
}
func TestEnsureConnectionProtectionSeparatesActionCategories(t *testing.T) {
config := connection.ConnectionConfig{
Type: "postgres",
Protection: connection.ConnectionProtectionConfig{
RestrictDataEdit: true,
RestrictDataImport: true,
RestrictStructureEdit: false,
},
}
if err := ensureConnectionAllowsQuery(config, "UPDATE users SET name = 'next'"); err != nil {
t.Fatalf("script execution should remain allowed when only data-edit/import restrictions are enabled: %v", err)
}
if err := ensureConnectionAllowsDataEdit(config, "connection.backend.action.apply_result_changes"); err == nil {
t.Fatal("data edit restriction should block result changes")
}
if err := ensureConnectionAllowsDataImport(config, "connection.backend.action.import_data"); err == nil {
t.Fatal("data import restriction should block imports")
}
if err := ensureConnectionAllowsStructureEdit(config, "connection.backend.action.drop_database"); err != nil {
t.Fatalf("structure edits should remain allowed when structure restriction is disabled: %v", err)
}
}