Search Apps Documentation Source Content File Folder Download Copy Actions Download

access.gno

3.01 Kb · 135 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// Creates the role if it doesn't exist, updates it if it does.
 18//
 19// Parameters:
 20//   - cur: current realm
 21//   - roleName: name of the role
 22//   - roleAddress: address for the role
 23//
 24// Only callable by RBAC contract.
 25func SetRoleAddress(cur realm, roleName string, roleAddress address) {
 26	prev := cur.Previous()
 27	assertIsRBAC(prev.Address())
 28
 29	// capture old value for event
 30	oldAddr, _ := roleAddresses[strings.TrimSpace(roleName)]
 31
 32	if err := setRoleAddress(roleName, roleAddress); err != nil {
 33		panic(err)
 34	}
 35
 36	chain.Emit(
 37		"SetRoleAddress",
 38		"prevAddr", prev.Address().String(),
 39		"role", roleName,
 40		"prevRoleAddr", oldAddr.String(),
 41		"roleAddress", roleAddress.String(),
 42	)
 43}
 44
 45// setRoleAddress is the internal implementation of SetRoleAddress.
 46// Separated for testability.
 47func setRoleAddress(roleName string, roleAddress address) error {
 48	roleName = strings.TrimSpace(roleName)
 49	if roleName == "" {
 50		panic("role name cannot be empty")
 51	}
 52
 53	// Validate address
 54	if !roleAddress.IsValid() || roleAddress == address("") {
 55		return ufmt.Errorf(errInvalidAddress, roleName, roleAddress)
 56	}
 57
 58	roleAddresses[roleName] = roleAddress
 59	return nil
 60}
 61
 62// RemoveRole removes a role from the system.
 63//
 64// Parameters:
 65//   - roleName: name of the role to remove
 66//
 67// Only callable by RBAC contract.
 68func RemoveRole(cur realm, roleName string) {
 69	prev := cur.Previous()
 70	assertIsRBAC(prev.Address())
 71
 72	// Validate role name
 73	roleName = strings.TrimSpace(roleName)
 74	if roleName == "" {
 75		panic("role name cannot be empty")
 76	}
 77
 78	if _, ok := roleAddresses[roleName]; !ok {
 79		panic(ufmt.Errorf("role %s does not exist", roleName))
 80	}
 81
 82	delete(roleAddresses, roleName)
 83
 84	chain.Emit(
 85		"RemoveRole",
 86		"prevAddr", prev.Address().String(),
 87		"role", roleName,
 88	)
 89}
 90
 91// IsAuthorized checks if caller has the specified role.
 92//
 93// Parameters:
 94//   - role: role name to check
 95//   - caller: address to verify
 96//
 97// Returns true if authorized, false otherwise.
 98func IsAuthorized(role string, caller address) bool {
 99	addr, ok := GetAddress(role)
100	if !ok {
101		return false
102	}
103
104	return caller == addr
105}
106
107// GetAddress returns the address for a role and whether it exists.
108func GetAddress(role string) (address, bool) {
109	role = strings.TrimSpace(role)
110	addr, ok := roleAddresses[role]
111	return addr, ok
112}
113
114// GetRoleAddresses returns a copy of all role addresses.
115func GetRoleAddresses() map[string]address {
116	addresses := make(map[string]address)
117
118	for role, data := range roleAddresses {
119		addresses[role] = data
120	}
121
122	return addresses
123}
124
125// MustGetAddress returns the address for a role or panics if it doesn't exist.
126// Use this when the role is expected to exist and failure is critical.
127func MustGetAddress(role string) address {
128	role = strings.TrimSpace(role)
129	addr, ok := GetAddress(role)
130	if !ok {
131		panic(ufmt.Errorf(errRoleNotFound, role))
132	}
133
134	return addr
135}