e2e/teams_test.go

61564b7c32807deb349e28f2b5c6909cb4143870
gitbay/e2e/teams_test.go history · blame · raw

119 lines · 5208 bytes

  1package e2e
  2
  3import (
  4	"strings"
  5	"testing"
  6)
  7
  8func TestOrgTeams(t *testing.T) {
  9	inst := startInstance(t)
 10	adminKey := inst.newKey(t, "alice")
 11	bobKey := inst.newKey(t, "bob")
 12	carolKey := inst.newKey(t, "carol")
 13	eveKey := inst.newKey(t, "eve")
 14	inst.admin(t, "admin", "user", "create", "alice", "--key", adminKey+".pub")
 15	inst.admin(t, "admin", "user", "create", "bob", "--key", bobKey+".pub")
 16	inst.admin(t, "admin", "user", "create", "carol", "--key", carolKey+".pub")
 17	inst.admin(t, "admin", "user", "create", "eve", "--key", eveKey+".pub")
 18
 19	// Org with two private repos; bob and carol are plain members.
 20	for _, args := range [][]string{
 21		{"org", "create", "acme"},
 22		{"org", "members", "add", "acme", "bob"},
 23		{"org", "members", "add", "acme", "carol"},
 24		{"repo", "create", "acme/core", "--private"},
 25		{"repo", "create", "acme/site", "--private"},
 26	} {
 27		if _, errOut, code := inst.ssh(t, adminKey, "", args...); code != 0 {
 28			t.Fatalf("%v: %s", args, errOut)
 29		}
 30	}
 31
 32	// Degenerate case: plain membership implies write everywhere.
 33	if _, _, code := inst.ssh(t, bobKey, "", "issue", "create", "acme/core", "--title", "'pre'"); code != 0 {
 34		t.Fatal("member write lost (degenerate case broken)")
 35	}
 36
 37	// Scope the org: members get nothing by default, teams grant.
 38	if _, _, code := inst.ssh(t, bobKey, "", "org", "settings", "members-role", "acme", "none"); code != 4 {
 39		t.Fatal("non-admin changed members-role")
 40	}
 41	if _, _, code := inst.ssh(t, adminKey, "", "org", "settings", "members-role", "acme", "none"); code != 0 {
 42		t.Fatal("members-role failed")
 43	}
 44	// bob now cannot even see the private repo.
 45	if _, _, code := inst.ssh(t, bobKey, "", "repo", "show", "acme/core"); code != 3 {
 46		t.Fatal("scoped member still sees private repo")
 47	}
 48
 49	// Team "core-devs": bob gets write on core, read on site.
 50	if _, _, code := inst.ssh(t, adminKey, "", "org", "team", "create", "acme", "core-devs"); code != 0 {
 51		t.Fatal("team create failed")
 52	}
 53	if _, errOut, code := inst.ssh(t, adminKey, "", "org", "team", "add", "acme", "core-devs", "eve"); code != 2 || !strings.Contains(errOut, "not a member") {
 54		t.Fatalf("non-member added to team: %d %s", code, errOut)
 55	}
 56	if _, _, code := inst.ssh(t, adminKey, "", "org", "team", "add", "acme", "core-devs", "bob"); code != 0 {
 57		t.Fatal("team add failed")
 58	}
 59	if _, _, code := inst.ssh(t, adminKey, "", "org", "team", "grant", "acme", "core-devs", "acme/core", "write"); code != 0 {
 60		t.Fatal("team grant failed")
 61	}
 62	if _, _, code := inst.ssh(t, adminKey, "", "org", "team", "grant", "acme", "core-devs", "acme/site", "read"); code != 0 {
 63		t.Fatal("second grant failed")
 64	}
 65	// Grants are limited to the org's own repos.
 66	if _, _, code := inst.ssh(t, adminKey, "", "repo", "create", "alice/own"); code != 0 {
 67		t.Fatal("repo create failed")
 68	}
 69	if _, errOut, code := inst.ssh(t, adminKey, "", "org", "team", "grant", "acme", "core-devs", "alice/own", "read"); code != 2 || !strings.Contains(errOut, "own org") {
 70		t.Fatalf("cross-org grant allowed: %d %s", code, errOut)
 71	}
 72
 73	// bob: write on core (can open issues), read-only on site (visible,
 74	// not writable). carol (no team): nothing.
 75	if _, _, code := inst.ssh(t, bobKey, "", "issue", "create", "acme/core", "--title", "'works'"); code != 0 {
 76		t.Fatal("team write not effective")
 77	}
 78	if _, _, code := inst.ssh(t, bobKey, "", "repo", "show", "acme/site"); code != 0 {
 79		t.Fatal("team read not effective")
 80	}
 81	if _, _, code := inst.ssh(t, bobKey, "", "repo", "settings", "protect", "acme/site", "main"); code != 4 {
 82		t.Fatal("read grant allowed admin action")
 83	}
 84	if _, _, code := inst.ssh(t, carolKey, "", "repo", "show", "acme/core"); code != 3 {
 85		t.Fatal("teamless member sees scoped repo")
 86	}
 87	out, _, _ := inst.ssh(t, bobKey, "", "repo", "list")
 88	if !strings.Contains(out, "acme/core") || !strings.Contains(out, "acme/site") {
 89		t.Fatalf("team repos missing from listing: %s", out)
 90	}
 91
 92	// show reflects members and grants; member removal drops access.
 93	out, _, _ = inst.ssh(t, adminKey, "", "org", "team", "show", "acme", "core-devs", "--json")
 94	if !strings.Contains(out, `"members":["bob"]`) || !strings.Contains(out, `"repo":"acme/core","role":"write"`) {
 95		t.Fatalf("team show: %s", out)
 96	}
 97	if _, _, code := inst.ssh(t, adminKey, "", "org", "team", "remove", "acme", "core-devs", "bob"); code != 0 {
 98		t.Fatal("team remove failed")
 99	}
100	if _, _, code := inst.ssh(t, bobKey, "", "repo", "show", "acme/core"); code != 3 {
101		t.Fatal("removed member kept access")
102	}
103
104	// Deleting the team cascades its grants.
105	inst.ssh(t, adminKey, "", "org", "team", "add", "acme", "core-devs", "carol")
106	if _, _, code := inst.ssh(t, carolKey, "", "repo", "show", "acme/core"); code != 0 {
107		t.Fatal("carol team access missing")
108	}
109	if _, _, code := inst.ssh(t, adminKey, "", "org", "team", "delete", "acme", "core-devs"); code != 0 {
110		t.Fatal("team delete failed")
111	}
112	if _, _, code := inst.ssh(t, carolKey, "", "repo", "show", "acme/core"); code != 3 {
113		t.Fatal("deleted team's grant survived")
114	}
115	// Org admins keep admin regardless of scoping.
116	if _, _, code := inst.ssh(t, adminKey, "", "repo", "settings", "protect", "acme/core", "main"); code != 0 {
117		t.Fatal("org admin lost access")
118	}
119}