From 0291730c2f2841e8181a2284f852a58294b28c51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Espino?= Date: Wed, 29 Aug 2018 15:07:37 +0200 Subject: MM-11270: Forbid react/de-react in archived channels (#9323) --- api4/reaction_test.go | 61 ++++++++++++++++++++++++++++++++++--- app/reaction.go | 83 +++++++++++++++++++++++++++------------------------ i18n/en.json | 8 +++++ 3 files changed, 109 insertions(+), 43 deletions(-) diff --git a/api4/reaction_test.go b/api4/reaction_test.go index ca2c49808..aa7e3fdb8 100644 --- a/api4/reaction_test.go +++ b/api4/reaction_test.go @@ -192,13 +192,36 @@ func TestSaveReaction(t *testing.T) { _, resp := Client.SaveReaction(reaction) CheckForbiddenStatus(t, resp) - if reactions, err := th.App.GetReactionsForPost(postId); err != nil || len(reactions) != 3 { - t.Fatal("should have not created a reactions") + if reactions, err := th.App.GetReactionsForPost(post.Id); err != nil || len(reactions) != 0 { + t.Fatal("should have not created a reaction") } th.App.RemoveLicense() th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.ExperimentalTownSquareIsReadOnly = false }) }) + + t.Run("unable-to-react-in-an-archived-channel", func(t *testing.T) { + th.LoginBasic() + + channel := th.CreatePublicChannel() + post := th.CreatePostWithClient(th.Client, channel) + + reaction := &model.Reaction{ + UserId: userId, + PostId: post.Id, + EmojiName: "smile", + } + + err := th.App.DeleteChannel(channel, userId) + assert.Nil(t, err) + + _, resp := Client.SaveReaction(reaction) + CheckForbiddenStatus(t, resp) + + if reactions, err := th.App.GetReactionsForPost(post.Id); err != nil || len(reactions) != 0 { + t.Fatal("should have not created a reaction") + } + }) } func TestGetReactions(t *testing.T) { @@ -498,7 +521,7 @@ func TestDeleteReaction(t *testing.T) { CheckNoError(t, resp) if reactions, err := th.App.GetReactionsForPost(postId); err != nil || len(reactions) != 1 { - t.Fatal("should have created a reactions") + t.Fatal("should have created a reaction") } th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.ExperimentalTownSquareIsReadOnly = true }) @@ -507,10 +530,40 @@ func TestDeleteReaction(t *testing.T) { CheckForbiddenStatus(t, resp) if reactions, err := th.App.GetReactionsForPost(postId); err != nil || len(reactions) != 1 { - t.Fatal("should have not deleted a reactions") + t.Fatal("should have not deleted a reaction") } th.App.RemoveLicense() th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.ExperimentalTownSquareIsReadOnly = false }) }) + + t.Run("unable-to-delete-reactions-in-an-archived-channel", func(t *testing.T) { + th.LoginBasic() + + channel := th.CreatePublicChannel() + post := th.CreatePostWithClient(th.Client, channel) + + reaction := &model.Reaction{ + UserId: userId, + PostId: post.Id, + EmojiName: "smile", + } + + r1, resp := Client.SaveReaction(reaction) + CheckNoError(t, resp) + + if reactions, err := th.App.GetReactionsForPost(postId); err != nil || len(reactions) != 1 { + t.Fatal("should have created a reaction") + } + + err := th.App.DeleteChannel(channel, userId) + assert.Nil(t, err) + + _, resp = Client.SaveReaction(r1) + CheckForbiddenStatus(t, resp) + + if reactions, err := th.App.GetReactionsForPost(post.Id); err != nil || len(reactions) != 1 { + t.Fatal("should have not deleted a reaction") + } + }) } diff --git a/app/reaction.go b/app/reaction.go index 082d28f0d..41fc7fca4 100644 --- a/app/reaction.go +++ b/app/reaction.go @@ -15,43 +15,46 @@ func (a *App) SaveReactionForPost(reaction *model.Reaction) (*model.Reaction, *m return nil, err } - if a.License() != nil && *a.Config().TeamSettings.ExperimentalTownSquareIsReadOnly { - var channel *model.Channel - if channel, err = a.GetChannel(post.ChannelId); err != nil { + channel, err := a.GetChannel(post.ChannelId) + if err != nil { + return nil, err + } + + if channel.DeleteAt > 0 { + return nil, model.NewAppError("deleteReactionForPost", "api.reaction.save.archived_channel.app_error", nil, "", http.StatusForbidden) + } + + if a.License() != nil && *a.Config().TeamSettings.ExperimentalTownSquareIsReadOnly && channel.Name == model.DEFAULT_CHANNEL { + user, err := a.GetUser(reaction.UserId) + if err != nil { return nil, err } - if channel.Name == model.DEFAULT_CHANNEL { - var user *model.User - if user, err = a.GetUser(reaction.UserId); err != nil { - return nil, err - } - - if !a.RolesGrantPermission(user.GetRoles(), model.PERMISSION_MANAGE_SYSTEM.Id) { - return nil, model.NewAppError("saveReactionForPost", "api.reaction.town_square_read_only", nil, "", http.StatusForbidden) - } + if !a.RolesGrantPermission(user.GetRoles(), model.PERMISSION_MANAGE_SYSTEM.Id) { + return nil, model.NewAppError("saveReactionForPost", "api.reaction.town_square_read_only", nil, "", http.StatusForbidden) } } - if result := <-a.Srv.Store.Reaction().Save(reaction); result.Err != nil { + result := <-a.Srv.Store.Reaction().Save(reaction) + if result.Err != nil { return nil, result.Err - } else { - reaction = result.Data.(*model.Reaction) + } - a.Go(func() { - a.sendReactionEvent(model.WEBSOCKET_EVENT_REACTION_ADDED, reaction, post, true) - }) + reaction = result.Data.(*model.Reaction) - return reaction, nil - } + a.Go(func() { + a.sendReactionEvent(model.WEBSOCKET_EVENT_REACTION_ADDED, reaction, post, true) + }) + + return reaction, nil } func (a *App) GetReactionsForPost(postId string) ([]*model.Reaction, *model.AppError) { - if result := <-a.Srv.Store.Reaction().GetForPost(postId, true); result.Err != nil { + result := <-a.Srv.Store.Reaction().GetForPost(postId, true) + if result.Err != nil { return nil, result.Err - } else { - return result.Data.([]*model.Reaction), nil } + return result.Data.([]*model.Reaction), nil } func (a *App) DeleteReactionForPost(reaction *model.Reaction) *model.AppError { @@ -60,21 +63,23 @@ func (a *App) DeleteReactionForPost(reaction *model.Reaction) *model.AppError { return err } - if a.License() != nil && *a.Config().TeamSettings.ExperimentalTownSquareIsReadOnly { - var channel *model.Channel - if channel, err = a.GetChannel(post.ChannelId); err != nil { + channel, err := a.GetChannel(post.ChannelId) + if err != nil { + return err + } + + if channel.DeleteAt > 0 { + return model.NewAppError("deleteReactionForPost", "api.reaction.delete.archived_channel.app_error", nil, "", http.StatusForbidden) + } + + if a.License() != nil && *a.Config().TeamSettings.ExperimentalTownSquareIsReadOnly && channel.Name == model.DEFAULT_CHANNEL { + user, err := a.GetUser(reaction.UserId) + if err != nil { return err } - if channel.Name == model.DEFAULT_CHANNEL { - var user *model.User - if user, err = a.GetUser(reaction.UserId); err != nil { - return err - } - - if !a.RolesGrantPermission(user.GetRoles(), model.PERMISSION_MANAGE_SYSTEM.Id) { - return model.NewAppError("deleteReactionForPost", "api.reaction.town_square_read_only", nil, "", http.StatusForbidden) - } + if !a.RolesGrantPermission(user.GetRoles(), model.PERMISSION_MANAGE_SYSTEM.Id) { + return model.NewAppError("deleteReactionForPost", "api.reaction.town_square_read_only", nil, "", http.StatusForbidden) } } @@ -85,12 +90,12 @@ func (a *App) DeleteReactionForPost(reaction *model.Reaction) *model.AppError { if result := <-a.Srv.Store.Reaction().Delete(reaction); result.Err != nil { return result.Err - } else { - a.Go(func() { - a.sendReactionEvent(model.WEBSOCKET_EVENT_REACTION_REMOVED, reaction, post, hasReactions) - }) } + a.Go(func() { + a.sendReactionEvent(model.WEBSOCKET_EVENT_REACTION_REMOVED, reaction, post, hasReactions) + }) + return nil } diff --git a/i18n/en.json b/i18n/en.json index 419c22d2d..a0733827a 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -1434,6 +1434,14 @@ "id": "api.preference.update_preferences.set.app_error", "translation": "Unable to set user preferences." }, + { + "id": "api.reaction.delete.archived_channel.app_error", + "translation": "You cannot remove a reaction in an archived channel." + }, + { + "id": "api.reaction.save.archived_channel.app_error", + "translation": "You cannot react in an archived channel." + }, { "id": "api.reaction.save_reaction.invalid.app_error", "translation": "Reaction is not valid." -- cgit v1.2.3-1-g7c22