mirror of
https://github.com/Syngnat/GoNavi.git
synced 2026-05-31 09:49:40 +08:00
- 诊断 SSE 支持空心跳事件,避免无输出时解码失败 - Arthas Tunnel 增加会话过期清理、配置漂移校验和取消兜底 - Provider 合约清理 Base URL 查询参数和片段,避免探测泄露敏感信息 - JVM 变更请求强制校验原因并规范化写入审计字段
195 lines
6.0 KiB
Go
195 lines
6.0 KiB
Go
package app
|
|
|
|
import (
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"GoNavi-Wails/internal/connection"
|
|
"GoNavi-Wails/internal/jvm"
|
|
)
|
|
|
|
var newJVMProvider = jvm.NewProvider
|
|
|
|
func buildJVMCapabilityError(mode string, cfg connection.ConnectionConfig, err error) jvm.Capability {
|
|
probeCfg := cfg
|
|
probeCfg.JVM.PreferredMode = mode
|
|
return jvm.Capability{
|
|
Mode: mode,
|
|
DisplayLabel: jvm.ModeDisplayLabel(mode),
|
|
Reason: jvm.DescribeConnectionTestError(probeCfg, err),
|
|
}
|
|
}
|
|
|
|
func resolveJVMProvider(cfg connection.ConnectionConfig) (connection.ConnectionConfig, jvm.Provider, error) {
|
|
return resolveJVMProviderForMode(cfg, "")
|
|
}
|
|
|
|
func resolveJVMProviderForMode(cfg connection.ConnectionConfig, mode string) (connection.ConnectionConfig, jvm.Provider, error) {
|
|
normalized, selectedMode, err := jvm.ResolveProviderMode(cfg, mode)
|
|
if err != nil {
|
|
return connection.ConnectionConfig{}, nil, err
|
|
}
|
|
|
|
normalized.JVM.PreferredMode = selectedMode
|
|
|
|
provider, err := newJVMProvider(selectedMode)
|
|
if err != nil {
|
|
return connection.ConnectionConfig{}, nil, err
|
|
}
|
|
|
|
return normalized, provider, nil
|
|
}
|
|
|
|
func (a *App) TestJVMConnection(cfg connection.ConnectionConfig) connection.QueryResult {
|
|
normalized, provider, err := resolveJVMProvider(cfg)
|
|
if err != nil {
|
|
return connection.QueryResult{Success: false, Message: err.Error()}
|
|
}
|
|
|
|
if err := provider.TestConnection(a.ctx, normalized); err != nil {
|
|
return connection.QueryResult{Success: false, Message: jvm.DescribeConnectionTestError(normalized, err)}
|
|
}
|
|
|
|
return connection.QueryResult{Success: true, Message: "JVM 连接成功"}
|
|
}
|
|
|
|
func (a *App) JVMListResources(cfg connection.ConnectionConfig, parentPath string) connection.QueryResult {
|
|
normalized, provider, err := resolveJVMProvider(cfg)
|
|
if err != nil {
|
|
return connection.QueryResult{Success: false, Message: err.Error()}
|
|
}
|
|
|
|
items, err := provider.ListResources(a.ctx, normalized, parentPath)
|
|
if err != nil {
|
|
return connection.QueryResult{Success: false, Message: err.Error()}
|
|
}
|
|
|
|
return connection.QueryResult{Success: true, Data: items}
|
|
}
|
|
|
|
func (a *App) JVMGetValue(cfg connection.ConnectionConfig, resourcePath string) connection.QueryResult {
|
|
normalized, provider, err := resolveJVMProvider(cfg)
|
|
if err != nil {
|
|
return connection.QueryResult{Success: false, Message: err.Error()}
|
|
}
|
|
|
|
value, err := provider.GetValue(a.ctx, normalized, resourcePath)
|
|
if err != nil {
|
|
return connection.QueryResult{Success: false, Message: err.Error()}
|
|
}
|
|
|
|
return connection.QueryResult{Success: true, Data: value}
|
|
}
|
|
|
|
func (a *App) JVMPreviewChange(cfg connection.ConnectionConfig, req jvm.ChangeRequest) connection.QueryResult {
|
|
var err error
|
|
req, err = jvm.NormalizeChangeRequest(req)
|
|
if err != nil {
|
|
return connection.QueryResult{Success: false, Message: err.Error()}
|
|
}
|
|
|
|
normalized, provider, err := resolveJVMProviderForMode(cfg, req.ProviderMode)
|
|
if err != nil {
|
|
return connection.QueryResult{Success: false, Message: err.Error()}
|
|
}
|
|
|
|
preview, err := jvm.BuildChangePreview(a.ctx, provider, normalized, req)
|
|
if err != nil {
|
|
return connection.QueryResult{Success: false, Message: err.Error()}
|
|
}
|
|
|
|
return connection.QueryResult{Success: true, Data: preview}
|
|
}
|
|
|
|
func (a *App) JVMApplyChange(cfg connection.ConnectionConfig, req jvm.ChangeRequest) connection.QueryResult {
|
|
var err error
|
|
req, err = jvm.NormalizeChangeRequest(req)
|
|
if err != nil {
|
|
return connection.QueryResult{Success: false, Message: err.Error()}
|
|
}
|
|
|
|
normalized, provider, err := resolveJVMProviderForMode(cfg, req.ProviderMode)
|
|
if err != nil {
|
|
return connection.QueryResult{Success: false, Message: err.Error()}
|
|
}
|
|
|
|
preview, err := jvm.BuildChangePreview(a.ctx, provider, normalized, req)
|
|
if err != nil {
|
|
return connection.QueryResult{Success: false, Message: err.Error()}
|
|
}
|
|
if !preview.Allowed {
|
|
message := strings.TrimSpace(preview.BlockingReason)
|
|
if message == "" {
|
|
message = "当前变更被 Guard 拦截"
|
|
}
|
|
return connection.QueryResult{Success: false, Message: message}
|
|
}
|
|
|
|
result, err := provider.ApplyChange(a.ctx, normalized, req)
|
|
if err != nil {
|
|
return connection.QueryResult{Success: false, Message: err.Error()}
|
|
}
|
|
|
|
if err := jvm.NewAuditStore(filepath.Join(a.auditRootDir(), "jvm_audit.jsonl")).Append(jvm.AuditRecord{
|
|
ConnectionID: normalized.ID,
|
|
ProviderMode: normalized.JVM.PreferredMode,
|
|
ResourceID: req.ResourceID,
|
|
Action: req.Action,
|
|
Reason: req.Reason,
|
|
Source: req.Source,
|
|
Result: result.Status,
|
|
}); err != nil {
|
|
if strings.TrimSpace(result.Message) == "" {
|
|
result.Message = "变更已执行,但审计记录写入失败: " + err.Error()
|
|
} else {
|
|
result.Message += ";审计记录写入失败: " + err.Error()
|
|
}
|
|
}
|
|
|
|
return connection.QueryResult{Success: true, Data: result}
|
|
}
|
|
|
|
func (a *App) JVMListAuditRecords(connectionID string, limit int) connection.QueryResult {
|
|
records, err := jvm.NewAuditStore(filepath.Join(a.auditRootDir(), "jvm_audit.jsonl")).List(connectionID, limit)
|
|
if err != nil {
|
|
return connection.QueryResult{Success: false, Message: err.Error()}
|
|
}
|
|
return connection.QueryResult{Success: true, Data: records}
|
|
}
|
|
|
|
func (a *App) JVMProbeCapabilities(cfg connection.ConnectionConfig) connection.QueryResult {
|
|
normalized, err := jvm.NormalizeConnectionConfig(cfg)
|
|
if err != nil {
|
|
return connection.QueryResult{Success: false, Message: err.Error()}
|
|
}
|
|
|
|
items := make([]jvm.Capability, 0, len(normalized.JVM.AllowedModes))
|
|
for _, mode := range normalized.JVM.AllowedModes {
|
|
probeCfg := normalized
|
|
probeCfg.JVM.PreferredMode = mode
|
|
|
|
provider, providerErr := newJVMProvider(mode)
|
|
if providerErr != nil {
|
|
items = append(items, buildJVMCapabilityError(mode, probeCfg, providerErr))
|
|
continue
|
|
}
|
|
|
|
caps, probeErr := provider.ProbeCapabilities(a.ctx, probeCfg)
|
|
if probeErr != nil {
|
|
items = append(items, buildJVMCapabilityError(mode, probeCfg, probeErr))
|
|
continue
|
|
}
|
|
|
|
items = append(items, caps...)
|
|
}
|
|
|
|
return connection.QueryResult{Success: true, Data: items}
|
|
}
|
|
|
|
func (a *App) auditRootDir() string {
|
|
if strings.TrimSpace(a.configDir) != "" {
|
|
return a.configDir
|
|
}
|
|
return resolveAppConfigDir()
|
|
}
|