mirror of
https://github.com/Syngnat/GoNavi.git
synced 2026-06-28 01:11:31 +08:00
✨ feat(security): 暴露连接配置与代理的密钥存储 API
This commit is contained in:
@@ -123,11 +123,26 @@ func proxyConfigEqual(a, b connection.ProxyConfig) bool {
|
||||
a.Password == b.Password
|
||||
}
|
||||
|
||||
func currentGlobalProxyView() connection.GlobalProxyView {
|
||||
snapshot := currentGlobalProxyConfig()
|
||||
if !snapshot.Enabled {
|
||||
return connection.GlobalProxyView{Enabled: false}
|
||||
}
|
||||
return connection.GlobalProxyView{
|
||||
Enabled: true,
|
||||
Type: snapshot.Proxy.Type,
|
||||
Host: snapshot.Proxy.Host,
|
||||
Port: snapshot.Proxy.Port,
|
||||
User: snapshot.Proxy.User,
|
||||
HasPassword: strings.TrimSpace(snapshot.Proxy.Password) != "",
|
||||
}
|
||||
}
|
||||
|
||||
func (a *App) GetGlobalProxyConfig() connection.QueryResult {
|
||||
return connection.QueryResult{
|
||||
Success: true,
|
||||
Message: "OK",
|
||||
Data: currentGlobalProxyConfig(),
|
||||
Data: currentGlobalProxyView(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -312,3 +327,4 @@ func buildProxyURLFromConfig(proxyConfig connection.ProxyConfig) (*url.URL, erro
|
||||
}
|
||||
return proxyURL, nil
|
||||
}
|
||||
|
||||
|
||||
44
internal/app/methods_saved_connections.go
Normal file
44
internal/app/methods_saved_connections.go
Normal file
@@ -0,0 +1,44 @@
|
||||
package app
|
||||
|
||||
import "GoNavi-Wails/internal/connection"
|
||||
|
||||
func (a *App) savedConnectionRepository() *savedConnectionRepository {
|
||||
return newSavedConnectionRepository(a.configDir, a.secretStore)
|
||||
}
|
||||
|
||||
func (a *App) GetSavedConnections() ([]connection.SavedConnectionView, error) {
|
||||
return a.savedConnectionRepository().List()
|
||||
}
|
||||
|
||||
func (a *App) SaveConnection(input connection.SavedConnectionInput) (connection.SavedConnectionView, error) {
|
||||
return a.savedConnectionRepository().Save(input)
|
||||
}
|
||||
|
||||
func (a *App) DeleteConnection(id string) error {
|
||||
return a.savedConnectionRepository().Delete(id)
|
||||
}
|
||||
|
||||
func (a *App) DuplicateConnection(id string) (connection.SavedConnectionView, error) {
|
||||
return a.savedConnectionRepository().Duplicate(id)
|
||||
}
|
||||
|
||||
func (a *App) ImportLegacyConnections(items []connection.LegacySavedConnection) ([]connection.SavedConnectionView, error) {
|
||||
result := make([]connection.SavedConnectionView, 0, len(items))
|
||||
repo := a.savedConnectionRepository()
|
||||
for _, item := range items {
|
||||
view, err := repo.Save(connection.SavedConnectionInput(item))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result = append(result, view)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (a *App) SaveGlobalProxy(input connection.SaveGlobalProxyInput) (connection.GlobalProxyView, error) {
|
||||
return a.saveGlobalProxy(input)
|
||||
}
|
||||
|
||||
func (a *App) ImportLegacyGlobalProxy(input connection.LegacyGlobalProxyInput) (connection.GlobalProxyView, error) {
|
||||
return a.saveGlobalProxy(connection.SaveGlobalProxyInput(input))
|
||||
}
|
||||
94
internal/app/methods_saved_connections_test.go
Normal file
94
internal/app/methods_saved_connections_test.go
Normal file
@@ -0,0 +1,94 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"GoNavi-Wails/internal/connection"
|
||||
)
|
||||
|
||||
func TestSaveConnectionMethodReturnsSecretlessView(t *testing.T) {
|
||||
app := NewAppWithSecretStore(newFakeAppSecretStore())
|
||||
app.configDir = t.TempDir()
|
||||
|
||||
result, err := app.SaveConnection(connection.SavedConnectionInput{
|
||||
ID: "conn-1",
|
||||
Name: "Primary",
|
||||
Config: connection.ConnectionConfig{
|
||||
ID: "conn-1",
|
||||
Type: "postgres",
|
||||
Host: "db.local",
|
||||
Port: 5432,
|
||||
User: "postgres",
|
||||
Password: "postgres-secret",
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if result.Config.Password != "" {
|
||||
t.Fatal("SaveConnection must not return plaintext password")
|
||||
}
|
||||
if !result.HasPrimaryPassword {
|
||||
t.Fatal("expected HasPrimaryPassword=true")
|
||||
}
|
||||
}
|
||||
|
||||
func TestDuplicateConnectionClonesSecretBundle(t *testing.T) {
|
||||
app := NewAppWithSecretStore(newFakeAppSecretStore())
|
||||
app.configDir = t.TempDir()
|
||||
|
||||
_, err := app.SaveConnection(connection.SavedConnectionInput{
|
||||
ID: "conn-1",
|
||||
Name: "Primary",
|
||||
Config: connection.ConnectionConfig{
|
||||
ID: "conn-1",
|
||||
Type: "postgres",
|
||||
Host: "db.local",
|
||||
Port: 5432,
|
||||
User: "postgres",
|
||||
Password: "postgres-secret",
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
duplicate, err := app.DuplicateConnection("conn-1")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if duplicate.ID == "conn-1" {
|
||||
t.Fatal("duplicate should have a new id")
|
||||
}
|
||||
|
||||
resolved, err := app.resolveConnectionSecrets(duplicate.Config)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if resolved.Password != "postgres-secret" {
|
||||
t.Fatalf("expected duplicated secret bundle, got %q", resolved.Password)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSaveGlobalProxyReturnsSecretlessView(t *testing.T) {
|
||||
app := NewAppWithSecretStore(newFakeAppSecretStore())
|
||||
app.configDir = t.TempDir()
|
||||
|
||||
view, err := app.SaveGlobalProxy(connection.SaveGlobalProxyInput{
|
||||
Enabled: true,
|
||||
Type: "http",
|
||||
Host: "127.0.0.1",
|
||||
Port: 8080,
|
||||
User: "ops",
|
||||
Password: "proxy-secret",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if view.Password != "" {
|
||||
t.Fatal("global proxy view must not expose plaintext password")
|
||||
}
|
||||
if !view.HasPassword {
|
||||
t.Fatal("expected hasPassword=true")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user