package store import "testing" // tree: company > engineering > backend, company > sales func aclFixture() *State { s := newState() s.Groups["company"] = &Group{ID: "company", Name: "Company"} s.Groups["eng"] = &Group{ID: "eng", Name: "Engineering", ParentID: "company"} s.Groups["backend"] = &Group{ID: "backend", Name: "Backend", ParentID: "eng"} s.Groups["sales"] = &Group{ID: "sales", Name: "Sales", ParentID: "company"} s.Users["alice"] = &User{ID: "alice", Username: "alice"} s.Users["bob"] = &User{ID: "bob", Username: "bob"} s.Users["root"] = &User{ID: "root", Username: "root", ServerAdmin: true} s.Memberships = []Membership{ {UserID: "alice", GroupID: "backend", Role: RoleMember}, {UserID: "bob", GroupID: "sales", Role: RoleAdmin}, } s.Databases["shared"] = &Database{ID: "shared", Name: "Shared", OwnerGroupID: "company"} s.Databases["salesdb"] = &Database{ID: "salesdb", Name: "Sales", OwnerGroupID: "sales"} s.Grants = []Grant{ {GroupID: "company", DatabaseID: "shared", Perm: PermRead}, {GroupID: "eng", DatabaseID: "shared", Perm: PermWrite}, } return s } func TestGrantOnAncestorReachesDescendantMember(t *testing.T) { s := aclFixture() if got := s.DatabasePerm("alice", "shared"); got != PermWrite { t.Fatalf("alice on shared = %q, want write (read from company, write from eng)", got) } } func TestGrantDoesNotLeakAcrossSiblings(t *testing.T) { s := aclFixture() if got := s.DatabasePerm("alice", "salesdb"); got != PermNone { t.Fatalf("alice on salesdb = %q, want none", got) } if got := s.DatabasePerm("bob", "shared"); got != PermRead { t.Fatalf("bob on shared = %q, want read", got) } } func TestOwnerGroupAdminGetsAdmin(t *testing.T) { s := aclFixture() if got := s.DatabasePerm("bob", "salesdb"); got != PermAdmin { t.Fatalf("bob on own group db = %q, want admin", got) } if !s.IsGroupAdmin("root", "backend") { t.Fatal("server admin should administer any group") } if s.IsGroupAdmin("bob", "eng") { t.Fatal("sales admin must not administer engineering") } } func TestAdminOfParentAdministersChild(t *testing.T) { s := aclFixture() s.Memberships = append(s.Memberships, Membership{UserID: "alice", GroupID: "company", Role: RoleAdmin}) if !s.IsGroupAdmin("alice", "backend") { t.Fatal("company admin should administer backend") } if got := s.DatabasePerm("alice", "salesdb"); got != PermAdmin { t.Fatalf("company admin on salesdb = %q, want admin", got) } } func TestAssignmentsAndWatchers(t *testing.T) { s := aclFixture() got := s.Assignments("alice") if len(got) != 1 || got[0].DB.ID != "shared" || got[0].Perm != PermWrite { t.Fatalf("alice assignments = %+v", got) } w := s.Watchers("shared") if len(w) != 3 { t.Fatalf("watchers of shared = %v, want alice, bob and root", w) } } func TestTreeWalksSurviveCycle(t *testing.T) { s := aclFixture() s.Groups["company"].ParentID = "backend" // corrupt if len(s.Ancestors("backend")) != 3 { t.Fatalf("cycle walk = %v", s.Ancestors("backend")) } if len(s.Descendants("company")) == 0 { t.Fatal("descendants must terminate on a cycle") } }