Search Apps Documentation Source Content File Folder Download Copy Actions Download

access_control.gno

2.12 Kb · 78 lines
 1package accesscontrol
 2
 3import "chain/runtime/unsafe"
 4
 5// AuthCheck must be owned by the calling realm/package.
 6// Do not pass callbacks received from untrusted callers.
 7type AuthCheck func(address) bool
 8
 9func AssertCurrentRealm(_ int, rlm realm) {
10	if !rlm.IsCurrent() {
11		panic("spoofed realm")
12	}
13}
14
15func AssertIsAdmin(_ int, rlm realm, isAdmin AuthCheck) {
16	MustGetAdminCaller(0, rlm, isAdmin)
17}
18
19func MustGetAdminCaller(_ int, rlm realm, isAdmin AuthCheck) address {
20	assertAuthCheck(isAdmin, "admin auth check is nil")
21	AssertCurrentRealm(0, rlm)
22
23	caller := rlm.Previous().Address()
24	if !isAdmin(caller) {
25		panic("admin access required")
26	}
27	return caller
28}
29
30func MustGetUserCaller(_ int, rlm realm) address {
31	AssertCurrentRealm(0, rlm)
32
33	prev := rlm.Previous()
34	if !prev.IsUserCall() {
35		panic("contract calls not allowed: function must be called directly by user")
36	}
37	return prev.Address()
38}
39
40// AssertIsAdminOrigin checks the transaction signer, not the direct caller realm.
41// Use it only for explicit delegation APIs that intentionally allow code-realm relays.
42func AssertIsAdminOrigin(isAdmin AuthCheck) {
43	MustGetAdminOrigin(isAdmin)
44}
45
46// MustGetAdminOrigin checks the transaction signer, not the direct caller realm.
47// Use it only for explicit delegation APIs that intentionally allow code-realm relays.
48func MustGetAdminOrigin(isAdmin AuthCheck) address {
49	assertAuthCheck(isAdmin, "admin auth check is nil")
50
51	caller := unsafe.OriginCaller()
52	if !isAdmin(caller) {
53		panic("admin access required")
54	}
55	return caller
56}
57
58func AssertIsAdminOrOperator(_ int, rlm realm, isAdmin AuthCheck, isOperator AuthCheck) {
59	MustGetAdminOrOperatorCaller(0, rlm, isAdmin, isOperator)
60}
61
62func MustGetAdminOrOperatorCaller(_ int, rlm realm, isAdmin AuthCheck, isOperator AuthCheck) address {
63	assertAuthCheck(isAdmin, "admin auth check is nil")
64	assertAuthCheck(isOperator, "operator auth check is nil")
65	AssertCurrentRealm(0, rlm)
66
67	caller := rlm.Previous().Address()
68	if !isAdmin(caller) && !isOperator(caller) {
69		panic("admin or operator access required")
70	}
71	return caller
72}
73
74func assertAuthCheck(check AuthCheck, msg string) {
75	if check == nil {
76		panic(msg)
77	}
78}