diff --git a/db/migrations/migrations.list b/db/migrations/migrations.list index dcdb14f484..1576dca650 100644 --- a/db/migrations/migrations.list +++ b/db/migrations/migrations.list @@ -186,6 +186,8 @@ db/migrations/mysql/000092_add_createat_to_teammembers.down.sql db/migrations/mysql/000092_add_createat_to_teammembers.up.sql db/migrations/mysql/000093_notify_admin.down.sql db/migrations/mysql/000093_notify_admin.up.sql +db/migrations/mysql/000094_threads_teamid.down.sql +db/migrations/mysql/000094_threads_teamid.up.sql db/migrations/postgres/000001_create_teams.down.sql db/migrations/postgres/000001_create_teams.up.sql db/migrations/postgres/000002_create_team_members.down.sql @@ -372,3 +374,5 @@ db/migrations/postgres/000092_add_createat_to_teamembers.down.sql db/migrations/postgres/000092_add_createat_to_teamembers.up.sql db/migrations/postgres/000093_notify_admin.down.sql db/migrations/postgres/000093_notify_admin.up.sql +db/migrations/postgres/000094_threads_teamid.down.sql +db/migrations/postgres/000094_threads_teamid.up.sql diff --git a/db/migrations/mysql/000094_threads_teamid.down.sql b/db/migrations/mysql/000094_threads_teamid.down.sql new file mode 100644 index 0000000000..2ac406dc39 --- /dev/null +++ b/db/migrations/mysql/000094_threads_teamid.down.sql @@ -0,0 +1,14 @@ +SET @preparedStatement = (SELECT IF( + EXISTS( + SELECT 1 FROM INFORMATION_SCHEMA.STATISTICS + WHERE table_name = 'Threads' + AND table_schema = DATABASE() + AND column_name = 'TeamId' + ), + 'ALTER TABLE Threads DROP COLUMN TeamId;', + 'SELECT 1;' +)); + +PREPARE removeColumnIfExists FROM @preparedStatement; +EXECUTE removeColumnIfExists; +DEALLOCATE PREPARE removeColumnIfExists; diff --git a/db/migrations/mysql/000094_threads_teamid.up.sql b/db/migrations/mysql/000094_threads_teamid.up.sql new file mode 100644 index 0000000000..392a2d58ae --- /dev/null +++ b/db/migrations/mysql/000094_threads_teamid.up.sql @@ -0,0 +1,19 @@ +SET @preparedStatement = (SELECT IF( + NOT EXISTS( + SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS + WHERE table_name = 'Threads' + AND table_schema = DATABASE() + AND column_name = 'TeamId' + ), + 'ALTER TABLE Threads ADD COLUMN TeamId varchar(26) DEFAULT NULL;', + 'SELECT 1;' +)); + +PREPARE addColumnIfNotExists FROM @preparedStatement; +EXECUTE addColumnIfNotExists; +DEALLOCATE PREPARE addColumnIfNotExists; + +UPDATE Threads, Channels +SET Threads.TeamId = Channels.TeamId +WHERE Channels.Id = Threads.ChannelId +AND Threads.TeamId IS NULL; diff --git a/db/migrations/postgres/000094_threads_teamid.down.sql b/db/migrations/postgres/000094_threads_teamid.down.sql new file mode 100644 index 0000000000..9f4c061f39 --- /dev/null +++ b/db/migrations/postgres/000094_threads_teamid.down.sql @@ -0,0 +1 @@ +ALTER TABLE threads DROP COLUMN IF EXISTS teamid; diff --git a/db/migrations/postgres/000094_threads_teamid.up.sql b/db/migrations/postgres/000094_threads_teamid.up.sql new file mode 100644 index 0000000000..5c66138f1e --- /dev/null +++ b/db/migrations/postgres/000094_threads_teamid.up.sql @@ -0,0 +1,2 @@ +ALTER TABLE threads ADD COLUMN IF NOT EXISTS teamid VARCHAR(26); +UPDATE threads SET teamid = channels.teamid FROM channels WHERE threads.teamid IS NULL AND channels.id = threads.channelid; diff --git a/model/thread.go b/model/thread.go index f9c4842c71..5d7bdb70f3 100644 --- a/model/thread.go +++ b/model/thread.go @@ -26,6 +26,9 @@ type Thread struct { // DeleteAt is a denormalized copy of the root posts's DeleteAt. In the database, it's // named ThreadDeleteAt to avoid introducing a query conflict with older server versions. DeleteAt int64 `json:"delete_at"` + + // TeamId is a denormalized copy of the Channel's teamId. + TeamId string `json:"team_id"` } type ThreadResponse struct { diff --git a/store/sqlstore/integrity.go b/store/sqlstore/integrity.go index 51a262a3e4..3ee486aa9c 100644 --- a/store/sqlstore/integrity.go +++ b/store/sqlstore/integrity.go @@ -468,6 +468,7 @@ func checkPostsIntegrity(ss *SqlStore, results chan<- model.IntegrityCheckResult results <- checkPostsFileInfoIntegrity(ss) results <- checkPostsPostsRootIdIntegrity(ss) results <- checkPostsReactionsIntegrity(ss) + results <- checkThreadsTeamsIntegrity(ss) } func checkSchemesIntegrity(ss *SqlStore, results chan<- model.IntegrityCheckResult) { @@ -511,6 +512,16 @@ func checkUsersIntegrity(ss *SqlStore, results chan<- model.IntegrityCheckResult results <- checkUsersUserAccessTokensIntegrity(ss) } +func checkThreadsTeamsIntegrity(ss *SqlStore) model.IntegrityCheckResult { + return checkParentChildIntegrity(ss, relationalCheckConfig{ + parentName: "Teams", + parentIdAttr: "TeamId", + childName: "Threads", + childIdAttr: "PostId", + canParentIdBeEmpty: false, + }) +} + func CheckRelationalIntegrity(ss *SqlStore, results chan<- model.IntegrityCheckResult) { mlog.Info("Starting relational integrity checks...") checkChannelsIntegrity(ss, results) diff --git a/store/sqlstore/integrity_test.go b/store/sqlstore/integrity_test.go index 84096ab998..2b775c6bd3 100644 --- a/store/sqlstore/integrity_test.go +++ b/store/sqlstore/integrity_test.go @@ -650,9 +650,10 @@ func TestCheckPostsPostsRootIdIntegrity(t *testing.T) { }) t.Run("should generate a report with one record", func(t *testing.T) { - root := createPost(ss, model.NewId(), model.NewId(), "", "") + channel := createChannel(ss, model.NewId(), model.NewId()) + root := createPost(ss, channel.Id, model.NewId(), "", "") rootId := root.Id - post := createPost(ss, model.NewId(), model.NewId(), root.Id, root.Id) + post := createPost(ss, channel.Id, model.NewId(), root.Id, root.Id) dbmap.Exec(`DELETE FROM Posts WHERE Id=?`, root.Id) result := checkPostsPostsRootIdIntegrity(store) require.NoError(t, result.Err) @@ -663,6 +664,8 @@ func TestCheckPostsPostsRootIdIntegrity(t *testing.T) { ChildId: &post.Id, }, data.Records[0]) dbmap.Exec(`DELETE FROM Posts WHERE Id=?`, post.Id) + dbmap.Exec(`DELETE FROM Channels WHERE Id=?`, channel.Id) + dbmap.Exec(`DELETE FROM Threads WHERE PostId=?`, rootId) }) }) } @@ -1602,3 +1605,39 @@ func TestCheckUsersUserAccessTokensIntegrity(t *testing.T) { }) }) } + +func TestCheckThreadsTeamsIntegrity(t *testing.T) { + StoreTest(t, func(t *testing.T, ss store.Store) { + store := ss.(*SqlStore) + dbmap := store.GetMasterX() + + t.Run("should generate a report with no records", func(t *testing.T) { + result := checkThreadsTeamsIntegrity(store) + require.NoError(t, result.Err) + data := result.Data.(model.RelationalIntegrityCheckData) + require.Empty(t, data.Records) + }) + + t.Run("should generate a report with one record", func(t *testing.T) { + team := createTeam(ss) + channel := createChannel(ss, team.Id, model.NewId()) + root := createPost(ss, channel.Id, model.NewId(), "", "") + post := createPost(ss, channel.Id, model.NewId(), root.Id, root.Id) + + dbmap.Exec(`DELETE FROM Teams WHERE Id=?`, team.Id) + result := checkThreadsTeamsIntegrity(store) + require.NoError(t, result.Err) + data := result.Data.(model.RelationalIntegrityCheckData) + require.Len(t, data.Records, 1) + + require.Equal(t, model.OrphanedRecord{ + ParentId: &team.Id, + ChildId: &root.Id, + }, data.Records[0]) + dbmap.Exec(`DELETE FROM Posts WHERE Id=?`, post.Id) + dbmap.Exec(`DELETE FROM Posts WHERE Id=?`, root.Id) + dbmap.Exec(`DELETE FROM Channels WHERE Id=?`, channel.Id) + dbmap.Exec(`DELETE FROM Threads WHERE PostId=?`, root.Id) + }) + }) +} diff --git a/store/sqlstore/post_store.go b/store/sqlstore/post_store.go index 33dee42c36..14cec75d2b 100644 --- a/store/sqlstore/post_store.go +++ b/store/sqlstore/post_store.go @@ -2948,7 +2948,8 @@ func (s *SqlPostStore) updateThreadsFromPosts(transaction *sqlxTxWrapper, posts } threadsByRoots := []*model.Thread{} - if err := transaction.Select(&threadsByRoots, threadsByRootsSql, threadsByRootsArgs...); err != nil { + err = transaction.Select(&threadsByRoots, threadsByRootsSql, threadsByRootsArgs...) + if err != nil { return err } @@ -2957,6 +2958,8 @@ func (s *SqlPostStore) updateThreadsFromPosts(transaction *sqlxTxWrapper, posts threadByRoot[thread.PostId] = thread } + teamIdByChannelId := map[string]string{} + for rootId, posts := range postsByRoot { if thread, found := threadByRoot[rootId]; !found { data := []struct { @@ -2986,16 +2989,30 @@ func (s *SqlPostStore) updateThreadsFromPosts(transaction *sqlxTxWrapper, posts if err != nil { return err } + + channelId := posts[0].ChannelId + teamId, ok := teamIdByChannelId[channelId] + if !ok { + // get teamId for channel + err = transaction.Get(&teamId, "SELECT COALESCE(Channels.TeamId, '') FROM Channels WHERE Channels.Id=?", channelId) + if err != nil { + return err + } + + // store teamId for channel for efficiency + teamIdByChannelId[channelId] = teamId + } // no metadata entry, create one if _, err := transaction.NamedExec(`INSERT INTO Threads - (PostId, ChannelId, ReplyCount, LastReplyAt, Participants) + (PostId, ChannelId, ReplyCount, LastReplyAt, Participants, TeamId) VALUES - (:PostId, :ChannelId, :ReplyCount, :LastReplyAt, :Participants)`, &model.Thread{ + (:PostId, :ChannelId, :ReplyCount, :LastReplyAt, :Participants, :TeamId)`, &model.Thread{ PostId: rootId, - ChannelId: posts[0].ChannelId, + ChannelId: channelId, ReplyCount: count, LastReplyAt: lastReplyAt, Participants: participants, + TeamId: teamId, }); err != nil { return err } diff --git a/store/sqlstore/thread_store.go b/store/sqlstore/thread_store.go index a20b4f9362..3306a2856d 100644 --- a/store/sqlstore/thread_store.go +++ b/store/sqlstore/thread_store.go @@ -51,6 +51,7 @@ func (s *SqlThreadStore) initializeQueries() { "Threads.LastReplyAt", "Threads.Participants", "COALESCE(Threads.ThreadDeleteAt, 0) AS DeleteAt", + "COALESCE(Threads.TeamId, '') AS TeamId", ). From("Threads") @@ -62,6 +63,7 @@ func (s *SqlThreadStore) initializeQueries() { "Threads.LastReplyAt", "Threads.Participants", "COALESCE(Threads.ThreadDeleteAt, 0) AS ThreadDeleteAt", + "COALESCE(Threads.TeamId, '') AS TeamId", ). From("Threads") } @@ -95,10 +97,9 @@ func (s *SqlThreadStore) getTotalThreadsQuery(userId, teamId string, opts model. if teamId != "" { query = query. - LeftJoin("Channels ON Threads.ChannelId = Channels.Id"). Where(sq.Or{ - sq.Eq{"Channels.TeamId": teamId}, - sq.Eq{"Channels.TeamId": ""}, + sq.Eq{"Threads.TeamId": teamId}, + sq.Eq{"Threads.TeamId": ""}, }) } @@ -158,10 +159,9 @@ func (s *SqlThreadStore) GetTotalUnreadMentions(userId, teamId string, opts mode if teamId != "" { query = query. - LeftJoin("Channels ON Threads.ChannelId = Channels.Id"). Where(sq.Or{ - sq.Eq{"Channels.TeamId": teamId}, - sq.Eq{"Channels.TeamId": ""}, + sq.Eq{"Threads.TeamId": teamId}, + sq.Eq{"Threads.TeamId": ""}, }) } @@ -192,6 +192,7 @@ func (s *SqlThreadStore) GetThreadsForUser(userId, teamId string, opts model.Get UnreadMentions int64 Participants model.StringArray ThreadDeleteAt int64 + TeamId string model.Post } @@ -223,10 +224,9 @@ func (s *SqlThreadStore) GetThreadsForUser(userId, teamId string, opts model.Get // a team at all. if teamId != "" { query = query. - Join("Channels ON Threads.ChannelId = Channels.Id"). Where(sq.Or{ - sq.Eq{"Channels.TeamId": teamId}, - sq.Eq{"Channels.TeamId": ""}, + sq.Eq{"Threads.TeamId": teamId}, + sq.Eq{"Threads.TeamId": ""}, }) } @@ -322,7 +322,7 @@ func (s *SqlThreadStore) GetTeamsUnreadForUser(userID string, teamIDs []string) fetchConditions := sq.And{ sq.Eq{"ThreadMemberships.UserId": userID}, sq.Eq{"ThreadMemberships.Following": true}, - sq.Eq{"Channels.TeamId": teamIDs}, + sq.Eq{"Threads.TeamId": teamIDs}, sq.Eq{"COALESCE(Threads.ThreadDeleteAt, 0)": 0}, } @@ -348,10 +348,9 @@ func (s *SqlThreadStore) GetTeamsUnreadForUser(userID string, teamIDs []string) Select("COUNT(Threads.PostId) AS Count, TeamId"). From("Threads"). LeftJoin("ThreadMemberships ON Threads.PostId = ThreadMemberships.PostId"). - LeftJoin("Channels ON Threads.ChannelId = Channels.Id"). Where(fetchConditions). Where("Threads.LastReplyAt > ThreadMemberships.LastViewed"). - GroupBy("Channels.TeamId") + GroupBy("Threads.TeamId") err := s.GetReplicaX().SelectBuilder(&unreadThreads, repliesQuery) if err != nil { @@ -366,9 +365,8 @@ func (s *SqlThreadStore) GetTeamsUnreadForUser(userID string, teamIDs []string) Select("COALESCE(SUM(ThreadMemberships.UnreadMentions),0) AS Count, TeamId"). From("ThreadMemberships"). LeftJoin("Threads ON Threads.PostId = ThreadMemberships.PostId"). - LeftJoin("Channels ON Threads.ChannelId = Channels.Id"). Where(fetchConditions). - GroupBy("Channels.TeamId") + GroupBy("Threads.TeamId") err := s.GetReplicaX().SelectBuilder(&unreadMentions, mentionsQuery) if err != nil { @@ -449,6 +447,7 @@ func (s *SqlThreadStore) GetThreadForUser(teamId string, threadMembership *model UnreadMentions int64 Participants model.StringArray ThreadDeleteAt int64 + TeamId string model.Post } @@ -462,7 +461,7 @@ func (s *SqlThreadStore) GetThreadForUser(teamId string, threadMembership *model }) fetchConditions := sq.And{ - sq.Or{sq.Eq{"Channels.TeamId": teamId}, sq.Eq{"Channels.TeamId": ""}}, + sq.Or{sq.Eq{"Threads.TeamId": teamId}, sq.Eq{"Threads.TeamId": ""}}, sq.Eq{"Threads.PostId": threadMembership.PostId}, } @@ -476,7 +475,6 @@ func (s *SqlThreadStore) GetThreadForUser(teamId string, threadMembership *model query = query. Column(sq.Alias(unreadRepliesQuery, "UnreadReplies")). LeftJoin("Posts ON Posts.Id = Threads.PostId"). - LeftJoin("Channels ON Posts.ChannelId = Channels.Id"). Where(fetchConditions) err := s.GetReplicaX().GetBuilder(&thread, query) @@ -671,9 +669,8 @@ func (s *SqlThreadStore) GetMembershipsForUser(userId, teamId string) ([]*model. query := s.getQueryBuilder(). Select("ThreadMemberships.*"). Join("Threads ON Threads.PostId = ThreadMemberships.PostId"). - Join("Channels ON Threads.ChannelId = Channels.Id"). From("ThreadMemberships"). - Where(sq.Or{sq.Eq{"Channels.TeamId": teamId}, sq.Eq{"Channels.TeamId": ""}}). + Where(sq.Or{sq.Eq{"Threads.TeamId": teamId}, sq.Eq{"Threads.TeamId": ""}}). Where(sq.Eq{"ThreadMemberships.UserId": userId}) err := s.GetReplicaX().SelectBuilder(&memberships, query) diff --git a/store/storetest/channel_store.go b/store/storetest/channel_store.go index 3f4dd4cedd..2138f011ed 100644 --- a/store/storetest/channel_store.go +++ b/store/storetest/channel_store.go @@ -6894,11 +6894,19 @@ func testChannelStoreGetPinnedPosts(t *testing.T, ss store.Store) { require.Empty(t, pl.Posts, "wasn't supposed to return posts") t.Run("with correct ReplyCount", func(t *testing.T) { - channelId := model.NewId() + teamId := model.NewId() + channel, err := ss.Channel().Save(&model.Channel{ + TeamId: teamId, + DisplayName: "DisplayName", + Name: "channel" + model.NewId(), + Type: model.ChannelTypeOpen, + }, -1) + require.NoError(t, err) + userId := model.NewId() post1, err := ss.Post().Save(&model.Post{ - ChannelId: channelId, + ChannelId: channel.Id, UserId: userId, Message: "message", IsPinned: true, @@ -6907,7 +6915,7 @@ func testChannelStoreGetPinnedPosts(t *testing.T, ss store.Store) { time.Sleep(time.Millisecond) post2, err := ss.Post().Save(&model.Post{ - ChannelId: channelId, + ChannelId: channel.Id, UserId: userId, Message: "message", IsPinned: true, @@ -6916,7 +6924,7 @@ func testChannelStoreGetPinnedPosts(t *testing.T, ss store.Store) { time.Sleep(time.Millisecond) post3, err := ss.Post().Save(&model.Post{ - ChannelId: channelId, + ChannelId: channel.Id, UserId: userId, RootId: post1.Id, Message: "message", @@ -6925,7 +6933,7 @@ func testChannelStoreGetPinnedPosts(t *testing.T, ss store.Store) { require.NoError(t, err) time.Sleep(time.Millisecond) - posts, err := ss.Channel().GetPinnedPosts(channelId) + posts, err := ss.Channel().GetPinnedPosts(channel.Id) require.NoError(t, err) require.Len(t, posts.Posts, 3) require.Equal(t, posts.Posts[post1.Id].ReplyCount, int64(1)) diff --git a/store/storetest/post_store.go b/store/storetest/post_store.go index dd1ba40ae4..677d049218 100644 --- a/store/storetest/post_store.go +++ b/store/storetest/post_store.go @@ -78,20 +78,45 @@ func testPostStoreSave(t *testing.T, ss store.Store) { }) t.Run("Save replies", func(t *testing.T) { + teamId := model.NewId() + channel1, err := ss.Channel().Save(&model.Channel{ + TeamId: teamId, + DisplayName: "DisplayName1", + Name: "channel" + model.NewId(), + Type: model.ChannelTypeOpen, + }, -1) + require.NoError(t, err) + o1 := model.Post{} - o1.ChannelId = model.NewId() + o1.ChannelId = channel1.Id o1.UserId = model.NewId() o1.RootId = model.NewId() o1.Message = NewTestId() + channel2, err := ss.Channel().Save(&model.Channel{ + TeamId: teamId, + DisplayName: "DisplayName2", + Name: "channel" + model.NewId(), + Type: model.ChannelTypeOpen, + }, -1) + require.NoError(t, err) + o2 := model.Post{} - o2.ChannelId = model.NewId() + o2.ChannelId = channel2.Id o2.UserId = model.NewId() o2.RootId = o1.RootId o2.Message = NewTestId() + channel3, err := ss.Channel().Save(&model.Channel{ + TeamId: teamId, + DisplayName: "DisplayName3", + Name: "channel" + model.NewId(), + Type: model.ChannelTypeOpen, + }, -1) + require.NoError(t, err) + o3 := model.Post{} - o3.ChannelId = model.NewId() + o3.ChannelId = channel3.Id o3.UserId = model.NewId() o3.RootId = model.NewId() o3.Message = NewTestId() @@ -123,12 +148,21 @@ func testPostStoreSave(t *testing.T, ss store.Store) { }) t.Run("Update reply should update the UpdateAt of the root post", func(t *testing.T) { + teamId := model.NewId() + channel, err := ss.Channel().Save(&model.Channel{ + TeamId: teamId, + DisplayName: "DisplayName1", + Name: "channel" + model.NewId(), + Type: model.ChannelTypeOpen, + }, -1) + require.NoError(t, err) + rootPost := model.Post{} - rootPost.ChannelId = model.NewId() + rootPost.ChannelId = channel.Id rootPost.UserId = model.NewId() rootPost.Message = NewTestId() - _, err := ss.Post().Save(&rootPost) + _, err = ss.Post().Save(&rootPost) require.NoError(t, err) time.Sleep(2 * time.Millisecond) @@ -241,26 +275,58 @@ func testPostStoreSaveMultiple(t *testing.T, ss store.Store) { }) t.Run("Save replies", func(t *testing.T) { + teamId := model.NewId() + channel1, err := ss.Channel().Save(&model.Channel{ + TeamId: teamId, + DisplayName: "DisplayName1", + Name: "channel" + model.NewId(), + Type: model.ChannelTypeOpen, + }, -1) + require.NoError(t, err) + + channel2, err := ss.Channel().Save(&model.Channel{ + TeamId: teamId, + DisplayName: "DisplayName2", + Name: "channel" + model.NewId(), + Type: model.ChannelTypeOpen, + }, -1) + require.NoError(t, err) + + channel3, err := ss.Channel().Save(&model.Channel{ + TeamId: teamId, + DisplayName: "DisplayName3", + Name: "channel" + model.NewId(), + Type: model.ChannelTypeOpen, + }, -1) + require.NoError(t, err) + + channel4, err := ss.Channel().Save(&model.Channel{ + TeamId: teamId, + DisplayName: "DisplayName4", + Name: "channel" + model.NewId(), + Type: model.ChannelTypeOpen, + }, -1) + require.NoError(t, err) o1 := model.Post{} - o1.ChannelId = model.NewId() + o1.ChannelId = channel1.Id o1.UserId = model.NewId() o1.RootId = model.NewId() o1.Message = NewTestId() o2 := model.Post{} - o2.ChannelId = model.NewId() + o2.ChannelId = channel2.Id o2.UserId = model.NewId() o2.RootId = o1.RootId o2.Message = NewTestId() o3 := model.Post{} - o3.ChannelId = model.NewId() + o3.ChannelId = channel3.Id o3.UserId = model.NewId() o3.RootId = model.NewId() o3.Message = NewTestId() o4 := model.Post{} - o4.ChannelId = model.NewId() + o4.ChannelId = channel4.Id o4.UserId = model.NewId() o4.Message = NewTestId() @@ -291,8 +357,17 @@ func testPostStoreSaveMultiple(t *testing.T, ss store.Store) { }) t.Run("Update reply should update the UpdateAt of the root post", func(t *testing.T) { + teamId := model.NewId() + channel, err := ss.Channel().Save(&model.Channel{ + TeamId: teamId, + DisplayName: "DisplayName", + Name: "channel" + model.NewId(), + Type: model.ChannelTypeOpen, + }, -1) + require.NoError(t, err) + rootPost := model.Post{} - rootPost.ChannelId = model.NewId() + rootPost.ChannelId = channel.Id rootPost.UserId = model.NewId() rootPost.Message = NewTestId() @@ -302,7 +377,7 @@ func testPostStoreSaveMultiple(t *testing.T, ss store.Store) { replyPost.Message = NewTestId() replyPost.RootId = rootPost.Id - _, _, err := ss.Post().SaveMultiple([]*model.Post{&rootPost, &replyPost}) + _, _, err = ss.Post().SaveMultiple([]*model.Post{&rootPost, &replyPost}) require.NoError(t, err) rrootPost, err := ss.Post().GetSingle(rootPost.Id, false) @@ -367,34 +442,74 @@ func testPostStoreSaveMultiple(t *testing.T, ss store.Store) { }) t.Run("Thread participants", func(t *testing.T) { + teamId := model.NewId() + channel1, err := ss.Channel().Save(&model.Channel{ + TeamId: teamId, + DisplayName: "DisplayName1", + Name: "channel" + model.NewId(), + Type: model.ChannelTypeOpen, + }, -1) + require.NoError(t, err) + o1 := model.Post{} - o1.ChannelId = model.NewId() + o1.ChannelId = channel1.Id o1.UserId = model.NewId() o1.Message = "jessica hyde" + model.NewId() + "b" root, err := ss.Post().Save(&o1) require.NoError(t, err) + channel2, err := ss.Channel().Save(&model.Channel{ + TeamId: teamId, + DisplayName: "DisplayName2", + Name: "channel" + model.NewId(), + Type: model.ChannelTypeOpen, + }, -1) + require.NoError(t, err) + + channel3, err := ss.Channel().Save(&model.Channel{ + TeamId: teamId, + DisplayName: "DisplayName3", + Name: "channel" + model.NewId(), + Type: model.ChannelTypeOpen, + }, -1) + require.NoError(t, err) + + channel4, err := ss.Channel().Save(&model.Channel{ + TeamId: teamId, + DisplayName: "DisplayName4", + Name: "channel" + model.NewId(), + Type: model.ChannelTypeOpen, + }, -1) + require.NoError(t, err) + + channel5, err := ss.Channel().Save(&model.Channel{ + TeamId: teamId, + DisplayName: "DisplayName5", + Name: "channel" + model.NewId(), + Type: model.ChannelTypeOpen, + }, -1) + require.NoError(t, err) o2 := model.Post{} - o2.ChannelId = model.NewId() + o2.ChannelId = channel2.Id o2.UserId = model.NewId() o2.RootId = root.Id o2.Message = "zz" + model.NewId() + "b" o3 := model.Post{} - o3.ChannelId = model.NewId() + o3.ChannelId = channel3.Id o3.UserId = model.NewId() o3.RootId = root.Id o3.Message = "zz" + model.NewId() + "b" o4 := model.Post{} - o4.ChannelId = model.NewId() + o4.ChannelId = channel4.Id o4.UserId = o2.UserId o4.RootId = root.Id o4.Message = "zz" + model.NewId() + "b" o5 := model.Post{} - o5.ChannelId = model.NewId() + o5.ChannelId = channel5.Id o5.UserId = o1.UserId o5.RootId = root.Id o5.Message = "zz" + model.NewId() + "b" @@ -438,7 +553,7 @@ func testPostStoreSaveMultiple(t *testing.T, ss store.Store) { } func testPostStoreSaveChannelMsgCounts(t *testing.T, ss store.Store) { - c1 := &model.Channel{Name: model.NewId(), DisplayName: "posttestchannel", Type: model.ChannelTypeOpen} + c1 := &model.Channel{Name: model.NewId(), DisplayName: "posttestchannel", Type: model.ChannelTypeOpen, TeamId: model.NewId()} _, err := ss.Channel().Save(c1, 1000000) require.NoError(t, err) @@ -484,15 +599,23 @@ func testPostStoreSaveChannelMsgCounts(t *testing.T, ss store.Store) { } func testPostStoreGet(t *testing.T, ss store.Store) { + teamId := model.NewId() + channel, err := ss.Channel().Save(&model.Channel{ + TeamId: teamId, + DisplayName: "DisplayName1", + Name: "channel" + model.NewId(), + Type: model.ChannelTypeOpen, + }, -1) + require.NoError(t, err) o1 := &model.Post{} - o1.ChannelId = model.NewId() + o1.ChannelId = channel.Id o1.UserId = model.NewId() o1.Message = NewTestId() etag1 := ss.Post().GetEtag(o1.ChannelId, false, false) require.Equal(t, 0, strings.Index(etag1, model.CurrentVersion+"."), "Invalid Etag") - o1, err := ss.Post().Save(o1) + o1, err = ss.Post().Save(o1) require.NoError(t, err) etag2 := ss.Post().GetEtag(o1.ChannelId, false, false) @@ -511,8 +634,17 @@ func testPostStoreGet(t *testing.T, ss store.Store) { func testPostStoreGetForThread(t *testing.T, ss store.Store) { t.Run("Post thread is followed", func(t *testing.T) { - o1 := &model.Post{ChannelId: model.NewId(), UserId: model.NewId(), Message: NewTestId()} - o1, err := ss.Post().Save(o1) + teamId := model.NewId() + channel, err := ss.Channel().Save(&model.Channel{ + TeamId: teamId, + DisplayName: "DisplayName1", + Name: "channel" + model.NewId(), + Type: model.ChannelTypeOpen, + }, -1) + require.NoError(t, err) + + o1 := &model.Post{ChannelId: channel.Id, UserId: model.NewId(), Message: NewTestId()} + o1, err = ss.Post().Save(o1) require.NoError(t, err) _, err = ss.Post().Save(&model.Post{ChannelId: o1.ChannelId, UserId: model.NewId(), Message: NewTestId(), RootId: o1.Id}) require.NoError(t, err) @@ -532,8 +664,17 @@ func testPostStoreGetForThread(t *testing.T, ss store.Store) { }) t.Run("Post thread is explicitly not followed", func(t *testing.T) { - o1 := &model.Post{ChannelId: model.NewId(), UserId: model.NewId(), Message: NewTestId()} - o1, err := ss.Post().Save(o1) + teamId := model.NewId() + channel, err := ss.Channel().Save(&model.Channel{ + TeamId: teamId, + DisplayName: "DisplayName1", + Name: "channel" + model.NewId(), + Type: model.ChannelTypeOpen, + }, -1) + require.NoError(t, err) + + o1 := &model.Post{ChannelId: channel.Id, UserId: model.NewId(), Message: NewTestId()} + o1, err = ss.Post().Save(o1) require.NoError(t, err) _, err = ss.Post().Save(&model.Post{ChannelId: o1.ChannelId, UserId: model.NewId(), Message: NewTestId(), RootId: o1.Id}) require.NoError(t, err) @@ -553,8 +694,17 @@ func testPostStoreGetForThread(t *testing.T, ss store.Store) { }) t.Run("Post threadmembership does not exist", func(t *testing.T) { - o1 := &model.Post{ChannelId: model.NewId(), UserId: model.NewId(), Message: NewTestId()} - o1, err := ss.Post().Save(o1) + teamId := model.NewId() + channel, err := ss.Channel().Save(&model.Channel{ + TeamId: teamId, + DisplayName: "DisplayName1", + Name: "channel" + model.NewId(), + Type: model.ChannelTypeOpen, + }, -1) + require.NoError(t, err) + + o1 := &model.Post{ChannelId: channel.Id, UserId: model.NewId(), Message: NewTestId()} + o1, err = ss.Post().Save(o1) require.NoError(t, err) _, err = ss.Post().Save(&model.Post{ChannelId: o1.ChannelId, UserId: model.NewId(), Message: NewTestId(), RootId: o1.Id}) require.NoError(t, err) @@ -570,7 +720,16 @@ func testPostStoreGetForThread(t *testing.T, ss store.Store) { t.Run("Pagination", func(t *testing.T) { t.Skip("MM-46134") - o1, err := ss.Post().Save(&model.Post{ChannelId: model.NewId(), UserId: model.NewId(), Message: NewTestId()}) + teamId := model.NewId() + channel, err := ss.Channel().Save(&model.Channel{ + TeamId: teamId, + DisplayName: "DisplayName1", + Name: "channel" + model.NewId(), + Type: model.ChannelTypeOpen, + }, -1) + require.NoError(t, err) + + o1, err := ss.Post().Save(&model.Post{ChannelId: channel.Id, UserId: model.NewId(), Message: NewTestId()}) require.NoError(t, err) _, err = ss.Post().Save(&model.Post{ChannelId: o1.ChannelId, UserId: model.NewId(), Message: NewTestId(), RootId: o1.Id}) require.NoError(t, err) @@ -698,8 +857,17 @@ func testPostStoreGetForThread(t *testing.T, ss store.Store) { } func testPostStoreGetSingle(t *testing.T, ss store.Store) { + teamId := model.NewId() + channel, err := ss.Channel().Save(&model.Channel{ + TeamId: teamId, + DisplayName: "DisplayName1", + Name: "channel" + model.NewId(), + Type: model.ChannelTypeOpen, + }, -1) + require.NoError(t, err) + o1 := &model.Post{} - o1.ChannelId = model.NewId() + o1.ChannelId = channel.Id o1.UserId = model.NewId() o1.Message = NewTestId() @@ -708,7 +876,7 @@ func testPostStoreGetSingle(t *testing.T, ss store.Store) { o2.UserId = o1.UserId o2.Message = NewTestId() - o1, err := ss.Post().Save(o1) + o1, err = ss.Post().Save(o1) require.NoError(t, err) o2, err = ss.Post().Save(o2) @@ -757,11 +925,20 @@ func testPostStoreGetSingle(t *testing.T, ss store.Store) { } func testPostStoreUpdate(t *testing.T, ss store.Store) { + teamId := model.NewId() + channel, err := ss.Channel().Save(&model.Channel{ + TeamId: teamId, + DisplayName: "DisplayName1", + Name: "channel" + model.NewId(), + Type: model.ChannelTypeOpen, + }, -1) + require.NoError(t, err) + o1 := &model.Post{} - o1.ChannelId = model.NewId() + o1.ChannelId = channel.Id o1.UserId = model.NewId() o1.Message = NewTestId() - o1, err := ss.Post().Save(o1) + o1, err = ss.Post().Save(o1) require.NoError(t, err) o2 := &model.Post{} @@ -828,8 +1005,15 @@ func testPostStoreUpdate(t *testing.T, ss store.Store) { require.Equal(t, ro3a.Hashtags, o3a.Hashtags, "Failed to update/get") } + channel2, err := ss.Channel().Save(&model.Channel{ + TeamId: teamId, + DisplayName: "DisplayName1", + Name: "channel" + model.NewId(), + Type: model.ChannelTypeOpen, + }, -1) + require.NoError(t, err) o4, err := ss.Post().Save(&model.Post{ - ChannelId: model.NewId(), + ChannelId: channel2.Id, UserId: model.NewId(), Message: model.NewId(), Filenames: []string{"test"}, @@ -856,9 +1040,18 @@ func testPostStoreUpdate(t *testing.T, ss store.Store) { func testPostStoreDelete(t *testing.T, ss store.Store) { t.Run("single post, no replies", func(t *testing.T) { + teamId := model.NewId() + channel, err := ss.Channel().Save(&model.Channel{ + TeamId: teamId, + DisplayName: "DisplayName1", + Name: "channel" + model.NewId(), + Type: model.ChannelTypeOpen, + }, -1) + require.NoError(t, err) + // Create a post rootPost, err := ss.Post().Save(&model.Post{ - ChannelId: model.NewId(), + ChannelId: channel.Id, UserId: model.NewId(), Message: model.NewRandomString(10), }) @@ -896,9 +1089,18 @@ func testPostStoreDelete(t *testing.T, ss store.Store) { }) t.Run("thread with one reply", func(t *testing.T) { + teamId := model.NewId() + channel, err := ss.Channel().Save(&model.Channel{ + TeamId: teamId, + DisplayName: "DisplayName1", + Name: "channel" + model.NewId(), + Type: model.ChannelTypeOpen, + }, -1) + require.NoError(t, err) + // Create a root post rootPost, err := ss.Post().Save(&model.Post{ - ChannelId: model.NewId(), + ChannelId: channel.Id, UserId: model.NewId(), Message: NewTestId(), }) @@ -929,9 +1131,18 @@ func testPostStoreDelete(t *testing.T, ss store.Store) { }) t.Run("thread with multiple replies", func(t *testing.T) { + teamId := model.NewId() + channel, err := ss.Channel().Save(&model.Channel{ + TeamId: teamId, + DisplayName: "DisplayName1", + Name: "channel" + model.NewId(), + Type: model.ChannelTypeOpen, + }, -1) + require.NoError(t, err) + // Create a root post rootPost1, err := ss.Post().Save(&model.Post{ - ChannelId: model.NewId(), + ChannelId: channel.Id, UserId: model.NewId(), Message: NewTestId(), }) @@ -955,9 +1166,17 @@ func testPostStoreDelete(t *testing.T, ss store.Store) { }) require.NoError(t, err) + channel2, err := ss.Channel().Save(&model.Channel{ + TeamId: teamId, + DisplayName: "DisplayName1", + Name: "channel" + model.NewId(), + Type: model.ChannelTypeOpen, + }, -1) + require.NoError(t, err) + // Create another root post in a separate channel rootPost2, err := ss.Post().Save(&model.Post{ - ChannelId: model.NewId(), + ChannelId: channel2.Id, UserId: model.NewId(), Message: NewTestId(), }) @@ -983,9 +1202,18 @@ func testPostStoreDelete(t *testing.T, ss store.Store) { }) t.Run("thread with multiple replies, update thread last reply at", func(t *testing.T) { + teamId := model.NewId() + channel, err := ss.Channel().Save(&model.Channel{ + TeamId: teamId, + DisplayName: "DisplayName1", + Name: "channel" + model.NewId(), + Type: model.ChannelTypeOpen, + }, -1) + require.NoError(t, err) + // Create a root post rootPost1, err := ss.Post().Save(&model.Post{ - ChannelId: model.NewId(), + ChannelId: channel.Id, UserId: model.NewId(), Message: NewTestId(), }) @@ -1052,11 +1280,20 @@ func testPostStoreDelete(t *testing.T, ss store.Store) { } func testPostStorePermDelete1Level(t *testing.T, ss store.Store) { + teamId := model.NewId() + channel, err := ss.Channel().Save(&model.Channel{ + TeamId: teamId, + DisplayName: "DisplayName1", + Name: "channel" + model.NewId(), + Type: model.ChannelTypeOpen, + }, -1) + require.NoError(t, err) + o1 := &model.Post{} - o1.ChannelId = model.NewId() + o1.ChannelId = channel.Id o1.UserId = model.NewId() o1.Message = NewTestId() - o1, err := ss.Post().Save(o1) + o1, err = ss.Post().Save(o1) require.NoError(t, err) o2 := &model.Post{} @@ -1067,15 +1304,30 @@ func testPostStorePermDelete1Level(t *testing.T, ss store.Store) { o2, err = ss.Post().Save(o2) require.NoError(t, err) + channel2, err := ss.Channel().Save(&model.Channel{ + TeamId: teamId, + DisplayName: "DisplayName2", + Name: "channel" + model.NewId(), + Type: model.ChannelTypeOpen, + }, -1) + require.NoError(t, err) o3 := &model.Post{} - o3.ChannelId = model.NewId() + o3.ChannelId = channel2.Id o3.UserId = model.NewId() o3.Message = NewTestId() o3, err = ss.Post().Save(o3) require.NoError(t, err) + channel3, err := ss.Channel().Save(&model.Channel{ + TeamId: teamId, + DisplayName: "DisplayName3", + Name: "channel" + model.NewId(), + Type: model.ChannelTypeOpen, + }, -1) + require.NoError(t, err) + o4 := &model.Post{} - o4.ChannelId = model.NewId() + o4.ChannelId = channel3.Id o4.RootId = o1.Id o4.UserId = o2.UserId o4.Message = NewTestId() @@ -1144,11 +1396,20 @@ func testPostStorePermDelete1Level(t *testing.T, ss store.Store) { } func testPostStorePermDelete1Level2(t *testing.T, ss store.Store) { + teamId := model.NewId() + channel1, err := ss.Channel().Save(&model.Channel{ + TeamId: teamId, + DisplayName: "DisplayName1", + Name: "channel" + model.NewId(), + Type: model.ChannelTypeOpen, + }, -1) + require.NoError(t, err) + o1 := &model.Post{} - o1.ChannelId = model.NewId() + o1.ChannelId = channel1.Id o1.UserId = model.NewId() o1.Message = NewTestId() - o1, err := ss.Post().Save(o1) + o1, err = ss.Post().Save(o1) require.NoError(t, err) o2 := &model.Post{} @@ -1159,8 +1420,16 @@ func testPostStorePermDelete1Level2(t *testing.T, ss store.Store) { o2, err = ss.Post().Save(o2) require.NoError(t, err) + channel2, err := ss.Channel().Save(&model.Channel{ + TeamId: teamId, + DisplayName: "DisplayName2", + Name: "channel" + model.NewId(), + Type: model.ChannelTypeOpen, + }, -1) + require.NoError(t, err) + o3 := &model.Post{} - o3.ChannelId = model.NewId() + o3.ChannelId = channel2.Id o3.UserId = model.NewId() o3.Message = NewTestId() o3, err = ss.Post().Save(o3) @@ -1180,11 +1449,20 @@ func testPostStorePermDelete1Level2(t *testing.T, ss store.Store) { } func testPostStoreGetWithChildren(t *testing.T, ss store.Store) { + teamId := model.NewId() + channel1, err := ss.Channel().Save(&model.Channel{ + TeamId: teamId, + DisplayName: "DisplayName1", + Name: "channel" + model.NewId(), + Type: model.ChannelTypeOpen, + }, -1) + require.NoError(t, err) + o1 := &model.Post{} - o1.ChannelId = model.NewId() + o1.ChannelId = channel1.Id o1.UserId = model.NewId() o1.Message = NewTestId() - o1, err := ss.Post().Save(o1) + o1, err = ss.Post().Save(o1) require.NoError(t, err) o2 := &model.Post{} @@ -1226,11 +1504,20 @@ func testPostStoreGetWithChildren(t *testing.T, ss store.Store) { } func testPostStoreGetPostsWithDetails(t *testing.T, ss store.Store) { + teamId := model.NewId() + channel1, err := ss.Channel().Save(&model.Channel{ + TeamId: teamId, + DisplayName: "DisplayName1", + Name: "channel" + model.NewId(), + Type: model.ChannelTypeOpen, + }, -1) + require.NoError(t, err) + o1 := &model.Post{} - o1.ChannelId = model.NewId() + o1.ChannelId = channel1.Id o1.UserId = model.NewId() o1.Message = NewTestId() - o1, err := ss.Post().Save(o1) + o1, err = ss.Post().Save(o1) require.NoError(t, err) time.Sleep(2 * time.Millisecond) @@ -1321,7 +1608,16 @@ func testPostStoreGetPostsWithDetails(t *testing.T, ss store.Store) { func testPostStoreGetPostsBeforeAfter(t *testing.T, ss store.Store) { t.Run("without threads", func(t *testing.T) { - channelId := model.NewId() + teamId := model.NewId() + channel1, err := ss.Channel().Save(&model.Channel{ + TeamId: teamId, + DisplayName: "DisplayName1", + Name: "channel" + model.NewId(), + Type: model.ChannelTypeOpen, + }, -1) + require.NoError(t, err) + + channelId := channel1.Id userId := model.NewId() var posts []*model.Post @@ -1416,7 +1712,16 @@ func testPostStoreGetPostsBeforeAfter(t *testing.T, ss store.Store) { }) }) t.Run("with threads", func(t *testing.T) { - channelId := model.NewId() + teamId := model.NewId() + channel1, err := ss.Channel().Save(&model.Channel{ + TeamId: teamId, + DisplayName: "DisplayName1", + Name: "channel" + model.NewId(), + Type: model.ChannelTypeOpen, + }, -1) + require.NoError(t, err) + + channelId := channel1.Id userId := model.NewId() // This creates a series of posts that looks like: @@ -1514,7 +1819,16 @@ func testPostStoreGetPostsBeforeAfter(t *testing.T, ss store.Store) { }) }) t.Run("with threads (skipFetchThreads)", func(t *testing.T) { - channelId := model.NewId() + teamId := model.NewId() + channel1, err := ss.Channel().Save(&model.Channel{ + TeamId: teamId, + DisplayName: "DisplayName1", + Name: "channel" + model.NewId(), + Type: model.ChannelTypeOpen, + }, -1) + require.NoError(t, err) + + channelId := channel1.Id userId := model.NewId() // This creates a series of posts that looks like: @@ -1620,7 +1934,16 @@ func testPostStoreGetPostsBeforeAfter(t *testing.T, ss store.Store) { }) }) t.Run("with threads (collapsedThreads)", func(t *testing.T) { - channelId := model.NewId() + teamId := model.NewId() + channel1, err := ss.Channel().Save(&model.Channel{ + TeamId: teamId, + DisplayName: "DisplayName1", + Name: "channel" + model.NewId(), + Type: model.ChannelTypeOpen, + }, -1) + require.NoError(t, err) + + channelId := channel1.Id userId := model.NewId() // This creates a series of posts that looks like: @@ -1715,7 +2038,16 @@ func testPostStoreGetPostsBeforeAfter(t *testing.T, ss store.Store) { func testPostStoreGetPostsSince(t *testing.T, ss store.Store) { t.Run("should return posts created after the given time", func(t *testing.T) { - channelId := model.NewId() + teamId := model.NewId() + channel1, err := ss.Channel().Save(&model.Channel{ + TeamId: teamId, + DisplayName: "DisplayName1", + Name: "channel" + model.NewId(), + Type: model.ChannelTypeOpen, + }, -1) + require.NoError(t, err) + + channelId := channel1.Id userId := model.NewId() post1, err := ss.Post().Save(&model.Post{ @@ -1788,7 +2120,16 @@ func testPostStoreGetPostsSince(t *testing.T, ss store.Store) { }) t.Run("should return empty list when nothing has changed", func(t *testing.T) { - channelId := model.NewId() + teamId := model.NewId() + channel1, err := ss.Channel().Save(&model.Channel{ + TeamId: teamId, + DisplayName: "DisplayName1", + Name: "channel" + model.NewId(), + Type: model.ChannelTypeOpen, + }, -1) + require.NoError(t, err) + + channelId := channel1.Id userId := model.NewId() post1, err := ss.Post().Save(&model.Post{ @@ -1809,7 +2150,16 @@ func testPostStoreGetPostsSince(t *testing.T, ss store.Store) { t.Run("should not cache a timestamp of 0 when nothing has changed", func(t *testing.T) { ss.Post().ClearCaches() - channelId := model.NewId() + teamId := model.NewId() + channel1, err := ss.Channel().Save(&model.Channel{ + TeamId: teamId, + DisplayName: "DisplayName1", + Name: "channel" + model.NewId(), + Type: model.ChannelTypeOpen, + }, -1) + require.NoError(t, err) + + channelId := channel1.Id userId := model.NewId() post1, err := ss.Post().Save(&model.Post{ @@ -1837,7 +2187,16 @@ func testPostStoreGetPostsSince(t *testing.T, ss store.Store) { } func testPostStoreGetPosts(t *testing.T, ss store.Store) { - channelId := model.NewId() + teamId := model.NewId() + channel1, err := ss.Channel().Save(&model.Channel{ + TeamId: teamId, + DisplayName: "DisplayName1", + Name: "channel" + model.NewId(), + Type: model.ChannelTypeOpen, + }, -1) + require.NoError(t, err) + + channelId := channel1.Id userId := model.NewId() post1, err := ss.Post().Save(&model.Post{ @@ -2016,13 +2375,22 @@ func testPostStoreGetPosts(t *testing.T, ss store.Store) { } func testPostStoreGetPostBeforeAfter(t *testing.T, ss store.Store) { - channelId := model.NewId() + teamId := model.NewId() + channel1, err := ss.Channel().Save(&model.Channel{ + TeamId: teamId, + DisplayName: "DisplayName1", + Name: "channel" + model.NewId(), + Type: model.ChannelTypeOpen, + }, -1) + require.NoError(t, err) + + channelId := channel1.Id o0 := &model.Post{} o0.ChannelId = channelId o0.UserId = model.NewId() o0.Message = NewTestId() - _, err := ss.Post().Save(o0) + _, err = ss.Post().Save(o0) require.NoError(t, err) time.Sleep(2 * time.Millisecond) @@ -2054,8 +2422,16 @@ func testPostStoreGetPostBeforeAfter(t *testing.T, ss store.Store) { require.NoError(t, err) time.Sleep(2 * time.Millisecond) + channel2, err := ss.Channel().Save(&model.Channel{ + TeamId: teamId, + DisplayName: "DisplayName2", + Name: "channel" + model.NewId(), + Type: model.ChannelTypeOpen, + }, -1) + require.NoError(t, err) + otherChannelPost := &model.Post{} - otherChannelPost.ChannelId = model.NewId() + otherChannelPost.ChannelId = channel2.Id otherChannelPost.UserId = model.NewId() otherChannelPost.Message = NewTestId() _, err = ss.Post().Save(otherChannelPost) @@ -2366,8 +2742,17 @@ func testPostStoreGetFlaggedPostsForTeam(t *testing.T, ss store.Store, s SqlStor _, err = ss.Channel().SaveMember(m0) require.NoError(t, err) + teamId := model.NewId() + channel2, err := ss.Channel().Save(&model.Channel{ + TeamId: teamId, + DisplayName: "DisplayName2", + Name: "channel" + model.NewId(), + Type: model.ChannelTypeOpen, + }, -1) + require.NoError(t, err) + o4 := &model.Post{} - o4.ChannelId = model.NewId() + o4.ChannelId = channel2.Id o4.UserId = model.NewId() o4.Message = NewTestId() o4, err = ss.Post().Save(o4) @@ -2401,8 +2786,16 @@ func testPostStoreGetFlaggedPostsForTeam(t *testing.T, ss store.Store, s SqlStor time.Sleep(2 * time.Millisecond) // Post on channel where user is not a member + channel3, err := ss.Channel().Save(&model.Channel{ + TeamId: teamId, + DisplayName: "DisplayName3", + Name: "channel" + model.NewId(), + Type: model.ChannelTypeOpen, + }, -1) + require.NoError(t, err) + o6 := &model.Post{} - o6.ChannelId = model.NewId() + o6.ChannelId = channel3.Id o6.UserId = m2.UserId o6.Message = NewTestId() o6, err = ss.Post().Save(o6) @@ -2562,8 +2955,17 @@ func testPostStoreGetFlaggedPosts(t *testing.T, ss store.Store) { time.Sleep(2 * time.Millisecond) // Post on channel where user is not a member + teamId := model.NewId() + channel2, err := ss.Channel().Save(&model.Channel{ + TeamId: teamId, + DisplayName: "DisplayName2", + Name: "channel" + model.NewId(), + Type: model.ChannelTypeOpen, + }, -1) + require.NoError(t, err) + o4 := &model.Post{} - o4.ChannelId = model.NewId() + o4.ChannelId = channel2.Id o4.UserId = model.NewId() o4.Message = NewTestId() o4, err = ss.Post().Save(o4) @@ -2692,8 +3094,17 @@ func testPostStoreGetFlaggedPostsForChannel(t *testing.T, ss store.Store) { time.Sleep(2 * time.Millisecond) // deleted post + teamId := model.NewId() + channel3, err := ss.Channel().Save(&model.Channel{ + TeamId: teamId, + DisplayName: "DisplayName3", + Name: "channel" + model.NewId(), + Type: model.ChannelTypeOpen, + }, -1) + require.NoError(t, err) + o3 := &model.Post{} - o3.ChannelId = model.NewId() + o3.ChannelId = channel3.Id o3.UserId = o1.ChannelId o3.Message = NewTestId() o3.DeleteAt = 1 @@ -2710,8 +3121,16 @@ func testPostStoreGetFlaggedPostsForChannel(t *testing.T, ss store.Store) { time.Sleep(2 * time.Millisecond) // Post on channel where user is not a member + channel4, err := ss.Channel().Save(&model.Channel{ + TeamId: teamId, + DisplayName: "DisplayName4", + Name: "channel" + model.NewId(), + Type: model.ChannelTypeOpen, + }, -1) + require.NoError(t, err) + o5 := &model.Post{} - o5.ChannelId = model.NewId() + o5.ChannelId = channel4.Id o5.UserId = model.NewId() o5.Message = NewTestId() o5, err = ss.Post().Save(o5) @@ -2792,13 +3211,22 @@ func testPostStoreGetFlaggedPostsForChannel(t *testing.T, ss store.Store) { } func testPostStoreGetLastPostRowCreateAt(t *testing.T, ss store.Store) { + teamId := model.NewId() + channel1, err := ss.Channel().Save(&model.Channel{ + TeamId: teamId, + DisplayName: "DisplayName1", + Name: "channel" + model.NewId(), + Type: model.ChannelTypeOpen, + }, -1) + require.NoError(t, err) + createTime1 := model.GetMillis() + 1 o0 := &model.Post{} - o0.ChannelId = model.NewId() + o0.ChannelId = channel1.Id o0.UserId = model.NewId() o0.Message = NewTestId() o0.CreateAt = createTime1 - o0, err := ss.Post().Save(o0) + o0, err = ss.Post().Save(o0) require.NoError(t, err) createTime2 := model.GetMillis() + 2 @@ -2817,14 +3245,23 @@ func testPostStoreGetLastPostRowCreateAt(t *testing.T, ss store.Store) { } func testPostStoreGetPostsCreatedAt(t *testing.T, ss store.Store) { + teamId := model.NewId() + channel1, err := ss.Channel().Save(&model.Channel{ + TeamId: teamId, + DisplayName: "DisplayName1", + Name: "channel" + model.NewId(), + Type: model.ChannelTypeOpen, + }, -1) + require.NoError(t, err) + createTime := model.GetMillis() + 1 o0 := &model.Post{} - o0.ChannelId = model.NewId() + o0.ChannelId = channel1.Id o0.UserId = model.NewId() o0.Message = NewTestId() o0.CreateAt = createTime - o0, err := ss.Post().Save(o0) + o0, err = ss.Post().Save(o0) require.NoError(t, err) o1 := &model.Post{} @@ -2844,8 +3281,16 @@ func testPostStoreGetPostsCreatedAt(t *testing.T, ss store.Store) { _, err = ss.Post().Save(o2) require.NoError(t, err) + channel2, err := ss.Channel().Save(&model.Channel{ + TeamId: teamId, + DisplayName: "DisplayName2", + Name: "channel" + model.NewId(), + Type: model.ChannelTypeOpen, + }, -1) + require.NoError(t, err) + o3 := &model.Post{} - o3.ChannelId = model.NewId() + o3.ChannelId = channel2.Id o3.UserId = model.NewId() o3.Message = NewTestId() o3.CreateAt = createTime @@ -2857,11 +3302,20 @@ func testPostStoreGetPostsCreatedAt(t *testing.T, ss store.Store) { } func testPostStoreOverwriteMultiple(t *testing.T, ss store.Store) { + teamId := model.NewId() + channel1, err := ss.Channel().Save(&model.Channel{ + TeamId: teamId, + DisplayName: "DisplayName1", + Name: "channel" + model.NewId(), + Type: model.ChannelTypeOpen, + }, -1) + require.NoError(t, err) + o1 := &model.Post{} - o1.ChannelId = model.NewId() + o1.ChannelId = channel1.Id o1.UserId = model.NewId() o1.Message = NewTestId() - o1, err := ss.Post().Save(o1) + o1, err = ss.Post().Save(o1) require.NoError(t, err) o2 := &model.Post{} @@ -2879,16 +3333,31 @@ func testPostStoreOverwriteMultiple(t *testing.T, ss store.Store) { o3, err = ss.Post().Save(o3) require.NoError(t, err) + channel2, err := ss.Channel().Save(&model.Channel{ + TeamId: teamId, + DisplayName: "DisplayName2", + Name: "channel" + model.NewId(), + Type: model.ChannelTypeOpen, + }, -1) + require.NoError(t, err) + o4, err := ss.Post().Save(&model.Post{ - ChannelId: model.NewId(), + ChannelId: channel2.Id, UserId: model.NewId(), Message: model.NewId(), Filenames: []string{"test"}, }) require.NoError(t, err) + channel3, err := ss.Channel().Save(&model.Channel{ + TeamId: teamId, + DisplayName: "DisplayName3", + Name: "channel" + model.NewId(), + Type: model.ChannelTypeOpen, + }, -1) + require.NoError(t, err) o5, err := ss.Post().Save(&model.Post{ - ChannelId: model.NewId(), + ChannelId: channel3.Id, UserId: model.NewId(), Message: model.NewId(), Filenames: []string{"test2", "test3"}, @@ -2983,11 +3452,20 @@ func testPostStoreOverwriteMultiple(t *testing.T, ss store.Store) { } func testPostStoreOverwrite(t *testing.T, ss store.Store) { + teamId := model.NewId() + channel1, err := ss.Channel().Save(&model.Channel{ + TeamId: teamId, + DisplayName: "DisplayName1", + Name: "channel" + model.NewId(), + Type: model.ChannelTypeOpen, + }, -1) + require.NoError(t, err) + o1 := &model.Post{} - o1.ChannelId = model.NewId() + o1.ChannelId = channel1.Id o1.UserId = model.NewId() o1.Message = NewTestId() - o1, err := ss.Post().Save(o1) + o1, err = ss.Post().Save(o1) require.NoError(t, err) o2 := &model.Post{} @@ -3005,8 +3483,15 @@ func testPostStoreOverwrite(t *testing.T, ss store.Store) { o3, err = ss.Post().Save(o3) require.NoError(t, err) + channel2, err := ss.Channel().Save(&model.Channel{ + TeamId: teamId, + DisplayName: "DisplayName2", + Name: "channel" + model.NewId(), + Type: model.ChannelTypeOpen, + }, -1) + require.NoError(t, err) o4, err := ss.Post().Save(&model.Post{ - ChannelId: model.NewId(), + ChannelId: channel2.Id, UserId: model.NewId(), Message: model.NewId(), Filenames: []string{"test"}, @@ -3084,11 +3569,20 @@ func testPostStoreOverwrite(t *testing.T, ss store.Store) { } func testPostStoreGetPostsByIds(t *testing.T, ss store.Store) { + teamId := model.NewId() + channel1, err := ss.Channel().Save(&model.Channel{ + TeamId: teamId, + DisplayName: "DisplayName1", + Name: "channel" + model.NewId(), + Type: model.ChannelTypeOpen, + }, -1) + require.NoError(t, err) + o1 := &model.Post{} - o1.ChannelId = model.NewId() + o1.ChannelId = channel1.Id o1.UserId = model.NewId() o1.Message = NewTestId() - o1, err := ss.Post().Save(o1) + o1, err = ss.Post().Save(o1) require.NoError(t, err) o2 := &model.Post{} @@ -3402,12 +3896,21 @@ func testPostStorePermanentDeleteBatch(t *testing.T, ss store.Store) { } func testPostStoreGetOldest(t *testing.T, ss store.Store) { + teamId := model.NewId() + channel1, err := ss.Channel().Save(&model.Channel{ + TeamId: teamId, + DisplayName: "DisplayName1", + Name: "channel" + model.NewId(), + Type: model.ChannelTypeOpen, + }, -1) + require.NoError(t, err) + o0 := &model.Post{} - o0.ChannelId = model.NewId() + o0.ChannelId = channel1.Id o0.UserId = model.NewId() o0.Message = NewTestId() o0.CreateAt = 3 - o0, err := ss.Post().Save(o0) + o0, err = ss.Post().Save(o0) require.NoError(t, err) o1 := &model.Post{} @@ -3751,10 +4254,19 @@ func testPostStoreGetDirectPostParentsForExportAfterBatched(t *testing.T, ss sto func testHasAutoResponsePostByUserSince(t *testing.T, ss store.Store) { t.Run("should return posts created after the given time", func(t *testing.T) { - channelId := model.NewId() + teamId := model.NewId() + channel1, err := ss.Channel().Save(&model.Channel{ + TeamId: teamId, + DisplayName: "DisplayName1", + Name: "channel" + model.NewId(), + Type: model.ChannelTypeOpen, + }, -1) + require.NoError(t, err) + + channelId := channel1.Id userId := model.NewId() - _, err := ss.Post().Save(&model.Post{ + _, err = ss.Post().Save(&model.Post{ ChannelId: channelId, UserId: userId, Message: "message", diff --git a/store/storetest/thread_store.go b/store/storetest/thread_store.go index e438ed8516..885a48c1a4 100644 --- a/store/storetest/thread_store.go +++ b/store/storetest/thread_store.go @@ -106,8 +106,17 @@ func testThreadStorePopulation(t *testing.T, ss store.Store) { require.Equal(t, int64(2), thread.ReplyCount) require.ElementsMatch(t, model.StringArray{newPosts[0].UserId, newPosts[1].UserId}, thread.Participants) + teamId := model.NewId() + channel, err := ss.Channel().Save(&model.Channel{ + TeamId: teamId, + DisplayName: "DisplayName1", + Name: "channel" + model.NewId(), + Type: model.ChannelTypeOpen, + }, -1) + require.NoError(t, err) + o5 := model.Post{} - o5.ChannelId = model.NewId() + o5.ChannelId = channel.Id o5.UserId = model.NewId() o5.RootId = newPosts[0].Id o5.Message = NewTestId() @@ -141,9 +150,18 @@ func testThreadStorePopulation(t *testing.T, ss store.Store) { }) t.Run("Update reply should update the UpdateAt of the thread", func(t *testing.T) { + teamId := model.NewId() + channel, err := ss.Channel().Save(&model.Channel{ + TeamId: teamId, + DisplayName: "DisplayName", + Name: "channel" + model.NewId(), + Type: model.ChannelTypeOpen, + }, -1) + require.NoError(t, err) + rootPost := model.Post{} rootPost.RootId = model.NewId() - rootPost.ChannelId = model.NewId() + rootPost.ChannelId = channel.Id rootPost.UserId = model.NewId() rootPost.Message = NewTestId() @@ -188,8 +206,17 @@ func testThreadStorePopulation(t *testing.T, ss store.Store) { }) t.Run("Deleting reply should update the thread", func(t *testing.T) { + teamId := model.NewId() + channel, err := ss.Channel().Save(&model.Channel{ + TeamId: teamId, + DisplayName: "DisplayName", + Name: "channel" + model.NewId(), + Type: model.ChannelTypeOpen, + }, -1) + require.NoError(t, err) + o1 := model.Post{} - o1.ChannelId = model.NewId() + o1.ChannelId = channel.Id o1.UserId = model.NewId() o1.Message = NewTestId() rootPost, err := ss.Post().Save(&o1) @@ -240,8 +267,17 @@ func testThreadStorePopulation(t *testing.T, ss store.Store) { }) t.Run("Deleting root post should delete the thread", func(t *testing.T) { + teamId := model.NewId() + channel, err := ss.Channel().Save(&model.Channel{ + TeamId: teamId, + DisplayName: "DisplayName", + Name: "channel" + model.NewId(), + Type: model.ChannelTypeOpen, + }, -1) + require.NoError(t, err) + rootPost := model.Post{} - rootPost.ChannelId = model.NewId() + rootPost.ChannelId = channel.Id rootPost.UserId = model.NewId() rootPost.Message = NewTestId()