authorizable.gno

2.98 Kb ยท 134 lines
  1// Package authorizable is an extension of p/demo/ownable;
  2// It allows the user to instantiate an Authorizable struct, which extends
  3// p/demo/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	"std"
 10
 11	"gno.land/p/demo/avl"
 12	"gno.land/p/demo/ownable"
 13	"gno.land/p/demo/ufmt"
 14)
 15
 16type Authorizable struct {
 17	*ownable.Ownable           // owner in ownable is superuser
 18	authorized       *avl.Tree // std.Addr > struct{}{}
 19}
 20
 21func NewAuthorizable() *Authorizable {
 22	a := &Authorizable{
 23		ownable.New(),
 24		avl.NewTree(),
 25	}
 26
 27	// Add owner to auth list
 28	a.authorized.Set(a.Owner().String(), struct{}{})
 29	return a
 30}
 31
 32func NewAuthorizableWithOrigin() *Authorizable {
 33	a := &Authorizable{
 34		ownable.NewWithOrigin(),
 35		avl.NewTree(),
 36	}
 37
 38	// Add owner to auth list
 39	a.authorized.Set(a.Owner().String(), struct{}{})
 40	return a
 41}
 42
 43func NewAuthorizableWithAddress(addr std.Address) *Authorizable {
 44	a := &Authorizable{
 45		ownable.NewWithAddress(addr),
 46		avl.NewTree(),
 47	}
 48
 49	// Add owner to auth list
 50	a.authorized.Set(a.Owner().String(), struct{}{})
 51	return a
 52}
 53
 54func (a *Authorizable) AddToAuthList(addr std.Address) error {
 55	if !a.OwnedByCurrent() {
 56		return ErrNotSuperuser
 57	}
 58	return a.addToAuthList(addr)
 59}
 60
 61func (a *Authorizable) AddToAuthListByPrevious(addr std.Address) error {
 62	if !a.OwnedByPrevious() {
 63		return ErrNotSuperuser
 64	}
 65	return a.addToAuthList(addr)
 66}
 67
 68func (a *Authorizable) addToAuthList(addr std.Address) error {
 69	if _, exists := a.authorized.Get(addr.String()); exists {
 70		return ErrAlreadyInList
 71	}
 72
 73	a.authorized.Set(addr.String(), struct{}{})
 74
 75	return nil
 76}
 77
 78func (a *Authorizable) DeleteFromAuthList(addr std.Address) error {
 79	if !a.OwnedByCurrent() {
 80		return ErrNotSuperuser
 81	}
 82	return a.deleteFromAuthList(addr)
 83}
 84
 85func (a *Authorizable) DeleteFromAuthListByPrevious(addr std.Address) error {
 86	if !a.OwnedByPrevious() {
 87		return ErrNotSuperuser
 88	}
 89	return a.deleteFromAuthList(addr)
 90}
 91
 92func (a *Authorizable) deleteFromAuthList(addr std.Address) error {
 93	if !a.authorized.Has(addr.String()) {
 94		return ErrNotInAuthList
 95	}
 96
 97	if _, removed := a.authorized.Remove(addr.String()); !removed {
 98		str := ufmt.Sprintf("authorizable: could not remove %s from auth list", addr.String())
 99		panic(str)
100	}
101
102	return nil
103}
104
105func (a *Authorizable) OnAuthList() error {
106	current := std.CurrentRealm().Address()
107	return a.onAuthList(current)
108}
109
110func (a *Authorizable) PreviousOnAuthList() error {
111	previous := std.PreviousRealm().Address()
112	return a.onAuthList(previous)
113}
114
115func (a *Authorizable) onAuthList(caller std.Address) error {
116	if !a.authorized.Has(caller.String()) {
117		return ErrNotInAuthList
118	}
119	return nil
120}
121
122func (a Authorizable) AssertOnAuthList() {
123	err := a.OnAuthList()
124	if err != nil {
125		panic(err)
126	}
127}
128
129func (a Authorizable) AssertPreviousOnAuthList() {
130	err := a.PreviousOnAuthList()
131	if err != nil {
132		panic(err)
133	}
134}