Search Apps Documentation Source Content File Folder Download Copy Actions Download

access.gno

3.10 Kb ยท 136 lines
  1package access
  2
  3import (
  4    "chain"
  5	"chain/runtime"
  6	"strings"
  7
  8	"gno.land/p/nt/ufmt"
  9)
 10
 11var roleAddresses map[string]address
 12
 13func init() {
 14	roleAddresses = make(map[string]address)
 15}
 16
 17// SetRoleAddress sets or updates a role's address.
 18// Creates the role if it doesn't exist, updates it if it does.
 19//
 20// Parameters:
 21//   - cur: current realm (required by interrealm spec; not used directly)
 22//   - roleName: name of the role
 23//   - roleAddress: address for the role
 24//
 25// Only callable by RBAC contract.
 26func SetRoleAddress(cur realm, roleName string, roleAddress address) {
 27	caller := runtime.PreviousRealm().Address()
 28	assertIsRBAC(caller)
 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", caller.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.
 64//
 65// Parameters:
 66//   - roleName: name of the role to remove
 67//
 68// Only callable by RBAC contract.
 69func RemoveRole(cur realm, roleName string) {
 70	caller := runtime.PreviousRealm().Address()
 71	assertIsRBAC(caller)
 72
 73	// Validate role name
 74	roleName = strings.TrimSpace(roleName)
 75	if roleName == "" {
 76		panic("role name cannot be empty")
 77	}
 78
 79	if _, ok := roleAddresses[roleName]; !ok {
 80		panic(ufmt.Errorf("role %s does not exist", roleName))
 81	}
 82
 83	delete(roleAddresses, roleName)
 84
 85	chain.Emit(
 86		"RemoveRole",
 87		"prevAddr", caller.String(),
 88		"role", roleName,
 89	)
 90}
 91
 92// IsAuthorized checks if caller has the specified role.
 93//
 94// Parameters:
 95//   - role: role name to check
 96//   - caller: address to verify
 97//
 98// Returns true if authorized, false otherwise.
 99func IsAuthorized(role string, caller address) bool {
100	addr, ok := GetAddress(role)
101	if !ok {
102		return false
103	}
104
105	return caller == addr
106}
107
108// GetAddress returns the address for a role and whether it exists.
109func GetAddress(role string) (address, bool) {
110    role = strings.TrimSpace(role)
111	addr, ok := roleAddresses[role]
112	return addr, ok
113}
114
115// GetRoleAddresses returns a copy of all role addresses.
116func GetRoleAddresses() map[string]address {
117	addresses := make(map[string]address)
118
119	for role, data := range roleAddresses {
120		addresses[role] = data
121	}
122
123	return addresses
124}
125
126// MustGetAddress returns the address for a role or panics if it doesn't exist.
127// Use this when the role is expected to exist and failure is critical.
128func MustGetAddress(role string) address {
129    role = strings.TrimSpace(role)
130	addr, ok := GetAddress(role)
131	if !ok {
132		panic(ufmt.Errorf(errRoleNotFound, role))
133	}
134
135	return addr
136}