Files
opsxdb/server/internal/aitools/connections.go
T
logan 2c0bfafd8d 同步完整源码至远程:扁平化重构现状 + 未入库源文件
- 补入库:server/internal/db/dump.go、redis 分页/扫描预算测试、opsxdb-mcp main_test、
  packages/opsxdb-mcp package-lock、docs 审计与对比文档等 37 个新文件
- 含结构扁平化进行中的 80 处修改与 155 处旧结构删除(server/ src/ src-tauri/ 为当前有效源)
- 构建产物(bin/target/dist)与签名私钥仍按规则排除
2026-10-16 03:47:33 +08:00

180 lines
4.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package aitools
import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"strings"
"opsxdb/server/internal/db"
)
// SavedConnection 与桌面 store SavedConnection JSON 对齐(磁盘形态,密码可为 ox1. 混淆)。 // Logan.Li
type SavedConnection struct {
ID string `json:"id"`
Name string `json:"name"`
Driver string `json:"driver"`
Host string `json:"host"`
Port int `json:"port"`
User string `json:"user"`
Password string `json:"password"`
Database string `json:"database"`
Service string `json:"service,omitempty"`
SSL bool `json:"ssl,omitempty"`
SSLMode string `json:"sslMode,omitempty"`
SSLCA string `json:"sslCA,omitempty"`
SSLCert string `json:"sslCert,omitempty"`
SSLKey string `json:"sslKey,omitempty"`
RedisMode string `json:"redisMode,omitempty"`
RedisNodes string `json:"redisNodes,omitempty"`
MasterName string `json:"masterName,omitempty"`
SentinelPassword string `json:"sentinelPassword,omitempty"`
SSHEnabled bool `json:"sshEnabled,omitempty"`
SSHHost string `json:"sshHost,omitempty"`
SSHPort int `json:"sshPort,omitempty"`
SSHUser string `json:"sshUser,omitempty"`
SSHAuth string `json:"sshAuth,omitempty"`
SSHPassword string `json:"sshPassword,omitempty"`
SSHPrivateKey string `json:"sshPrivateKey,omitempty"`
SSHPassphrase string `json:"sshPassphrase,omitempty"`
SavePassword *bool `json:"savePassword,omitempty"`
}
// ConnectionSummary 列表对外字段,永不含密码。
type ConnectionSummary struct {
ID string `json:"id"`
Name string `json:"name"`
Driver string `json:"driver"`
Host string `json:"host"`
Port int `json:"port"`
Database string `json:"database"`
}
func ConnectionsPath() (string, error) {
dir, err := opsxdbDir()
if err != nil {
return "", err
}
return filepath.Join(dir, "connections.json"), nil
}
// LoadConnections 读 ~/.opsxdb/connections.json。
func LoadConnections() ([]SavedConnection, error) {
path, err := ConnectionsPath()
if err != nil {
return nil, err
}
b, err := os.ReadFile(path)
if err != nil {
if os.IsNotExist(err) {
return nil, nil
}
return nil, err
}
var list []SavedConnection
if err := json.Unmarshal(b, &list); err != nil {
return nil, fmt.Errorf("connections.json: %w", err)
}
return list, nil
}
// SaveConnections 写 ~/.opsxdb/connections.json(0600);供桌面双写 API 调用。
func SaveConnections(list []SavedConnection) error {
path, err := ConnectionsPath()
if err != nil {
return err
}
if err := os.MkdirAll(filepath.Dir(path), 0700); err != nil {
return err
}
b, err := json.MarshalIndent(list, "", " ")
if err != nil {
return err
}
f, err := os.CreateTemp(filepath.Dir(path), ".connections-*.json")
if err != nil {
return err
}
defer os.Remove(f.Name())
if _, err := f.Write(b); err != nil {
f.Close()
return err
}
if err := f.Close(); err != nil {
return err
}
return os.Rename(f.Name(), path)
}
func FindConnection(id string) (*SavedConnection, error) {
list, err := LoadConnections()
if err != nil {
return nil, err
}
for i := range list {
if list[i].ID == id {
c := list[i]
return &c, nil
}
}
return nil, fmt.Errorf("connection not found: %s", id)
}
// ToConnReq 映射为 db.ConnReq(解码 ox1. 密码)。
func (c SavedConnection) ToConnReq() db.ConnReq {
sslOn := c.SSL || (c.SSLMode != "" && c.SSLMode != "disable")
mode := c.SSLMode
if sslOn {
if mode == "" || mode == "disable" {
mode = "require"
}
} else {
mode = "disable"
}
return db.ConnReq{
Driver: c.Driver,
Host: c.Host,
Port: c.Port,
User: c.User,
Password: DecodeSecret(c.Password),
Database: c.Database,
Service: c.Service,
SSL: sslOn,
SSLMode: mode,
SSLCA: c.SSLCA,
SSLCert: c.SSLCert,
SSLKey: c.SSLKey,
RedisMode: orDefault(c.RedisMode, "standalone"),
RedisNodes: c.RedisNodes,
MasterName: c.MasterName,
SentinelPassword: DecodeSecret(c.SentinelPassword),
SSHEnabled: c.SSHEnabled,
SSHHost: c.SSHHost,
SSHPort: c.SSHPort,
SSHUser: c.SSHUser,
SSHAuth: c.SSHAuth,
SSHPassword: DecodeSecret(c.SSHPassword),
SSHPrivateKey: c.SSHPrivateKey,
SSHPassphrase: DecodeSecret(c.SSHPassphrase),
}
}
func (c SavedConnection) Summary() ConnectionSummary {
return ConnectionSummary{
ID: c.ID,
Name: c.Name,
Driver: c.Driver,
Host: c.Host,
Port: c.Port,
Database: c.Database,
}
}
func orDefault(s, def string) string {
if strings.TrimSpace(s) == "" {
return def
}
return s
}