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}