From c88232d71e1ef40e81f8ba76fe1fe039f9ea3c10 Mon Sep 17 00:00:00 2001 From: Ashish Bhate Date: Fri, 16 Jul 2021 19:34:22 +0530 Subject: [PATCH] [MM-35925] Follow thread when posting in one, even if previously unfollowed (#17926) --- app/post.go | 10 ++++++++++ app/post_test.go | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/app/post.go b/app/post.go index 54f25061c5..95811b66fa 100644 --- a/app/post.go +++ b/app/post.go @@ -353,6 +353,16 @@ func (a *App) CreatePost(c *request.Context, post *model.Post, channel *model.Ch // to be done when we send the post over the websocket in handlePostEvents rpost = a.PreparePostForClient(rpost, true, false) + // Make sure poster is following the thread + if *a.Config().ServiceSettings.ThreadAutoFollow && rpost.RootId != "" { + _, err := a.Srv().Store.Thread().MaintainMembership(user.Id, rpost.RootId, store.ThreadMembershipOpts{ + Following: true, + }) + if err != nil { + mlog.Warn("Failed to update thread membership", mlog.Err(err)) + } + } + if err := a.handlePostEvents(c, rpost, user, channel, triggerWebhooks, parentPostList, setOnline); err != nil { mlog.Warn("Failed to handle post events", mlog.Err(err)) } diff --git a/app/post_test.go b/app/post_test.go index 6106eb98f5..6de58a6aa1 100644 --- a/app/post_test.go +++ b/app/post_test.go @@ -20,6 +20,7 @@ import ( "github.com/mattermost/mattermost-server/v5/services/imageproxy" "github.com/mattermost/mattermost-server/v5/services/searchengine/mocks" "github.com/mattermost/mattermost-server/v5/shared/mlog" + "github.com/mattermost/mattermost-server/v5/store" "github.com/mattermost/mattermost-server/v5/store/storetest" storemocks "github.com/mattermost/mattermost-server/v5/store/storetest/mocks" "github.com/mattermost/mattermost-server/v5/testlib" @@ -2258,3 +2259,45 @@ func TestSharedChannelSyncForPostActions(t *testing.T) { assert.Equal(t, channel.Id, remoteClusterService.channelNotifications[2]) }) } + +func TestAutofollowOnPostingAfterUnfollow(t *testing.T) { + th := Setup(t).InitBasic() + defer th.TearDown() + os.Setenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS", "true") + defer os.Unsetenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS") + + th.App.UpdateConfig(func(cfg *model.Config) { + *cfg.ServiceSettings.ThreadAutoFollow = true + *cfg.ServiceSettings.CollapsedThreads = model.COLLAPSED_THREADS_DEFAULT_ON + }) + + channel := th.BasicChannel + user := th.BasicUser + user2 := th.BasicUser2 + appErr := th.App.JoinChannel(th.Context, channel, user.Id) + require.Nil(t, appErr) + appErr = th.App.JoinChannel(th.Context, channel, user2.Id) + require.Nil(t, appErr) + p1, err := th.App.CreatePost(th.Context, &model.Post{UserId: user.Id, ChannelId: channel.Id, Message: "Hi @" + user2.Username}, channel, false, false) + require.Nil(t, err) + _, err = th.App.CreatePost(th.Context, &model.Post{RootId: p1.Id, UserId: user2.Id, ChannelId: channel.Id, Message: "Hola"}, channel, false, false) + require.Nil(t, err) + _, err = th.App.CreatePost(th.Context, &model.Post{RootId: p1.Id, UserId: user.Id, ChannelId: channel.Id, Message: "reply"}, channel, false, false) + require.Nil(t, err) + + // unfollow thread + m, nErr := th.App.Srv().Store.Thread().MaintainMembership(user.Id, p1.Id, store.ThreadMembershipOpts{ + Following: false, + }) + require.NoError(t, nErr) + require.False(t, m.Following) + + _, err = th.App.CreatePost(th.Context, &model.Post{RootId: p1.Id, UserId: user.Id, ChannelId: channel.Id, Message: "another reply"}, channel, false, false) + require.Nil(t, err) + + // User should be following thread after posting in it, even after previously + // unfollowing it, if ThreadAutoFollow is true + m, err = th.App.GetThreadMembershipForUser(user.Id, p1.Id) + require.Nil(t, err) + require.True(t, m.Following) +}