Repository navigation
Expand file tree
/
Copy pathapprovals_test.go
More file actions
164 lines (153 loc) · 4.84 KB
/
Copy pathapprovals_test.go
File metadata and controls
164 lines (153 loc) · 4.84 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
package main
import (
"context"
"net/http"
"regexp"
"runtime"
"testing"
"time"
"github.com/Agent-Field/codeaf/internal/chatlist"
"github.com/Agent-Field/codeaf/internal/devname"
"github.com/Agent-Field/codeaf/internal/directory"
"github.com/Agent-Field/codeaf/internal/identity"
"github.com/Agent-Field/codeaf/internal/pair"
"github.com/Agent-Field/codeaf/internal/pairbox"
"github.com/Agent-Field/codeaf/internal/tui3"
)
// doorAt is the production Approvals door for one home of the rig.
func (r *pairRig) approvalsAt(home string) *approvalsDoor {
d := newApprovalsDoor(home)
d.mailbox = func(string) (pair.Mailbox, error) {
return pair.Mailbox{Box: pairbox.NewHTTP(r.url, &http.Client{Timeout: time.Minute}), URL: r.url, Host: "relay.test"}, nil
}
d.approver = linkApprover(home)
return d
}
// enrol writes the first computer's own record, as its first sync does.
func (r *pairRig) enrol(t *testing.T, door *approvalsDoor, name string) {
t.Helper()
if _, err := devname.Set(door.dir, name); err != nil {
t.Fatal(err)
}
client, id, self, err := door.home()
if err != nil {
t.Fatal(err)
}
sealed, err := directory.SealName(directory.MetadataKey(id.CellKey()), name)
if err != nil {
t.Fatal(err)
}
dev := directory.Device{V: 1, Name: sealed, AddedBy: id.ID(), Platform: "linux"}
if err := client.PutDevice(context.Background(), self, dev); err != nil {
t.Fatal(err)
}
}
// A link pasted on device A is read, approved through the door, and B joins;
// then the list names both, A is Self, and Revoke stops B.
func TestApprovalsDoorApprovesListsAndRevokes(t *testing.T) {
rig := newPairRig(t)
if _, err := devname.Set(rig.homeB, "laptop"); err != nil {
t.Fatal(err)
}
screen, done := rig.asking(t)
link := screen.waitFor(t, regexp.QuoteMeta(rig.url)+`/p/\S+#\S+`)[0]
door := rig.approvalsAt(rig.homeA)
ctx := context.Background()
rig.enrol(t, door, "this computer")
p, err := door.Pending(ctx, link)
if err != nil {
t.Fatal(err)
}
if p.Name != "laptop" || p.Platform != runtime.GOOS || len(p.Check) != 4 || p.Device == "" {
t.Fatalf("pending = %+v", p)
}
if err := door.Approve(ctx, p); err != nil {
t.Fatal(err)
}
if err := <-done; err != nil {
t.Fatal(err)
}
if first, _ := identity.Load(rig.homeA); first.ID() == "" {
t.Fatal("no identity")
}
rows, err := door.Devices(ctx)
if err != nil || len(rows) != 2 {
t.Fatalf("devices = %+v, %v", rows, err)
}
var self, joined *tui3.DeviceRow
for i := range rows {
if rows[i].Self {
self = &rows[i]
} else {
joined = &rows[i]
}
}
if self == nil || joined == nil || joined.ID != p.Device || joined.Name != "laptop" || self.Name != "this computer" {
t.Fatalf("rows = %+v, want one self and the joined %s", rows, p.Device)
}
if err := door.Revoke(ctx, p.Device); err != nil {
t.Fatal(err)
}
rows, _ = door.Devices(ctx)
for _, row := range rows {
if row.ID == p.Device && !row.Revoked {
t.Fatalf("revoked device still listed in: %+v", row)
}
}
}
// Deny turns the asker away, and a decided request cannot be answered again.
func TestApprovalsDoorDeny(t *testing.T) {
rig := newPairRig(t)
screen, done := rig.asking(t)
link := screen.waitFor(t, regexp.QuoteMeta(rig.url)+`/p/\S+#\S+`)[0]
door := rig.approvalsAt(rig.homeA)
p, err := door.Pending(context.Background(), link)
if err != nil {
t.Fatal(err)
}
if err := door.Deny(context.Background(), p); err != nil {
t.Fatal(err)
}
if err := <-done; err == nil {
t.Fatal("the new device was let in after a deny")
}
if err := door.Approve(context.Background(), p); err == nil {
t.Fatal("answered twice")
}
}
func TestApprovalsDoorRefusesAWrongLink(t *testing.T) {
rig := newPairRig(t)
if _, err := rig.approvalsAt(rig.homeA).Pending(context.Background(), "nope"); err == nil {
t.Fatal("a bad link was read")
}
}
// A computer that another of the person's computers stopped is told so, in the
// one sentence every sync surface uses, by the screens that list devices.
func TestApprovalsDoorTellsAStoppedComputerItWasStopped(t *testing.T) {
rig := newPairRig(t)
screen, done := rig.asking(t)
link := screen.waitFor(t, regexp.QuoteMeta(rig.url)+`/p/\S+#\S+`)[0]
door := rig.approvalsAt(rig.homeA)
ctx := context.Background()
rig.enrol(t, door, "this computer")
p, err := door.Pending(ctx, link)
if err != nil {
t.Fatal(err)
}
if err := door.Approve(ctx, p); err != nil {
t.Fatal(err)
}
if err := <-done; err != nil {
t.Fatal(err)
}
if err := door.Revoke(ctx, p.Device); err != nil {
t.Fatal(err)
}
stopped := rig.approvalsAt(rig.homeB)
if _, err := stopped.Devices(ctx); err == nil || err.Error() != chatlist.RemovedChat {
t.Fatalf("the stopped computer's device list said %v, want %q", err, chatlist.RemovedChat)
}
if err := stopped.Revoke(ctx, p.Device); err == nil || err.Error() != chatlist.RemovedChat {
t.Fatalf("the stopped computer's revoke said %v, want %q", err, chatlist.RemovedChat)
}
}