summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSaturnino Abril <saturnino.abril@gmail.com>2017-03-14 21:08:58 +0900
committerGeorge Goldberg <george@gberg.me>2017-03-14 12:08:58 +0000
commita71a9fc3bff1b6a6c9d5e0a65f53686922572834 (patch)
treec132dcdb82cef953634e091d91fddab1c3572efe
parentaafc63933a7e213261e28ac7f528cea50b70e1af (diff)
downloadchat-a71a9fc3bff1b6a6c9d5e0a65f53686922572834.tar.gz
chat-a71a9fc3bff1b6a6c9d5e0a65f53686922572834.tar.bz2
chat-a71a9fc3bff1b6a6c9d5e0a65f53686922572834.zip
APIv4 DELETE channels/{channel_id} (#5723)
-rw-r--r--api4/apitestlib.go46
-rw-r--r--api4/channel.go35
-rw-r--r--api4/channel_test.go239
-rw-r--r--app/channel.go3
-rw-r--r--i18n/en.json4
-rw-r--r--model/client4.go10
6 files changed, 337 insertions, 0 deletions
diff --git a/api4/apitestlib.go b/api4/apitestlib.go
index 2b7b707c7..fbad3d6be 100644
--- a/api4/apitestlib.go
+++ b/api4/apitestlib.go
@@ -572,3 +572,49 @@ func cleanupTestFile(info *model.FileInfo) error {
return nil
}
+
+func MakeUserChannelAdmin(user *model.User, channel *model.Channel) {
+ utils.DisableDebugLogForTest()
+
+ if cmr := <-app.Srv.Store.Channel().GetMember(channel.Id, user.Id); cmr.Err == nil {
+ cm := cmr.Data.(*model.ChannelMember)
+ cm.Roles = "channel_admin channel_user"
+ if sr := <-app.Srv.Store.Channel().UpdateMember(cm); sr.Err != nil {
+ utils.EnableDebugLogForTest()
+ panic(sr.Err)
+ }
+ } else {
+ utils.EnableDebugLogForTest()
+ panic(cmr.Err)
+ }
+
+ utils.EnableDebugLogForTest()
+}
+
+func UpdateUserToTeamAdmin(user *model.User, team *model.Team) {
+ utils.DisableDebugLogForTest()
+
+ tm := &model.TeamMember{TeamId: team.Id, UserId: user.Id, Roles: model.ROLE_TEAM_USER.Id + " " + model.ROLE_TEAM_ADMIN.Id}
+ if tmr := <-app.Srv.Store.Team().UpdateMember(tm); tmr.Err != nil {
+ utils.EnableDebugLogForTest()
+ l4g.Error(tmr.Err.Error())
+ l4g.Close()
+ time.Sleep(time.Second)
+ panic(tmr.Err)
+ }
+ utils.EnableDebugLogForTest()
+}
+
+func UpdateUserToNonTeamAdmin(user *model.User, team *model.Team) {
+ utils.DisableDebugLogForTest()
+
+ tm := &model.TeamMember{TeamId: team.Id, UserId: user.Id, Roles: model.ROLE_TEAM_USER.Id}
+ if tmr := <-app.Srv.Store.Team().UpdateMember(tm); tmr.Err != nil {
+ utils.EnableDebugLogForTest()
+ l4g.Error(tmr.Err.Error())
+ l4g.Close()
+ time.Sleep(time.Second)
+ panic(tmr.Err)
+ }
+ utils.EnableDebugLogForTest()
+}
diff --git a/api4/channel.go b/api4/channel.go
index 80ae9fa30..acf14846a 100644
--- a/api4/channel.go
+++ b/api4/channel.go
@@ -22,6 +22,7 @@ func InitChannel() {
BaseRoutes.Channel.Handle("", ApiSessionRequired(getChannel)).Methods("GET")
BaseRoutes.Channel.Handle("", ApiSessionRequired(updateChannel)).Methods("PUT")
+ BaseRoutes.Channel.Handle("", ApiSessionRequired(deleteChannel)).Methods("DELETE")
BaseRoutes.ChannelByName.Handle("", ApiSessionRequired(getChannelByName)).Methods("GET")
BaseRoutes.ChannelByNameForTeamName.Handle("", ApiSessionRequired(getChannelByNameForTeamName)).Methods("GET")
@@ -226,6 +227,40 @@ func getPublicChannelsForTeam(c *Context, w http.ResponseWriter, r *http.Request
}
}
+func deleteChannel(c *Context, w http.ResponseWriter, r *http.Request) {
+ c.RequireChannelId()
+ if c.Err != nil {
+ return
+ }
+
+ var channel *model.Channel
+ var err *model.AppError
+ if channel, err = app.GetChannel(c.Params.ChannelId); err != nil {
+ c.Err = err
+ return
+ }
+
+ if channel.Type == model.CHANNEL_OPEN && !app.SessionHasPermissionToChannel(c.Session, channel.Id, model.PERMISSION_DELETE_PUBLIC_CHANNEL) {
+ c.SetPermissionError(model.PERMISSION_DELETE_PUBLIC_CHANNEL)
+ return
+ }
+
+ if channel.Type == model.CHANNEL_PRIVATE && !app.SessionHasPermissionToChannel(c.Session, channel.Id, model.PERMISSION_DELETE_PRIVATE_CHANNEL) {
+ c.SetPermissionError(model.PERMISSION_DELETE_PRIVATE_CHANNEL)
+ return
+ }
+
+ err = app.DeleteChannel(channel, c.Session.UserId)
+ if err != nil {
+ c.Err = err
+ return
+ }
+
+ c.LogAudit("name=" + channel.Name)
+
+ ReturnStatusOK(w)
+}
+
func getChannelByName(c *Context, w http.ResponseWriter, r *http.Request) {
c.RequireTeamId().RequireChannelName()
if c.Err != nil {
diff --git a/api4/channel_test.go b/api4/channel_test.go
index 27fe5aa44..97364a73e 100644
--- a/api4/channel_test.go
+++ b/api4/channel_test.go
@@ -11,6 +11,7 @@ import (
"github.com/mattermost/platform/app"
"github.com/mattermost/platform/model"
+ "github.com/mattermost/platform/store"
"github.com/mattermost/platform/utils"
)
@@ -406,6 +407,244 @@ func TestGetPublicChannelsForTeam(t *testing.T) {
CheckNoError(t, resp)
}
+func TestDeleteChannel(t *testing.T) {
+ th := Setup().InitBasic().InitSystemAdmin()
+ defer TearDown()
+ Client := th.Client
+ team := th.BasicTeam
+ user := th.BasicUser
+ user2 := th.BasicUser2
+
+ // successful delete of public channel
+ publicChannel1 := th.CreatePublicChannel()
+ pass, resp := Client.DeleteChannel(publicChannel1.Id)
+ CheckNoError(t, resp)
+
+ if !pass {
+ t.Fatal("should have passed")
+ }
+
+ if ch, err := app.GetChannel(publicChannel1.Id); err == nil && ch.DeleteAt == 0 {
+ t.Fatal("should have failed to get deleted channel")
+ } else if err := app.JoinChannel(ch, user2.Id); err == nil {
+ t.Fatal("should have failed to join deleted channel")
+ }
+
+ post1 := &model.Post{ChannelId: publicChannel1.Id, Message: "a" + GenerateTestId() + "a"}
+ if _, err := Client.CreatePost(post1); err == nil {
+ t.Fatal("should have failed to post to deleted channel")
+ }
+
+ // successful delete of private channel
+ privateChannel2 := th.CreatePrivateChannel()
+ _, resp = Client.DeleteChannel(privateChannel2.Id)
+ CheckNoError(t, resp)
+
+ // successful delete of channel with multiple members
+ publicChannel3 := th.CreatePublicChannel()
+ app.AddUserToChannel(user2, publicChannel3)
+ _, resp = Client.DeleteChannel(publicChannel3.Id)
+ CheckNoError(t, resp)
+
+ // successful delete by TeamAdmin of channel created by user
+ publicChannel4 := th.CreatePublicChannel()
+ th.LoginTeamAdmin()
+ _, resp = Client.DeleteChannel(publicChannel4.Id)
+ CheckNoError(t, resp)
+
+ // default channel cannot be deleted.
+ defaultChannel, _ := app.GetChannelByName(model.DEFAULT_CHANNEL, team.Id)
+ pass, resp = Client.DeleteChannel(defaultChannel.Id)
+ CheckBadRequestStatus(t, resp)
+
+ if pass {
+ t.Fatal("should have failed")
+ }
+
+ th.LoginBasic()
+ publicChannel5 := th.CreatePublicChannel()
+ Client.Logout()
+
+ Client.Login(user2.Id, user2.Password)
+ _, resp = Client.DeleteChannel(publicChannel5.Id)
+ CheckUnauthorizedStatus(t, resp)
+
+ _, resp = Client.DeleteChannel("junk")
+ CheckUnauthorizedStatus(t, resp)
+
+ Client.Logout()
+ _, resp = Client.DeleteChannel(GenerateTestId())
+ CheckUnauthorizedStatus(t, resp)
+
+ _, resp = th.SystemAdminClient.DeleteChannel(publicChannel5.Id)
+ CheckNoError(t, resp)
+
+ isLicensed := utils.IsLicensed
+ license := utils.License
+ restrictPublicChannel := *utils.Cfg.TeamSettings.RestrictPublicChannelManagement
+ restrictPrivateChannel := *utils.Cfg.TeamSettings.RestrictPrivateChannelManagement
+ defer func() {
+ *utils.Cfg.TeamSettings.RestrictPublicChannelManagement = restrictPublicChannel
+ *utils.Cfg.TeamSettings.RestrictPrivateChannelManagement = restrictPrivateChannel
+ utils.IsLicensed = isLicensed
+ utils.License = license
+ utils.SetDefaultRolesBasedOnConfig()
+ }()
+ *utils.Cfg.TeamSettings.RestrictPublicChannelManagement = model.PERMISSIONS_ALL
+ *utils.Cfg.TeamSettings.RestrictPrivateChannelManagement = model.PERMISSIONS_ALL
+ utils.IsLicensed = true
+ utils.License = &model.License{Features: &model.Features{}}
+ utils.License.Features.SetDefaults()
+ utils.SetDefaultRolesBasedOnConfig()
+
+ th = Setup().InitBasic().InitSystemAdmin()
+ Client = th.Client
+ team = th.BasicTeam
+ user = th.BasicUser
+
+ // channels created by SystemAdmin
+ publicChannel6 := th.CreateChannelWithClient(th.SystemAdminClient, model.CHANNEL_OPEN)
+ privateChannel7 := th.CreateChannelWithClient(th.SystemAdminClient, model.CHANNEL_PRIVATE)
+ app.AddUserToChannel(user, publicChannel6)
+ app.AddUserToChannel(user, privateChannel7)
+
+ // successful delete by user
+ _, resp = Client.DeleteChannel(publicChannel6.Id)
+ CheckNoError(t, resp)
+
+ _, resp = Client.DeleteChannel(privateChannel7.Id)
+ CheckNoError(t, resp)
+
+ *utils.Cfg.TeamSettings.RestrictPublicChannelDeletion = model.PERMISSIONS_CHANNEL_ADMIN
+ *utils.Cfg.TeamSettings.RestrictPrivateChannelDeletion = model.PERMISSIONS_CHANNEL_ADMIN
+ utils.SetDefaultRolesBasedOnConfig()
+
+ // channels created by SystemAdmin
+ publicChannel6 = th.CreateChannelWithClient(th.SystemAdminClient, model.CHANNEL_OPEN)
+ privateChannel7 = th.CreateChannelWithClient(th.SystemAdminClient, model.CHANNEL_PRIVATE)
+ app.AddUserToChannel(user, publicChannel6)
+ app.AddUserToChannel(user, privateChannel7)
+
+ // cannot delete by user
+ _, resp = Client.DeleteChannel(publicChannel6.Id)
+ CheckForbiddenStatus(t, resp)
+
+ _, resp = Client.DeleteChannel(privateChannel7.Id)
+ CheckForbiddenStatus(t, resp)
+
+ // successful delete by channel admin
+ MakeUserChannelAdmin(user, publicChannel6)
+ MakeUserChannelAdmin(user, privateChannel7)
+ store.ClearChannelCaches()
+
+ _, resp = Client.DeleteChannel(publicChannel6.Id)
+ CheckNoError(t, resp)
+
+ _, resp = Client.DeleteChannel(privateChannel7.Id)
+ CheckNoError(t, resp)
+
+ // // channels created by SystemAdmin
+ publicChannel6 = th.CreateChannelWithClient(th.SystemAdminClient, model.CHANNEL_OPEN)
+ privateChannel7 = th.CreateChannelWithClient(th.SystemAdminClient, model.CHANNEL_PRIVATE)
+ app.AddUserToChannel(user, publicChannel6)
+ app.AddUserToChannel(user, privateChannel7)
+
+ // successful delete by team admin
+ UpdateUserToTeamAdmin(user, team)
+ app.InvalidateAllCaches()
+
+ _, resp = Client.DeleteChannel(publicChannel6.Id)
+ CheckNoError(t, resp)
+
+ _, resp = Client.DeleteChannel(privateChannel7.Id)
+ CheckNoError(t, resp)
+
+ *utils.Cfg.TeamSettings.RestrictPublicChannelDeletion = model.PERMISSIONS_TEAM_ADMIN
+ *utils.Cfg.TeamSettings.RestrictPrivateChannelDeletion = model.PERMISSIONS_TEAM_ADMIN
+ utils.SetDefaultRolesBasedOnConfig()
+ UpdateUserToNonTeamAdmin(user, team)
+ app.InvalidateAllCaches()
+
+ // channels created by SystemAdmin
+ publicChannel6 = th.CreateChannelWithClient(th.SystemAdminClient, model.CHANNEL_OPEN)
+ privateChannel7 = th.CreateChannelWithClient(th.SystemAdminClient, model.CHANNEL_PRIVATE)
+ app.AddUserToChannel(user, publicChannel6)
+ app.AddUserToChannel(user, privateChannel7)
+
+ // cannot delete by user
+ _, resp = Client.DeleteChannel(publicChannel6.Id)
+ CheckForbiddenStatus(t, resp)
+
+ _, resp = Client.DeleteChannel(privateChannel7.Id)
+ CheckForbiddenStatus(t, resp)
+
+ // // cannot delete by channel admin
+ MakeUserChannelAdmin(user, publicChannel6)
+ MakeUserChannelAdmin(user, privateChannel7)
+ store.ClearChannelCaches()
+
+ _, resp = Client.DeleteChannel(publicChannel6.Id)
+ CheckForbiddenStatus(t, resp)
+
+ _, resp = Client.DeleteChannel(privateChannel7.Id)
+ CheckForbiddenStatus(t, resp)
+
+ // successful delete by team admin
+ UpdateUserToTeamAdmin(th.BasicUser, team)
+ app.InvalidateAllCaches()
+
+ _, resp = Client.DeleteChannel(publicChannel6.Id)
+ CheckNoError(t, resp)
+
+ _, resp = Client.DeleteChannel(privateChannel7.Id)
+ CheckNoError(t, resp)
+
+ *utils.Cfg.TeamSettings.RestrictPublicChannelDeletion = model.PERMISSIONS_SYSTEM_ADMIN
+ *utils.Cfg.TeamSettings.RestrictPrivateChannelDeletion = model.PERMISSIONS_SYSTEM_ADMIN
+ utils.SetDefaultRolesBasedOnConfig()
+
+ // channels created by SystemAdmin
+ publicChannel6 = th.CreateChannelWithClient(th.SystemAdminClient, model.CHANNEL_OPEN)
+ privateChannel7 = th.CreateChannelWithClient(th.SystemAdminClient, model.CHANNEL_PRIVATE)
+ app.AddUserToChannel(user, publicChannel6)
+ app.AddUserToChannel(user, privateChannel7)
+
+ // cannot delete by user
+ _, resp = Client.DeleteChannel(publicChannel6.Id)
+ CheckForbiddenStatus(t, resp)
+
+ _, resp = Client.DeleteChannel(privateChannel7.Id)
+ CheckForbiddenStatus(t, resp)
+
+ // cannot delete by channel admin
+ MakeUserChannelAdmin(user, publicChannel6)
+ MakeUserChannelAdmin(user, privateChannel7)
+ store.ClearChannelCaches()
+
+ _, resp = Client.DeleteChannel(publicChannel6.Id)
+ CheckForbiddenStatus(t, resp)
+
+ _, resp = Client.DeleteChannel(privateChannel7.Id)
+ CheckForbiddenStatus(t, resp)
+
+ // cannot delete by team admin
+ UpdateUserToTeamAdmin(th.BasicUser, team)
+ app.InvalidateAllCaches()
+
+ _, resp = Client.DeleteChannel(publicChannel6.Id)
+ CheckForbiddenStatus(t, resp)
+
+ _, resp = Client.DeleteChannel(privateChannel7.Id)
+ CheckForbiddenStatus(t, resp)
+
+ // successful delete by SystemAdmin
+ _, resp = th.SystemAdminClient.DeleteChannel(publicChannel6.Id)
+ CheckNoError(t, resp)
+
+ _, resp = th.SystemAdminClient.DeleteChannel(privateChannel7.Id)
+ CheckNoError(t, resp)
+}
+
func TestGetChannelByName(t *testing.T) {
th := Setup().InitBasic().InitSystemAdmin()
defer TearDown()
diff --git a/app/channel.go b/app/channel.go
index 59b71c0a5..49d55e52f 100644
--- a/app/channel.go
+++ b/app/channel.go
@@ -703,6 +703,9 @@ func GetChannelCounts(teamId string, userId string) (*model.ChannelCounts, *mode
}
func JoinChannel(channel *model.Channel, userId string) *model.AppError {
+ if channel.DeleteAt > 0 {
+ return model.NewLocAppError("JoinChannel", "api.channel.join_channel.already_deleted.app_error", nil, "")
+ }
userChan := Srv.Store.User().Get(userId)
memberChan := Srv.Store.Channel().GetMember(channel.Id, userId)
diff --git a/i18n/en.json b/i18n/en.json
index 017ac7bc0..04a312115 100644
--- a/i18n/en.json
+++ b/i18n/en.json
@@ -304,6 +304,10 @@
"translation": "You do not have the appropriate permissions"
},
{
+ "id": "api.channel.join_channel.already_deleted.app_error",
+ "translation": "Channel is already deleted"
+ },
+ {
"id": "api.channel.join_channel.post_and_forget",
"translation": "%v has joined the channel."
},
diff --git a/model/client4.go b/model/client4.go
index 16e8bf7d3..38b89e74f 100644
--- a/model/client4.go
+++ b/model/client4.go
@@ -841,6 +841,16 @@ func (c *Client4) GetPublicChannelsForTeam(teamId string, page int, perPage int,
}
}
+// DeleteChannel deletes channel based on the provided channel id string.
+func (c *Client4) DeleteChannel(channelId string) (bool, *Response) {
+ if r, err := c.DoApiDelete(c.GetChannelRoute(channelId)); err != nil {
+ return false, &Response{StatusCode: r.StatusCode, Error: err}
+ } else {
+ defer closeBody(r)
+ return CheckStatusOK(r), BuildResponse(r)
+ }
+}
+
// GetChannelByName returns a channel based on the provided channel name and team id strings.
func (c *Client4) GetChannelByName(channelName, teamId string, etag string) (*Channel, *Response) {
if r, err := c.DoApiGet(c.GetChannelByNameRoute(channelName, teamId), etag); err != nil {