nestedpkg.gno
2.76 Kb ยท 89 lines
1// Package nestedpkg provides helpers for package-path based access control.
2// It is useful for upgrade patterns relying on namespaces.
3package nestedpkg
4
5// To test this from a realm and have std.CurrentRealm/PreviousRealm work correctly,
6// this file is tested from gno.land/r/demo/tests/nestedpkg_test.gno
7// XXX: move test to ths directory once we support testing a package and
8// specifying values for both PreviousRealm and CurrentRealm.
9
10import (
11 "std"
12 "strings"
13)
14
15// IsCallerSubPath checks if the caller realm is located in a subfolder of the current realm.
16func IsCallerSubPath() bool {
17 var (
18 cur = std.CurrentRealm().PkgPath() + "/"
19 prev = std.PreviousRealm().PkgPath() + "/"
20 )
21 return strings.HasPrefix(prev, cur)
22}
23
24// AssertCallerIsSubPath panics if IsCallerSubPath returns false.
25func AssertCallerIsSubPath() {
26 var (
27 cur = std.CurrentRealm().PkgPath() + "/"
28 prev = std.PreviousRealm().PkgPath() + "/"
29 )
30 if !strings.HasPrefix(prev, cur) {
31 panic("call restricted to nested packages. current realm is " + cur + ", previous realm is " + prev)
32 }
33}
34
35// IsCallerParentPath checks if the caller realm is located in a parent location of the current realm.
36func IsCallerParentPath() bool {
37 var (
38 cur = std.CurrentRealm().PkgPath() + "/"
39 prev = std.PreviousRealm().PkgPath() + "/"
40 )
41 return strings.HasPrefix(cur, prev)
42}
43
44// AssertCallerIsParentPath panics if IsCallerParentPath returns false.
45func AssertCallerIsParentPath() {
46 var (
47 cur = std.CurrentRealm().PkgPath() + "/"
48 prev = std.PreviousRealm().PkgPath() + "/"
49 )
50 if !strings.HasPrefix(cur, prev) {
51 panic("call restricted to parent packages. current realm is " + cur + ", previous realm is " + prev)
52 }
53}
54
55// IsSameNamespace checks if the caller realm and the current realm are in the same namespace.
56func IsSameNamespace() bool {
57 var (
58 cur = nsFromPath(std.CurrentRealm().PkgPath()) + "/"
59 prev = nsFromPath(std.PreviousRealm().PkgPath()) + "/"
60 )
61 return cur == prev
62}
63
64// AssertIsSameNamespace panics if IsSameNamespace returns false.
65func AssertIsSameNamespace() {
66 var (
67 cur = nsFromPath(std.CurrentRealm().PkgPath()) + "/"
68 prev = nsFromPath(std.PreviousRealm().PkgPath()) + "/"
69 )
70 if cur != prev {
71 panic("call restricted to packages from the same namespace. current realm is " + cur + ", previous realm is " + prev)
72 }
73}
74
75// nsFromPath extracts the namespace from a package path.
76func nsFromPath(pkgpath string) string {
77 parts := strings.Split(pkgpath, "/")
78
79 // Specifically for gno.land, potential paths are in the form of DOMAIN/r/NAMESPACE/...
80 // XXX: Consider extra checks.
81 // XXX: Support non gno.land domains, where p/ and r/ won't be enforced.
82 if len(parts) >= 3 {
83 return parts[2]
84 }
85 return ""
86}
87
88// XXX: Consider adding IsCallerDirectlySubPath
89// XXX: Consider adding IsCallerDirectlyParentPath