oficina / meet Public

Clone
git clone https://amadan.net/oficina/meet

Plain git — no account needed to clone.

Download

Download this file

1package calls
2
3import (
4 "bytes"
5 "context"
6 "errors"
7 "testing"
8)
9
10func TestShareReusesSealedInvitationAndPreservesLegacyLinks(t *testing.T) {
11 s, _ := testStore(t)
12 ctx := context.Background()
13 m, original, err := s.createMeeting(ctx, "Share test", nil, "person:1")
14 if err != nil {
15 t.Fatal(err)
16 }
17 shared, err := s.shareLink(ctx, m.ID, "person:2")
18 if err != nil || shared != original {
19 t.Fatalf("share original: %v", err)
20 }
21 link, _, _, err := s.liveLink(ctx, shared)
22 if err != nil || len(link.TokenSealed) == 0 || bytes.Contains(link.TokenSealed, []byte(shared)) {
23 t.Fatal("invitation was not sealed")
24 }
25 // Model a migrated meeting: its original token cannot be recovered.
26 if err := s.g.Model(&MeetingLink{}).Where("id = ?", link.ID).Update("token_sealed", nil).Error; err != nil {
27 t.Fatal(err)
28 }
29 results := make(chan string, 8)
30 failures := make(chan error, 8)
31 for i := 0; i < 8; i++ {
32 go func() {
33 token, err := s.shareLink(ctx, m.ID, "person:1")
34 results <- token
35 failures <- err
36 }()
37 }
38 replacement := ""
39 for i := 0; i < 8; i++ {
40 token := <-results
41 if err := <-failures; err != nil {
42 t.Fatal(err)
43 }
44 if replacement == "" {
45 replacement = token
46 }
47 if token != replacement || token == original {
48 t.Fatal("concurrent shares did not reuse one new invitation")
49 }
50 }
51 for _, token := range []string{original, replacement} {
52 if _, _, live, err := s.liveLink(ctx, token); err != nil || !live {
53 t.Fatal("sharing invalidated a current invitation")
54 }
55 }
56 var count int64
57 if err := s.g.Model(&MeetingLink{}).Where("meeting_id = ?", m.ID).Count(&count).Error; err != nil || count != 2 {
58 t.Fatalf("links = %d, error %v", count, err)
59 }
60 fresh, err := s.replaceLink(ctx, m.ID, "person:1")
61 if err != nil {
62 t.Fatal(err)
63 }
64 for _, token := range []string{original, replacement} {
65 if _, _, live, _ := s.liveLink(ctx, token); live {
66 t.Fatal("replacement failed to revoke an invitation")
67 }
68 }
69 shared, err = s.shareLink(ctx, m.ID, "person:1")
70 if err != nil || shared != fresh {
71 t.Fatal("share did not use the replacement")
72 }
73 if _, err := s.endMeeting(ctx, m.ID, "person:1"); err != nil {
74 t.Fatal(err)
75 }
76 if _, err := s.shareLink(ctx, m.ID, "person:1"); !errors.Is(err, errMeetingEnded) {
77 t.Fatalf("sharing ended meeting: %v", err)
78 }
79}
80
81func TestShareRefusesCorruptedSealedInvitation(t *testing.T) {
82 s, _ := testStore(t)
83 ctx := context.Background()
84 m, _, err := s.createMeeting(ctx, "Share test", nil, "person:1")
85 if err != nil {
86 t.Fatal(err)
87 }
88 if err := s.g.Model(&MeetingLink{}).Where("meeting_id = ?", m.ID).Update("token_sealed", []byte("broken")).Error; err != nil {
89 t.Fatal(err)
90 }
91 if _, err := s.shareLink(ctx, m.ID, "person:1"); err == nil {
92 t.Fatal("corrupt invitation was silently replaced")
93 }
94}
95