diff --git a/api4/team.go b/api4/team.go index bdbed5cdca..9f01dda811 100644 --- a/api4/team.go +++ b/api4/team.go @@ -367,8 +367,12 @@ func deleteTeam(c *Context, w http.ResponseWriter, r *http.Request) { } var err *model.AppError - if c.Params.Permanent && *c.App.Config().ServiceSettings.EnableAPITeamDeletion { - err = c.App.PermanentDeleteTeamId(c.Params.TeamId) + if c.Params.Permanent { + if *c.App.Config().ServiceSettings.EnableAPITeamDeletion { + err = c.App.PermanentDeleteTeamId(c.Params.TeamId) + } else { + err = model.NewAppError("deleteTeam", "api.user.delete_team.not_enabled.app_error", nil, "teamId="+c.Params.TeamId, http.StatusUnauthorized) + } } else { err = c.App.SoftDeleteTeam(c.Params.TeamId) } diff --git a/api4/team_local.go b/api4/team_local.go index dde70b2e55..a658e0a7e7 100644 --- a/api4/team_local.go +++ b/api4/team_local.go @@ -18,7 +18,7 @@ func (api *API) InitTeamLocal() { 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("", api.ApiLocal(localDeleteTeam)).Methods("DELETE") api.BaseRoutes.Team.Handle("/invite/email", api.ApiLocal(localInviteUsersToTeam)).Methods("POST") api.BaseRoutes.Team.Handle("/patch", api.ApiLocal(patchTeam)).Methods("PUT") @@ -27,6 +27,35 @@ func (api *API) InitTeamLocal() { api.BaseRoutes.TeamMember.Handle("", api.ApiLocal(removeTeamMember)).Methods("DELETE") } +func localDeleteTeam(c *Context, w http.ResponseWriter, r *http.Request) { + c.RequireTeamId() + if c.Err != nil { + return + } + + auditRec := c.MakeAuditRecord("localDeleteTeam", audit.Fail) + defer c.LogAuditRec(auditRec) + + if team, err := c.App.GetTeam(c.Params.TeamId); err == nil { + auditRec.AddMeta("team", team) + } + + var err *model.AppError + if c.Params.Permanent { + err = c.App.PermanentDeleteTeamId(c.Params.TeamId) + } else { + err = c.App.SoftDeleteTeam(c.Params.TeamId) + } + + if err != nil { + c.Err = err + return + } + + auditRec.Success() + ReturnStatusOK(w) +} + func localInviteUsersToTeam(c *Context, w http.ResponseWriter, r *http.Request) { c.RequireTeamId() if c.Err != nil { diff --git a/api4/team_test.go b/api4/team_test.go index ae23a655b2..d2e716b176 100644 --- a/api4/team_test.go +++ b/api4/team_test.go @@ -773,45 +773,52 @@ func TestPermanentDeleteTeam(t *testing.T) { th := Setup(t).InitBasic() defer th.TearDown() - 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 }) + }() + th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableAPITeamDeletion = false }) - enableAPITeamDeletion := *th.App.Config().ServiceSettings.EnableAPITeamDeletion + t.Run("Permanent deletion not available through API if EnableAPITeamDeletion is not set", func(t *testing.T) { + team := &model.Team{DisplayName: "DisplayName", Name: GenerateTestTeamName(), Email: th.GenerateTestEmail(), Type: model.TEAM_OPEN} + team, _ = th.Client.CreateTeam(team) + + _, resp := th.Client.PermanentDeleteTeam(team.Id) + CheckUnauthorizedStatus(t, resp) + + _, resp = th.SystemAdminClient.PermanentDeleteTeam(team.Id) + CheckUnauthorizedStatus(t, resp) + }) + + t.Run("Permanent deletion available through local mode even if EnableAPITeamDeletion is not set", func(t *testing.T) { + team := &model.Team{DisplayName: "DisplayName", Name: GenerateTestTeamName(), Email: th.GenerateTestEmail(), Type: model.TEAM_OPEN} + team, _ = th.Client.CreateTeam(team) + + ok, resp := th.LocalClient.PermanentDeleteTeam(team.Id) + CheckNoError(t, resp) + assert.True(t, ok) + }) + + th.TestForAllClients(t, func(t *testing.T, client *model.Client4) { defer func() { th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableAPITeamDeletion = &enableAPITeamDeletion }) }() + th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableAPITeamDeletion = true }) - th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableAPITeamDeletion = false }) - - // Does not error when deletion is disabled, just soft deletes + team := &model.Team{DisplayName: "DisplayName", Name: GenerateTestTeamName(), Email: th.GenerateTestEmail(), Type: model.TEAM_OPEN} + team, _ = client.CreateTeam(team) 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) - - th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableAPITeamDeletion = true }) - - ok, resp = client.PermanentDeleteTeam(team.Id) - CheckNoError(t, resp) - assert.True(t, ok) - - _, err = th.App.GetTeam(team.Id) + _, err := th.App.GetTeam(team.Id) assert.NotNil(t, err) ok, resp = client.PermanentDeleteTeam("junk") CheckBadRequestStatus(t, resp) 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) - }) + }, "Permanent deletion with EnableAPITeamDeletion set") } func TestGetAllTeams(t *testing.T) { diff --git a/i18n/en.json b/i18n/en.json index a503d946d1..478dad9c64 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -2618,6 +2618,10 @@ "id": "api.user.create_user.signup_link_invalid.app_error", "translation": "The signup link does not appear to be valid." }, + { + "id": "api.user.delete_team.not_enabled.app_error", + "translation": "Permanent team deletion feature is not enabled. Please contact your System Administrator." + }, { "id": "api.user.demote_user_to_guest.already_guest.app_error", "translation": "Unable to convert the user to guest because is already a guest."