access_control_test.gno
6.59 Kb · 267 lines
1package accesscontrol
2
3import (
4 "testing"
5
6 "gno.land/p/nt/testutils/v0"
7 "gno.land/p/nt/uassert/v0"
8)
9
10var (
11 testAdmin = testutils.TestAddress("acAdmin")
12 testOperator = testutils.TestAddress("acOperator")
13 testUser = testutils.TestAddress("acUser")
14 testOther = testutils.TestAddress("acOther")
15)
16
17func testIsAdmin(addr address) bool {
18 return addr == testAdmin
19}
20
21func testIsOperator(addr address) bool {
22 return addr == testOperator
23}
24
25func probeMustGetAdminCaller(cur realm, isAdmin AuthCheck) address {
26 return MustGetAdminCaller(0, cur, isAdmin)
27}
28
29func probeAssertIsAdmin(cur realm, isAdmin AuthCheck) address {
30 AssertIsAdmin(0, cur, isAdmin)
31 return ""
32}
33
34func probeMustGetUserCaller(cur realm) address {
35 return MustGetUserCaller(0, cur)
36}
37
38func probeMustGetAdminOrOperatorCaller(cur realm, isAdmin AuthCheck, isOperator AuthCheck) address {
39 return MustGetAdminOrOperatorCaller(0, cur, isAdmin, isOperator)
40}
41
42func probeAssertIsAdminOrOperator(cur realm, isAdmin AuthCheck, isOperator AuthCheck) address {
43 AssertIsAdminOrOperator(0, cur, isAdmin, isOperator)
44 return ""
45}
46
47func TestAccessControl(cur realm, t *testing.T) {
48 tests := []struct {
49 label string
50 setup func(realm) realm
51 call func(realm, realm) address
52 panicKind string
53 panicMsg string
54 wantCaller address
55 }{
56 {
57 label: "current realm",
58 setup: func(cur realm) realm {
59 return cur
60 },
61 call: func(cur realm, rlm realm) address {
62 AssertCurrentRealm(0, rlm)
63 return ""
64 },
65 },
66 {
67 label: "stale realm",
68 setup: func(cur realm) realm {
69 testing.SetRealm(testing.NewCodeRealm("gno.land/r/akkadia/beta/accesscontrol_stale_probe"))
70 return cur.Previous()
71 },
72 call: func(cur realm, rlm realm) address {
73 AssertCurrentRealm(0, rlm)
74 return ""
75 },
76 panicKind: "panic",
77 panicMsg: "spoofed realm",
78 },
79 {
80 label: "admin caller",
81 setup: func(cur realm) realm {
82 testing.SetRealm(testing.NewUserRealm(testAdmin))
83 return nil
84 },
85 call: func(cur realm, rlm realm) address {
86 return probeMustGetAdminCaller(cross(cur), testIsAdmin)
87 },
88 wantCaller: testAdmin,
89 },
90 {
91 label: "assert admin caller",
92 setup: func(cur realm) realm {
93 testing.SetRealm(testing.NewUserRealm(testAdmin))
94 return nil
95 },
96 call: func(cur realm, rlm realm) address {
97 return probeAssertIsAdmin(cross(cur), testIsAdmin)
98 },
99 },
100 {
101 label: "unauthorized admin caller",
102 setup: func(cur realm) realm {
103 testing.SetRealm(testing.NewUserRealm(testOther))
104 return nil
105 },
106 call: func(cur realm, rlm realm) address {
107 return probeMustGetAdminCaller(cross(cur), testIsAdmin)
108 },
109 panicKind: "abort",
110 panicMsg: "admin access required",
111 },
112 {
113 label: "direct user caller",
114 setup: func(cur realm) realm {
115 testing.SetRealm(testing.NewUserRealm(testUser))
116 return nil
117 },
118 call: func(cur realm, rlm realm) address {
119 return probeMustGetUserCaller(cross(cur))
120 },
121 wantCaller: testUser,
122 },
123 {
124 label: "code realm rejected as user caller",
125 setup: func(cur realm) realm {
126 testing.SetRealm(testing.NewCodeRealm("gno.land/r/akkadia/beta/accesscontrol_relay"))
127 return nil
128 },
129 call: func(cur realm, rlm realm) address {
130 return probeMustGetUserCaller(cross(cur))
131 },
132 panicKind: "abort",
133 panicMsg: "contract calls not allowed: function must be called directly by user",
134 },
135 {
136 label: "admin caller for admin or operator",
137 setup: func(cur realm) realm {
138 testing.SetRealm(testing.NewUserRealm(testAdmin))
139 return nil
140 },
141 call: func(cur realm, rlm realm) address {
142 return probeMustGetAdminOrOperatorCaller(cross(cur), testIsAdmin, testIsOperator)
143 },
144 wantCaller: testAdmin,
145 },
146 {
147 label: "operator caller for admin or operator",
148 setup: func(cur realm) realm {
149 testing.SetRealm(testing.NewUserRealm(testOperator))
150 return nil
151 },
152 call: func(cur realm, rlm realm) address {
153 return probeMustGetAdminOrOperatorCaller(cross(cur), testIsAdmin, testIsOperator)
154 },
155 wantCaller: testOperator,
156 },
157 {
158 label: "assert admin or operator",
159 setup: func(cur realm) realm {
160 testing.SetRealm(testing.NewUserRealm(testOperator))
161 return nil
162 },
163 call: func(cur realm, rlm realm) address {
164 return probeAssertIsAdminOrOperator(cross(cur), testIsAdmin, testIsOperator)
165 },
166 },
167 {
168 label: "unauthorized admin or operator caller",
169 setup: func(cur realm) realm {
170 testing.SetRealm(testing.NewUserRealm(testOther))
171 return nil
172 },
173 call: func(cur realm, rlm realm) address {
174 return probeMustGetAdminOrOperatorCaller(cross(cur), testIsAdmin, testIsOperator)
175 },
176 panicKind: "abort",
177 panicMsg: "admin or operator access required",
178 },
179 {
180 label: "admin origin",
181 setup: func(cur realm) realm {
182 testing.SetOriginCaller(testAdmin)
183 return nil
184 },
185 call: func(cur realm, rlm realm) address {
186 return MustGetAdminOrigin(testIsAdmin)
187 },
188 wantCaller: testAdmin,
189 },
190 {
191 label: "assert admin origin",
192 setup: func(cur realm) realm {
193 testing.SetOriginCaller(testAdmin)
194 return nil
195 },
196 call: func(cur realm, rlm realm) address {
197 AssertIsAdminOrigin(testIsAdmin)
198 return ""
199 },
200 },
201 {
202 label: "unauthorized admin origin",
203 setup: func(cur realm) realm {
204 testing.SetOriginCaller(testOther)
205 return nil
206 },
207 call: func(cur realm, rlm realm) address {
208 return MustGetAdminOrigin(testIsAdmin)
209 },
210 panicKind: "panic",
211 panicMsg: "admin access required",
212 },
213 {
214 label: "nil admin check",
215 setup: func(cur realm) realm {
216 return cur
217 },
218 call: func(cur realm, rlm realm) address {
219 return MustGetAdminCaller(0, rlm, nil)
220 },
221 panicKind: "panic",
222 panicMsg: "admin auth check is nil",
223 },
224 {
225 label: "nil origin admin check",
226 setup: func(cur realm) realm {
227 return nil
228 },
229 call: func(cur realm, rlm realm) address {
230 return MustGetAdminOrigin(nil)
231 },
232 panicKind: "panic",
233 panicMsg: "admin auth check is nil",
234 },
235 {
236 label: "nil operator check",
237 setup: func(cur realm) realm {
238 return cur
239 },
240 call: func(cur realm, rlm realm) address {
241 return MustGetAdminOrOperatorCaller(0, rlm, testIsAdmin, nil)
242 },
243 panicKind: "panic",
244 panicMsg: "operator auth check is nil",
245 },
246 }
247
248 for _, tt := range tests {
249 rlm := tt.setup(cur)
250 call := func() {
251 got := tt.call(cur, rlm)
252 if tt.wantCaller != "" {
253 uassert.Equal(t, tt.wantCaller.String(), got.String())
254 }
255 }
256
257 if tt.panicKind == "panic" {
258 uassert.PanicsWithMessage(t, cur, tt.panicMsg, call)
259 continue
260 }
261 if tt.panicKind == "abort" {
262 uassert.AbortsWithMessage(t, cur, tt.panicMsg, call)
263 continue
264 }
265 call()
266 }
267}