Package rbac provides a simple address-based Role-Based Access Control (RBAC) system for Gno smart contracts. It enables dynamic registration, update, and removal of roles with assigned addresses.
## Overview
The RBAC package provides a manager that maintains an internal registry of roles. Each role is identified by a unique name and is associated with a single address. Authorization is performed by checking if a given address matches the role's assigned address.
Key components of this package include:
- **Role**: Represents a role with a name and an assigned address.
- **RBAC Manager**: The core type (RBAC) that manages role registration, address assignment, authorization verification, and role removal.
- **Ownable2Step**: Provides two-step ownership transfer functionality integrated into the RBAC manager.
## Key Features
- **Dynamic Role Management**: Roles can be registered, updated, and removed at runtime without requiring contract redeployment.
- **Address-Based Authorization**: Each role is associated with a single address,
- **System Roles**: Reserved system-role names (admin, devops, pool, etc.) cannot be removed once registered. The constructor does not pre-populate these role entries; callers register their addresses explicitly.
- **Two-Step Ownership Transfer**: Built-in secure ownership transfer mechanism requiring explicit acceptance by the new owner.
- **Encapsulation**: Internal state (roles registry) is encapsulated within the RBAC manager, preventing unintended external modifications.
## Workflow
Typical usage of the RBAC package includes the following steps:
- **Initialization**: Create a new RBAC manager with `NewRBACWithAddress(addr)`, passing the intended owner explicitly.
- **Role Registration**: Register roles using `RegisterRole(roleName, address)`.
- **Authorization Check**: Verify if an address is authorized for a role using `IsAuthorized(roleName, address)`.
- **Role Management**: Update role addresses with `UpdateRoleAddress` or remove non-system roles with `RemoveRole`.
## Example Usage
The following example demonstrates how to use the RBAC package:
```gno package main
import (
Example
1"gno.land/p/gnoswap/rbac/v1"
)
Example
1func main() {
2 // The owner is supplied explicitly; no constructor derives it from
3 // an implicit origin caller.
4 ownerAddr := address("g1...")
5 manager := rbac.NewRBACWithAddress(ownerAddr)
6
7 // Define example addresses
8 adminAddr := address("g1...")
9 userAddr := address("g1...")
10
11 // Register an "admin" role with adminAddr
12 if err := manager.RegisterRole("admin", adminAddr); err != nil {
13 panic(err)
14 }
15
16 // Register a custom "editor" role with userAddr
17 if err := manager.RegisterRole("editor", userAddr); err != nil {
18 panic(err)
19 }
20
21 // Check if adminAddr is authorized for the "admin" role
22 if manager.IsAuthorized("admin", adminAddr) {
23 println("Admin access granted")
24 }
25
26 // Check if userAddr is authorized for the "admin" role
27 if !manager.IsAuthorized("admin", userAddr) {
28 println("User does not have admin access")
29 }
30
31 // Update the editor role to a different address
32 newEditorAddr := address("g1...")
33 if err := manager.UpdateRoleAddress("editor", newEditorAddr); err != nil {
34 panic(err)
35 }
36
37 // Get all role addresses
38 allRoles := manager.GetAllRoleAddresses()
39 for roleName, addr := range allRoles {
40 println(roleName, "->", addr.String())
41 }
42}
```
## System Roles
The package reserves the following system-role names. A new RBAC manager starts with no role entries, so callers must register each role and address explicitly. Once registered, a system role cannot be removed:
- admin: System administrator role
- devops: DevOps operations role
- community_pool: Community pool management role
- governance: Governance system role
- gov_staker: Governance staker role
- xgns: xGNS token role
- pool: Pool management role
- position: Position management role
- router: Router role
- staker: Staker role
- emission: Emission management role
- launchpad: Launchpad role
- protocol_fee: Protocol fee management role
## Error Handling
The package defines several error types:
- ErrRoleAlreadyExists: Attempting to register a role that already exists.
- ErrRoleDoesNotExist: Attempting to access or modify a non-existent role.
- ErrCannotRemoveSystemRole: Attempting to remove a registered system role.
- ErrInvalidAddress: Providing an invalid address to UpdateRoleAddress or an ownership-transfer method. RegisterRole stores its supplied address without validating it.
- ErrUnauthorized: Caller is not the owner when owner permission is required.
- ErrNoPendingOwner: Attempting to accept ownership when no transfer is pending.
- ErrPendingUnauthorized: Caller is not the pending owner when accepting ownership.
## Ownership Management
The RBAC manager includes built-in two-step ownership transfer functionality:
- Current owner calls TransferOwnershipBy to initiate transfer.
- New owner calls AcceptOwnershipBy to complete the transfer.
- Owner can drop ownership entirely using DropOwnershipBy.
## Limitations and Considerations
- Each role can only have one assigned address. For multi-address authorization, consider creating multiple roles or implementing a wrapper.
- System roles are protected and cannot be removed to ensure system stability.
- `RegisterRole` does not validate the supplied address. Address validation is performed by `UpdateRoleAddress` and ownership-transfer methods.
Package rbac is intended for use in Gno smart contracts requiring simple, address-based access control with role management capabilities.