tenseleyflow/shithub / 5713625

Browse files

orgs tests: bad-signature webhook is 400 and writes no receipt

Authored by mfwolffe <wolffemf@dukes.jmu.edu>
SHA
57136252f18be54129996bd8201604ed33d9b7c8
Parents
74a52ec
Tree
cb4c387

1 changed file

StatusFile+-
M internal/web/handlers/orgs/billing_webhook_guard_test.go 34 0
internal/web/handlers/orgs/billing_webhook_guard_test.gomodified
@@ -5,6 +5,7 @@ package orgs_test
5
 import (
5
 import (
6
 	"context"
6
 	"context"
7
 	"encoding/json"
7
 	"encoding/json"
8
+	"errors"
8
 	"net/http"
9
 	"net/http"
9
 	"strconv"
10
 	"strconv"
10
 	"strings"
11
 	"strings"
@@ -263,6 +264,39 @@ func TestBillingWebhookSubscriptionUpdatedForUnknownSubReturnsError(t *testing.T
263
 	}
264
 	}
264
 }
265
 }
265
 
266
 
267
+// TestBillingWebhookRejectsBadSignature locks Agent A's untested
268
+// claim: a tampered/bad signature returns 400 and writes no row.
269
+// The real stripe-go signature check is exercised in production;
270
+// this test wires a fake VerifyWebhook that errors and asserts the
271
+// handler short-circuits cleanly.
272
+func TestBillingWebhookRejectsBadSignature(t *testing.T) {
273
+	t.Parallel()
274
+	ctx := context.Background()
275
+	pool := dbtest.NewTestDB(t)
276
+	ownerID := insertOrgAvatarUser(t, pool, "owner")
277
+	_ = insertOrgAvatarOrg(t, pool, ownerID, "acme")
278
+
279
+	fake := &fakeStripeRemote{
280
+		verifyWebhookFn: func(_ []byte, _ string) (stripeapi.Event, error) {
281
+			return stripeapi.Event{}, errors.New("bad signature")
282
+		},
283
+	}
284
+	mux := newOrgBillingMux(t, pool, ownerID, fake)
285
+	resp := postBillingWebhook(t, mux, "evt_will_be_rejected")
286
+	if resp.Code != http.StatusBadRequest {
287
+		t.Fatalf("bad-sig status=%d body=%s want 400", resp.Code, resp.Body.String())
288
+	}
289
+	// No receipt row should exist — signature failure short-circuits
290
+	// before RecordWebhookEvent runs.
291
+	var count int
292
+	if err := pool.QueryRow(ctx, `SELECT count(*) FROM billing_webhook_events`).Scan(&count); err != nil {
293
+		t.Fatalf("count receipts: %v", err)
294
+	}
295
+	if count != 0 {
296
+		t.Fatalf("bad-sig should not insert receipt row, got count=%d", count)
297
+	}
298
+}
299
+
266
 // TestBillingWebhookDropsStaleEvent locks PRO08 D4: a Stripe event
300
 // TestBillingWebhookDropsStaleEvent locks PRO08 D4: a Stripe event
267
 // with `created` older than the persisted last_event_at must NOT
301
 // with `created` older than the persisted last_event_at must NOT
268
 // regress state. Pre-PRO08 a reverse-ordered retry could re-activate
302
 // regress state. Pre-PRO08 a reverse-ordered retry could re-activate