Artifact f58aaacbc2dfa3ce70e4dcf2cc31b1adab1cc315f665b87f249af012827be463:
- File
internal/oltp/caps_test.go
— part of check-in
[be3686ccbe]
at
2026-08-22 14:19:19
on branch fossil-caps
— caps phase 1: fossil cap strings in OLTP, EffectiveCaps expansion, roles→caps migration
RFC 0004 §3/§5. v never implies u; a excludes s x y; s is universal; blank nobody+anonymous = private. Migration runs on every open, idempotent, never clobbers explicit caps. (user: dmestas, size: 5202) [annotate] [blame] [check-ins using] [more...]
package oltp import "testing" // The expansion rules are fossil's, kept exactly (RFC 0004 §3): every // visitor holds the nobody set; logging in adds anonymous; u inherits // the reader category, v the developer category — and v does NOT imply // u; a grants everything except s, x, y; s grants everything. func TestEffectiveCapsExpansion(t *testing.T) { db := testDB(t) // Anonymous visitor: stock nobody. eff := db.EffectiveCaps("", "r") for _, c := range []string{"g", "j", "o", "r", "z"} { if !eff.HasAny(c) { t.Fatalf("visitor lacks nobody cap %q (eff=%q)", c, eff) } } if eff.HasAny("h") || eff.HasAny("i") { t.Fatalf("visitor holds login-gated caps: %q", eff) } // A signed-in account with no explicit caps: nobody + anonymous. if err := db.AddAccount("plain", "pw12345678", false); err != nil { t.Fatal(err) } eff = db.EffectiveCaps("plain", "r") for _, c := range []string{"h", "m", "n", "c", "o"} { if !eff.HasAny(c) { t.Fatalf("signed-in lacks %q (eff=%q)", c, eff) } } if eff.HasAny("k") || eff.HasAny("i") { t.Fatalf("signed-in holds category caps unasked: %q", eff) } // u inherits the reader category (stock kptw). if err := db.SetCaps("plain", "r", "u"); err != nil { t.Fatal(err) } eff = db.EffectiveCaps("plain", "r") if !eff.HasAny("k") || !eff.HasAny("w") { t.Fatalf("u did not expand to reader caps: %q", eff) } if eff.HasAny("i") { t.Fatalf("u granted developer caps: %q", eff) } // v inherits developer (stock ei) — and NOT reader. Fossil's trap, // kept deliberately. if err := db.SetCaps("plain", "r", "v"); err != nil { t.Fatal(err) } eff = db.EffectiveCaps("plain", "r") if !eff.HasAny("i") || !eff.HasAny("e") { t.Fatalf("v did not expand to developer caps: %q", eff) } if eff.HasAny("k") || eff.HasAny("w") { t.Fatalf("v implied u — fossil's rule broken: %q", eff) } } func TestAdminAndSetupRules(t *testing.T) { db := testDB(t) if err := db.AddAccount("boss", "pw12345678", false); err != nil { t.Fatal(err) } if err := db.SetCaps("boss", "r", "a"); err != nil { t.Fatal(err) } eff := db.EffectiveCaps("boss", "r") for _, c := range []string{"i", "k", "w", "5", "e"} { if !eff.HasAny(c) { t.Fatalf("a does not grant %q", c) } } for _, c := range []string{"s", "x", "y"} { if eff.HasAny(c) { t.Fatalf("a granted excluded cap %q", c) } } // s grants everything, including the exclusions. if err := db.SetCaps("boss", "r", "s"); err != nil { t.Fatal(err) } eff = db.EffectiveCaps("boss", "r") for _, c := range []string{"a", "s", "x", "y", "i", "5"} { if !eff.HasAny(c) { t.Fatalf("s does not grant %q", c) } } // The site-admin account flag IS s, everywhere. if err := db.AddAccount("root", "pw12345678", true); err != nil { t.Fatal(err) } if !db.EffectiveCaps("root", "anything").HasAny("s") { t.Fatal("site admin lacks s") } } func TestPerRepoCategoryOverride(t *testing.T) { db := testDB(t) // A repo "taken private": nobody and anonymous blanked (fossil's // Security-Audit action). Visitors hold nothing. if err := db.SetCategoryCaps("priv", "nobody", ""); err != nil { t.Fatal(err) } if err := db.SetCategoryCaps("priv", "anonymous", ""); err != nil { t.Fatal(err) } if eff := db.EffectiveCaps("", "priv"); eff.HasAny("gjorz2h") { t.Fatalf("private repo leaks visitor caps: %q", eff) } // Another repo on the same forge keeps stock defaults. if eff := db.EffectiveCaps("", "open"); !eff.HasAny("o") { t.Fatalf("open repo lost stock nobody: %q", eff) } } func TestRoleRowsTranslateToCaps(t *testing.T) { db := testDB(t) must := func(err error) { t.Helper() if err != nil { t.Fatal(err) } } must(db.AddAccount("r1", "pw12345678", false)) must(db.AddAccount("w1", "pw12345678", false)) must(db.AddAccount("a1", "pw12345678", false)) must(db.Grant("r1", "repo", Read)) must(db.Grant("w1", "repo", Write)) must(db.Grant("a1", "repo", RepoAdmin)) must(db.MigrateRolesToCaps()) if eff := db.EffectiveCaps("r1", "repo"); !eff.HasAny("k") || eff.HasAny("i") { t.Fatalf("read→u wrong: %q", eff) } if eff := db.EffectiveCaps("w1", "repo"); !eff.HasAny("k") || !eff.HasAny("i") { t.Fatalf("write→uv wrong: %q", eff) } if eff := db.EffectiveCaps("a1", "repo"); !eff.HasAny("5") || eff.HasAny("s") { t.Fatalf("admin→a wrong: %q", eff) } // Migration is idempotent and never clobbers explicit caps. must(db.SetCaps("r1", "repo", "uv")) must(db.MigrateRolesToCaps()) if eff := db.EffectiveCaps("r1", "repo"); !eff.HasAny("i") { t.Fatalf("migration clobbered explicit caps: %q", eff) } } func TestPurgeRepoSweepsCaps(t *testing.T) { db := testDB(t) if err := db.AddAccount("u1", "pw12345678", false); err != nil { t.Fatal(err) } if err := db.SetCaps("u1", "gone", "uv"); err != nil { t.Fatal(err) } if err := db.SetCategoryCaps("gone", "nobody", ""); err != nil { t.Fatal(err) } if err := db.PurgeRepo("gone"); err != nil { t.Fatal(err) } if caps, _ := db.CapsOf("u1", "gone"); caps != "" { t.Fatalf("caps survived purge: %q", caps) } if eff := db.EffectiveCaps("", "gone"); !eff.HasAny("o") { t.Fatal("category override survived purge (stock should return)") } }