fix(api): surface a failed key read and align the settings echo

This commit is contained in:
Hintay
2026-07-30 02:18:12 +09:00
parent 7f820eaa62
commit 1be0f99e04
2 changed files with 27 additions and 10 deletions

View File

@@ -19,7 +19,7 @@ import (
gossh "golang.org/x/crypto/ssh"
)
var resetSSHClient = nginx.ResetSSHClient
var resetSSHClient = nginx.ResetHostNginxState
// Preview renders all snippets from the posted SetupParams (or current
// settings if body is empty). Does not persist anything.
@@ -107,7 +107,13 @@ func GenerateKeypair(c *gin.Context) {
cosy.ErrHandler(c, err)
return
}
priv, _ := os.ReadFile(path)
// The one-time private key is the only copy the operator gets, so a failed
// read must not be rendered as a clean 200 with the field simply absent.
priv, err := os.ReadFile(path)
if err != nil {
cosy.ErrHandler(c, cosy.WrapErrorWithParams(setup.ErrKeyfileRead, path, err.Error()))
return
}
c.JSON(http.StatusOK, keypairResponse{PublicKey: pub, PrivateKey: string(priv)})
}
@@ -376,19 +382,22 @@ func ScanHostKey(c *gin.Context) {
}
var keys []gossh.PublicKey
// Pasted output carries no evidence about which algorithms answered, so it
// leaves the coverage nil and no entry is reported stale from it.
var probed map[string]bool
if req.KeyscanOutput != "" {
keys, err = hostssh.ParseSSHKeyscanOutput(req.KeyscanOutput)
} else {
ctx, cancel := context.WithTimeout(c.Request.Context(), 10*time.Second)
defer cancel()
keys, err = hostssh.ScanHostKeys(ctx, req.HostAddress, 10*time.Second)
keys, probed, err = hostssh.ScanHostKeysWithCoverage(ctx, req.HostAddress, 10*time.Second)
}
if err != nil {
cosy.ErrHandler(c, err)
return
}
result, err := hostssh.ClassifyHostKeys(req.HostAddress, keys, kh)
result, err := hostssh.ClassifyScannedHostKeys(req.HostAddress, keys, probed, kh)
if err != nil {
cosy.ErrHandler(c, err)
return

View File

@@ -152,6 +152,11 @@ func applyNginxControlSettings(target *appsettings.Nginx, payload nginxControlSe
target.ErrorLogPath = payload.ErrorLogPath
}
// TestConfigCmd, ReloadCmd and RestartCmd are deliberately left alone here.
// Nothing in the wizard writes them, so they are operator authored, and
// execShell already routes them at the current target. Clearing them on a
// mode switch would silently discard input the operator typed elsewhere.
//
// Paths detected on the SSH host do not describe a local or docker install.
// Clear them on the way out so path resolution falls back to detection.
if wasHostViaSSH && payload.Mode != appsettings.ControlModeHostViaSSH {
@@ -187,11 +192,14 @@ func currentNginxControlSettings() nginxControlSettingsPayload {
HostConfigDir: n.HostConfigDir,
HostLogDir: n.HostLogDir,
SbinPath: n.SbinPath,
PIDPath: n.PIDPath,
ConfigDir: n.ConfigDir,
ConfigPath: n.ConfigPath,
AccessLogPath: n.AccessLogPath,
ErrorLogPath: n.ErrorLogPath,
// GET /settings reports the resolved values for these, and the frontend
// merges this response into the same store without refetching, so the
// two must agree or a save would blank the displayed paths.
PIDPath: nginx.GetPIDPath(),
ConfigDir: nginx.GetConfPath(),
ConfigPath: n.ConfigPath,
AccessLogPath: nginx.GetAccessLogPath(),
ErrorLogPath: nginx.GetErrorLogPath(),
}
}
@@ -221,7 +229,7 @@ func SaveNginxControlSettings(c *gin.Context) {
return
}
nginx.ResetSSHClient()
nginx.ResetHostNginxState()
c.JSON(http.StatusOK, currentNginxControlSettings())
}