webui: add activity log support to curated pages

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
Joachim Wiberg
2026-06-14 22:07:40 +02:00
parent a80a731324
commit 1a33604ed6
3 changed files with 17 additions and 14 deletions
@@ -157,8 +157,7 @@ func (h *ConfigureKeystoreHandler) AddSymKey(w http.ResponseWriter, r *http.Requ
renderSaveError(w, err)
return
}
w.Header().Set("HX-Location", `{"path":"/configure/keystore","target":"#content"}`)
w.WriteHeader(http.StatusNoContent)
renderSavedRedirect(w, "Symmetric key added", "/configure/keystore")
}
// DeleteSymKey removes a symmetric key from the candidate.
@@ -171,8 +170,7 @@ func (h *ConfigureKeystoreHandler) DeleteSymKey(w http.ResponseWriter, r *http.R
renderSaveError(w, err)
return
}
w.Header().Set("HX-Location", `{"path":"/configure/keystore","target":"#content"}`)
w.WriteHeader(http.StatusNoContent)
renderSavedRedirect(w, "Symmetric key deleted", "/configure/keystore")
}
// AddAsymKey adds an asymmetric key from a PEM-encoded private key.
@@ -225,8 +223,7 @@ func (h *ConfigureKeystoreHandler) AddAsymKey(w http.ResponseWriter, r *http.Req
renderSaveError(w, err)
return
}
w.Header().Set("HX-Location", `{"path":"/configure/keystore","target":"#content"}`)
w.WriteHeader(http.StatusNoContent)
renderSavedRedirect(w, "Asymmetric key added", "/configure/keystore")
}
// derivePublicKeyFromDER extracts the public key from DER-encoded private key bytes
@@ -289,8 +286,7 @@ func (h *ConfigureKeystoreHandler) DeleteAsymKey(w http.ResponseWriter, r *http.
renderSaveError(w, err)
return
}
w.Header().Set("HX-Location", `{"path":"/configure/keystore","target":"#content"}`)
w.WriteHeader(http.StatusNoContent)
renderSavedRedirect(w, "Asymmetric key deleted", "/configure/keystore")
}
// AddCert adds a certificate to an asymmetric key entry.
@@ -327,8 +323,7 @@ func (h *ConfigureKeystoreHandler) AddCert(w http.ResponseWriter, r *http.Reques
renderSaveError(w, err)
return
}
w.Header().Set("HX-Location", `{"path":"/configure/keystore","target":"#content"}`)
w.WriteHeader(http.StatusNoContent)
renderSavedRedirect(w, "Certificate added", "/configure/keystore")
}
// UpdateCert replaces the PEM data of an existing certificate.
@@ -380,8 +375,7 @@ func (h *ConfigureKeystoreHandler) DeleteCert(w http.ResponseWriter, r *http.Req
renderSaveError(w, err)
return
}
w.Header().Set("HX-Location", `{"path":"/configure/keystore","target":"#content"}`)
w.WriteHeader(http.StatusNoContent)
renderSavedRedirect(w, "Certificate deleted", "/configure/keystore")
}
// derBase64ToPEM converts a base64-encoded DER blob (as returned by RESTCONF
@@ -365,6 +365,16 @@ func renderSaved(w http.ResponseWriter, msg string) {
w.WriteHeader(http.StatusOK)
}
// renderSavedRedirect logs a cfgSaved activity entry and then navigates HTMX to
// the given page path (targeting #content). Use this instead of a bare HX-Location
// for Add/Delete operations that redirect back to the listing page after success.
func renderSavedRedirect(w http.ResponseWriter, msg, path string) {
b, _ := json.Marshal(msg)
w.Header().Set("HX-Trigger", `{"cfgSaved":`+string(b)+`}`)
w.Header().Set("HX-Location", `{"path":"`+path+`","target":"#content"}`)
w.WriteHeader(http.StatusNoContent)
}
// renderSaveError writes an inline error for HTMX. HX-Trigger ensures forms with
// hx-swap="none" still receive the cfgError event (body swap alone would be silenced).
// RESTCONF errors surface their server-side Message; all other errors fall back to
@@ -339,7 +339,6 @@ func (h *ConfigureUsersHandler) DeleteKey(w http.ResponseWriter, r *http.Request
renderSaveError(w, err)
return
}
var userEntry map[string]any
for _, u := range raw.System.Auth.Users {
if u.Name != name {
@@ -391,7 +390,7 @@ func (h *ConfigureUsersHandler) DeleteKey(w http.ResponseWriter, r *http.Request
renderSaveError(w, err)
return
}
w.WriteHeader(http.StatusOK)
renderSavedRedirect(w, "SSH key deleted", "/configure/users")
}
// fetchAllGroups reads NACM groups from candidate, falling back to running on 404.