MCPcopy Create free account
hub / github.com/Mnexa-AI/e2a / UpdateWebhook

Method UpdateWebhook

internal/identity/webhooks.go:374–446  ·  view source on GitHub ↗

UpdateWebhook applies a partial update to a webhook. Only fields with a non-nil pointer in WebhookUpdate are touched. Returns the updated row. Validation (charset, count caps, agent ownership) is the handler's job; the storage layer enforces only the re-enable cooldown and the per-row CHECK constra

(ctx context.Context, webhookID, userID string, u WebhookUpdate)

Source from the content-addressed store, hash-verified

372// job; the storage layer enforces only the re-enable cooldown and
373// the per-row CHECK constraints (events non-empty, url non-empty).
374func (s *Store) UpdateWebhook(ctx context.Context, webhookID, userID string, u WebhookUpdate) (*Webhook, error) {
375 // Re-enable cooldown — read the current state once before
376 // running the UPDATE so we can return a typed error.
377 if u.Enabled != nil && *u.Enabled {
378 var autoDisabledAt *time.Time
379 err := s.pool.QueryRow(ctx,
380 `SELECT auto_disabled_at FROM webhooks WHERE id = $1 AND user_id = $2`,
381 webhookID, userID,
382 ).Scan(&autoDisabledAt)
383 if err != nil {
384 if errors.Is(err, pgx.ErrNoRows) {
385 return nil, ErrWebhookNotFound
386 }
387 return nil, err
388 }
389 if autoDisabledAt != nil && time.Since(*autoDisabledAt) < reEnableCooldown {
390 return nil, ErrWebhookCooldown
391 }
392 }
393
394 // Build a dynamic UPDATE based on which fields are present. Using
395 // COALESCE keeps the query simple at the cost of always touching
396 // every column; at slice-1 webhook counts this isn't a concern.
397 args := []interface{}{webhookID, userID}
398 sets := []string{}
399 add := func(col string, val interface{}) {
400 args = append(args, val)
401 sets = append(sets, fmt.Sprintf("%s = $%d", col, len(args)))
402 }
403 if u.URL != nil {
404 add("url", *u.URL)
405 }
406 if u.Description != nil {
407 add("description", *u.Description)
408 }
409 if u.Events != nil {
410 add("events", *u.Events)
411 }
412 if u.Filters != nil {
413 filtersJSON, err := json.Marshal(*u.Filters)
414 if err != nil {
415 return nil, fmt.Errorf("marshal filters: %w", err)
416 }
417 add("filters", filtersJSON)
418 }
419 if u.Enabled != nil {
420 add("enabled", *u.Enabled)
421 // Re-enabling clears auto_disabled_at so a subsequent fail
422 // burst can re-trip it cleanly.
423 if *u.Enabled {
424 args = append(args, nil)
425 sets = append(sets, fmt.Sprintf("auto_disabled_at = $%d", len(args)))
426 }
427 }
428
429 if len(sets) == 0 {
430 // No-op PATCH. Return the current row.
431 return s.GetWebhookByID(ctx, webhookID, userID)

Implementers 1

Storeinternal/identity/store.go

Calls 4

GetWebhookByIDMethod · 0.95
joinCommaFunction · 0.85
ScanMethod · 0.80
QueryRowMethod · 0.80