From aba07e5cb9e9b5668c4fb94bfe9f096a26538528 Mon Sep 17 00:00:00 2001 From: Joram Wilander Date: Fri, 31 Mar 2017 12:25:39 -0400 Subject: PLT-5483 Fix bug where flagged posts endpoint returned posts on other teams (#5765) * Fix bug where flagged posts endpoint returned posts on other teams * Include flagged posts from DMs/GMs --- api/post.go | 7 +- api/post_test.go | 5 ++ app/post.go | 8 +++ store/sql_post_store.go | 52 ++++++++++++++ store/sql_post_store_test.go | 168 +++++++++++++++++++++++++++++++++++++++++++ store/store.go | 1 + 6 files changed, 240 insertions(+), 1 deletion(-) diff --git a/api/post.go b/api/post.go index afe60144d..b4c34bca2 100644 --- a/api/post.go +++ b/api/post.go @@ -161,7 +161,12 @@ func getFlaggedPosts(c *Context, w http.ResponseWriter, r *http.Request) { return } - if posts, err := app.GetFlaggedPosts(c.Session.UserId, offset, limit); err != nil { + if !app.SessionHasPermissionToTeam(c.Session, c.TeamId, model.PERMISSION_VIEW_TEAM) { + c.SetPermissionError(model.PERMISSION_VIEW_TEAM) + return + } + + if posts, err := app.GetFlaggedPostsForTeam(c.Session.UserId, c.TeamId, offset, limit); err != nil { c.Err = err return } else { diff --git a/api/post_test.go b/api/post_test.go index 6558aeb5b..a72074547 100644 --- a/api/post_test.go +++ b/api/post_test.go @@ -1115,6 +1115,11 @@ func TestGetFlaggedPosts(t *testing.T) { if len(r2.Order) != 0 { t.Fatal("should not have gotten a flagged post") } + + Client.SetTeamId(model.NewId()) + if _, err := Client.GetFlaggedPosts(0, 2); err == nil { + t.Fatal("should have failed - bad team id") + } } func TestGetMessageForNotification(t *testing.T) { diff --git a/app/post.go b/app/post.go index 375b775e8..bf797b984 100644 --- a/app/post.go +++ b/app/post.go @@ -397,6 +397,14 @@ func GetFlaggedPosts(userId string, offset int, limit int) (*model.PostList, *mo } } +func GetFlaggedPostsForTeam(userId, teamId string, offset int, limit int) (*model.PostList, *model.AppError) { + if result := <-Srv.Store.Post().GetFlaggedPostsForTeam(userId, teamId, offset, limit); result.Err != nil { + return nil, result.Err + } else { + return result.Data.(*model.PostList), nil + } +} + func GetPermalinkPost(postId string, userId string, siteURL string) (*model.PostList, *model.AppError) { if result := <-Srv.Store.Post().Get(postId); result.Err != nil { return nil, result.Err diff --git a/store/sql_post_store.go b/store/sql_post_store.go index eb14a66a2..14580dc5f 100644 --- a/store/sql_post_store.go +++ b/store/sql_post_store.go @@ -212,6 +212,58 @@ func (s SqlPostStore) GetFlaggedPosts(userId string, offset int, limit int) Stor return storeChannel } +func (s SqlPostStore) GetFlaggedPostsForTeam(userId, teamId string, offset int, limit int) StoreChannel { + storeChannel := make(StoreChannel, 1) + go func() { + result := StoreResult{} + pl := model.NewPostList() + + var posts []*model.Post + + query := ` + SELECT + A.* + FROM + (SELECT + * + FROM + Posts + WHERE + Id + IN + (SELECT + Name + FROM + Preferences + WHERE + UserId = :UserId + AND Category = 'flagged_post') + AND DeleteAt = 0 + ) as A + INNER JOIN Channels as B + ON B.Id = A.ChannelId + WHERE B.TeamId = :TeamId OR B.TeamId = '' + ORDER BY CreateAt DESC + LIMIT :Limit OFFSET :Offset` + + if _, err := s.GetReplica().Select(&posts, query, map[string]interface{}{"UserId": userId, "Category": model.PREFERENCE_CATEGORY_FLAGGED_POST, "Offset": offset, "Limit": limit, "TeamId": teamId}); err != nil { + result.Err = model.NewLocAppError("SqlPostStore.GetFlaggedPosts", "store.sql_post.get_flagged_posts.app_error", nil, err.Error()) + } else { + for _, post := range posts { + pl.AddPost(post) + pl.AddOrder(post.Id) + } + } + + result.Data = pl + + storeChannel <- result + close(storeChannel) + }() + + return storeChannel +} + func (s SqlPostStore) Get(id string) StoreChannel { storeChannel := make(StoreChannel, 1) diff --git a/store/sql_post_store_test.go b/store/sql_post_store_test.go index 82490fffd..f9dc5499f 100644 --- a/store/sql_post_store_test.go +++ b/store/sql_post_store_test.go @@ -1041,6 +1041,172 @@ func TestPostCountsByDay(t *testing.T) { } } +func TestPostStoreGetFlaggedPostsForTeam(t *testing.T) { + Setup() + + c1 := &model.Channel{} + c1.TeamId = model.NewId() + c1.DisplayName = "Channel1" + c1.Name = "a" + model.NewId() + "b" + c1.Type = model.CHANNEL_OPEN + c1 = Must(store.Channel().Save(c1)).(*model.Channel) + + o1 := &model.Post{} + o1.ChannelId = c1.Id + o1.UserId = model.NewId() + o1.Message = "a" + model.NewId() + "b" + o1 = (<-store.Post().Save(o1)).Data.(*model.Post) + time.Sleep(2 * time.Millisecond) + + o2 := &model.Post{} + o2.ChannelId = o1.ChannelId + o2.UserId = model.NewId() + o2.Message = "a" + model.NewId() + "b" + o2 = (<-store.Post().Save(o2)).Data.(*model.Post) + time.Sleep(2 * time.Millisecond) + + o3 := &model.Post{} + o3.ChannelId = o1.ChannelId + o3.UserId = model.NewId() + o3.Message = "a" + model.NewId() + "b" + o3.DeleteAt = 1 + o3 = (<-store.Post().Save(o3)).Data.(*model.Post) + time.Sleep(2 * time.Millisecond) + + o4 := &model.Post{} + o4.ChannelId = model.NewId() + o4.UserId = model.NewId() + o4.Message = "a" + model.NewId() + "b" + o4 = (<-store.Post().Save(o4)).Data.(*model.Post) + time.Sleep(2 * time.Millisecond) + + c2 := &model.Channel{} + c2.DisplayName = "DMChannel1" + c2.Name = "a" + model.NewId() + "b" + c2.Type = model.CHANNEL_DIRECT + + m1 := &model.ChannelMember{} + m1.ChannelId = c2.Id + m1.UserId = o1.UserId + m1.NotifyProps = model.GetDefaultChannelNotifyProps() + + m2 := &model.ChannelMember{} + m2.ChannelId = c2.Id + m2.UserId = model.NewId() + m2.NotifyProps = model.GetDefaultChannelNotifyProps() + + c2 = Must(store.Channel().SaveDirectChannel(c2, m1, m2)).(*model.Channel) + + o5 := &model.Post{} + o5.ChannelId = c2.Id + o5.UserId = m2.UserId + o5.Message = "a" + model.NewId() + "b" + o5 = (<-store.Post().Save(o5)).Data.(*model.Post) + time.Sleep(2 * time.Millisecond) + + r1 := (<-store.Post().GetFlaggedPosts(o1.ChannelId, 0, 2)).Data.(*model.PostList) + + if len(r1.Order) != 0 { + t.Fatal("should be empty") + } + + preferences := model.Preferences{ + { + UserId: o1.UserId, + Category: model.PREFERENCE_CATEGORY_FLAGGED_POST, + Name: o1.Id, + Value: "true", + }, + } + + Must(store.Preference().Save(&preferences)) + + r2 := (<-store.Post().GetFlaggedPostsForTeam(o1.UserId, c1.TeamId, 0, 2)).Data.(*model.PostList) + + if len(r2.Order) != 1 { + t.Fatal("should have 1 post") + } + + preferences = model.Preferences{ + { + UserId: o1.UserId, + Category: model.PREFERENCE_CATEGORY_FLAGGED_POST, + Name: o2.Id, + Value: "true", + }, + } + + Must(store.Preference().Save(&preferences)) + + r3 := (<-store.Post().GetFlaggedPostsForTeam(o1.UserId, c1.TeamId, 0, 1)).Data.(*model.PostList) + + if len(r3.Order) != 1 { + t.Fatal("should have 1 post") + } + + r4 := (<-store.Post().GetFlaggedPostsForTeam(o1.UserId, c1.TeamId, 0, 2)).Data.(*model.PostList) + + if len(r4.Order) != 2 { + t.Fatal("should have 2 posts") + } + + preferences = model.Preferences{ + { + UserId: o1.UserId, + Category: model.PREFERENCE_CATEGORY_FLAGGED_POST, + Name: o3.Id, + Value: "true", + }, + } + + Must(store.Preference().Save(&preferences)) + + r4 = (<-store.Post().GetFlaggedPostsForTeam(o1.UserId, c1.TeamId, 0, 2)).Data.(*model.PostList) + + if len(r4.Order) != 2 { + t.Fatal("should have 2 posts") + } + + preferences = model.Preferences{ + { + UserId: o1.UserId, + Category: model.PREFERENCE_CATEGORY_FLAGGED_POST, + Name: o4.Id, + Value: "true", + }, + } + Must(store.Preference().Save(&preferences)) + + r4 = (<-store.Post().GetFlaggedPostsForTeam(o1.UserId, c1.TeamId, 0, 2)).Data.(*model.PostList) + + if len(r4.Order) != 2 { + t.Fatal("should have 2 posts") + } + + r4 = (<-store.Post().GetFlaggedPostsForTeam(o1.UserId, model.NewId(), 0, 2)).Data.(*model.PostList) + + if len(r4.Order) != 0 { + t.Fatal("should have 0 posts") + } + + preferences = model.Preferences{ + { + UserId: o1.UserId, + Category: model.PREFERENCE_CATEGORY_FLAGGED_POST, + Name: o5.Id, + Value: "true", + }, + } + Must(store.Preference().Save(&preferences)) + + r4 = (<-store.Post().GetFlaggedPostsForTeam(o1.UserId, c1.TeamId, 0, 10)).Data.(*model.PostList) + + if len(r4.Order) != 3 { + t.Log(len(r4.Order)) + t.Fatal("should have 3 posts") + } +} + func TestPostStoreGetFlaggedPosts(t *testing.T) { Setup() @@ -1123,6 +1289,8 @@ func TestPostStoreGetFlaggedPosts(t *testing.T) { Must(store.Preference().Save(&preferences)) + r4 = (<-store.Post().GetFlaggedPosts(o1.UserId, 0, 2)).Data.(*model.PostList) + if len(r4.Order) != 2 { t.Fatal("should have 2 posts") } diff --git a/store/store.go b/store/store.go index 6523df0c8..079268b08 100644 --- a/store/store.go +++ b/store/store.go @@ -148,6 +148,7 @@ type PostStore interface { PermanentDeleteByChannel(channelId string) StoreChannel GetPosts(channelId string, offset int, limit int, allowFromCache bool) StoreChannel GetFlaggedPosts(userId string, offset int, limit int) StoreChannel + GetFlaggedPostsForTeam(userId, teamId string, offset int, limit int) StoreChannel GetPostsBefore(channelId string, postId string, numPosts int, offset int) StoreChannel GetPostsAfter(channelId string, postId string, numPosts int, offset int) StoreChannel GetPostsSince(channelId string, time int64, allowFromCache bool) StoreChannel -- cgit v1.2.3-1-g7c22