From a87d21d615c69990a844c1b1add8be99aee9deed Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Wed, 12 Jun 2024 16:19:20 +0300 Subject: [PATCH 1/6] feat: add p/nestedpkg Signed-off-by: moul <94029+moul@users.noreply.github.com> --- .../gno.land/p/demo/nestedpkg/nestedpkg.gno | 80 +++++++++++++++++++ .../p/demo/nestedpkg/nestedpkg_test.gno | 76 ++++++++++++++++++ 2 files changed, 156 insertions(+) create mode 100644 examples/gno.land/p/demo/nestedpkg/nestedpkg.gno create mode 100644 examples/gno.land/p/demo/nestedpkg/nestedpkg_test.gno diff --git a/examples/gno.land/p/demo/nestedpkg/nestedpkg.gno b/examples/gno.land/p/demo/nestedpkg/nestedpkg.gno new file mode 100644 index 00000000000..fe8a13188c0 --- /dev/null +++ b/examples/gno.land/p/demo/nestedpkg/nestedpkg.gno @@ -0,0 +1,80 @@ +// Package nestedpkg provides helpers for package-path based access control. +// It can be convenient for some upgrade patterns relying on namespaces. +package nestedpkg + +import ( + "std" + "strings" +) + +// IsCallerSubPath checks if the caller realm is located in a subfolder of the current realm. +func IsCallerSubPath() bool { + var ( + cur = std.CurrentRealm().PkgPath() + "/" + prev = std.PrevRealm().PkgPath() + "/" + ) + return strings.HasPrefix(prev, cur) +} + +// AssertCallerIsSubPath panics when IsCallerSubPath is false. +func AssertCallerIsSubPath() { + var ( + cur = std.CurrentRealm().PkgPath() + "/" + prev = std.PrevRealm().PkgPath() + "/" + ) + if !strings.HasPrefix(prev, cur) { + panic("call restricted to nested packages. current realm is " + cur + ", prev realm is " + prev) + } +} + +// IsCallerParentPath checks if the caller realm is located in a parent location of the current realm. +func IsCallerParentPath() bool { + var ( + cur = std.CurrentRealm().PkgPath() + "/" + prev = std.PrevRealm().PkgPath() + "/" + ) + return strings.HasPrefix(cur, prev) +} + +func AssertCallerIsParentPath() { + var ( + cur = std.CurrentRealm().PkgPath() + "/" + prev = std.PrevRealm().PkgPath() + "/" + ) + if !strings.HasPrefix(cur, prev) { + panic("call restricted to parent packages. current realm is " + cur + ", prev realm is " + prev) + } +} + +func IsSameNamespace() bool { + var ( + cur = nsFromPath(std.CurrentRealm().PkgPath()) + "/" + prev = nsFromPath(std.PrevRealm().PkgPath()) + "/" + ) + return cur == prev +} + +func AssertIsSameNamespace() { + var ( + cur = nsFromPath(std.CurrentRealm().PkgPath()) + "/" + prev = nsFromPath(std.PrevRealm().PkgPath()) + "/" + ) + if cur != prev { + panic("call restricted to packages from the same namespace. current realm is " + cur + ", prev realm is " + prev) + } +} + +func nsFromPath(pkgpath string) string { + parts := strings.Split(pkgpath, "/") + + // specifically about gno.land, potential paths are in the form of DOMAIN/r/NAMESPACE/... + // XXX: consider extra checks. + // XXX: support non gno.land domains, where p/ and r/ won't be enforced. + if len(parts) >= 3 { + return parts[2] + } + return "" +} + +// XXX: consider adding IsCallerDirectlySubPath +// XXX: consider adding IsCallerDirectlyParentPath diff --git a/examples/gno.land/p/demo/nestedpkg/nestedpkg_test.gno b/examples/gno.land/p/demo/nestedpkg/nestedpkg_test.gno new file mode 100644 index 00000000000..f3b674cc5f0 --- /dev/null +++ b/examples/gno.land/p/demo/nestedpkg/nestedpkg_test.gno @@ -0,0 +1,76 @@ +package nestedpkg + +import ( + "std" + "testing" + + "gno.land/p/demo/nestedpkg" + "gno.land/r/demo/tests" +) + +func TestPackage(t *testing.T) { + // direct child + cur := "gno.land/r/demo/tests/foo" + std.TestSetRealm(std.NewCodeRealm(cur)) + if !tests.IsCallerSubPath() { + t.Errorf(cur + " should be a sub path") + } + if tests.IsCallerParentPath() { + t.Errorf(cur + " should not be a parent path") + } + if !tests.HasCallerSameNamespace() { + t.Errorf(cur + " should be from the same namespace") + } + + // grand-grand-child + cur = "gno.land/r/demo/tests/foo/bar/baz" + std.TestSetRealm(std.NewCodeRealm(cur)) + if !tests.IsCallerSubPath() { + t.Errorf(cur + " should be a sub path") + } + if tests.IsCallerParentPath() { + t.Errorf(cur + " should not be a parent path") + } + if !tests.HasCallerSameNamespace() { + t.Errorf(cur + " should be from the same namespace") + } + + // direct parent + cur = "gno.land/r/demo" + std.TestSetRealm(std.NewCodeRealm(cur)) + if tests.IsCallerSubPath() { + t.Errorf(cur + " should not be a sub path") + } + if !tests.IsCallerParentPath() { + t.Errorf(cur + " should be a parent path") + } + if !tests.HasCallerSameNamespace() { + t.Errorf(cur + " should be from the same namespace") + } + + // fake parent (prefix) + cur = "gno.land/r/dem" + std.TestSetRealm(std.NewCodeRealm(cur)) + if tests.IsCallerSubPath() { + t.Errorf(cur + " should not be a sub path") + } + if tests.IsCallerParentPath() { + t.Errorf(cur + " should not be a parent path") + } + if tests.HasCallerSameNamespace() { + t.Errorf(cur + " should not be from the same namespace") + } + + // different namespace + cur = "gno.land/r/foo" + std.TestSetRealm(std.NewCodeRealm(cur)) + if tests.IsCallerSubPath() { + t.Errorf(cur + " should not be a sub path") + } + if tests.IsCallerParentPath() { + t.Errorf(cur + " should not be a parent path") + } + if tests.HasCallerSameNamespace() { + t.Errorf(cur + " should not be from the same namespace") + } +} From 78f73b44a306932408d4f4d3498ab0d7db319fbf Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Wed, 12 Jun 2024 18:00:55 +0200 Subject: [PATCH 2/6] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- .../gno.land/p/demo/nestedpkg/nestedpkg.gno | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/examples/gno.land/p/demo/nestedpkg/nestedpkg.gno b/examples/gno.land/p/demo/nestedpkg/nestedpkg.gno index fe8a13188c0..cf44dae007b 100644 --- a/examples/gno.land/p/demo/nestedpkg/nestedpkg.gno +++ b/examples/gno.land/p/demo/nestedpkg/nestedpkg.gno @@ -1,5 +1,5 @@ // Package nestedpkg provides helpers for package-path based access control. -// It can be convenient for some upgrade patterns relying on namespaces. +// It is useful for upgrade patterns relying on namespaces. package nestedpkg import ( @@ -16,14 +16,14 @@ func IsCallerSubPath() bool { return strings.HasPrefix(prev, cur) } -// AssertCallerIsSubPath panics when IsCallerSubPath is false. +// AssertCallerIsSubPath panics if IsCallerSubPath returns false. func AssertCallerIsSubPath() { var ( cur = std.CurrentRealm().PkgPath() + "/" prev = std.PrevRealm().PkgPath() + "/" ) if !strings.HasPrefix(prev, cur) { - panic("call restricted to nested packages. current realm is " + cur + ", prev realm is " + prev) + panic("call restricted to nested packages. current realm is " + cur + ", previous realm is " + prev) } } @@ -36,16 +36,18 @@ func IsCallerParentPath() bool { return strings.HasPrefix(cur, prev) } +// AssertCallerIsParentPath panics if IsCallerParentPath returns false. func AssertCallerIsParentPath() { var ( cur = std.CurrentRealm().PkgPath() + "/" prev = std.PrevRealm().PkgPath() + "/" ) if !strings.HasPrefix(cur, prev) { - panic("call restricted to parent packages. current realm is " + cur + ", prev realm is " + prev) + panic("call restricted to parent packages. current realm is " + cur + ", previous realm is " + prev) } } +// IsSameNamespace checks if the caller realm and the current realm are in the same namespace. func IsSameNamespace() bool { var ( cur = nsFromPath(std.CurrentRealm().PkgPath()) + "/" @@ -54,27 +56,29 @@ func IsSameNamespace() bool { return cur == prev } +// AssertIsSameNamespace panics if IsSameNamespace returns false. func AssertIsSameNamespace() { var ( cur = nsFromPath(std.CurrentRealm().PkgPath()) + "/" prev = nsFromPath(std.PrevRealm().PkgPath()) + "/" ) if cur != prev { - panic("call restricted to packages from the same namespace. current realm is " + cur + ", prev realm is " + prev) + panic("call restricted to packages from the same namespace. current realm is " + cur + ", previous realm is " + prev) } } +// nsFromPath extracts the namespace from a package path. func nsFromPath(pkgpath string) string { parts := strings.Split(pkgpath, "/") - // specifically about gno.land, potential paths are in the form of DOMAIN/r/NAMESPACE/... - // XXX: consider extra checks. - // XXX: support non gno.land domains, where p/ and r/ won't be enforced. + // Specifically for gno.land, potential paths are in the form of DOMAIN/r/NAMESPACE/... + // XXX: Consider extra checks. + // XXX: Support non gno.land domains, where p/ and r/ won't be enforced. if len(parts) >= 3 { return parts[2] } return "" } -// XXX: consider adding IsCallerDirectlySubPath -// XXX: consider adding IsCallerDirectlyParentPath +// XXX: Consider adding IsCallerDirectlySubPath +// XXX: Consider adding IsCallerDirectlyParentPath From 32486388df8ff60a5f322ce5f0e14c05f645ab03 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Wed, 12 Jun 2024 18:07:19 +0200 Subject: [PATCH 3/6] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- examples/gno.land/p/demo/nestedpkg/gno.mod | 1 + examples/gno.land/r/demo/tests/tests.gno | 13 +++++++++++++ 2 files changed, 14 insertions(+) create mode 100644 examples/gno.land/p/demo/nestedpkg/gno.mod diff --git a/examples/gno.land/p/demo/nestedpkg/gno.mod b/examples/gno.land/p/demo/nestedpkg/gno.mod new file mode 100644 index 00000000000..3f913bbff43 --- /dev/null +++ b/examples/gno.land/p/demo/nestedpkg/gno.mod @@ -0,0 +1 @@ +module nestedpkg diff --git a/examples/gno.land/r/demo/tests/tests.gno b/examples/gno.land/r/demo/tests/tests.gno index 773412c3db9..421ac6528c9 100644 --- a/examples/gno.land/r/demo/tests/tests.gno +++ b/examples/gno.land/r/demo/tests/tests.gno @@ -3,6 +3,7 @@ package tests import ( "std" + "gno.land/p/demo/nestedpkg" rsubtests "gno.land/r/demo/tests/subtests" ) @@ -99,3 +100,15 @@ func GetRSubtestsPrevRealm() std.Realm { func Exec(fn func()) { fn() } + +func IsCallerSubPath() bool { + return nestedpkg.IsCallerSubPath() +} + +func IsCallerParentPath() bool { + return nestedpkg.IsCallerParentPath() +} + +func HasCallerSameNamespace() bool { + return nestedpkg.IsSameNamespace() +} From 0285026d8b046c5f228287bd18048bf3b4aa8940 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Wed, 12 Jun 2024 18:39:12 +0200 Subject: [PATCH 4/6] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- examples/gno.land/p/demo/nestedpkg/gno.mod | 2 ++ examples/gno.land/p/demo/nestedpkg/nestedpkg_test.gno | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/gno.land/p/demo/nestedpkg/gno.mod b/examples/gno.land/p/demo/nestedpkg/gno.mod index 3f913bbff43..b6071128815 100644 --- a/examples/gno.land/p/demo/nestedpkg/gno.mod +++ b/examples/gno.land/p/demo/nestedpkg/gno.mod @@ -1 +1,3 @@ module nestedpkg + +require gno.land/r/demo/tests v0.0.0-latest diff --git a/examples/gno.land/p/demo/nestedpkg/nestedpkg_test.gno b/examples/gno.land/p/demo/nestedpkg/nestedpkg_test.gno index f3b674cc5f0..bc0a98f47fb 100644 --- a/examples/gno.land/p/demo/nestedpkg/nestedpkg_test.gno +++ b/examples/gno.land/p/demo/nestedpkg/nestedpkg_test.gno @@ -4,7 +4,6 @@ import ( "std" "testing" - "gno.land/p/demo/nestedpkg" "gno.land/r/demo/tests" ) From d6dd0a4e4fe20271872cf2c416a672e0920770bd Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Wed, 12 Jun 2024 18:59:22 +0200 Subject: [PATCH 5/6] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- examples/gno.land/r/demo/tests/gno.mod | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/gno.land/r/demo/tests/gno.mod b/examples/gno.land/r/demo/tests/gno.mod index 9c5162f848e..e48dc60f217 100644 --- a/examples/gno.land/r/demo/tests/gno.mod +++ b/examples/gno.land/r/demo/tests/gno.mod @@ -1,6 +1,7 @@ module gno.land/r/demo/tests require ( + gno.land/p/demo/nestedpkg v0.0.0-latest gno.land/p/demo/testutils v0.0.0-latest gno.land/r/demo/tests/subtests v0.0.0-latest ) From 46da63b0e99e25f303ae458cd92bcc30f1eee1a3 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Tue, 2 Jul 2024 20:39:29 +0200 Subject: [PATCH 6/6] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- examples/gno.land/r/demo/tests/gno.mod | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/gno.land/r/demo/tests/gno.mod b/examples/gno.land/r/demo/tests/gno.mod index e48dc60f217..c51571e7d04 100644 --- a/examples/gno.land/r/demo/tests/gno.mod +++ b/examples/gno.land/r/demo/tests/gno.mod @@ -2,6 +2,5 @@ module gno.land/r/demo/tests require ( gno.land/p/demo/nestedpkg v0.0.0-latest - gno.land/p/demo/testutils v0.0.0-latest gno.land/r/demo/tests/subtests v0.0.0-latest )