- Kind
- Pure package
- Name
- v1
- Namespace
- gnoswap / rbac
- Exported functions
- n/a — not supported for pure packages by the node (vm/qfuncs)
- Module
- gno.land/p/gnoswap/rbac/v1
- gno
- 0.9
rbac.gnogno
1package rbac23import (4 "errors"5 "strings"6)78
not supported for pure packages by the node (vm/qfuncs)
Signatures reconstructed verbatim from vm/qfuncs — interface params keep their inline definitions.
// RBAC encapsulates and manages roles and their permissions.
9// It combines role management with two-step ownership transfer functionality.
10type RBAC struct {
11 ownable *Ownable2Step
12 // roles maps role names to their respective `Role` objects
13 roles map[string]*Role
14}
15
16// NewRBACWithAddress creates a new RBAC instance with addr as owner.
17//
18// Parameters:
19// - addr: Address stored as the initial owner of the RBAC instance.
20//
21// Returns:
22// - *RBAC: New RBAC manager with an empty role registry and addr as owner.
23func NewRBACWithAddress(addr address) *RBAC {
24 return &RBAC{
25 ownable: newOwnable2StepWithAddress(addr),
26 roles: make(map[string]*Role),
27 }
28}
29
30// IsAuthorized checks if addr has the specified roleName. Returns false if the role does not exist.
31//
32// Parameters:
33// - roleName: Exact role name to look up in the role registry.
34// - addr: Address to compare with the address assigned to roleName.
35//
36// Returns:
37// - bool: true when roleName exists and its assigned address equals addr; false when it does not.
38func (rb *RBAC) IsAuthorized(roleName string, addr address) bool {
39 role, exists := rb.roles[roleName]
40 if !exists {
41 return false
42 }
43
44 return role.IsAuthorized(addr)
45}
46
47// RegisterRole registers a new role with given role name and address.
48//
49// Parameters:
50// - roleName: Role identifier; leading and trailing whitespace is removed before validation and storage.
51// - addr: Address initially assigned to the role; this method stores it without address validation.
52//
53// Errors:
54// `RegisterRole` returns an error in the following situations:
55// - `ErrInvalidRoleName`: role name is an empty string or contains only whitespace
56// - `ErrRoleAlreadyExists`: the role to be registered already exists in RBAC.
57// - A system-role name may be registered when absent, but remains protected
58// from removal; this package does not pre-register system roles.
59//
60// Returns:
61// - error: nil when the trimmed role is registered; otherwise ErrInvalidRoleName or ErrRoleAlreadyExists.
62func (rb *RBAC) RegisterRole(roleName string, addr address) error {
63 roleName = strings.TrimSpace(roleName)
64 if roleName == "" {
65 return errors.New(ErrInvalidRoleName)
66 }
67
68 if rb.existsRole(roleName) {
69 return errors.New(ErrRoleAlreadyExists)
70 }
71
72 rb.roles[roleName] = NewRole(roleName, addr)
73
74 return nil
75}
76
77// UpdateRoleAddress assigns addr to roleName.
78//
79// Parameters:
80// - roleName: Existing role identifier; leading and trailing whitespace is removed before lookup.
81// - addr: Non-zero, syntactically valid address to assign to the role.
82//
83// Errors:
84// - `ErrInvalidRoleName`: role name is an empty string or contains only whitespace
85// - `ErrRoleDoesNotExist`: the specified role does not exist in the RBAC system
86// - `ErrInvalidAddress`: addr is empty or has an invalid format
87//
88// Returns:
89// - error: nil when the existing role is updated; otherwise an error identifying invalid input or a missing role.
90func (rb *RBAC) UpdateRoleAddress(roleName string, addr address) error {
91 roleName = strings.TrimSpace(roleName)
92 if roleName == "" {
93 return errors.New(ErrInvalidRoleName)
94 }
95
96 role, exists := rb.roles[roleName]
97 if !exists {
98 return errors.New(ErrRoleDoesNotExist)
99 }
100
101 if addr == zeroAddress || !addr.IsValid() {
102 return errors.New(ErrInvalidAddress)
103 }
104
105 role.setAddress(addr)
106
107 return nil
108}
109
110// RemoveRole removes roleName from the RBAC system.
111//
112// Parameters:
113// - roleName: Role identifier to remove; leading and trailing whitespace is removed before lookup.
114//
115// Errors:
116// - `ErrInvalidRoleName`: role name is an empty string or contains only whitespace
117// - `ErrRoleDoesNotExist`: the specified role does not exist in the RBAC system
118// - `ErrCannotRemoveSystemRole`: attempting to remove a system role (e.g., admin, governance, pool, etc.)
119//
120// Returns:
121// - error: nil when a non-system role is removed; otherwise an error for invalid, missing, or protected roles.
122func (rb *RBAC) RemoveRole(roleName string) error {
123 roleName = strings.TrimSpace(roleName)
124 if roleName == "" {
125 return errors.New(ErrInvalidRoleName)
126 }
127
128 if !rb.existsRole(roleName) {
129 return errors.New(ErrRoleDoesNotExist)
130 }
131
132 // Check if it's a system role
133 if IsSystemRole(roleName) {
134 return errors.New(ErrCannotRemoveSystemRole)
135 }
136
137 // Simply delete the role since permissions are no longer managed here
138 delete(rb.roles, roleName)
139
140 return nil
141}
142
143// GetAllRoleAddresses returns a map of all role names to their assigned addresses.
144//
145// Returns:
146// - map[string]address: Newly allocated map containing each registered role name and its assigned address.
147func (rb *RBAC) GetAllRoleAddresses() map[string]address {
148 addresses := make(map[string]address)
149
150 for roleName, role := range rb.roles {
151 addresses[roleName] = role.Address()
152 }
153
154 return addresses
155}
156
157// GetRoleAddress returns the address assigned to roleName.
158//
159// Parameters:
160// - roleName: Exact role name to look up; this method does not trim whitespace.
161//
162// Errors:
163// - `ErrRoleDoesNotExist`: the specified role does not exist in the RBAC system
164//
165// Returns:
166// - address: Address assigned to roleName, or the empty address when the role is absent.
167// - error: nil when roleName exists; otherwise ErrRoleDoesNotExist.
168func (rb *RBAC) GetRoleAddress(roleName string) (address, error) {
169 role, exists := rb.roles[roleName]
170 if !exists {
171 return "", errors.New(ErrRoleDoesNotExist)
172 }
173
174 return role.Address(), nil
175}
176
177// Owner returns the current owner address.
178//
179// Returns:
180// - address: Current RBAC owner address, or the empty address if ownership has been dropped.
181func (rb *RBAC) Owner() address {
182 return rb.ownable.Owner()
183}
184
185// PendingOwner returns the pending owner address during ownership transfer.
186//
187// Returns:
188// - address: Pending owner address, or the empty address when no transfer is pending.
189func (rb *RBAC) PendingOwner() address {
190 return rb.ownable.PendingOwner()
191}
192
193// AcceptOwnershipBy completes the ownership transfer process.
194// Must be called by the pending owner.
195//
196// Parameters:
197// - addr: Address attempting to accept ownership; it must equal the recorded pending owner.
198//
199// Errors:
200// - `ErrNoPendingOwner`: no ownership transfer is pending
201// - `ErrPendingUnauthorized`: addr is not the pending owner
202//
203// Returns:
204// - error: nil when ownership is transferred to addr; otherwise ErrNoPendingOwner or ErrPendingUnauthorized.
205func (rb *RBAC) AcceptOwnershipBy(addr address) error {
206 return rb.ownable.AcceptOwnershipBy(addr)
207}
208
209// DropOwnershipBy removes the owner, effectively disabling owner-only actions.
210// This is irreversible and will prevent any future owner-only operations.
211//
212// Parameters:
213// - addr: Address requesting the drop; it must equal the current owner.
214//
215// Errors:
216// - `ErrUnauthorized`: addr is not the current owner
217//
218// Returns:
219// - error: nil when owner and pending owner are cleared; otherwise ErrUnauthorized.
220func (rb *RBAC) DropOwnershipBy(addr address) error {
221 return rb.ownable.DropOwnershipBy(addr)
222}
223
224// TransferOwnershipBy initiates the two-step ownership transfer process.
225// The newOwner must call AcceptOwnershipBy to complete the transfer.
226//
227// Parameters:
228// - newOwner: Non-zero, syntactically valid address to record as the pending owner.
229// - caller: Address authorized to initiate the transfer; it must equal the current owner.
230//
231// Errors:
232// - `ErrUnauthorized`: caller is not the current owner
233// - `ErrInvalidAddress`: newOwner is empty or has an invalid format
234//
235// Returns:
236// - error: nil when the pending owner is set; otherwise ErrUnauthorized or ErrInvalidAddress.
237func (rb *RBAC) TransferOwnershipBy(newOwner, caller address) error {
238 return rb.ownable.TransferOwnershipBy(newOwner, caller)
239}
240
241// existsRole checks if name exists in the RBAC system.
242func (rb *RBAC) existsRole(name string) bool {
243 _, exists := rb.roles[name]
244 return exists
245}
246