tinyrelayfile
tinyrelay/internal/daemon/nip96_test.go/

internal/daemon/nip96_test.go raw
1package daemon
2
3import (
4 "bytes"
5 "context"
6 "encoding/json"
7 "io"
8 "mime/multipart"
9 "net/http"
10 "net/http/httptest"
11 "net/textproto"
12 "strings"
13 "testing"
14
15 "github.com/FelineStateMachine/tinyrelay/internal/event"
16)
17
18func TestNIP96MultipartUploadGetAndDeleteOnNonDefaultTenant(t *testing.T) {
19 ctx := context.Background()
20 secret := strings.Repeat("0", 63) + "1"
21 owner, err := event.PublicKey(secret)
22 if err != nil {
23 t.Fatal(err)
24 }
25 app, err := New(ctx, Config{DataDir: t.TempDir(), DefaultTenant: "main"})
26 if err != nil {
27 t.Fatal(err)
28 }
29 defer app.Close(ctx)
30 meta, err := app.Create(ctx, CreateOptions{Name: "media", Owner: owner, Template: "default"})
31 if err != nil {
32 t.Fatal(err)
33 }
34
35 var body bytes.Buffer
36 form := multipart.NewWriter(&body)
37 part, err := form.CreatePart(textproto.MIMEHeader{
38 "Content-Disposition": {`form-data; name="file"; filename="photo.webp"`},
39 "Content-Type": {"image/webp"},
40 })
41 if err != nil {
42 t.Fatal(err)
43 }
44 if _, err := io.WriteString(part, "webp payload"); err != nil {
45 t.Fatal(err)
46 }
47 if err := form.Close(); err != nil {
48 t.Fatal(err)
49 }
50 raw := append([]byte(nil), body.Bytes()...)
51 url := "http://relay.test/r/media/nip96"
52 req := httptest.NewRequest(http.MethodPost, url, bytes.NewReader(raw))
53 req.Header.Set("Content-Type", form.FormDataContentType())
54 signRequest(t, req, string(raw))
55 res := httptest.NewRecorder()
56 app.ServeHTTP(res, req)
57 if res.Code != http.StatusCreated {
58 t.Fatalf("upload status=%d body=%s", res.Code, res.Body.String())
59 }
60 var descriptor struct {
61 URL string `json:"url"`
62 }
63 if err := json.Unmarshal(res.Body.Bytes(), &descriptor); err != nil {
64 t.Fatal(err)
65 }
66 if !strings.Contains(descriptor.URL, "/r/media/") || !strings.HasSuffix(descriptor.URL, ".webp") {
67 t.Fatalf("descriptor URL=%q", descriptor.URL)
68 }
69
70 sha := strings.TrimSuffix(strings.TrimPrefix(descriptor.URL, "http://relay.test/r/media/"), ".webp")
71 getURL := "http://relay.test/r/media/nip96/" + sha + ".webp"
72 get := httptest.NewRequest(http.MethodGet, getURL, nil)
73 signRequest(t, get, "")
74 getRes := httptest.NewRecorder()
75 app.ServeHTTP(getRes, get)
76 if getRes.Code != http.StatusOK || getRes.Body.String() != "webp payload" {
77 t.Fatalf("get url=%s status=%d body=%q", getURL, getRes.Code, getRes.Body.String())
78 }
79
80 del := httptest.NewRequest(http.MethodDelete, getURL, nil)
81 signRequest(t, del, "")
82 delRes := httptest.NewRecorder()
83 app.ServeHTTP(delRes, del)
84 if delRes.Code != http.StatusNoContent {
85 t.Fatalf("delete status=%d body=%s", delRes.Code, delRes.Body.String())
86 }
87 tenant := app.tenants[meta.ID]
88 updated := tenant.Policy()
89 updated.Features.Files = false
90 if err := tenant.applyPolicy(ctx, updated); err != nil {
91 t.Fatal(err)
92 }
93 disabled := httptest.NewRequest(http.MethodGet, getURL, nil)
94 disabledRes := httptest.NewRecorder()
95 app.ServeHTTP(disabledRes, disabled)
96 if disabledRes.Code != http.StatusNotFound {
97 t.Fatalf("disabled files status=%d", disabledRes.Code)
98 }
99
100 bad := httptest.NewRequest(http.MethodPost, url, bytes.NewReader(raw))
101 bad.Header.Set("Content-Type", form.FormDataContentType())
102 signRequest(t, bad, "tampered")
103 badRes := httptest.NewRecorder()
104 app.ServeHTTP(badRes, bad)
105 if badRes.Code == http.StatusCreated || badRes.Code == http.StatusOK {
106 t.Fatalf("tampered payload accepted: %d %s", badRes.Code, badRes.Body.String())
107 }
108}

About

ownerc01503e8035f
visibilitypublic
headd730679639bf

Maintainers

  • c01503e8035f owner
  • ba1b5beed5b5 agent hermes

Clone

  • https://012.run/npub1cq2s86qrtadf36eqq3epm38wmhdynrrcwxf84eldk3f94dkv7ttsrulrz5/tinyrelay.git

Refs