// ui_repo_hooks.go — host-default pre/post hook editor on the Repo // page (P2R-12). Per-source-group hooks live on the source group // edit form; this surface lets the operator set defaults that apply // to every group that doesn't override them. // // POST /hosts/{id}/repo/hooks takes pre_hook + post_hook form // fields; encrypts each with the AEAD key (per-host AD bytes); and // persists the (possibly empty) blobs via store.SetHostHooks. package http import ( "log/slog" stdhttp "net/http" ) func (s *Server) handleUIRepoHooksSave(w stdhttp.ResponseWriter, r *stdhttp.Request) { u := s.requireUIUser(w, r) if u == nil { return } host, ok := s.loadHostForUI(w, r) if !ok { return } if err := r.ParseForm(); err != nil { stdhttp.Error(w, "bad request", stdhttp.StatusBadRequest) return } pre := r.PostForm.Get("pre_hook") post := r.PostForm.Get("post_hook") preEnc, err := s.EncryptHookForHost(host.ID, "pre", pre) if err != nil { slog.Error("ui repo hooks: encrypt pre", "err", err) stdhttp.Error(w, "internal", stdhttp.StatusInternalServerError) return } postEnc, err := s.EncryptHookForHost(host.ID, "post", post) if err != nil { slog.Error("ui repo hooks: encrypt post", "err", err) stdhttp.Error(w, "internal", stdhttp.StatusInternalServerError) return } if err := s.deps.Store.SetHostHooks(r.Context(), host.ID, preEnc, postEnc); err != nil { slog.Error("ui repo hooks: persist", "err", err) stdhttp.Error(w, "internal", stdhttp.StatusInternalServerError) return } stdhttp.Redirect(w, r, "/hosts/"+host.ID+"/repo?saved=hooks", stdhttp.StatusSeeOther) }