From 90e9fda90c9904e273c30ed6563eb4e15de915e6 Mon Sep 17 00:00:00 2001 From: Leonard Gram Date: Fri, 8 Mar 2019 15:46:15 +0100 Subject: [PATCH] teams: start of team update guardian for editors --- pkg/models/team.go | 8 +- pkg/services/teams/team.go | 35 ++++++ pkg/services/teams/teams_test.go | 176 +++++++++++++++++++++++++------ 3 files changed, 183 insertions(+), 36 deletions(-) diff --git a/pkg/models/team.go b/pkg/models/team.go index 61285db3a5f..bd0d803d9d3 100644 --- a/pkg/models/team.go +++ b/pkg/models/team.go @@ -7,9 +7,11 @@ import ( // Typed errors var ( - ErrTeamNotFound = errors.New("Team not found") - ErrTeamNameTaken = errors.New("Team name is taken") - ErrTeamMemberNotFound = errors.New("Team member not found") + ErrTeamNotFound = errors.New("Team not found") + ErrTeamNameTaken = errors.New("Team name is taken") + ErrTeamMemberNotFound = errors.New("Team member not found") + ErrNotAllowedToUpdateTeam = errors.New("User not allowed to update team") + ErrNotAllowedToUpdateTeamInDifferentOrg = errors.New("User not allowed to update team in another org") ) // Team model diff --git a/pkg/services/teams/team.go b/pkg/services/teams/team.go index 4bd4b78d587..7ff18820b62 100644 --- a/pkg/services/teams/team.go +++ b/pkg/services/teams/team.go @@ -5,6 +5,41 @@ import ( m "github.com/grafana/grafana/pkg/models" ) +func canUpdateTeam(orgId int64, teamId int64, user m.SignedInUser) error { + if user.OrgRole == m.ROLE_ADMIN { + return nil + } + + if user.OrgId != orgId { + return m.ErrNotAllowedToUpdateTeamInDifferentOrg + } + + cmd := m.GetTeamMembersQuery{ + OrgId: orgId, + TeamId: teamId, + UserId: user.UserId, + // TODO: do we need to do something special about external users + // External: false, + } + + if err := bus.Dispatch(&cmd); err != nil { + // TODO: look into how we want to do logging + return err + } + + for _, member := range cmd.Result { + if member.UserId == user.UserId && member.Permission == int64(m.PERMISSION_ADMIN) { + return nil + } + } + + return m.ErrNotAllowedToUpdateTeam +} + func UpdateTeam(user m.SignedInUser, cmd *m.UpdateTeamCommand) error { + if err := canUpdateTeam(cmd.OrgId, cmd.Id, user); err != nil { + return err + } + return bus.Dispatch(cmd) } diff --git a/pkg/services/teams/teams_test.go b/pkg/services/teams/teams_test.go index aaa19440bb4..9dd42e1add5 100644 --- a/pkg/services/teams/teams_test.go +++ b/pkg/services/teams/teams_test.go @@ -1,42 +1,152 @@ package teams import ( - . "github.com/smartystreets/goconvey/convey" + "github.com/grafana/grafana/pkg/bus" m "github.com/grafana/grafana/pkg/models" + "github.com/pkg/errors" + . "github.com/smartystreets/goconvey/convey" + "testing" ) - func TestUpdateTeam(t *testing.T) { - Convey("Updating a team as an editor", t, func() { + Convey("Updating a team", t, func() { + bus.ClearBusHandlers() Convey("Given an editor and a team he isn't a member of", func() { - - UpdateTeam(editor, m.UpdateTeamCommand{ - Id: 0, - Name: "", - Email: "", - OrgId: 0, + editor := m.SignedInUser{ + UserId: 1, + OrgId: 1, + OrgRole: m.ROLE_EDITOR, + } + + Convey("Should not be able to update the team", func() { + cmd := m.UpdateTeamCommand{ + Id: 1, + OrgId: editor.OrgId, + } + + bus.AddHandler("test", func(cmd *m.UpdateTeamCommand) error { + return errors.New("Editor not allowed to update team.") + }) + bus.AddHandler("test", func(cmd *m.GetTeamMembersQuery) error { + cmd.Result = []*m.TeamMemberDTO{} + return nil + }) + + err := UpdateTeam(editor, &cmd) + + So(err, ShouldEqual, m.ErrNotAllowedToUpdateTeam) + }) + }) + + Convey("Given an editor and a team he is a member of", func() { + editor := m.SignedInUser{ + UserId: 1, + OrgId: 1, + OrgRole: m.ROLE_EDITOR, + } + + testTeam := m.Team{ + Id: 1, + OrgId: 1, + } + + Convey("Should be able to update the team", func() { + cmd := m.UpdateTeamCommand{ + Id: testTeam.Id, + OrgId: testTeam.OrgId, + } + + teamUpdated := false + + bus.AddHandler("test", func(cmd *m.UpdateTeamCommand) error { + teamUpdated = true + return nil + }) + + bus.AddHandler("test", func(cmd *m.GetTeamMembersQuery) error { + cmd.Result = []*m.TeamMemberDTO{{ + OrgId: testTeam.OrgId, + TeamId: testTeam.Id, + UserId: editor.UserId, + Permission: int64(m.PERMISSION_ADMIN), + }} + return nil + }) + + err := UpdateTeam(editor, &cmd) + + So(teamUpdated, ShouldBeTrue) + So(err, ShouldBeNil) + }) + }) + + Convey("Given an editor and a team in another org", func() { + editor := m.SignedInUser{ + UserId: 1, + OrgId: 1, + OrgRole: m.ROLE_EDITOR, + } + + testTeam := m.Team{ + Id: 1, + OrgId: 2, + } + + Convey("Shouldn't be able to update the team", func() { + cmd := m.UpdateTeamCommand{ + Id: testTeam.Id, + OrgId: testTeam.OrgId, + } + + bus.AddHandler("test", func(cmd *m.UpdateTeamCommand) error { + return errors.New("Can't update a team in a different org.") + }) + bus.AddHandler("test", func(cmd *m.GetTeamMembersQuery) error { + cmd.Result = []*m.TeamMemberDTO{{ + OrgId: testTeam.OrgId, + TeamId: testTeam.Id, + UserId: editor.UserId, + Permission: int64(m.PERMISSION_ADMIN), + }} + return nil + }) + + err := UpdateTeam(editor, &cmd) + + So(err, ShouldEqual, m.ErrNotAllowedToUpdateTeamInDifferentOrg) + }) + }) + + Convey("Given an org admin and a team", func() { + editor := m.SignedInUser{ + UserId: 1, + OrgId: 1, + OrgRole: m.ROLE_ADMIN, + } + + testTeam := m.Team{ + Id: 1, + OrgId: 1, + } + + Convey("Should be able to update the team", func() { + cmd := m.UpdateTeamCommand{ + Id: testTeam.Id, + OrgId: testTeam.OrgId, + } + + teamUpdated := false + + bus.AddHandler("test", func(cmd *m.UpdateTeamCommand) error { + teamUpdated = true + return nil + }) + + err := UpdateTeam(editor, &cmd) + + So(teamUpdated, ShouldBeTrue) + So(err, ShouldBeNil) + }) + }) }) - }) - - // the editor should not be able to update the team if they aren't members of it - - fakeDash := m.NewDashboard("Child dash") - fakeDash.Id = 1 - fakeDash.FolderId = 1 - fakeDash.HasAcl = false - - bus.AddHandler("test", func(query *m.GetDashboardsBySlugQuery) error { - dashboards := []*m.Dashboard{fakeDash} - query.Result = dashboards - return nil - }) - - var getDashboardQueries []*m.GetDashboardQuery - - bus.AddHandler("test", func(query *m.GetDashboardQuery) error { - query.Result = fakeDash - getDashboardQueries = append(getDashboardQueries, query) - return nil - }) - - bus.AddHandler("test", func(query *m.IsDashboardProvisionedQuery) error { +}