Files
MyGoNavi/internal/app/legacy_webkit_storage_test.go
Syngnat c7cf9526de 🐛 fix(security): 修复 macOS 无法打开应用及三平台依赖系统钥匙串的问题
- 密文存储:新增 dailysecret 本地存储引擎,连接/代理/AI 密钥不再依赖系统钥匙串
- 启动迁移:自动将已有钥匙串密文迁移到本地 JSON,用户无感知
- WebKit 迁移:从旧版 Wails WebKit LocalStorage 中恢复连接与代理数据
- DMG 修复:移除 --sandbox-safe 避免扩展属性污染签名,新增 xattr 清理与签名校验
- 安全适配:钥匙串不可用时标记完成而非回滚,消除无钥匙串环境下的阻塞
- 出口脱敏:所有连接/代理 API 返回前统一 sanitize 防止密文泄漏
2026-04-13 12:40:25 +08:00

184 lines
4.8 KiB
Go

package app
import (
"database/sql"
"encoding/json"
"os"
"path/filepath"
"testing"
"GoNavi-Wails/internal/connection"
_ "modernc.org/sqlite"
)
func TestMigrateLegacyWebKitStorageIfNeededImportsConnectionsForDevBuild(t *testing.T) {
app := NewAppWithSecretStore(newFakeAppSecretStore())
app.configDir = t.TempDir()
homeDir := t.TempDir()
writeLegacyWebKitStorage(t, homeDir, "com.wails.GoNavi", legacyWebKitStoragePayload{
Connections: []connection.LegacySavedConnection{
{
ID: "legacy-1",
Name: "Legacy One",
Config: connection.ConnectionConfig{
ID: "legacy-1",
Type: "postgres",
Host: "db.local",
Port: 5432,
User: "postgres",
Password: "secret-1",
},
},
},
GlobalProxy: &connection.LegacyGlobalProxyInput{
Enabled: true,
Type: "http",
Host: "127.0.0.1",
Port: 8080,
User: "ops",
Password: "proxy-secret",
},
})
if err := migrateLegacyWebKitStorageIfNeededWithHome(app, "dev", func() (string, error) {
return homeDir, nil
}); err != nil {
t.Fatalf("migrateLegacyWebKitStorageIfNeededWithHome returned error: %v", err)
}
saved, err := app.GetSavedConnections()
if err != nil {
t.Fatalf("GetSavedConnections returned error: %v", err)
}
if len(saved) != 1 {
t.Fatalf("expected 1 saved connection, got %d", len(saved))
}
if saved[0].Name != "Legacy One" {
t.Fatalf("expected imported connection name to be preserved, got %q", saved[0].Name)
}
resolved, err := app.resolveConnectionSecrets(saved[0].Config)
if err != nil {
t.Fatalf("resolveConnectionSecrets returned error: %v", err)
}
if resolved.Password != "secret-1" {
t.Fatalf("expected imported primary password, got %q", resolved.Password)
}
view := app.GetGlobalProxyConfig()
if !view.Success {
t.Fatalf("expected GetGlobalProxyConfig success, got %#v", view)
}
proxy, ok := view.Data.(connection.GlobalProxyView)
if !ok {
t.Fatalf("expected GlobalProxyView payload, got %#v", view.Data)
}
if proxy.Host != "127.0.0.1" || !proxy.HasPassword {
t.Fatalf("expected imported global proxy to be restored, got %#v", proxy)
}
}
func TestMigrateLegacyWebKitStorageIfNeededSkipsWhenConnectionsFileAlreadyExists(t *testing.T) {
app := NewAppWithSecretStore(newFakeAppSecretStore())
app.configDir = t.TempDir()
homeDir := t.TempDir()
if _, err := app.SaveConnection(connection.SavedConnectionInput{
ID: "current-1",
Name: "Current",
Config: connection.ConnectionConfig{
ID: "current-1",
Type: "postgres",
Host: "current.local",
Port: 5432,
User: "postgres",
},
}); err != nil {
t.Fatalf("SaveConnection returned error: %v", err)
}
writeLegacyWebKitStorage(t, homeDir, "com.wails.GoNavi", legacyWebKitStoragePayload{
Connections: []connection.LegacySavedConnection{
{
ID: "legacy-1",
Name: "Legacy One",
Config: connection.ConnectionConfig{
ID: "legacy-1",
Type: "postgres",
Host: "legacy.local",
Port: 5432,
User: "postgres",
},
},
},
})
if err := migrateLegacyWebKitStorageIfNeededWithHome(app, "dev", func() (string, error) {
return homeDir, nil
}); err != nil {
t.Fatalf("migrateLegacyWebKitStorageIfNeededWithHome returned error: %v", err)
}
saved, err := app.GetSavedConnections()
if err != nil {
t.Fatalf("GetSavedConnections returned error: %v", err)
}
if len(saved) != 1 {
t.Fatalf("expected existing connections to remain unchanged, got %d", len(saved))
}
if saved[0].Name != "Current" {
t.Fatalf("expected migration to skip existing repository, got %q", saved[0].Name)
}
}
type legacyWebKitStoragePayload struct {
Connections []connection.LegacySavedConnection `json:"connections"`
GlobalProxy *connection.LegacyGlobalProxyInput `json:"globalProxy,omitempty"`
}
func writeLegacyWebKitStorage(t *testing.T, homeDir string, bundleID string, payload legacyWebKitStoragePayload) {
t.Helper()
dbPath := filepath.Join(
homeDir,
"Library",
"WebKit",
bundleID,
"WebsiteData",
"Default",
"test-origin",
"test-origin",
"LocalStorage",
"localstorage.sqlite3",
)
if err := os.MkdirAll(filepath.Dir(dbPath), 0o755); err != nil {
t.Fatalf("MkdirAll returned error: %v", err)
}
db, err := sql.Open("sqlite", dbPath)
if err != nil {
t.Fatalf("sql.Open returned error: %v", err)
}
defer db.Close()
if _, err := db.Exec(`CREATE TABLE ItemTable (key TEXT PRIMARY KEY, value TEXT)`); err != nil {
t.Fatalf("CREATE TABLE returned error: %v", err)
}
raw, err := json.Marshal(map[string]any{
"state": map[string]any{
"connections": payload.Connections,
"globalProxy": payload.GlobalProxy,
},
})
if err != nil {
t.Fatalf("json.Marshal returned error: %v", err)
}
if _, err := db.Exec(`INSERT INTO ItemTable(key, value) VALUES(?, ?)`, "lite-db-storage", string(raw)); err != nil {
t.Fatalf("INSERT returned error: %v", err)
}
}