access.gno
4.02 Kb · 154 lines
1package access
2
3import (
4 "chain"
5 "strings"
6
7 ufmt "gno.land/p/nt/ufmt/v0"
8)
9
10var roleAddresses map[string]address
11
12func init() {
13 roleAddresses = make(map[string]address)
14}
15
16// SetRoleAddress sets or updates a role's address.
17// It trims surrounding whitespace from roleName, creates missing roles, and
18// replaces the address for an existing role.
19//
20// Parameters:
21// - cur: current realm context; callers use cross(cur) when crossing into this realm
22// - roleName: role identifier; surrounding whitespace is ignored and an empty name panics
23// - roleAddress: non-empty, valid address to associate with roleName
24//
25// Only callable by the RBAC contract.
26func SetRoleAddress(cur realm, roleName string, roleAddress address) {
27 prev := cur.Previous()
28 assertIsRBAC(prev.Address())
29
30 // capture old value for event
31 oldAddr, _ := roleAddresses[strings.TrimSpace(roleName)]
32
33 if err := setRoleAddress(roleName, roleAddress); err != nil {
34 panic(err)
35 }
36
37 chain.Emit(
38 "SetRoleAddress",
39 "prevAddr", prev.Address().String(),
40 "role", roleName,
41 "prevRoleAddr", oldAddr.String(),
42 "roleAddress", roleAddress.String(),
43 )
44}
45
46// setRoleAddress is the internal implementation of SetRoleAddress.
47// Separated for testability.
48func setRoleAddress(roleName string, roleAddress address) error {
49 roleName = strings.TrimSpace(roleName)
50 if roleName == "" {
51 panic("role name cannot be empty")
52 }
53
54 // Validate address
55 if !roleAddress.IsValid() || roleAddress == address("") {
56 return ufmt.Errorf(errInvalidAddress, roleName, roleAddress)
57 }
58
59 roleAddresses[roleName] = roleAddress
60 return nil
61}
62
63// RemoveRole removes a role from the system after trimming its name.
64//
65// Parameters:
66// - cur: current realm context; callers use cross(cur) when crossing into this realm
67// - roleName: role identifier to trim and remove; an empty or unknown name panics
68//
69// Only callable by the RBAC contract.
70func RemoveRole(cur realm, roleName string) {
71 prev := cur.Previous()
72 assertIsRBAC(prev.Address())
73
74 // Validate role name
75 roleName = strings.TrimSpace(roleName)
76 if roleName == "" {
77 panic("role name cannot be empty")
78 }
79
80 if _, ok := roleAddresses[roleName]; !ok {
81 panic(ufmt.Errorf("role %s does not exist", roleName))
82 }
83
84 delete(roleAddresses, roleName)
85
86 chain.Emit(
87 "RemoveRole",
88 "prevAddr", prev.Address().String(),
89 "role", roleName,
90 )
91}
92
93// IsAuthorized reports whether caller is the address currently mapped to role.
94//
95// Parameters:
96// - role: role name to trim and look up
97// - caller: address to compare with the mapped role address
98//
99// Returns:
100// - authorized: true when role exists and caller matches its address; false when the role is absent or does not match
101func IsAuthorized(role string, caller address) bool {
102 addr, ok := GetAddress(role)
103 if !ok {
104 return false
105 }
106
107 return caller == addr
108}
109
110// GetAddress returns the address mapped to a role and whether that mapping exists.
111//
112// Parameters:
113// - role: role name to trim before lookup
114//
115// Returns:
116// - addr: mapped address, or the zero address when role is not present
117// - exists: true when role has a stored address; false otherwise
118func GetAddress(role string) (address, bool) {
119 role = strings.TrimSpace(role)
120 addr, ok := roleAddresses[role]
121 return addr, ok
122}
123
124// GetRoleAddresses returns an independent map copy of all stored role addresses.
125//
126// Returns:
127// - roleAddresses: map from normalized role names to their configured addresses
128func GetRoleAddresses() map[string]address {
129 addresses := make(map[string]address)
130
131 for role, data := range roleAddresses {
132 addresses[role] = data
133 }
134
135 return addresses
136}
137
138// MustGetAddress returns the address mapped to a role or panics if it is absent.
139// Surrounding whitespace is ignored; an empty or unknown role is considered absent.
140//
141// Parameters:
142// - role: role name to trim and require in the role mapping
143//
144// Returns:
145// - addr: configured address for role
146func MustGetAddress(role string) address {
147 role = strings.TrimSpace(role)
148 addr, ok := GetAddress(role)
149 if !ok {
150 panic(ufmt.Errorf(errRoleNotFound, role))
151 }
152
153 return addr
154}