MCPcopy Create free account
hub / github.com/PerpetualSoftware/pad / handleCreateWebhook

Method handleCreateWebhook

internal/server/handlers_webhooks.go:33–84  ·  view source on GitHub ↗

handleCreateWebhook registers a new webhook for a workspace.

(w http.ResponseWriter, r *http.Request)

Source from the content-addressed store, hash-verified

31
32// handleCreateWebhook registers a new webhook for a workspace.
33func (s *Server) handleCreateWebhook(w http.ResponseWriter, r *http.Request) {
34 if !requireMinRole(w, r, "owner") {
35 return
36 }
37 workspaceID, ok := s.getWorkspaceID(w, r)
38 if !ok {
39 return
40 }
41
42 // Enforce webhook count limit (workspace-scoped)
43 if !s.enforcePlanLimit(w, workspaceID, "webhooks") {
44 return
45 }
46
47 var input models.WebhookCreate
48 if err := decodeJSON(r, &input); err != nil {
49 writeError(w, http.StatusBadRequest, "bad_request", err.Error())
50 return
51 }
52
53 if input.URL == "" {
54 writeError(w, http.StatusBadRequest, "bad_request", "url is required")
55 return
56 }
57
58 // "enc:" is the reserved marker the store uses to tag encrypted secrets at
59 // rest (see internal/store/encryption.go::encryptedPrefix). Reject a raw
60 // secret that starts with it so a user-supplied plaintext can never be
61 // mistaken for ciphertext on read (which would break signing/dispatch,
62 // including on keyless self-host instances).
63 if strings.HasPrefix(input.Secret, "enc:") {
64 writeError(w, http.StatusBadRequest, "bad_request", "secret must not start with the reserved prefix \"enc:\"")
65 return
66 }
67
68 // Validate URL to prevent SSRF attacks
69 if err := webhooks.ValidateWebhookURL(input.URL); err != nil {
70 writeError(w, http.StatusBadRequest, "bad_request", "Invalid webhook URL: "+err.Error())
71 return
72 }
73
74 hook, err := s.store.CreateWebhook(workspaceID, input)
75 if err != nil {
76 writeInternalError(w, err)
77 return
78 }
79
80 // The creation response is the ONLY place the raw secret is returned, so
81 // the caller can record it for HMAC verification. It is masked everywhere
82 // else (BUG-2057).
83 writeJSON(w, http.StatusCreated, hook)
84}
85
86// handleListWebhooks returns all webhooks for a workspace.
87// Restricted to owners since webhook URLs may contain secret tokens.

Callers

nothing calls this directly

Calls 10

getWorkspaceIDMethod · 0.95
enforcePlanLimitMethod · 0.95
ValidateWebhookURLFunction · 0.92
requireMinRoleFunction · 0.85
decodeJSONFunction · 0.85
writeErrorFunction · 0.85
writeInternalErrorFunction · 0.85
writeJSONFunction · 0.85
ErrorMethod · 0.45
CreateWebhookMethod · 0.45

Tested by

no test coverage detected