Skip to content
quarry Artifact [f58aaacbc2]
Login

Artifact [f58aaacbc2]

Artifact f58aaacbc2dfa3ce70e4dcf2cc31b1adab1cc315f665b87f249af012827be463:


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)")
	}
}