Search Apps Documentation Source Content File Folder Download Copy Actions Download State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

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}