Search Apps Documentation Source Content File Folder Download Copy Actions Download

authorizable.gno

2.90 Kb · 114 lines
  1// Package authorizable is an extension of p/nt/ownable;
  2// It allows the user to instantiate an Authorizable struct, which extends
  3// p/nt/ownable with a list of users that are authorized for something.
  4// By using authorizable, you have a superuser (ownable), as well as another
  5// authorization level, which can be used for adding moderators or similar to your realm.
  6package authorizable
  7
  8import (
  9	"chain/runtime"
 10
 11	"gno.land/p/nt/avl/v0"
 12	"gno.land/p/nt/ownable/v0"
 13	"gno.land/p/nt/ufmt/v0"
 14)
 15
 16type Authorizable struct {
 17	*ownable.Ownable           // owner in ownable is superuser
 18	authorized       *avl.Tree // chain.Addr > struct{}{}
 19}
 20
 21// New creates an Authorizable from an existing *ownable.Ownable.
 22// The owner is automatically added to the auth list.
 23// The auth mode (current-realm vs previous-realm) is inherited from the
 24// provided Ownable. Use the ownable constructors to choose the mode:
 25//
 26//	// Current-realm auth (caller is the realm making the call):
 27//	authorizable.New(ownable.New())
 28//
 29//	// Previous-realm auth (caller is the user/realm one step back):
 30//	authorizable.New(ownable.NewWithOrigin())
 31//
 32//	// Explicit address, current-realm auth:
 33//	authorizable.New(ownable.NewWithAddress(addr))
 34//
 35//	// Explicit address, previous-realm auth:
 36//	authorizable.New(ownable.NewWithAddressByPrevious(addr))
 37func New(o *ownable.Ownable) *Authorizable {
 38	a := &Authorizable{
 39		Ownable:    o,
 40		authorized: avl.NewTree(),
 41	}
 42
 43	// Add owner to auth list
 44	a.authorized.Set(a.Owner().String(), struct{}{})
 45	return a
 46}
 47
 48func (a *Authorizable) AddToAuthList(addr address) error {
 49	if !a.Owned() {
 50		return ErrNotSuperuser
 51	}
 52	return a.addToAuthList(addr)
 53}
 54
 55func (a *Authorizable) addToAuthList(addr address) error {
 56	if _, exists := a.authorized.Get(addr.String()); exists {
 57		return ErrAlreadyInList
 58	}
 59
 60	a.authorized.Set(addr.String(), struct{}{})
 61
 62	return nil
 63}
 64
 65func (a *Authorizable) DeleteFromAuthList(addr address) error {
 66	if !a.Owned() {
 67		return ErrNotSuperuser
 68	}
 69	return a.deleteFromAuthList(addr)
 70}
 71
 72func (a *Authorizable) deleteFromAuthList(addr address) error {
 73	if !a.authorized.Has(addr.String()) {
 74		return ErrNotInAuthList
 75	}
 76
 77	if _, removed := a.authorized.Remove(addr.String()); !removed {
 78		str := ufmt.Sprintf("authorizable: could not remove %s from auth list", addr.String())
 79		panic(str)
 80	}
 81
 82	return nil
 83}
 84
 85func (a *Authorizable) OnAuthList() error {
 86	current := runtime.CurrentRealm().Address()
 87	return a.onAuthList(current)
 88}
 89
 90func (a *Authorizable) PreviousOnAuthList() error {
 91	previous := runtime.PreviousRealm().Address()
 92	return a.onAuthList(previous)
 93}
 94
 95func (a *Authorizable) onAuthList(caller address) error {
 96	if !a.authorized.Has(caller.String()) {
 97		return ErrNotInAuthList
 98	}
 99	return nil
100}
101
102func (a Authorizable) AssertOnAuthList() {
103	err := a.OnAuthList()
104	if err != nil {
105		panic(err)
106	}
107}
108
109func (a Authorizable) AssertPreviousOnAuthList() {
110	err := a.PreviousOnAuthList()
111	if err != nil {
112		panic(err)
113	}
114}