From b78175c3904926f913e4ef6eaf373c964be9afea Mon Sep 17 00:00:00 2001 From: Scott Bishel Date: Tue, 2 Jul 2024 05:35:43 -0600 Subject: [PATCH] require Permission to user to mark channels as read (#27468) --- server/channels/api4/channel.go | 5 ++ server/channels/api4/channel_test.go | 79 ++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+) diff --git a/server/channels/api4/channel.go b/server/channels/api4/channel.go index 1a9e0e7e3b..ee42d06f2d 100644 --- a/server/channels/api4/channel.go +++ b/server/channels/api4/channel.go @@ -1605,6 +1605,11 @@ func readMultipleChannels(c *Context, w http.ResponseWriter, r *http.Request) { return } + if !c.App.SessionHasPermissionToUser(*c.AppContext.Session(), c.Params.UserId) { + c.SetPermissionError(model.PermissionEditOtherUsers) + return + } + times, appErr := c.App.MarkChannelsAsViewed(c.AppContext, channelIds, c.Params.UserId, c.AppContext.Session().Id, true, c.App.IsCRTEnabledForUser(c.AppContext, c.Params.UserId)) if appErr != nil { c.Err = appErr diff --git a/server/channels/api4/channel_test.go b/server/channels/api4/channel_test.go index 9d6304e709..8c5dfbe364 100644 --- a/server/channels/api4/channel_test.go +++ b/server/channels/api4/channel_test.go @@ -2686,6 +2686,85 @@ func TestViewChannel(t *testing.T) { require.NoError(t, err) } +func TestReadMultipleChannels(t *testing.T) { + th := Setup(t).InitBasic() + defer th.TearDown() + client := th.Client + user := th.BasicUser + + t.Run("Should successfully mark public channels as read for self", func(t *testing.T) { + channel, _, err := client.GetChannel(context.Background(), th.BasicChannel.Id, "") + require.NoError(t, err) + channel2, _, err := client.GetChannel(context.Background(), th.BasicChannel2.Id, "") + require.NoError(t, err) + + channelResponse, _, err := client.ReadMultipleChannels(context.Background(), user.Id, []string{channel.Id, channel2.Id}) + require.NoError(t, err) + require.Equal(t, "OK", channelResponse.Status, "invalid status return") + require.Equal(t, channel.LastPostAt, channelResponse.LastViewedAtTimes[channel.Id], "wrong number of viewed at times") + require.Equal(t, channel2.LastPostAt, channelResponse.LastViewedAtTimes[channel2.Id], "wrong number of viewed at times") + }) + + t.Run("Should successfully mark private channels as read for self", func(t *testing.T) { + channel, _, err := client.GetChannel(context.Background(), th.BasicPrivateChannel.Id, "") + require.NoError(t, err) + + // private channel without membership should be ignored + channelResponse, _, err := client.ReadMultipleChannels(context.Background(), user.Id, []string{channel.Id, th.BasicPrivateChannel2.Id}) + require.NoError(t, err) + require.Equal(t, "OK", channelResponse.Status, "invalid status return") + require.Equal(t, 1, len(channelResponse.LastViewedAtTimes), "unexpected response") + require.Equal(t, channel.LastPostAt, channelResponse.LastViewedAtTimes[channel.Id], "wrong number of viewed at times") + }) + + t.Run("Should fail marking public/private channels for other user", func(t *testing.T) { + channel, _, err := client.GetChannel(context.Background(), th.BasicChannel.Id, "") + require.NoError(t, err) + + _, _, err = client.ReadMultipleChannels(context.Background(), th.BasicUser2.Id, []string{channel.Id}) + require.Error(t, err) + }) + + t.Run("Admin should succeed in marking public/private channels for other user", func(t *testing.T) { + adminClient := th.SystemAdminClient + channel, _, err := adminClient.GetChannel(context.Background(), th.BasicChannel.Id, "") + require.NoError(t, err) + privateChannel, _, err := adminClient.GetChannel(context.Background(), th.BasicPrivateChannel.Id, "") + require.NoError(t, err) + + channelResponse, _, err := adminClient.ReadMultipleChannels(context.Background(), th.BasicUser2.Id, []string{channel.Id, privateChannel.Id}) + require.NoError(t, err) + require.Equal(t, "OK", channelResponse.Status, "invalid status return") + require.Equal(t, channel.LastPostAt, channelResponse.LastViewedAtTimes[channel.Id], "wrong number of viewed at times") + require.Equal(t, privateChannel.LastPostAt, channelResponse.LastViewedAtTimes[privateChannel.Id], "wrong number of viewed at times") + }) + + t.Run("SystemManager should succeed in marking public/private channels for other user", func(t *testing.T) { + th.LoginSystemManager() + sysMgrClient := th.SystemManagerClient + + channel, _, err := sysMgrClient.GetChannel(context.Background(), th.BasicChannel.Id, "") + require.NoError(t, err) + privateChannel, _, err := sysMgrClient.GetChannel(context.Background(), th.BasicPrivateChannel.Id, "") + require.NoError(t, err) + + _, _, err = sysMgrClient.ReadMultipleChannels(context.Background(), th.BasicUser2.Id, []string{channel.Id, privateChannel.Id}) + require.Error(t, err) + }) + + t.Run("SystemManager without editOtherUsers should fail in marking public/private channels for other user", func(t *testing.T) { + sysMgrClient := th.SystemManagerClient + th.RemovePermissionFromRole(model.PermissionEditOtherUsers.Id, model.SystemManagerRoleId) + + defer func() { + th.AddPermissionToRole(model.PermissionEditOtherUsers.Id, model.SystemManagerRoleId) + }() + + _, _, err := sysMgrClient.ReadMultipleChannels(context.Background(), th.BasicUser2.Id, []string{th.BasicChannel.Id}) + require.Error(t, err) + }) +} + func TestGetChannelUnread(t *testing.T) { th := Setup(t).InitBasic() defer th.TearDown()