Files
geniusrun/backend/internal/api/appconfig.go

89 lines
2.5 KiB
Go
Raw Normal View History

package api
import (
"encoding/json"
"net/http"
"geniusrun/backend/internal/config"
)
// EnvVar is one read-only environment-configuration entry, already
// display-safe (masking happens in config.Config.DisplayEnv).
type EnvVar struct {
Name string `json:"name"`
Value string `json:"value"`
}
type appConfigEntry struct {
Key string `json:"key"`
Value string `json:"value"`
Default string `json:"default"`
Overridden bool `json:"overridden"`
Description string `json:"description"`
}
// configView assembles the GET/PUT response: registry defaults overlaid
// with DB overrides, plus the env snapshot.
func (s *Server) configView(r *http.Request) (map[string]any, error) {
overrides, err := s.DB.ConfigValues(r.Context())
if err != nil {
return nil, err
}
registry := config.AppRegistry()
app := make([]appConfigEntry, 0, len(registry))
for _, k := range registry {
value, overridden := overrides[k.Key]
if !overridden {
value = k.Default
}
app = append(app, appConfigEntry{
Key: k.Key, Value: value, Default: k.Default,
Overridden: overridden, Description: k.Description,
})
}
envVars := s.EnvVars
if envVars == nil {
envVars = []EnvVar{}
}
return map[string]any{"application": app, "environment": envVars}, nil
}
func (s *Server) handleGetConfig(w http.ResponseWriter, r *http.Request) {
resp, err := s.configView(r)
if err != nil {
writeError(w, http.StatusInternalServerError, err.Error())
return
}
writeJSON(w, http.StatusOK, resp)
}
// handlePutConfig updates application configuration. Cold: saved values
// take effect on the next backend restart; the response is just the
// refreshed view, same shape as GET.
func (s *Server) handlePutConfig(w http.ResponseWriter, r *http.Request) {
var body map[string]string
if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
writeError(w, http.StatusBadRequest, "invalid request body")
return
}
// Validate every pair before writing anything -- all-or-nothing.
for key, value := range body {
if err := config.ValidateAppValue(key, value); err != nil {
writeError(w, http.StatusBadRequest, err.Error())
return
}
}
for key, value := range body {
if err := s.DB.SetConfigValue(r.Context(), key, value); err != nil {
writeError(w, http.StatusInternalServerError, err.Error())
return
}
}
resp, err := s.configView(r)
if err != nil {
writeError(w, http.StatusInternalServerError, err.Error())
return
}
writeJSON(w, http.StatusOK, resp)
}