package oltp
import "testing"
// RFC 0026 steps 4 and 5: a repository's or a team's own agent holds
// what it was granted, inside its scope only, and never the flag.
func TestARepositoryAgentHoldsItsGrantThereOnly(t *testing.T) {
db := agentRig(t)
if err := db.NewDedicatedAgent("priv-ci", "repo:priv", "dmestas"); err != nil {
t.Fatal(err)
}
if db.EffectiveCaps("priv-ci", "priv").HasAny("o") {
t.Errorf("FAIL: a new repository agent holds something before a grant")
}
if err := db.Grant("priv-ci", "priv", Write); err != nil {
t.Fatal(err)
}
if !db.EffectiveCaps("priv-ci", "priv").HasAny("i") {
t.Errorf("FAIL: a repository agent granted developer cannot check in")
}
// A grant elsewhere does nothing: it is the repository's agent.
if err := db.SetRepoVisibility("pub", Private); err != nil {
t.Fatal(err)
}
if err := db.Grant("priv-ci", "pub", Write); err != nil {
t.Fatal(err)
}
if got := db.EffectiveCaps("priv-ci", "pub"); got.HasAny("o") {
t.Errorf("FAIL: a repository agent reaches another repository: %q", letters(got))
}
t.Log("ok: repository agent")
// It goes with its repository: disabled, tokens revoked, and no
// later repository of the name owns it.
if _, _, err := db.MintToken("priv-ci", TokenSpec{Name: "ci", Scopes: []string{ScopeAPI}}); err != nil {
t.Fatal(err)
}
if err := db.PurgeRepo("priv"); err != nil {
t.Fatal(err)
}
a, _ := db.AccountByName("priv-ci")
if a.Disabled == "" || a.Operator == "repo:priv" {
t.Errorf("FAIL: after its repository was deleted the agent is disabled=%q operator=%q", a.Disabled, a.Operator)
}
toks, _ := db.Tokens("priv-ci")
for _, tk := range toks {
if tk.Revoked == "" {
t.Errorf("FAIL: a deleted repository's agent kept a live token")
}
}
t.Log("ok: goes with its repository")
}
func TestATeamAgentReachesItsTeamsRepositories(t *testing.T) {
db := agentRig(t)
if err := db.AddTeam("crew", "", "", "dmestas"); err != nil {
t.Fatal(err)
}
if err := db.SetTeamRepo("crew", "priv", "dmestas"); err != nil {
t.Fatal(err)
}
if err := db.NewDedicatedAgent("crew-ci", "team:crew", "dmestas"); err != nil {
t.Fatal(err)
}
if err := db.SetTeamMember("crew", "crew-ci", Write.Caps(), false, true); err != nil {
t.Fatal(err)
}
if !db.EffectiveCaps("crew-ci", "priv").HasAny("i") {
t.Errorf("FAIL: a team agent added as a developer member cannot check in on the team's repository")
}
if err := db.SetRepoVisibility("pub", Private); err != nil {
t.Fatal(err)
}
if err := db.Grant("crew-ci", "pub", Write); err != nil {
t.Fatal(err)
}
if got := db.EffectiveCaps("crew-ci", "pub"); got.HasAny("o") {
t.Errorf("FAIL: a team agent reaches a repository outside its team: %q", letters(got))
}
t.Log("ok: team agent")
}
func TestADedicatedAgentNeedsARealScopeAndHasACap(t *testing.T) {
db := agentRig(t)
for _, s := range []string{"repo:nope", "team:nope", "site", ""} {
if err := db.NewDedicatedAgent("x-ci", s, "dmestas"); err == nil {
t.Errorf("FAIL: scope %q was accepted", s)
}
}
for i := 0; i < DedicatedAgentsPer; i++ {
if err := db.NewDedicatedAgent("ci-"+string(rune('a'+i)), "repo:pub", "dmestas"); err != nil {
t.Fatal(err)
}
}
if err := db.NewDedicatedAgent("ci-over", "repo:pub", "dmestas"); err == nil {
t.Errorf("FAIL: a repository took more than %d agents", DedicatedAgentsPer)
}
t.Log("ok: scope and cap")
}