diff --git a/chfs-ng/internal/auth/auth_test.go b/chfs-ng/internal/auth/auth_test.go index 7804b3a..1def33e 100644 --- a/chfs-ng/internal/auth/auth_test.go +++ b/chfs-ng/internal/auth/auth_test.go @@ -51,3 +51,55 @@ func TestParseRulesGuestDefaultAndOverride(t *testing.T) { t.Fatalf("unexpected parsed masks: %#v %#v err=%v", m.Guest, m.Accounts["demo"], err) } } + +func TestSectionRuleSemantics(t *testing.T) { + a := &Account{Mask: Delete, Rules: []PathRule{ + {Dir: "private", Mask: None, Deny: true}, + {Dir: "readonly", Mask: ParseMask("r"), ChildrenOnly: true}, + {Dir: "writable", Mask: ParseMask("w"), ChildrenOnly: true}, + {Dir: "full", Mask: ParseMask("d"), ChildrenOnly: true}, + }} + if got := a.MaskFor("private"); got != None { + t.Fatalf("private=%v", got) + } + if got := a.MaskFor("private/file"); got != None { + t.Fatalf("private/file=%v", got) + } + if got := a.MaskForEntry("readonly"); got != Delete { + t.Fatalf("readonly entry=%v", got) + } + if got := a.MaskFor("readonly/file"); got != Read { + t.Fatalf("readonly/file=%v", got) + } + if got := a.MaskForEntry("writable"); got != Delete { + t.Fatalf("writable entry=%v", got) + } + if got := a.MaskFor("writable/file"); got != ParseMask("w") { + t.Fatalf("writable/file=%v", got) + } + if got := a.MaskForEntry("full"); got != Delete { + t.Fatalf("full entry=%v", got) + } + if got := a.MaskFor("full/file"); got != (Read | Write | Delete) { + t.Fatalf("full/file=%v", got) + } + if got := a.MaskForEntry("readonly"); got != Delete { + t.Fatalf("readonly entry mask=%v", got) + } + if got := a.MaskForEntry("private"); got != None { + t.Fatalf("private entry mask=%v", got) + } +} + +func TestWildcardSectionRules(t *testing.T) { + a := &Account{Mask: Read, Rules: []PathRule{{Dir: "project-*", Mask: Write, ChildrenOnly: true}}} + if got := a.MaskFor("project-one/file"); got != Write { + t.Fatalf("project-one/file=%v", got) + } + if got := a.MaskFor("project-two/file"); got != Write { + t.Fatalf("project-two/file=%v", got) + } + if got := a.MaskFor("project/file"); got != Read { + t.Fatalf("project/file=%v", got) + } +} diff --git a/chfs-ng/internal/config/config_test.go b/chfs-ng/internal/config/config_test.go new file mode 100644 index 0000000..1b27a70 --- /dev/null +++ b/chfs-ng/internal/config/config_test.go @@ -0,0 +1,46 @@ +package config + +import ( + "os" + "path/filepath" + "testing" +) + +func TestLoadAccountSections(t *testing.T) { + d := t.TempDir() + p := filepath.Join(d, "chfs.ini") + content := `path=/srv/share +port=8080 +[demo] +password=abc +rule.default=r +rule.none=secret|private +rule.r=docs +rule.r=public +rule.w=upload +rule.d=admin +[guest] +password= +rule.default= +rule.none=hidden +` + if err := os.WriteFile(p, []byte(content), 0600); err != nil { + t.Fatal(err) + } + c, err := Load(p) + if err != nil { + t.Fatal(err) + } + if len(c.Accounts) != 2 { + t.Fatalf("accounts=%d", len(c.Accounts)) + } + if c.Accounts[0].Username != "demo" || c.Accounts[0].Default != "r" { + t.Fatalf("demo=%#v", c.Accounts[0]) + } + if len(c.Accounts[0].Read) != 2 || c.Accounts[0].Read[0] != "docs" || c.Accounts[0].Read[1] != "public" { + t.Fatalf("read=%#v", c.Accounts[0].Read) + } + if len(c.Accounts[0].Write) != 1 || len(c.Accounts[0].Delete) != 1 || len(c.Accounts[0].None) != 2 { + t.Fatalf("rules=%#v", c.Accounts[0]) + } +}