From 5022826948fda8b6acb3ab7f80e4e1d71dc1cd89 Mon Sep 17 00:00:00 2001 From: OpenClaw Agent Date: Mon, 21 Sep 2026 18:32:57 +0800 Subject: [PATCH] fix: preserve composite permissions in account rules --- chfs-ng/cmd/chfs/main.go | 4 +-- chfs-ng/internal/auth/rules_test.go | 42 +++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 chfs-ng/internal/auth/rules_test.go diff --git a/chfs-ng/cmd/chfs/main.go b/chfs-ng/cmd/chfs/main.go index 2b288c4..90c8021 100644 --- a/chfs-ng/cmd/chfs/main.go +++ b/chfs-ng/cmd/chfs/main.go @@ -73,10 +73,10 @@ func main() { a.Rules = append(a.Rules, auth.PathRule{Dir: d, Mask: auth.Read, ChildrenOnly: true}) } for _, d := range ac.Write { - a.Rules = append(a.Rules, auth.PathRule{Dir: d, Mask: auth.Write, ChildrenOnly: true}) + a.Rules = append(a.Rules, auth.PathRule{Dir: d, Mask: auth.ParseMask("w"), ChildrenOnly: true}) } for _, d := range ac.Delete { - a.Rules = append(a.Rules, auth.PathRule{Dir: d, Mask: auth.Delete, ChildrenOnly: true}) + a.Rules = append(a.Rules, auth.PathRule{Dir: d, Mask: auth.ParseMask("d"), ChildrenOnly: true}) } if ac.Username == "guest" { mgr.Guest = a diff --git a/chfs-ng/internal/auth/rules_test.go b/chfs-ng/internal/auth/rules_test.go new file mode 100644 index 0000000..1510d7f --- /dev/null +++ b/chfs-ng/internal/auth/rules_test.go @@ -0,0 +1,42 @@ +package auth + +import "testing" + +func TestPathRuleSemantics(t *testing.T) { + a := &Account{Mask: ParseMask("r")} + a.Rules = []PathRule{ + {Dir: "private", Deny: true}, + {Dir: "share", Mask: ParseMask("w"), ChildrenOnly: true}, + {Dir: "drop", Mask: ParseMask("d"), ChildrenOnly: true}, + {Dir: "pub*", Mask: ParseMask("r")}, + } + cases := []struct{ path, want string }{ + {"", "R"}, + {"private", ""}, + {"private/x.txt", ""}, + {"share", "R"}, + {"share/x.txt", "RW"}, + {"drop", "R"}, + {"drop/x.txt", "RWD"}, + {"public/x.txt", "R"}, + {"public/sub/x.txt", "R"}, + } + for _, tc := range cases { + if got := permStringForTest(a.MaskFor(tc.path)); got != tc.want { + t.Errorf("MaskFor(%q)=%q want %q", tc.path, got, tc.want) + } + } +} + +func permStringForTest(p PermMask) string { + if p.HasDelete() { + return "RWD" + } + if p.HasWrite() { + return "RW" + } + if p.HasRead() { + return "R" + } + return "" +}