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

Method CreateWebhook

internal/identity/webhooks.go:104–147  ·  view source on GitHub ↗

CreateWebhook inserts a new row and returns it with the plaintext signing secret populated. The plaintext is only available on this response — subsequent GET/list calls scrub it. Filters validation (charset, count caps, agent ownership) is the handler's job in slice 2; the storage layer only verifi

(ctx context.Context, userID, url, description string, events []string, filters WebhookFilters)

Source from the content-addressed store, hash-verified

102// handler's job in slice 2; the storage layer only verifies the
103// per-user count cap from account_limits.max_webhooks.
104func (s *Store) CreateWebhook(ctx context.Context, userID, url, description string, events []string, filters WebhookFilters) (*Webhook, error) {
105 // Enforce the per-user cap before generating any state. Race
106 // across concurrent creates is bounded by the cap + 1 in the
107 // worst case; an exact race-free check would need SELECT FOR
108 // UPDATE on a sentinel row, which is not worth it for a cap of
109 // 50. The race-window cost is "one user briefly has 51 webhooks"
110 // — acceptable.
111 max, err := s.MaxWebhooksForUser(ctx, userID)
112 if err != nil {
113 return nil, err
114 }
115 count, err := s.CountWebhooksByUser(ctx, userID)
116 if err != nil {
117 return nil, err
118 }
119 if count >= max {
120 return nil, ErrWebhookCapReached
121 }
122
123 filtersJSON, err := json.Marshal(filters)
124 if err != nil {
125 return nil, fmt.Errorf("marshal filters: %w", err)
126 }
127
128 w := &Webhook{
129 ID: generateWebhookID(),
130 UserID: userID,
131 URL: url,
132 Description: description,
133 Events: events,
134 Filters: filters,
135 SigningSecret: generateWebhookSecret(),
136 Enabled: true,
137 CreatedAt: time.Now(),
138 }
139 if _, err := s.pool.Exec(ctx,
140 `INSERT INTO webhooks (id, user_id, url, description, events, filters, signing_secret, enabled, created_at)
141 VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)`,
142 w.ID, w.UserID, w.URL, w.Description, w.Events, filtersJSON, w.SigningSecret, w.Enabled, w.CreatedAt,
143 ); err != nil {
144 return nil, fmt.Errorf("insert webhook: %w", err)
145 }
146 return w, nil
147}
148
149// GetWebhookByID returns the webhook iff it's owned by userID. Cross-
150// user reads (or missing rows) return ErrWebhookNotFound — same

Implementers 1

Storeinternal/identity/store.go

Calls 5

MaxWebhooksForUserMethod · 0.95
CountWebhooksByUserMethod · 0.95
generateWebhookIDFunction · 0.85
generateWebhookSecretFunction · 0.85
ExecMethod · 0.65