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.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}