From 0076e4841630bd97687bfc19b46c3f79a17e5e2b Mon Sep 17 00:00:00 2001 From: Leon Hudak <33522493+leohhhn@users.noreply.github.com> Date: Thu, 2 Nov 2023 14:06:35 +0100 Subject: [PATCH 1/2] feat: add p/demo/ownable (#1314) --- examples/gno.land/p/demo/ownable/errors.gno | 8 ++ examples/gno.land/p/demo/ownable/gno.mod | 1 + examples/gno.land/p/demo/ownable/ownable.gno | 57 +++++++++ .../gno.land/p/demo/ownable/ownable_test.gno | 113 ++++++++++++++++++ 4 files changed, 179 insertions(+) create mode 100644 examples/gno.land/p/demo/ownable/errors.gno create mode 100644 examples/gno.land/p/demo/ownable/gno.mod create mode 100644 examples/gno.land/p/demo/ownable/ownable.gno create mode 100644 examples/gno.land/p/demo/ownable/ownable_test.gno diff --git a/examples/gno.land/p/demo/ownable/errors.gno b/examples/gno.land/p/demo/ownable/errors.gno new file mode 100644 index 00000000000..ffbf6ab3f6f --- /dev/null +++ b/examples/gno.land/p/demo/ownable/errors.gno @@ -0,0 +1,8 @@ +package ownable + +import "errors" + +var ( + ErrUnauthorized = errors.New("unauthorized; caller is not owner") + ErrInvalidAddress = errors.New("new owner address is invalid") +) diff --git a/examples/gno.land/p/demo/ownable/gno.mod b/examples/gno.land/p/demo/ownable/gno.mod new file mode 100644 index 00000000000..9a9abb1e661 --- /dev/null +++ b/examples/gno.land/p/demo/ownable/gno.mod @@ -0,0 +1 @@ +module gno.land/p/demo/ownable diff --git a/examples/gno.land/p/demo/ownable/ownable.gno b/examples/gno.land/p/demo/ownable/ownable.gno new file mode 100644 index 00000000000..7f2eac008e1 --- /dev/null +++ b/examples/gno.land/p/demo/ownable/ownable.gno @@ -0,0 +1,57 @@ +package ownable + +import ( + "std" +) + +// Ownable is meant to be used as a top-level object to make your contract ownable OR +// being embedded in a Gno object to manage per-object ownership. +type Ownable struct { + owner std.Address +} + +func New() *Ownable { + return &Ownable{ + owner: std.GetOrigCaller(), + } +} + +// TransferOwnership transfers ownership of the Ownable struct to a new address +func (o *Ownable) TransferOwnership(newOwner std.Address) error { + err := o.CallerIsOwner() + if err != nil { + return err + } + + if !newOwner.IsValid() { + return ErrInvalidAddress + } + + o.owner = newOwner + return nil +} + +// DropOwnership removes the owner, effectively disabling any owner-related actions +// Top-level usage: disables all only-owner actions/functions, +// Embedded usage: behaves like a burn functionality, removing the owner from the struct +func (o *Ownable) DropOwnership() error { + err := o.CallerIsOwner() + if err != nil { + return err + } + + o.owner = "" + return nil +} + +// CallerIsOwner checks if the caller of the function is the Realm's owner +func (o *Ownable) CallerIsOwner() error { + if std.GetOrigCaller() == o.owner { + return nil + } + return ErrUnauthorized +} + +func (o *Ownable) Owner() std.Address { + return o.owner +} diff --git a/examples/gno.land/p/demo/ownable/ownable_test.gno b/examples/gno.land/p/demo/ownable/ownable_test.gno new file mode 100644 index 00000000000..f725795fd47 --- /dev/null +++ b/examples/gno.land/p/demo/ownable/ownable_test.gno @@ -0,0 +1,113 @@ +package ownable + +import ( + "std" + "testing" +) + +var ( + firstCaller = std.Address("g1l9aypkr8xfvs82zeux486ddzec88ty69lue9de") + secondCaller = std.Address("g127jydsh6cms3lrtdenydxsckh23a8d6emqcvfa") +) + +func TestNew(t *testing.T) { + std.TestSetOrigCaller(firstCaller) + + result := New() + if firstCaller != result.owner { + t.Fatalf("Expected %s, got: %s\n", firstCaller, result.owner) + } +} + +func TestOwner(t *testing.T) { + std.TestSetOrigCaller(firstCaller) + + result := New() + resultOwner := result.Owner() + + expected := firstCaller + if resultOwner != expected { + t.Fatalf("Expected %s, got: %s\n", expected, result) + } +} + +func TestTransferOwnership(t *testing.T) { + std.TestSetOrigCaller(firstCaller) + o := New() + + err := o.TransferOwnership(secondCaller) + if err != nil { + t.Fatalf("TransferOwnership failed, %v", err) + } + + result := o.Owner() + if secondCaller != result { + t.Fatalf("Expected: %s, got: %s\n", secondCaller, result) + } +} + +func TestCallerIsOwner(t *testing.T) { + std.TestSetOrigCaller(firstCaller) + + o := New() + unauthorizedCaller := secondCaller + + std.TestSetOrigCaller(unauthorizedCaller) + + err := o.CallerIsOwner() + if err == nil { + t.Fatalf("Expected %s to not be owner\n", unauthorizedCaller) + } +} + +func TestDropOwnership(t *testing.T) { + std.TestSetOrigCaller(firstCaller) + + o := New() + + err := o.DropOwnership() + if err != nil { + t.Fatalf("DropOwnership failed, %v", err) + } + + owner := o.Owner() + if owner != "" { + t.Fatalf("Expected owner to be empty, not %s\n", owner) + } +} + +// Errors + +func TestErrUnauthorized(t *testing.T) { + std.TestSetOrigCaller(firstCaller) + + o := New() + + std.TestSetOrigCaller(secondCaller) + + err := o.TransferOwnership(firstCaller) + if err != ErrUnauthorized { + t.Fatalf("Should've been ErrUnauthorized, was %v", err) + } + + err = o.DropOwnership() + if err != ErrUnauthorized { + t.Fatalf("Should've been ErrUnauthorized, was %v", err) + } +} + +func TestErrInvalidAddress(t *testing.T) { + std.TestSetOrigCaller(firstCaller) + + o := New() + + err := o.TransferOwnership("") + if err != ErrInvalidAddress { + t.Fatalf("Should've been ErrInvalidAddress, was %v", err) + } + + err = o.TransferOwnership("10000000001000000000100000000010000000001000000000") + if err != ErrInvalidAddress { + t.Fatalf("Should've been ErrInvalidAddress, was %v", err) + } +} From 789f4de1d4940eced86f6311479de0819f3f4b11 Mon Sep 17 00:00:00 2001 From: Morgan Date: Thu, 2 Nov 2023 14:00:46 -0400 Subject: [PATCH 2/2] fix(misc/gendocs): convert paths for async-loaded scripts (#1307) This should allow js to fully load correctly on gnolang.github.io :) --- misc/gendocs/gendocs.sh | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/misc/gendocs/gendocs.sh b/misc/gendocs/gendocs.sh index 4336516aba1..b50c597bc39 100755 --- a/misc/gendocs/gendocs.sh +++ b/misc/gendocs/gendocs.sh @@ -5,6 +5,8 @@ set -u DOC_DIR=godoc PKG=github.com/gnolang/gno +# Used to load /static content +STATIC_PREFIX=/gno # Run a pkgsite server which we will scrape. Use env to run it from our repo's root directory. env -C ../.. pkgsite & @@ -30,7 +32,11 @@ wget \ --page-requisites \ -erobots=off \ --accept-regex='8080/((search|license-policy|about|)$|(static|images)/|github.com/gnolang/)' \ - http://localhost:8080/ + http://localhost:8080/ \ + http://localhost:8080/static/frontend/frontend.js \ + http://localhost:8080/static/frontend/unit/unit.js \ + http://localhost:8080/static/frontend/unit/main/main.js \ + http://localhost:8080/third_party/dialog-polyfill/dialog-polyfill.js # Stop the pkgsite server kill -9 $DOC_PID @@ -46,6 +52,7 @@ mv localhost\:8080 $DOC_DIR find godoc -type f -exec sed -ri 's#http://localhost:8080/files/[^"]*/github.com/gnolang/([^/"]+)/([^"]*)#https://github.com/gnolang/\1/blob/master/\2#g s#http://localhost:8080/[^"?]*\?tab=(importedby|versions)#\##g s#http://localhost:8080([^")]*)#https://pkg.go.dev\1#g -s#/files/[^" ]*/(github.com/[^" ]*)/#\1#g' {} + +s#/files/[^" ]*/(github.com/[^" ]*)/#\1#g +s#s\.src = src;#s.src = "'"$STATIC_PREFIX"'" + src;#g' {} + echo "Docs can be found in $DOC_DIR"