From 7c3d71c089fc0d8cba1594ad0692bcad8de7cffb Mon Sep 17 00:00:00 2001 From: Harshil Sharma <18575143+harshilsharma63@users.noreply.github.com> Date: Tue, 12 Nov 2024 12:29:29 +0530 Subject: [PATCH] Scheudled post test enhancement (#29187) * Added test for user beloonging to channel but not team * Added test for read onmly channel * Added test for fetching scheduled posts for team you don;'t belong to * Added more tests * test enhancements * CI --- server/channels/api4/scheduled_post_test.go | 73 +++++++++++++++ server/channels/app/helper_test.go | 8 ++ .../channels/app/scheduled_post_job_test.go | 53 +++++++++++ server/channels/app/scheduled_post_test.go | 89 ++++++++++++++++++- 4 files changed, 222 insertions(+), 1 deletion(-) create mode 100644 server/channels/api4/scheduled_post_test.go diff --git a/server/channels/api4/scheduled_post_test.go b/server/channels/api4/scheduled_post_test.go new file mode 100644 index 0000000000..34d34b859c --- /dev/null +++ b/server/channels/api4/scheduled_post_test.go @@ -0,0 +1,73 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +package api4 + +import ( + "context" + "testing" + + "github.com/mattermost/mattermost/server/public/model" + "github.com/stretchr/testify/require" +) + +func TestCreateScheduledPost(t *testing.T) { + th := Setup(t).InitBasic() + defer th.TearDown() + + th.App.Srv().SetLicense(model.NewTestLicenseSKU(model.LicenseShortSkuProfessional)) + + client := th.Client + + t.Run("base case", func(t *testing.T) { + userId := model.NewId() + + scheduledPost := &model.ScheduledPost{ + Draft: model.Draft{ + CreateAt: model.GetMillis(), + UserId: userId, + ChannelId: th.BasicChannel.Id, + Message: "this is a scheduled post", + }, + ScheduledAt: model.GetMillis() + 100000, // 100 seconds in the future + } + createdScheduledPost, _, err := client.CreateScheduledPost(context.Background(), scheduledPost) + require.NoError(t, err) + require.NotNil(t, createdScheduledPost) + }) + + t.Run("should not allow created scheduled post in read-only channel", func(t *testing.T) { + channel := th.CreatePublicChannel() + th.AddUserToChannel(th.BasicUser, channel) + + channelModerationPatches := []*model.ChannelModerationPatch{ + { + Name: model.NewPointer(model.PermissionCreatePost.Id), + Roles: &model.ChannelModeratedRolesPatch{ + Guests: model.NewPointer(true), + Members: model.NewPointer(false), + }, + }, + } + + err := th.App.SetPhase2PermissionsMigrationStatus(true) + require.NoError(t, err) + + _, appErr := th.App.PatchChannelModerationsForChannel(th.Context, channel, channelModerationPatches) + require.Nil(t, appErr) + + scheduledPost := &model.ScheduledPost{ + Draft: model.Draft{ + CreateAt: model.GetMillis(), + UserId: th.BasicUser.Id, + ChannelId: channel.Id, + Message: "this is a scheduled post", + }, + ScheduledAt: model.GetMillis() + 100000, // 100 seconds in the future + } + createdScheduledPost, _, httpErr := client.CreateScheduledPost(context.Background(), scheduledPost) + require.Error(t, httpErr) + require.Contains(t, httpErr.Error(), "You do not have the appropriate permissions.") + require.Nil(t, createdScheduledPost) + }) +} diff --git a/server/channels/app/helper_test.go b/server/channels/app/helper_test.go index 768edd5469..58a0c11a86 100644 --- a/server/channels/app/helper_test.go +++ b/server/channels/app/helper_test.go @@ -519,6 +519,14 @@ func (th *TestHelper) AddUserToChannel(user *model.User, channel *model.Channel) return member } +func (th *TestHelper) RemoveUserFromChannel(user *model.User, channel *model.Channel) *model.AppError { + appErr := th.App.RemoveUserFromChannel(th.Context, user.Id, user.Id, channel) + if appErr != nil { + panic(appErr) + } + return appErr +} + func (th *TestHelper) CreateRole(roleName string) *model.Role { role, _ := th.App.CreateRole(&model.Role{Name: roleName, DisplayName: roleName, Description: roleName, Permissions: []string{}}) return role diff --git a/server/channels/app/scheduled_post_job_test.go b/server/channels/app/scheduled_post_job_test.go index 10722e46a7..32c6b33f45 100644 --- a/server/channels/app/scheduled_post_job_test.go +++ b/server/channels/app/scheduled_post_job_test.go @@ -208,4 +208,57 @@ func TestProcessScheduledPosts(t *testing.T) { assert.Equal(t, model.ScheduledPostErrorCodeNoChannelPermission, scheduledPosts[1].ErrorCode) assert.Greater(t, scheduledPosts[1].ProcessedAt, int64(0)) }) + + t.Run("sets error code when user is not a team member", func(t *testing.T) { + th := Setup(t).InitBasic() + defer th.TearDown() + + th.App.Srv().SetLicense(getLicWithSkuShortName(model.LicenseShortSkuProfessional)) + + scheduledAt := model.GetMillis() + 1000 + scheduledPost1 := &model.ScheduledPost{ + Draft: model.Draft{ + CreateAt: model.GetMillis(), + UserId: th.BasicUser.Id, + ChannelId: th.BasicChannel.Id, + Message: "this is a scheduled post", + }, + ScheduledAt: scheduledAt, + } + _, err := th.Server.Store().ScheduledPost().CreateScheduledPost(scheduledPost1) + assert.NoError(t, err) + + scheduledPost2 := &model.ScheduledPost{ + Draft: model.Draft{ + CreateAt: model.GetMillis(), + UserId: th.BasicUser.Id, + ChannelId: th.BasicChannel.Id, + Message: "this is second scheduled post", + }, + ScheduledAt: scheduledAt, + } + _, err = th.Server.Store().ScheduledPost().CreateScheduledPost(scheduledPost2) + assert.NoError(t, err) + + appErr := th.App.RemoveUserFromTeam(th.Context, th.BasicTeam.Id, th.BasicUser.Id, th.BasicUser.Id) + assert.Nil(t, appErr) + + defer func() { + _, _, _ = th.App.AddUserToTeam(th.Context, th.BasicTeam.Id, th.BasicUser.Id, th.BasicUser.Id) + }() + + time.Sleep(1 * time.Second) + + th.App.ProcessScheduledPosts(th.Context) + + scheduledPosts, err := th.App.Srv().Store().ScheduledPost().GetScheduledPostsForUser(th.BasicUser.Id, th.BasicChannel.TeamId) + assert.NoError(t, err) + assert.Len(t, scheduledPosts, 2) + + assert.Equal(t, model.ScheduledPostErrorCodeNoChannelPermission, scheduledPosts[0].ErrorCode) + assert.Greater(t, scheduledPosts[0].ProcessedAt, int64(0)) + + assert.Equal(t, model.ScheduledPostErrorCodeNoChannelPermission, scheduledPosts[1].ErrorCode) + assert.Greater(t, scheduledPosts[1].ProcessedAt, int64(0)) + }) } diff --git a/server/channels/app/scheduled_post_test.go b/server/channels/app/scheduled_post_test.go index 4268218e5b..c07f3f32b5 100644 --- a/server/channels/app/scheduled_post_test.go +++ b/server/channels/app/scheduled_post_test.go @@ -6,6 +6,7 @@ package app import ( "net/http" "testing" + "time" "github.com/mattermost/mattermost/server/public/model" "github.com/stretchr/testify/require" @@ -228,7 +229,6 @@ func TestGetUserTeamScheduledPosts(t *testing.T) { user1ConnID := model.NewId() t.Run("should get created scheduled posts", func(t *testing.T) { - t.Skip("https://mattermost.atlassian.net/browse/MM-61523") scheduledPost1 := &model.ScheduledPost{ Draft: model.Draft{ CreateAt: model.GetMillis(), @@ -242,6 +242,10 @@ func TestGetUserTeamScheduledPosts(t *testing.T) { require.Nil(t, appErr) require.NotNil(t, createdScheduledPost1) + // this wait is to ensure scheduled post 2 and 1 have some time gap between the two + // to ensure a deterministic ordering + time.Sleep(1 * time.Second) + scheduledPost2 := &model.ScheduledPost{ Draft: model.Draft{ CreateAt: model.GetMillis(), @@ -414,6 +418,43 @@ func TestGetUserTeamScheduledPosts(t *testing.T) { require.Equal(t, createdScheduledPost1.Id, retrievedScheduledPosts[0].Id) require.Equal(t, createdScheduledPost2.Id, retrievedScheduledPosts[1].Id) }) + + t.Run("should not be able to fetch scheduled posts for team user doesn't belong to", func(t *testing.T) { + // create a dummy team + team := th.CreateTeam() + _, appErr := th.App.JoinUserToTeam(th.Context, team, th.BasicUser, th.BasicUser.Id) + require.Nil(t, appErr) + + // create a channel in this team + channel := th.CreateChannel(th.Context, team) + + // create scheduled post + scheduledPost1 := &model.ScheduledPost{ + Draft: model.Draft{ + CreateAt: model.GetMillis(), + UserId: th.BasicUser.Id, + ChannelId: channel.Id, + Message: "this is a scheduled post", + }, + ScheduledAt: model.GetMillis() + 100000, // 100 seconds in the future + } + createdScheduledPost1, appErr := th.App.SaveScheduledPost(th.Context, scheduledPost1, user1ConnID) + require.Nil(t, appErr) + require.NotNil(t, createdScheduledPost1) + + // verify we are able to fetch this scheduled post + retrievedScheduledPosts, appErr := th.App.GetUserTeamScheduledPosts(th.Context, th.BasicUser.Id, team.Id) + require.Nil(t, appErr) + require.Equal(t, 1, len(retrievedScheduledPosts)) + + appErr = th.App.RemoveUserFromTeam(th.Context, team.Id, th.BasicUser.Id, th.BasicUser.Id) + require.Nil(t, appErr) + + // now we should not be able to fetch this scheduled post + retrievedScheduledPosts, appErr = th.App.GetUserTeamScheduledPosts(th.Context, th.BasicUser.Id, th.BasicChannel.TeamId) + require.Nil(t, appErr) + require.Equal(t, 0, len(retrievedScheduledPosts)) + }) } func TestUpdateScheduledPost(t *testing.T) { @@ -581,6 +622,52 @@ func TestUpdateScheduledPost(t *testing.T) { require.Equal(t, 2, len(updatedScheduledPost.FileIds)) require.Equal(t, model.ScheduledPostErrorUnknownError, createdScheduledPost.ErrorCode) }) + + t.Run("should be able to update scheduled posts for channels user does not belong to", func(t *testing.T) { + channel := th.CreateChannel(th.Context, th.BasicTeam) + th.AddUserToChannel(th.BasicUser, channel) + + scheduledPost := &model.ScheduledPost{ + Draft: model.Draft{ + CreateAt: model.GetMillis(), + UserId: th.BasicUser.Id, + ChannelId: channel.Id, + Message: "this is a scheduled post", + }, + ScheduledAt: model.GetMillis() + 100000, // 100 seconds in the future + } + createdScheduledPost, appErr := th.App.SaveScheduledPost(th.Context, scheduledPost, user1ConnID) + require.Nil(t, appErr) + require.NotNil(t, createdScheduledPost) + + // now user will leave the channel + appErr = th.RemoveUserFromChannel(th.BasicUser, channel) + require.Nil(t, appErr) + + createdScheduledPost.Message = "Updated message" + + updatedScheduledPost, appErr := th.App.UpdateScheduledPost(th.Context, th.BasicUser.Id, createdScheduledPost, user1ConnID) + require.Nil(t, appErr) + require.NotNil(t, updatedScheduledPost) + require.Equal(t, updatedScheduledPost.Message, "Updated message") + }) + + t.Run("should not be able to update a non existing scheduled post", func(t *testing.T) { + scheduledPost := &model.ScheduledPost{ + Draft: model.Draft{ + CreateAt: model.GetMillis(), + UserId: th.BasicUser.Id, + ChannelId: th.BasicChannel.Id, + Message: "this is a scheduled post", + }, + Id: model.NewId(), + ScheduledAt: model.GetMillis() + 100000, // 100 seconds in the future + } + + updatedScheduledPost, appErr := th.App.UpdateScheduledPost(th.Context, th.BasicUser.Id, scheduledPost, user1ConnID) + require.NotNil(t, appErr) + require.Nil(t, updatedScheduledPost) + }) } func TestDeleteScheduledPost(t *testing.T) {