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

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}