clone

a self-hosted multitenant nostr relay with sites, file storage, git hosting, and inbox and outbox delivery

main
tinyrelay / internal / daemon / room_attachments_test.go
room_attachments_test.go 3.9K
1package daemon23import (4 "context"5 "encoding/json"6 "strings"7 "testing"8 "time"910 "github.com/FelineStateMachine/tinyrelay/internal/blob"11 "github.com/FelineStateMachine/tinyrelay/internal/event"12)1314func TestRoomAttachmentAccessFollowsMembership(t *testing.T) {15 h := newRoomHarness(t)16 ctx := context.Background()17 h.must("alice", event.KIND_CREATE_GROUP, [][]string{{"h", "secret"}, {"closed"}}, "")18 entry, err := h.tenant.blobs.Put(ctx, blob.PutOptions{Reader: strings.NewReader("room secret"), Type: "text/plain", Uploader: h.keys["alice"]})19 if err != nil {20 t.Fatal(err)21 }22 room, err := h.tenant.community.Room(ctx, "secret")23 if err != nil {24 t.Fatal(err)25 }26 if _, err := h.tenant.store.DB().ExecContext(ctx, "INSERT INTO room_attachments(room_id,room_event_id,sha256,filename,created_at) VALUES(?,?,?,?,unixepoch())", "secret", room.EventID, entry.SHA256, "secret.txt"); err != nil {27 t.Fatal(err)28 }29 if err := h.tenant.roomAttachmentAccess(ctx, h.keys["stranger"], entry.SHA256); err == nil {30 t.Fatal("nonmember can read room attachment")31 }32 if err := h.tenant.roomAttachmentAccess(ctx, h.keys["owner"], entry.SHA256); err != nil {33 t.Fatalf("member cannot read room attachment: %v", err)34 }35}3637func TestGenericBlobRemainsUnscoped(t *testing.T) {38 h := newRoomHarness(t)39 entry, err := h.tenant.blobs.Put(context.Background(), blob.PutOptions{Reader: strings.NewReader("public"), Type: "text/plain", Uploader: h.keys["alice"]})40 if err != nil {41 t.Fatal(err)42 }43 if err := h.tenant.roomAttachmentAccess(context.Background(), "", entry.SHA256); err != nil {44 t.Fatalf("generic blob unexpectedly scoped: %v", err)45 }46}4748func TestRoomAttachmentAgentGrantAndStorageLimits(t *testing.T) {49 _, tenant := testTenant(t)50 ctx := context.Background()51 owner := tenant.Policy().Owner52 agent, _ := event.PublicKey(testAgentSecret)53 now := time.Now().Unix()54 if err := publishAs(t, tenant, agentGrantEvent(t, agent, now, now+3600, []string{"k", "9"}, []string{"h", "main"})); err != nil {55 t.Fatal(err)56 }57 input := roomAttachmentInput{Body: []byte("generated attachment"), Type: "text/plain"}58 if _, err := tenant.storeRoomAttachment(ctx, agent, "main", input); err != nil {59 t.Fatalf("active agent upload: %v", err)60 }61 if _, err := tenant.Execute(ctx, owner, "pauseagent", []json.RawMessage{rawJSON(agent)}); err != nil {62 t.Fatal(err)63 }64 if _, err := tenant.storeRoomAttachment(ctx, agent, "main", input); err == nil {65 t.Fatal("paused agent uploaded")66 }67 if _, err := tenant.Execute(ctx, owner, "revokeagent", []json.RawMessage{rawJSON(agent)}); err != nil {68 t.Fatal(err)69 }70 if _, err := tenant.storeRoomAttachment(ctx, agent, "main", input); err == nil {71 t.Fatal("revoked agent uploaded")72 }73 if _, err := tenant.Execute(ctx, owner, "setpolicy", []json.RawMessage{rawJSON(map[string]any{"fileLimits": map[string]any{"maxFileBytes": 4}})}); err != nil {74 t.Fatal(err)75 }76 if _, err := tenant.storeRoomAttachment(ctx, owner, "main", input); err == nil {77 t.Fatal("room upload bypassed file limit")78 }79}8081func TestRoomAttachmentCannotPrivatizeExistingUnscopedBlob(t *testing.T) {82 h := newRoomHarness(t)83 entry, err := h.tenant.blobs.Put(h.ctx, blob.PutOptions{Reader: strings.NewReader("shared bytes"), Type: "text/plain", Uploader: h.keys["alice"]})84 if err != nil {85 t.Fatal(err)86 }87 if _, err := h.tenant.storeRoomAttachment(h.ctx, h.keys["bob"], "main", roomAttachmentInput{Body: []byte("shared bytes"), Type: "text/plain"}); err == nil || !strings.HasPrefix(err.Error(), "conflict:") {88 t.Fatalf("existing public blob should conflict: %v", err)89 }90 scopes, err := h.tenant.roomAttachmentRooms(h.ctx, entry.SHA256)91 if err != nil || len(scopes) != 0 {92 t.Fatalf("conflicted upload changed visibility: %v %v", scopes, err)93 }94 var claims int95 if err := h.tenant.store.DB().QueryRowContext(h.ctx, "SELECT COUNT(*) FROM blob_claims WHERE sha256=? AND uploader=?", entry.SHA256, h.keys["bob"]).Scan(&claims); err != nil || claims != 0 {96 t.Fatalf("conflicted upload left a claim: %d %v", claims, err)97 }98}