Preserve source group hooks through the API

This commit is contained in:
2026-08-22 13:42:42 +01:00
parent ec448157d9
commit 25866ff102
2 changed files with 65 additions and 1 deletions
+39 -1
View File
@@ -29,6 +29,8 @@ type sourceGroupView struct {
RetryMax int `json:"retry_max"`
RetryBackoffSeconds int `json:"retry_backoff_seconds"`
ConflictDimension string `json:"conflict_dimension,omitempty"`
HasPreHook bool `json:"has_pre_hook"`
HasPostHook bool `json:"has_post_hook"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
@@ -49,6 +51,8 @@ func toSourceGroupView(g store.SourceGroup) sourceGroupView {
RetryMax: g.RetryMax,
RetryBackoffSeconds: g.RetryBackoffSeconds,
ConflictDimension: g.ConflictDimension,
HasPreHook: g.PreHook != "",
HasPostHook: g.PostHook != "",
CreatedAt: g.CreatedAt,
UpdatedAt: g.UpdatedAt,
}
@@ -62,6 +66,29 @@ type sourceGroupWriteRequest struct {
RetentionPolicy store.RetentionPolicy `json:"retention_policy"`
RetryMax int `json:"retry_max"`
RetryBackoffSeconds int `json:"retry_backoff_seconds"`
// Pointer fields distinguish omission (preserve on PUT) from an explicit
// empty string (clear). Hook plaintext is accepted on write but never
// returned by the JSON API.
PreHook *string `json:"pre_hook,omitempty"`
PostHook *string `json:"post_hook,omitempty"`
}
func (s *Server) applySourceGroupHooks(hostID string, req sourceGroupWriteRequest, g *store.SourceGroup) error {
if req.PreHook != nil {
enc, err := s.EncryptHookForGroup(hostID, "pre", *req.PreHook)
if err != nil {
return err
}
g.PreHook = enc
}
if req.PostHook != nil {
enc, err := s.EncryptHookForGroup(hostID, "post", *req.PostHook)
if err != nil {
return err
}
g.PostHook = enc
}
return nil
}
func (s *Server) handleListSourceGroups(w stdhttp.ResponseWriter, r *stdhttp.Request) {
@@ -142,6 +169,10 @@ func (s *Server) handleCreateSourceGroup(w stdhttp.ResponseWriter, r *stdhttp.Re
RetryMax: req.RetryMax,
RetryBackoffSeconds: req.RetryBackoffSeconds,
}
if err := s.applySourceGroupHooks(hostID, req, &g); err != nil {
writeJSONError(w, stdhttp.StatusInternalServerError, "hook_encryption_failed", "")
return
}
if err := s.deps.Store.CreateSourceGroup(r.Context(), &g); err != nil {
writeJSONError(w, stdhttp.StatusInternalServerError, "internal", err.Error())
return
@@ -157,7 +188,8 @@ func (s *Server) handleUpdateSourceGroup(w stdhttp.ResponseWriter, r *stdhttp.Re
}
hostID := chi.URLParam(r, "id")
groupID := chi.URLParam(r, "gid")
if _, err := s.deps.Store.GetSourceGroup(r.Context(), hostID, groupID); err != nil {
existingGroup, err := s.deps.Store.GetSourceGroup(r.Context(), hostID, groupID)
if err != nil {
if errors.Is(err, store.ErrNotFound) {
writeJSONError(w, stdhttp.StatusNotFound, "group_not_found", "")
return
@@ -188,6 +220,12 @@ func (s *Server) handleUpdateSourceGroup(w stdhttp.ResponseWriter, r *stdhttp.Re
RetentionPolicy: req.RetentionPolicy,
RetryMax: req.RetryMax,
RetryBackoffSeconds: req.RetryBackoffSeconds,
PreHook: existingGroup.PreHook,
PostHook: existingGroup.PostHook,
}
if err := s.applySourceGroupHooks(hostID, req, &g); err != nil {
writeJSONError(w, stdhttp.StatusInternalServerError, "hook_encryption_failed", "")
return
}
if err := s.deps.Store.UpdateSourceGroup(r.Context(), &g); err != nil {
writeJSONError(w, stdhttp.StatusInternalServerError, "internal", err.Error())