From 19e5afd60746d16741d3016176ad9b4802638995 Mon Sep 17 00:00:00 2001 From: Ibrahim Serdar Acikgoz Date: Wed, 3 Jun 2020 14:14:21 +0300 Subject: [PATCH] [MM-24863] Migrate update/patch/search/delete team endpoints for local mode (#14581) * [MM-24146] Add unix socket listener for mmctl local mode (#14296) * add unix socket listener for mmctl local mode * add a constant for local-mode socket path * reflect review comments * [MM-24401] Base approach for Local Mode (#14333) * add unix socket listener for mmctl local mode * First working PoC * Adds the channel list endpoint * Add team list endpoint * Add a LocalClient to the api test helper and start local mode * Add helper to test with both SystemAdmin and Local clients * Add some docs * Adds TestForAllClients test helper * Incorporating @ashishbhate's proposal for adding test names to the helpers * Fix init errors after merge * Adds create channel tests * Always init local mode to allow for enabling-disabling it via config * Check the RemoteAddr of the request before marking session as local * Mark the request as errored if it's local and the origin is remote * Set the socket permissions to read/write when initialising * Fix linter * Replace RemoteAddr check to ditch connections with the IP:PORT shape Co-authored-by: Ibrahim Serdar Acikgoz * Fix translations order * [MM-24832] Migrate plugin endpoints to local mode (#14543) * [MM-24832] Migrate plugin endpoints to local mode * Fix client reference in helper * api4/team: add local endpoints * [MM-24776] Migrate config endpoints to local mode (#14544) * [MM-24776] Migrate get config endpoint to local mode * [MM-24777] Migrate update config endpoint to local mode * Fix update config to bypass RestrictSystemAdmin flag * Add patchConfig endpoint * MM-24774/MM-24755: local mode for addLicense and removeLicense (#14491) Automatic Merge * api4/team: reflect review comments * api4/team: add to permissions * fix post conflict issues * fix formatting Co-authored-by: Miguel de la Cruz Co-authored-by: Ashish Bhate --- api4/api.go | 4 +- api4/channel_local.go | 2 +- api4/team_local.go | 41 ++++ api4/team_test.go | 432 ++++++++++++++++++++++-------------------- app/authorization.go | 1 + 5 files changed, 270 insertions(+), 210 deletions(-) diff --git a/api4/api.go b/api4/api.go index 6011673a96..9b20633b67 100644 --- a/api4/api.go +++ b/api4/api.go @@ -304,10 +304,10 @@ func InitLocal(configservice configservice.ConfigService, globalOptionsFunc app. api.InitUserLocal() api.InitTeamLocal() api.InitChannelLocal() - api.InitLicenseLocal() api.InitConfigLocal() - api.InitCommandLocal() api.InitPluginLocal() + api.InitCommandLocal() + api.InitLicenseLocal() api.InitGroupLocal() root.Handle("/api/v4/{anything:.*}", http.HandlerFunc(api.Handle404)) diff --git a/api4/channel_local.go b/api4/channel_local.go index 4d8daf0972..2b577586dd 100644 --- a/api4/channel_local.go +++ b/api4/channel_local.go @@ -15,9 +15,9 @@ func (api *API) InitChannelLocal() { api.BaseRoutes.Channels.Handle("", api.ApiLocal(localCreateChannel)).Methods("POST") api.BaseRoutes.Channel.Handle("", api.ApiLocal(deleteChannel)).Methods("DELETE") - api.BaseRoutes.ChannelMembers.Handle("", api.ApiLocal(localAddChannelMember)).Methods("POST") api.BaseRoutes.ChannelMember.Handle("", api.ApiLocal(localRemoveChannelMember)).Methods("DELETE") api.BaseRoutes.ChannelMember.Handle("", api.ApiLocal(getChannelMember)).Methods("GET") + api.BaseRoutes.ChannelMembers.Handle("", api.ApiLocal(localAddChannelMember)).Methods("POST") api.BaseRoutes.ChannelMembers.Handle("", api.ApiLocal(getChannelMembers)).Methods("GET") api.BaseRoutes.ChannelsForTeam.Handle("", api.ApiLocal(getPublicChannelsForTeam)).Methods("GET") diff --git a/api4/team_local.go b/api4/team_local.go index 340d72f6ae..a1b0404602 100644 --- a/api4/team_local.go +++ b/api4/team_local.go @@ -3,8 +3,49 @@ package api4 +import ( + "net/http" + "strings" + + "github.com/mattermost/mattermost-server/v5/audit" + "github.com/mattermost/mattermost-server/v5/model" +) + func (api *API) InitTeamLocal() { + api.BaseRoutes.Teams.Handle("", api.ApiLocal(localCreateTeam)).Methods("POST") api.BaseRoutes.Teams.Handle("", api.ApiLocal(getAllTeams)).Methods("GET") + api.BaseRoutes.Teams.Handle("/search", api.ApiLocal(searchTeams)).Methods("POST") + api.BaseRoutes.Team.Handle("", api.ApiLocal(getTeam)).Methods("GET") + api.BaseRoutes.Team.Handle("", api.ApiLocal(updateTeam)).Methods("PUT") + api.BaseRoutes.Team.Handle("", api.ApiLocal(deleteTeam)).Methods("DELETE") + api.BaseRoutes.Team.Handle("/patch", api.ApiLocal(patchTeam)).Methods("PUT") + api.BaseRoutes.TeamByName.Handle("", api.ApiLocal(getTeamByName)).Methods("GET") api.BaseRoutes.TeamMembers.Handle("", api.ApiLocal(addTeamMember)).Methods("POST") api.BaseRoutes.TeamMember.Handle("", api.ApiLocal(removeTeamMember)).Methods("DELETE") } + +func localCreateTeam(c *Context, w http.ResponseWriter, r *http.Request) { + team := model.TeamFromJson(r.Body) + if team == nil { + c.SetInvalidParam("team") + return + } + team.Email = strings.ToLower(team.Email) + + auditRec := c.MakeAuditRecord("localCreateTeam", audit.Fail) + defer c.LogAuditRec(auditRec) + auditRec.AddMeta("team", team) + + rteam, err := c.App.CreateTeam(team) + if err != nil { + c.Err = err + return + } + // Don't sanitize the team here since the user will be a team admin and their session won't reflect that yet + + auditRec.Success() + auditRec.AddMeta("team", team) // overwrite meta + + w.WriteHeader(http.StatusCreated) + w.Write([]byte(rteam.ToJson())) +} diff --git a/api4/team_test.go b/api4/team_test.go index dc860389a5..907a6febb4 100644 --- a/api4/team_test.go +++ b/api4/team_test.go @@ -255,88 +255,99 @@ func TestGetTeamUnread(t *testing.T) { func TestUpdateTeam(t *testing.T) { th := Setup(t).InitBasic() defer th.TearDown() - Client := th.Client - team := &model.Team{DisplayName: "Name", Description: "Some description", AllowOpenInvite: false, InviteId: "inviteid0", Name: "z-z-" + model.NewRandomTeamName() + "a", Email: "success+" + model.NewId() + "@simulator.amazonses.com", Type: model.TEAM_OPEN} - team, _ = Client.CreateTeam(team) + th.TestForAllClients(t, func(t *testing.T, client *model.Client4) { + team := &model.Team{DisplayName: "Name", Description: "Some description", AllowOpenInvite: false, InviteId: "inviteid0", Name: "z-z-" + model.NewRandomTeamName() + "a", Email: "success+" + model.NewId() + "@simulator.amazonses.com", Type: model.TEAM_OPEN} + var resp *model.Response + team, resp = th.Client.CreateTeam(team) + CheckNoError(t, resp) - team.Description = "updated description" - uteam, resp := Client.UpdateTeam(team) - CheckNoError(t, resp) + team.Description = "updated description" + uteam, resp := client.UpdateTeam(team) + CheckNoError(t, resp) - require.Equal(t, uteam.Description, "updated description", "Update failed") + require.Equal(t, uteam.Description, "updated description", "Update failed") - team.DisplayName = "Updated Name" - uteam, resp = Client.UpdateTeam(team) - CheckNoError(t, resp) + team.DisplayName = "Updated Name" + uteam, resp = client.UpdateTeam(team) + CheckNoError(t, resp) - require.Equal(t, uteam.DisplayName, "Updated Name", "Update failed") + require.Equal(t, uteam.DisplayName, "Updated Name", "Update failed") - // Test GroupConstrained flag - team.GroupConstrained = model.NewBool(true) - rteam, resp := Client.UpdateTeam(team) - CheckNoError(t, resp) - CheckOKStatus(t, resp) + // Test GroupConstrained flag + team.GroupConstrained = model.NewBool(true) + rteam, resp := client.UpdateTeam(team) + CheckNoError(t, resp) + CheckOKStatus(t, resp) - require.Equal(t, *rteam.GroupConstrained, *team.GroupConstrained, "GroupConstrained flags do not match") + require.Equal(t, *rteam.GroupConstrained, *team.GroupConstrained, "GroupConstrained flags do not match") - team.GroupConstrained = nil + team.GroupConstrained = nil - team.AllowOpenInvite = true - uteam, resp = Client.UpdateTeam(team) - CheckNoError(t, resp) + team.AllowOpenInvite = true + uteam, resp = client.UpdateTeam(team) + CheckNoError(t, resp) - require.True(t, uteam.AllowOpenInvite, "Update failed") + require.True(t, uteam.AllowOpenInvite, "Update failed") - team.InviteId = "inviteid1" - uteam, resp = Client.UpdateTeam(team) - CheckNoError(t, resp) + team.InviteId = "inviteid1" + uteam, resp = client.UpdateTeam(team) + CheckNoError(t, resp) - require.NotEqual(t, uteam.InviteId, "inviteid1", "InviteID should not be updated") + require.NotEqual(t, uteam.InviteId, "inviteid1", "InviteID should not be updated") - team.AllowedDomains = "domain" - uteam, resp = Client.UpdateTeam(team) - CheckNoError(t, resp) + team.AllowedDomains = "domain" + uteam, resp = client.UpdateTeam(team) + CheckNoError(t, resp) - require.Equal(t, uteam.AllowedDomains, "domain", "Update failed") + require.Equal(t, uteam.AllowedDomains, "domain", "Update failed") - team.Name = "Updated name" - uteam, resp = Client.UpdateTeam(team) - CheckNoError(t, resp) + team.Name = "Updated name" + uteam, resp = client.UpdateTeam(team) + CheckNoError(t, resp) - require.NotEqual(t, uteam.Name, "Updated name", "Should not update name") + require.NotEqual(t, uteam.Name, "Updated name", "Should not update name") - team.Email = "test@domain.com" - uteam, resp = Client.UpdateTeam(team) - CheckNoError(t, resp) + team.Email = "test@domain.com" + uteam, resp = client.UpdateTeam(team) + CheckNoError(t, resp) - require.NotEqual(t, uteam.Email, "test@domain.com", "Should not update email") + require.NotEqual(t, uteam.Email, "test@domain.com", "Should not update email") - team.Type = model.TEAM_INVITE - uteam, resp = Client.UpdateTeam(team) - CheckNoError(t, resp) + team.Type = model.TEAM_INVITE + uteam, resp = client.UpdateTeam(team) + CheckNoError(t, resp) - require.NotEqual(t, uteam.Type, model.TEAM_INVITE, "Should not update type") + require.NotEqual(t, uteam.Type, model.TEAM_INVITE, "Should not update type") - originalTeamId := team.Id - team.Id = model.NewId() + originalTeamId := team.Id + team.Id = model.NewId() - r, _ := Client.DoApiPut(Client.GetTeamRoute(originalTeamId), team.ToJson()) - assert.Equal(t, http.StatusBadRequest, r.StatusCode) + r, _ := client.DoApiPut(client.GetTeamRoute(originalTeamId), team.ToJson()) + assert.Equal(t, http.StatusBadRequest, r.StatusCode) - require.Equal(t, uteam.Id, originalTeamId, "wrong team id") + require.Equal(t, uteam.Id, originalTeamId, "wrong team id") - team.Id = "fake" - _, resp = Client.UpdateTeam(team) - CheckBadRequestStatus(t, resp) + team.Id = "fake" + _, resp = client.UpdateTeam(team) + CheckBadRequestStatus(t, resp) - Client.Logout() - _, resp = Client.UpdateTeam(team) - CheckUnauthorizedStatus(t, resp) + th.Client.Logout() // for non-local clients + _, resp = th.Client.UpdateTeam(team) + CheckUnauthorizedStatus(t, resp) + th.LoginBasic() + }) - team.Id = originalTeamId - _, resp = th.SystemAdminClient.UpdateTeam(team) - CheckNoError(t, resp) + th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) { + team := &model.Team{DisplayName: "New", Description: "Some description", AllowOpenInvite: false, InviteId: "inviteid0", Name: "z-z-" + model.NewRandomTeamName() + "a", Email: "success+" + model.NewId() + "@simulator.amazonses.com", Type: model.TEAM_OPEN} + var resp *model.Response + team, resp = client.CreateTeam(team) + CheckNoError(t, resp) + + team.Name = "new-name" + _, resp = client.UpdateTeam(team) + CheckNoError(t, resp) + }) } func TestUpdateTeamSanitization(t *testing.T) { @@ -374,87 +385,88 @@ func TestUpdateTeamSanitization(t *testing.T) { func TestPatchTeam(t *testing.T) { th := Setup(t).InitBasic() defer th.TearDown() - Client := th.Client team := &model.Team{DisplayName: "Name", Description: "Some description", CompanyName: "Some company name", AllowOpenInvite: false, InviteId: "inviteid0", Name: "z-z-" + model.NewRandomTeamName() + "a", Email: "success+" + model.NewId() + "@simulator.amazonses.com", Type: model.TEAM_OPEN} - team, _ = Client.CreateTeam(team) + team, _ = th.Client.CreateTeam(team) patch := &model.TeamPatch{} - patch.DisplayName = model.NewString("Other name") patch.Description = model.NewString("Other description") patch.CompanyName = model.NewString("Other company name") patch.AllowOpenInvite = model.NewBool(true) - rteam, resp := Client.PatchTeam(team.Id, patch) - CheckNoError(t, resp) - - require.Equal(t, rteam.DisplayName, "Other name", "DisplayName did not update properly") - require.Equal(t, rteam.Description, "Other description", "Description did not update properly") - require.Equal(t, rteam.CompanyName, "Other company name", "CompanyName did not update properly") - require.NotEqual(t, rteam.InviteId, "inviteid1", "InviteId should not update") - require.True(t, rteam.AllowOpenInvite, "AllowOpenInvite did not update properly") - - t.Run("Changing AllowOpenInvite to false regenerates InviteID", func(t *testing.T) { - team2 := &model.Team{DisplayName: "Name2", Description: "Some description", CompanyName: "Some company name", AllowOpenInvite: true, InviteId: model.NewId(), Name: "z-z-" + model.NewRandomTeamName() + "a", Email: "success+" + model.NewId() + "@simulator.amazonses.com", Type: model.TEAM_OPEN} - team2, _ = Client.CreateTeam(team2) - - patch2 := &model.TeamPatch{ - AllowOpenInvite: model.NewBool(false), - } - - rteam2, resp2 := Client.PatchTeam(team2.Id, patch2) - CheckNoError(t, resp2) - require.Equal(t, team2.Id, rteam2.Id) - require.False(t, rteam2.AllowOpenInvite) - require.NotEqual(t, team2.InviteId, rteam2.InviteId) - }) - - t.Run("Changing AllowOpenInvite to true doesn't regenerate InviteID", func(t *testing.T) { - team2 := &model.Team{DisplayName: "Name3", Description: "Some description", CompanyName: "Some company name", AllowOpenInvite: false, InviteId: model.NewId(), Name: "z-z-" + model.NewRandomTeamName() + "a", Email: "success+" + model.NewId() + "@simulator.amazonses.com", Type: model.TEAM_OPEN} - team2, _ = Client.CreateTeam(team2) - - patch2 := &model.TeamPatch{ - AllowOpenInvite: model.NewBool(true), - } - - rteam2, resp2 := Client.PatchTeam(team2.Id, patch2) - CheckNoError(t, resp2) - require.Equal(t, team2.Id, rteam2.Id) - require.True(t, rteam2.AllowOpenInvite) - require.Equal(t, team2.InviteId, rteam2.InviteId) - }) - - // Test GroupConstrained flag - patch.GroupConstrained = model.NewBool(true) - rteam, resp = Client.PatchTeam(team.Id, patch) - CheckNoError(t, resp) - CheckOKStatus(t, resp) - - require.Equal(t, *rteam.GroupConstrained, *patch.GroupConstrained, "GroupConstrained flags do not match") - patch.GroupConstrained = nil - - _, resp = Client.PatchTeam("junk", patch) - CheckBadRequestStatus(t, resp) - - _, resp = Client.PatchTeam(GenerateTestId(), patch) + _, resp := th.Client.PatchTeam(GenerateTestId(), patch) CheckForbiddenStatus(t, resp) - r, err := Client.DoApiPut("/teams/"+team.Id+"/patch", "garbage") - require.NotNil(t, err, "should have errored") - - require.Equalf(t, r.StatusCode, http.StatusBadRequest, "wrong status code, actual: %s, expected: %s", strconv.Itoa(r.StatusCode), strconv.Itoa(http.StatusBadRequest)) - - Client.Logout() - _, resp = Client.PatchTeam(team.Id, patch) + th.Client.Logout() + _, resp = th.Client.PatchTeam(team.Id, patch) CheckUnauthorizedStatus(t, resp) th.LoginBasic2() - _, resp = Client.PatchTeam(team.Id, patch) + _, resp = th.Client.PatchTeam(team.Id, patch) CheckForbiddenStatus(t, resp) + th.LoginBasic() - _, resp = th.SystemAdminClient.PatchTeam(team.Id, patch) - CheckNoError(t, resp) + th.TestForAllClients(t, func(t *testing.T, client *model.Client4) { + rteam, resp := client.PatchTeam(team.Id, patch) + CheckNoError(t, resp) + + require.Equal(t, rteam.DisplayName, "Other name", "DisplayName did not update properly") + require.Equal(t, rteam.Description, "Other description", "Description did not update properly") + require.Equal(t, rteam.CompanyName, "Other company name", "CompanyName did not update properly") + require.NotEqual(t, rteam.InviteId, "inviteid1", "InviteId should not update") + require.True(t, rteam.AllowOpenInvite, "AllowOpenInvite did not update properly") + + t.Run("Changing AllowOpenInvite to false regenerates InviteID", func(t *testing.T) { + team2 := &model.Team{DisplayName: "Name2", Description: "Some description", CompanyName: "Some company name", AllowOpenInvite: true, InviteId: model.NewId(), Name: "z-z-" + model.NewRandomTeamName() + "a", Email: "success+" + model.NewId() + "@simulator.amazonses.com", Type: model.TEAM_OPEN} + team2, _ = client.CreateTeam(team2) + + patch2 := &model.TeamPatch{ + AllowOpenInvite: model.NewBool(false), + } + + rteam2, resp2 := client.PatchTeam(team2.Id, patch2) + CheckNoError(t, resp2) + require.Equal(t, team2.Id, rteam2.Id) + require.False(t, rteam2.AllowOpenInvite) + require.NotEqual(t, team2.InviteId, rteam2.InviteId) + }) + + t.Run("Changing AllowOpenInvite to true doesn't regenerate InviteID", func(t *testing.T) { + team2 := &model.Team{DisplayName: "Name3", Description: "Some description", CompanyName: "Some company name", AllowOpenInvite: false, InviteId: model.NewId(), Name: "z-z-" + model.NewRandomTeamName() + "a", Email: "success+" + model.NewId() + "@simulator.amazonses.com", Type: model.TEAM_OPEN} + team2, _ = client.CreateTeam(team2) + + patch2 := &model.TeamPatch{ + AllowOpenInvite: model.NewBool(true), + } + + rteam2, resp2 := client.PatchTeam(team2.Id, patch2) + CheckNoError(t, resp2) + require.Equal(t, team2.Id, rteam2.Id) + require.True(t, rteam2.AllowOpenInvite) + require.Equal(t, team2.InviteId, rteam2.InviteId) + }) + + // Test GroupConstrained flag + patch.GroupConstrained = model.NewBool(true) + rteam, resp = client.PatchTeam(team.Id, patch) + CheckNoError(t, resp) + CheckOKStatus(t, resp) + require.Equal(t, *rteam.GroupConstrained, *patch.GroupConstrained, "GroupConstrained flags do not match") + + patch.GroupConstrained = nil + _, resp = client.PatchTeam("junk", patch) + CheckBadRequestStatus(t, resp) + + r, err := client.DoApiPut("/teams/"+team.Id+"/patch", "garbage") + require.NotNil(t, err, "should have errored") + require.Equalf(t, r.StatusCode, http.StatusBadRequest, "wrong status code, actual: %s, expected: %s", strconv.Itoa(r.StatusCode), strconv.Itoa(http.StatusBadRequest)) + }) + + th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) { + _, resp := client.PatchTeam(th.BasicTeam.Id, patch) + CheckNoError(t, resp) + }) } func TestRestoreTeam(t *testing.T) { @@ -723,74 +735,83 @@ func TestRegenerateTeamInviteId(t *testing.T) { func TestSoftDeleteTeam(t *testing.T) { th := Setup(t).InitBasic() defer th.TearDown() - Client := th.Client - team := &model.Team{DisplayName: "DisplayName", Name: GenerateTestTeamName(), Email: th.GenerateTestEmail(), Type: model.TEAM_OPEN} - team, _ = Client.CreateTeam(team) - - ok, resp := Client.SoftDeleteTeam(team.Id) - CheckNoError(t, resp) - - require.True(t, ok, "should have returned true") - - rteam, err := th.App.GetTeam(team.Id) - require.Nil(t, err, "should have returned archived team") - require.NotEqual(t, rteam.DeleteAt, 0, "should have not set to zero") - - ok, resp = Client.SoftDeleteTeam("junk") - CheckBadRequestStatus(t, resp) - - require.False(t, ok, "should have returned false") - - otherTeam := th.BasicTeam - _, resp = Client.SoftDeleteTeam(otherTeam.Id) + _, resp := th.Client.SoftDeleteTeam(th.BasicTeam.Id) CheckForbiddenStatus(t, resp) - Client.Logout() - _, resp = Client.SoftDeleteTeam(otherTeam.Id) + th.Client.Logout() + _, resp = th.Client.SoftDeleteTeam(th.BasicTeam.Id) CheckUnauthorizedStatus(t, resp) - _, resp = th.SystemAdminClient.SoftDeleteTeam(otherTeam.Id) - CheckNoError(t, resp) + th.LoginBasic() + team := &model.Team{DisplayName: "DisplayName", Name: GenerateTestTeamName(), Email: th.GenerateTestEmail(), Type: model.TEAM_OPEN} + team, _ = th.Client.CreateTeam(team) + + th.TestForAllClients(t, func(t *testing.T, client *model.Client4) { + ok, resp := client.SoftDeleteTeam(team.Id) + CheckNoError(t, resp) + + require.True(t, ok, "should have returned true") + + rteam, err := th.App.GetTeam(team.Id) + require.Nil(t, err, "should have returned archived team") + require.NotEqual(t, rteam.DeleteAt, 0, "should have not set to zero") + + ok, resp = client.SoftDeleteTeam("junk") + CheckBadRequestStatus(t, resp) + + require.False(t, ok, "should have returned false") + }) + + th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) { + _, resp := client.SoftDeleteTeam(th.BasicTeam.Id) + CheckNoError(t, resp) + }) } func TestPermanentDeleteTeam(t *testing.T) { th := Setup(t).InitBasic() defer th.TearDown() - Client := th.Client - team := &model.Team{DisplayName: "DisplayName", Name: GenerateTestTeamName(), Email: th.GenerateTestEmail(), Type: model.TEAM_OPEN} - team, _ = Client.CreateTeam(team) + th.TestForAllClients(t, func(t *testing.T, client *model.Client4) { + team := &model.Team{DisplayName: "DisplayName", Name: GenerateTestTeamName(), Email: th.GenerateTestEmail(), Type: model.TEAM_OPEN} + team, _ = client.CreateTeam(team) - enableAPITeamDeletion := *th.App.Config().ServiceSettings.EnableAPITeamDeletion - defer func() { - th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableAPITeamDeletion = &enableAPITeamDeletion }) - }() + enableAPITeamDeletion := *th.App.Config().ServiceSettings.EnableAPITeamDeletion + defer func() { + th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableAPITeamDeletion = &enableAPITeamDeletion }) + }() - th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableAPITeamDeletion = false }) + th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableAPITeamDeletion = false }) - // Does not error when deletion is disabled, just soft deletes - ok, resp := Client.PermanentDeleteTeam(team.Id) - CheckNoError(t, resp) - assert.True(t, ok) + // Does not error when deletion is disabled, just soft deletes + ok, resp := client.PermanentDeleteTeam(team.Id) + CheckNoError(t, resp) + assert.True(t, ok) - rteam, err := th.App.GetTeam(team.Id) - assert.Nil(t, err) - assert.True(t, rteam.DeleteAt > 0) + rteam, err := th.App.GetTeam(team.Id) + assert.Nil(t, err) + assert.True(t, rteam.DeleteAt > 0) - th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableAPITeamDeletion = true }) + th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableAPITeamDeletion = true }) - ok, resp = Client.PermanentDeleteTeam(team.Id) - CheckNoError(t, resp) - assert.True(t, ok) + ok, resp = client.PermanentDeleteTeam(team.Id) + CheckNoError(t, resp) + assert.True(t, ok) - _, err = th.App.GetTeam(team.Id) - assert.NotNil(t, err) + _, err = th.App.GetTeam(team.Id) + assert.NotNil(t, err) - ok, resp = Client.PermanentDeleteTeam("junk") - CheckBadRequestStatus(t, resp) + ok, resp = client.PermanentDeleteTeam("junk") + CheckBadRequestStatus(t, resp) - require.False(t, ok, "should have returned false") + require.False(t, ok, "should have returned false") + }) + + th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) { + _, resp := client.PermanentDeleteTeam(th.BasicTeam.Id) + CheckNoError(t, resp) + }) } func TestGetAllTeams(t *testing.T) { @@ -1125,7 +1146,7 @@ func TestGetTeamByNameSanitization(t *testing.T) { func TestSearchAllTeams(t *testing.T) { th := Setup(t).InitBasic() defer th.TearDown() - Client := th.Client + oTeam := th.BasicTeam oTeam.AllowOpenInvite = true @@ -1134,54 +1155,51 @@ func TestSearchAllTeams(t *testing.T) { oTeam.UpdateAt = updatedTeam.UpdateAt pTeam := &model.Team{DisplayName: "PName", Name: GenerateTestTeamName(), Email: th.GenerateTestEmail(), Type: model.TEAM_INVITE} - Client.CreateTeam(pTeam) + th.Client.CreateTeam(pTeam) - rteams, resp := Client.SearchTeams(&model.TeamSearch{Term: oTeam.Name}) + rteams, resp := th.Client.SearchTeams(&model.TeamSearch{Term: pTeam.Name}) CheckNoError(t, resp) - - require.Len(t, rteams, 1, "should have returned 1 team") - - require.Equal(t, oTeam.Id, rteams[0].Id, "invalid team") - - rteams, resp = Client.SearchTeams(&model.TeamSearch{Term: oTeam.DisplayName}) - CheckNoError(t, resp) - - require.Len(t, rteams, 1, "should have returned 1 team") - - require.Equal(t, oTeam.Id, rteams[0].Id, "invalid team") - - rteams, resp = Client.SearchTeams(&model.TeamSearch{Term: pTeam.Name}) - CheckNoError(t, resp) - require.Empty(t, rteams, "should have not returned team") - rteams, resp = Client.SearchTeams(&model.TeamSearch{Term: pTeam.DisplayName}) + rteams, resp = th.Client.SearchTeams(&model.TeamSearch{Term: pTeam.DisplayName}) CheckNoError(t, resp) - require.Empty(t, rteams, "should have not returned team") - rteams, resp = th.SystemAdminClient.SearchTeams(&model.TeamSearch{Term: oTeam.Name}) - CheckNoError(t, resp) + th.Client.Logout() - require.Len(t, rteams, 1, "should have returned 1 team") - - rteams, resp = th.SystemAdminClient.SearchTeams(&model.TeamSearch{Term: pTeam.DisplayName}) - CheckNoError(t, resp) - - require.Len(t, rteams, 1, "should have returned 1 team") - - rteams, resp = Client.SearchTeams(&model.TeamSearch{Term: "junk"}) - CheckNoError(t, resp) - - require.Empty(t, rteams, "should have not returned team") - - Client.Logout() - - _, resp = Client.SearchTeams(&model.TeamSearch{Term: pTeam.Name}) + _, resp = th.Client.SearchTeams(&model.TeamSearch{Term: pTeam.Name}) CheckUnauthorizedStatus(t, resp) - _, resp = Client.SearchTeams(&model.TeamSearch{Term: pTeam.DisplayName}) + _, resp = th.Client.SearchTeams(&model.TeamSearch{Term: pTeam.DisplayName}) CheckUnauthorizedStatus(t, resp) + + th.LoginBasic() + + th.TestForAllClients(t, func(t *testing.T, client *model.Client4) { + rteams, resp := client.SearchTeams(&model.TeamSearch{Term: oTeam.Name}) + CheckNoError(t, resp) + require.Len(t, rteams, 1, "should have returned 1 team") + require.Equal(t, oTeam.Id, rteams[0].Id, "invalid team") + + rteams, resp = client.SearchTeams(&model.TeamSearch{Term: oTeam.DisplayName}) + CheckNoError(t, resp) + require.Len(t, rteams, 1, "should have returned 1 team") + require.Equal(t, oTeam.Id, rteams[0].Id, "invalid team") + + rteams, resp = client.SearchTeams(&model.TeamSearch{Term: "junk"}) + CheckNoError(t, resp) + require.Empty(t, rteams, "should have not returned team") + }) + + th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) { + rteams, resp := client.SearchTeams(&model.TeamSearch{Term: oTeam.Name}) + CheckNoError(t, resp) + require.Len(t, rteams, 1, "should have returned 1 team") + + rteams, resp = client.SearchTeams(&model.TeamSearch{Term: pTeam.DisplayName}) + CheckNoError(t, resp) + require.Len(t, rteams, 1, "should have returned 1 team") + }) } func TestSearchAllTeamsPaged(t *testing.T) { diff --git a/app/authorization.go b/app/authorization.go index 32604b04e8..098ae725f9 100644 --- a/app/authorization.go +++ b/app/authorization.go @@ -29,6 +29,7 @@ func (a *App) SessionHasPermissionToTeam(session model.Session, teamId string, p if session.IsUnrestricted() { return true } + teamMember := session.GetTeamByTeamId(teamId) if teamMember != nil { if a.RolesGrantPermission(teamMember.GetRoles(), permission.Id) {