eleven / ocho Public

Clone
git clone https://amadan.net/eleven/ocho

Plain git — no account needed to clone.

Download

Download this file

1package main
2
3import (
4 "fmt"
5 "net/http"
6 "strings"
7 "testing"
8)
9
10// A push subscription may only be removed by its own token — not by anyone who
11// happens to know the endpoint.
12func TestUnsubscribePushIsOwnerScoped(t *testing.T) {
13 ts, srv := newTestServer(t)
14 aTok := mintDeviceToken(t, srv.db, "A")
15 bTok := mintDeviceToken(t, srv.db, "B")
16 if err := srv.db.addSubscription(PushSub{Endpoint: "https://e/1", Token: aTok, P256dh: "p", Auth: "a"}); err != nil {
17 t.Fatalf("addSubscription: %v", err)
18 }
19
20 post := func(body string) int {
21 resp, err := http.Post(ts.URL+"/api/push/unsubscribe", "application/json", strings.NewReader(body))
22 if err != nil {
23 t.Fatal(err)
24 }
25 resp.Body.Close()
26 return resp.StatusCode
27 }
28 subCount := func() int { subs, _ := srv.db.listSubscriptions(); return len(subs) }
29
30 // No token → refused, nothing deleted.
31 if got := post(`{"endpoint":"https://e/1"}`); got != http.StatusForbidden {
32 t.Fatalf("no token: want 403, got %d", got)
33 }
34 if subCount() != 1 {
35 t.Fatalf("no-token request deleted a sub")
36 }
37 // Valid but non-owning token → accepted, but the other user's sub survives.
38 if got := post(fmt.Sprintf(`{"token":%q,"endpoint":"https://e/1"}`, bTok)); got != http.StatusOK {
39 t.Fatalf("non-owner: want 200, got %d", got)
40 }
41 if subCount() != 1 {
42 t.Fatalf("non-owner deleted someone else's subscription")
43 }
44 // Owner token → removed.
45 if got := post(fmt.Sprintf(`{"token":%q,"endpoint":"https://e/1"}`, aTok)); got != http.StatusOK {
46 t.Fatalf("owner: want 200, got %d", got)
47 }
48 if subCount() != 0 {
49 t.Fatalf("owner unsubscribe left the sub")
50 }
51}
52
53// A second grant must not overwrite a member's existing wrapped instance key.
54func TestGrantInstanceKeyNeverOverwrites(t *testing.T) {
55 db := newTestDB(t)
56 if err := db.grantInstanceKey("u1", "GOOD"); err != nil {
57 t.Fatalf("grant: %v", err)
58 }
59 if err := db.grantInstanceKey("u1", "JUNK"); err != nil {
60 t.Fatalf("re-grant: %v", err)
61 }
62 got, _, _ := db.instanceKeyFor("u1")
63 if got != "GOOD" {
64 t.Fatalf("instance key overwritten: got %q, want GOOD", got)
65 }
66}
67
68// Re-adding an existing member must not clobber their wrapped thread key.
69func TestAddThreadMemberNeverClobbers(t *testing.T) {
70 db := newTestDB(t)
71 if err := db.addThreadMember("t1", "m1", "GOOD"); err != nil {
72 t.Fatalf("add: %v", err)
73 }
74 if err := db.addThreadMember("t1", "m1", "JUNK"); err != nil {
75 t.Fatalf("re-add: %v", err)
76 }
77 var wrapped string
78 if err := db.sql.QueryRow(
79 "SELECT wrapped FROM thread_keys WHERE thread_id = ? AND user_id = ?", "t1", "m1",
80 ).Scan(&wrapped); err != nil {
81 t.Fatalf("read thread key: %v", err)
82 }
83 if wrapped != "GOOD" {
84 t.Fatalf("thread key clobbered: got %q, want GOOD", wrapped)
85 }
86}
87