package oltp
import "testing"
// RFC 0026 step 3: a personal agent scoped to one repository or one
// team inherits there and holds what any signed-in account holds
// everywhere else.
func TestAScopedAgentReachesOnlyItsScope(t *testing.T) {
db := agentRig(t)
for _, r := range []string{"priv", "priv2"} {
if r == "priv2" {
if err := db.AddRepo(r, t.TempDir(), "", Private); err != nil {
t.Fatal(err)
}
}
if err := db.Grant("dmestas", r, Write); err != nil {
t.Fatal(err)
}
}
if err := db.NewScopedAgent("priv-bot", "dmestas", "repo:priv", -1); err != nil {
t.Fatal(err)
}
if !db.EffectiveCaps("priv-bot", "priv").HasAny("i") {
t.Errorf("FAIL: a repository agent lacks its operator's check-in on its repository")
}
if got := db.EffectiveCaps("priv-bot", "priv2"); got.HasAny("o") {
t.Errorf("FAIL: a repository agent reads another private repository: %q", letters(got))
}
t.Log("ok: repository scope")
if err := db.AddTeam("crew", "", "", "dmestas"); err != nil {
t.Fatal(err)
}
if err := db.SetTeamMember("crew", "dmestas", "", true, true); err != nil {
t.Fatal(err)
}
if err := db.SetTeamRepo("crew", "priv2", "dmestas"); err != nil {
t.Fatal(err)
}
if err := db.NewScopedAgent("crew-bot", "dmestas", "team:crew", -1); err != nil {
t.Fatal(err)
}
if !db.EffectiveCaps("crew-bot", "priv2").HasAny("i") {
t.Errorf("FAIL: a team agent lacks check-in on its team's repository")
}
if got := db.EffectiveCaps("crew-bot", "priv"); got.HasAny("o") {
t.Errorf("FAIL: a team agent reads a repository outside its team: %q", letters(got))
}
t.Log("ok: team scope")
// Deleting the scope leaves the agent nothing, even under a name
// taken again.
if err := db.DeleteRepo("priv"); err != nil {
t.Fatal(err)
}
if a, _ := db.AccountByName("priv-bot"); a.Scope != "gone" {
t.Errorf("FAIL: after its repository was deleted the agent's scope is %q", a.Scope)
}
t.Log("ok: a deleted scope is gone")
}
func TestAScopeMustBeTheOperatorsToGive(t *testing.T) {
db := agentRig(t)
if err := db.NewScopedAgent("x-bot", "dmestas", "team:nobody", -1); err == nil {
t.Errorf("FAIL: an agent was scoped to a team its operator is not in")
}
if err := db.NewScopedAgent("y-bot", "dmestas", "repo:priv", -1); err == nil {
t.Errorf("FAIL: an agent was scoped to a private repository its operator cannot read")
}
if err := db.NewScopedAgent("z-bot", "dmestas", "fleet", -1); err == nil {
t.Errorf("FAIL: a scope that is no scope was accepted")
}
t.Log("ok: scope checks")
}
func TestTheRosterKeepsAScopedAgentInsideItsScope(t *testing.T) {
db := agentRig(t)
if err := db.Grant("dmestas", "priv", Write); err != nil {
t.Fatal(err)
}
if err := db.Grant("dmestas", "pub", Write); err != nil {
t.Fatal(err)
}
if err := db.NewScopedAgent("priv-bot", "dmestas", "repo:priv", -1); err != nil {
t.Fatal(err)
}
in := func(repo string) string {
hs, _ := db.CapHolders(repo)
for _, h := range hs {
if h.Account == "priv-bot" {
return h.Inherits
}
}
return ""
}
if in("priv") != "dmestas" || in("pub") != "" {
t.Errorf("FAIL: the roster shows the repository agent inheriting on priv=%q pub=%q", in("priv"), in("pub"))
}
t.Log("ok: roster within scope")
}