forked from gnolang/gno
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
<!-- please provide a detailed description of the changes made in this pull request. --> ## Description This PR adds the r/gnoland/events realm. It handles events gno.land is attending dynamically. An admin and modetators can add new events, delete old ones, or make changes to existing ones. <details><summary>Contributors' checklist...</summary> - [x] Added new tests, or not needed, or not feasible - [x] Provided an example (e.g. screenshot) to aid review or the PR is self-explanatory - [x] Updated the official documentation or not needed - [x] No breaking changes were made, or a `BREAKING CHANGE: xxx` message was included in the description - [x] Added references to related issues and PRs - [x] Provided any useful hints for running manual tests - [x] Added new benchmarks to [generated graphs](https://gnoland.github.io/benchmarks), if any. More info [here](https://github.com/gnolang/gno/blob/master/.benchmarks/README.md). </details> --------- Co-authored-by: Manfred Touron <[email protected]>
- Loading branch information
1 parent
7e1bd78
commit 8c78251
Showing
18 changed files
with
791 additions
and
463 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
90 changes: 90 additions & 0 deletions
90
examples/gno.land/p/demo/ownable/exts/authorizable/authorizable.gno
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
// Package authorizable is an extension of p/demo/ownable; | ||
// It allows the user to instantiate an Authorizable struct, which extends | ||
// p/demo/ownable with a list of users that are authorized for something. | ||
// By using authorizable, you have a superuser (ownable), as well as another | ||
// authorization level, which can be used for adding moderators or similar to your realm. | ||
package authorizable | ||
|
||
import ( | ||
"std" | ||
|
||
"gno.land/p/demo/avl" | ||
"gno.land/p/demo/ownable" | ||
"gno.land/p/demo/ufmt" | ||
) | ||
|
||
type Authorizable struct { | ||
*ownable.Ownable // owner in ownable is superuser | ||
authorized *avl.Tree // std.Addr > struct{}{} | ||
} | ||
|
||
func NewAuthorizable() *Authorizable { | ||
a := &Authorizable{ | ||
ownable.New(), | ||
avl.NewTree(), | ||
} | ||
|
||
// Add owner to auth list | ||
a.authorized.Set(a.Owner().String(), struct{}{}) | ||
return a | ||
} | ||
|
||
func NewAuthorizableWithAddress(addr std.Address) *Authorizable { | ||
a := &Authorizable{ | ||
ownable.NewWithAddress(addr), | ||
avl.NewTree(), | ||
} | ||
|
||
// Add owner to auth list | ||
a.authorized.Set(a.Owner().String(), struct{}{}) | ||
return a | ||
} | ||
|
||
func (a *Authorizable) AddToAuthList(addr std.Address) error { | ||
if err := a.CallerIsOwner(); err != nil { | ||
return ErrNotSuperuser | ||
} | ||
|
||
if _, exists := a.authorized.Get(addr.String()); exists { | ||
return ErrAlreadyInList | ||
} | ||
|
||
a.authorized.Set(addr.String(), struct{}{}) | ||
|
||
return nil | ||
} | ||
|
||
func (a *Authorizable) DeleteFromAuthList(addr std.Address) error { | ||
if err := a.CallerIsOwner(); err != nil { | ||
return ErrNotSuperuser | ||
} | ||
|
||
if !a.authorized.Has(addr.String()) { | ||
return ErrNotInAuthList | ||
} | ||
|
||
if _, removed := a.authorized.Remove(addr.String()); !removed { | ||
str := ufmt.Sprintf("authorizable: could not remove %s from auth list", addr.String()) | ||
panic(str) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func (a Authorizable) CallerOnAuthList() error { | ||
caller := std.PrevRealm().Addr() | ||
|
||
if !a.authorized.Has(caller.String()) { | ||
return ErrNotInAuthList | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func (a Authorizable) AssertOnAuthList() { | ||
caller := std.PrevRealm().Addr() | ||
|
||
if !a.authorized.Has(caller.String()) { | ||
panic(ErrNotInAuthList) | ||
} | ||
} |
116 changes: 116 additions & 0 deletions
116
examples/gno.land/p/demo/ownable/exts/authorizable/authorizable_test.gno
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
package authorizable | ||
|
||
import ( | ||
"std" | ||
"testing" | ||
|
||
"gno.land/p/demo/testutils" | ||
"gno.land/p/demo/uassert" | ||
) | ||
|
||
var ( | ||
alice = testutils.TestAddress("alice") | ||
bob = testutils.TestAddress("bob") | ||
charlie = testutils.TestAddress("charlie") | ||
) | ||
|
||
func TestNewAuthorizable(t *testing.T) { | ||
std.TestSetRealm(std.NewUserRealm(alice)) | ||
std.TestSetOrigCaller(alice) // TODO(bug, issue #2371): should not be needed | ||
|
||
a := NewAuthorizable() | ||
got := a.Owner() | ||
|
||
if alice != got { | ||
t.Fatalf("Expected %s, got: %s", alice, got) | ||
} | ||
} | ||
|
||
func TestNewAuthorizableWithAddress(t *testing.T) { | ||
a := NewAuthorizableWithAddress(alice) | ||
|
||
got := a.Owner() | ||
|
||
if alice != got { | ||
t.Fatalf("Expected %s, got: %s", alice, got) | ||
} | ||
} | ||
|
||
func TestCallerOnAuthList(t *testing.T) { | ||
a := NewAuthorizableWithAddress(alice) | ||
std.TestSetRealm(std.NewUserRealm(alice)) | ||
std.TestSetOrigCaller(alice) | ||
|
||
if err := a.CallerOnAuthList(); err == ErrNotInAuthList { | ||
t.Fatalf("expected alice to be on the list") | ||
} | ||
} | ||
|
||
func TestNotCallerOnAuthList(t *testing.T) { | ||
a := NewAuthorizableWithAddress(alice) | ||
std.TestSetRealm(std.NewUserRealm(bob)) | ||
std.TestSetOrigCaller(bob) | ||
|
||
if err := a.CallerOnAuthList(); err == nil { | ||
t.Fatalf("expected bob to not be on the list") | ||
} | ||
} | ||
|
||
func TestAddToAuthList(t *testing.T) { | ||
a := NewAuthorizableWithAddress(alice) | ||
std.TestSetRealm(std.NewUserRealm(alice)) | ||
std.TestSetOrigCaller(alice) | ||
|
||
if err := a.AddToAuthList(bob); err != nil { | ||
t.Fatalf("Expected no error, got %v", err) | ||
} | ||
|
||
std.TestSetRealm(std.NewUserRealm(bob)) | ||
std.TestSetOrigCaller(bob) | ||
|
||
if err := a.AddToAuthList(bob); err == nil { | ||
t.Fatalf("Expected AddToAuth to error while bob called it, but it didn't") | ||
} | ||
} | ||
|
||
func TestDeleteFromList(t *testing.T) { | ||
a := NewAuthorizableWithAddress(alice) | ||
std.TestSetRealm(std.NewUserRealm(alice)) | ||
std.TestSetOrigCaller(alice) | ||
|
||
if err := a.AddToAuthList(bob); err != nil { | ||
t.Fatalf("Expected no error, got %v", err) | ||
} | ||
|
||
if err := a.AddToAuthList(charlie); err != nil { | ||
t.Fatalf("Expected no error, got %v", err) | ||
} | ||
|
||
std.TestSetRealm(std.NewUserRealm(bob)) | ||
std.TestSetOrigCaller(bob) | ||
|
||
// Try an unauthorized deletion | ||
if err := a.DeleteFromAuthList(alice); err == nil { | ||
t.Fatalf("Expected DelFromAuth to error with %v", err) | ||
} | ||
|
||
std.TestSetRealm(std.NewUserRealm(alice)) | ||
std.TestSetOrigCaller(alice) | ||
|
||
if err := a.DeleteFromAuthList(charlie); err != nil { | ||
t.Fatalf("Expected no error, got %v", err) | ||
} | ||
} | ||
|
||
func TestAssertOnList(t *testing.T) { | ||
std.TestSetRealm(std.NewUserRealm(alice)) | ||
std.TestSetOrigCaller(alice) | ||
a := NewAuthorizableWithAddress(alice) | ||
|
||
std.TestSetRealm(std.NewUserRealm(bob)) | ||
std.TestSetOrigCaller(bob) | ||
|
||
uassert.PanicsWithMessage(t, ErrNotInAuthList.Error(), func() { | ||
a.AssertOnAuthList() | ||
}) | ||
} |
9 changes: 9 additions & 0 deletions
9
examples/gno.land/p/demo/ownable/exts/authorizable/errors.gno
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package authorizable | ||
|
||
import "errors" | ||
|
||
var ( | ||
ErrNotInAuthList = errors.New("authorizable: caller is not in authorized list") | ||
ErrNotSuperuser = errors.New("authorizable: caller is not superuser") | ||
ErrAlreadyInList = errors.New("authorizable: address is already in authorized list") | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
module gno.land/p/demo/ownable/exts/authorizable | ||
|
||
require ( | ||
gno.land/p/demo/avl v0.0.0-latest | ||
gno.land/p/demo/ownable v0.0.0-latest | ||
gno.land/p/demo/testutils v0.0.0-latest | ||
gno.land/p/demo/uassert v0.0.0-latest | ||
gno.land/p/demo/ufmt v0.0.0-latest | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.