Skip to content
quarry Artifact [33e3d03cc7]
Login

Artifact [33e3d03cc7]

Artifact 33e3d03cc759da70e9b954b6b0120a0f9e43b64f8b446fae7783d7be95366301:


package oltp

import "testing"

// The gate that let a stranger write. A repository created through
// repo.add has no sync users, and "no sync users" used to mean "anyone
// may push" — so every fresh public repository on an internet-facing
// forge accepted a check-in from nobody at all. The letters decide now.
func TestNoSyncUsersFallsBackToTheLetters(t *testing.T) {
	db := testDB(t)
	// Stock: a signed-out visitor holds the nobody category, which
	// carries no i. No sync users, and still gated.
	if !db.Gated("fresh") {
		t.Error("a fresh repository accepted an unauthenticated push")
	}
	if eff := db.EffectiveCaps("", "fresh"); eff.HasAny("i") {
		t.Fatalf("premise broken: a signed-out visitor already holds i (%q)", eff)
	}
}

// The opt-in still works, so a single-user local forge is not broken by
// closing the default. This is the case RFC 0001 §7 wanted; it just
// has to be asked for now.
func TestAnonymousPushIsAnOptInThroughTheLetters(t *testing.T) {
	db := testDB(t)
	if err := db.SetCategoryCaps("local", "nobody", "i"); err != nil {
		t.Fatal(err)
	}
	if db.Gated("local") {
		t.Error("a repository whose nobody category grants i still refused an anonymous push")
	}
}

// i reached through a category pull-in counts, because the gate asks
// the EXPANDED set. A raw string match would miss this and refuse a
// push the settings page says is allowed.
func TestInheritedCheckInOpensTheGate(t *testing.T) {
	db := testDB(t)
	// v pulls in the developer category; put i only there.
	if err := db.SetCategoryCaps("inherit", "nobody", "v"); err != nil {
		t.Fatal(err)
	}
	if err := db.SetCategoryCaps("inherit", "developer", "i"); err != nil {
		t.Fatal(err)
	}
	if !db.EffectiveCaps("", "inherit").HasAny("i") {
		t.Skip("this build does not expand v for a signed-out visitor")
	}
	if db.Gated("inherit") {
		t.Error("i inherited through v did not open the gate")
	}
}

// A credential row is NOT policy. This is the clause that caused the
// outage: Gated also answered true whenever the repository had any sync
// user, so provisioning one person closed the gate on a repository
// whose letters said anyone could push — and left it closed, because
// the only thing that could issue the row it now demanded was an admin
// running the CLI on the server.
//
// "Must a push authenticate" and "has anybody been issued a credential"
// are different questions. This one answers the first.
func TestACredentialRowIsNotPolicy(t *testing.T) {
	db := testDB(t)
	if err := db.SetCategoryCaps("named", "nobody", "i"); err != nil {
		t.Fatal(err)
	}
	if db.Gated("named") {
		t.Fatal("premise broken: the letters should have opened this")
	}
	if err := db.SetSyncUser("named", "dan", "secret"); err != nil {
		t.Fatal(err)
	}
	if db.Gated("named") {
		t.Error("issuing one person a credential closed the gate on everyone else")
	}
}

// A gate that cannot read its own table must refuse, not wave the
// caller through. This returned false — open — on any query error.
func TestGateFailsClosedWhenItCannotAsk(t *testing.T) {
	db := testDB(t)
	if err := db.SetCategoryCaps("broken", "nobody", "i"); err != nil {
		t.Fatal(err)
	}
	if db.Gated("broken") {
		t.Fatal("premise broken: this should be open before the database goes away")
	}
	// Close the handle underneath it: every query now errors.
	if err := db.db.Close(); err != nil {
		t.Fatal(err)
	}
	if !db.Gated("broken") {
		t.Error("a database that could not answer granted the write")
	}
}