Search Apps Documentation Source Content File Folder Download Copy Actions Download

rbac.gno

5.01 Kb · 176 lines
  1package rbac
  2
  3import (
  4	"strings"
  5)
  6
  7// RBAC encapsulates and manages roles and their permissions.
  8// It combines role management with two-step ownership transfer functionality.
  9type RBAC struct {
 10	ownable *Ownable2Step
 11	// roles maps role names to their respective `Role` objects
 12	roles map[string]*Role
 13}
 14
 15// NewRBACWithAddress creates a new RBAC instance with addr as owner.
 16func NewRBACWithAddress(addr address) *RBAC {
 17	return &RBAC{
 18		ownable: newOwnable2StepWithAddress(addr),
 19		roles:   make(map[string]*Role),
 20	}
 21}
 22
 23// IsAuthorized checks if addr has the specified roleName. Returns false if the role does not exist.
 24func (rb *RBAC) IsAuthorized(roleName string, addr address) bool {
 25	role, exists := rb.roles[roleName]
 26	if !exists {
 27		return false
 28	}
 29
 30	return role.IsAuthorized(addr)
 31}
 32
 33// RegisterRole registers a new role with given role name and address.
 34//
 35// Errors:
 36// `RegisterRole` returns an error in the following situations:
 37//  - `ErrInvalidRoleName`: role name is an empty string or contains only whitespace
 38//  - `ErrRoleAlreadyExists`: the role to be registered already exists in rbac.
 39//    Since system roles are registered through `initRbac`, attempting to register
 40//    a new role with a system role name will return an `ErrRoleAlreadyExists` error.
 41func (rb *RBAC) RegisterRole(roleName string, addr address) error {
 42	roleName = strings.TrimSpace(roleName)
 43	if roleName == "" {
 44		return ErrInvalidRoleName
 45	}
 46
 47	if rb.existsRole(roleName) {
 48		return ErrRoleAlreadyExists
 49	}
 50
 51	rb.roles[roleName] = NewRole(roleName, addr)
 52
 53	return nil
 54}
 55
 56// UpdateRoleAddress assigns addr to roleName.
 57//
 58// Errors:
 59//   - `ErrInvalidRoleName`: role name is an empty string or contains only whitespace
 60//   - `ErrRoleDoesNotExist`: the specified role does not exist in the RBAC system
 61//   - `ErrInvalidAddress`: addr is empty or has an invalid format
 62func (rb *RBAC) UpdateRoleAddress(roleName string, addr address) error {
 63	roleName = strings.TrimSpace(roleName)
 64	if roleName == "" {
 65		return ErrInvalidRoleName
 66	}
 67
 68	role, exists := rb.roles[roleName]
 69	if !exists {
 70		return ErrRoleDoesNotExist
 71	}
 72
 73	if addr == zeroAddress || !addr.IsValid() {
 74		return ErrInvalidAddress
 75	}
 76
 77	role.setAddress(addr)
 78
 79	return nil
 80}
 81
 82// RemoveRole removes roleName from the RBAC system.
 83//
 84// Errors:
 85//   - `ErrInvalidRoleName`: role name is an empty string or contains only whitespace
 86//   - `ErrRoleDoesNotExist`: the specified role does not exist in the RBAC system
 87//   - `ErrCannotRemoveSystemRole`: attempting to remove a system role (e.g., admin, governance, pool, etc.)
 88func (rb *RBAC) RemoveRole(roleName string) error {
 89	roleName = strings.TrimSpace(roleName)
 90	if roleName == "" {
 91		return ErrInvalidRoleName
 92	}
 93
 94	if !rb.existsRole(roleName) {
 95		return ErrRoleDoesNotExist
 96	}
 97
 98	// Check if it's a system role
 99	if IsSystemRole(roleName) {
100		return ErrCannotRemoveSystemRole
101	}
102
103	// Simply delete the role since permissions are no longer managed here
104	delete(rb.roles, roleName)
105
106	return nil
107}
108
109// GetAllRoleAddresses returns a map of all role names to their assigned addresses.
110func (rb *RBAC) GetAllRoleAddresses() map[string]address {
111	addresses := make(map[string]address)
112
113	for roleName, role := range rb.roles {
114		addresses[roleName] = role.Address()
115	}
116
117	return addresses
118}
119
120// GetRoleAddress returns the address assigned to roleName.
121//
122// Errors:
123//   - `ErrRoleDoesNotExist`: the specified role does not exist in the RBAC system
124func (rb *RBAC) GetRoleAddress(roleName string) (address, error) {
125	role, exists := rb.roles[roleName]
126	if !exists {
127		return "", ErrRoleDoesNotExist
128	}
129
130	return role.Address(), nil
131}
132
133// Owner returns the current owner address.
134func (rb *RBAC) Owner() address {
135    return rb.ownable.Owner()
136}
137
138// PendingOwner returns the pending owner address during ownership transfer.
139func (rb *RBAC) PendingOwner() address {
140    return rb.ownable.PendingOwner()
141}
142
143// AcceptOwnershipBy completes the ownership transfer process.
144// Must be called by the pending owner.
145//
146// Errors:
147//   - `ErrNoPendingOwner`: no ownership transfer is pending
148//   - `ErrPendingUnauthorized`: addr is not the pending owner
149func (rb *RBAC) AcceptOwnershipBy(addr address) error {
150    return rb.ownable.AcceptOwnershipBy(addr)
151}
152
153// DropOwnershipBy removes the owner, effectively disabling owner-only actions.
154// This is irreversible and will prevent any future owner-only operations.
155//
156// Errors:
157//   - `ErrUnauthorized`: addr is not the current owner
158func (rb *RBAC) DropOwnershipBy(addr address) error {
159    return rb.ownable.DropOwnershipBy(addr)
160}
161
162// TransferOwnershipBy initiates the two-step ownership transfer process.
163// The newOwner must call AcceptOwnershipBy to complete the transfer.
164//
165// Errors:
166//   - `ErrUnauthorized`: caller is not the current owner
167//   - `ErrInvalidAddress`: newOwner is empty or has an invalid format
168func (rb *RBAC) TransferOwnershipBy(newOwner, caller address) error {
169	return rb.ownable.TransferOwnershipBy(newOwner, caller)
170}
171
172// existsRole checks if name exists in the RBAC system.
173func (rb *RBAC) existsRole(name string) bool {
174	_, exists := rb.roles[name]
175	return exists
176}