diff --git a/server/channels/store/sqlstore/post_store.go b/server/channels/store/sqlstore/post_store.go index d1af5c846f..93605e3f8d 100644 --- a/server/channels/store/sqlstore/post_store.go +++ b/server/channels/store/sqlstore/post_store.go @@ -1065,6 +1065,7 @@ func (s *SqlPostStore) PermanentDeleteByUser(rctx request.CTX, userId string) er // Now attempt to delete all the root posts for a user. This will also // delete all the comments for each post + const maxLoops = 10 count := 0 for { var ids []string @@ -1083,8 +1084,8 @@ func (s *SqlPostStore) PermanentDeleteByUser(rctx request.CTX, userId string) er // This is a fail safe, give up if more than 10k messages count++ - if count >= 10 { - return errors.Wrapf(err, "too many Posts to delete with userId=%s", userId) + if count >= maxLoops { + return store.NewErrLimitExceeded("permanently deleting posts for user", maxLoops*1000, "userId="+userId) } } diff --git a/server/channels/store/storetest/post_store.go b/server/channels/store/storetest/post_store.go index 2e74d60747..df6a55fc83 100644 --- a/server/channels/store/storetest/post_store.go +++ b/server/channels/store/storetest/post_store.go @@ -31,6 +31,7 @@ func TestPostStore(t *testing.T, rctx request.CTX, ss store.Store, s SqlStore) { t.Run("Delete", func(t *testing.T) { testPostStoreDelete(t, rctx, ss) }) t.Run("PermDelete1Level", func(t *testing.T) { testPostStorePermDelete1Level(t, rctx, ss) }) t.Run("PermDelete1Level2", func(t *testing.T) { testPostStorePermDelete1Level2(t, rctx, ss) }) + t.Run("PermDeleteLimitExceeded", func(t *testing.T) { testPostStorePermDeleteLimitExceeded(t, rctx, ss) }) t.Run("GetWithChildren", func(t *testing.T) { testPostStoreGetWithChildren(t, rctx, ss) }) t.Run("GetPostsWithDetails", func(t *testing.T) { testPostStoreGetPostsWithDetails(t, rctx, ss) }) t.Run("GetPostsBeforeAfter", func(t *testing.T) { testPostStoreGetPostsBeforeAfter(t, rctx, ss) }) @@ -1686,6 +1687,33 @@ func testPostStorePermDelete1Level2(t *testing.T, rctx request.CTX, ss store.Sto require.NoError(t, err, "Deleted id should have failed") } +func testPostStorePermDeleteLimitExceeded(t *testing.T, rctx request.CTX, ss store.Store) { + const maxPosts = 10000 + teamID := model.NewId() + userID := model.NewId() + channel, err := ss.Channel().Save(rctx, &model.Channel{ + TeamId: teamID, + DisplayName: "10KPosts", + Name: "channel" + model.NewId(), + Type: model.ChannelTypeOpen, + }, -1) + require.NoError(t, err) + + for i := 0; i < maxPosts+100; i++ { + post := &model.Post{ + ChannelId: channel.Id, + UserId: userID, + Message: NewTestID(), + } + _, err = ss.Post().Save(rctx, post) + require.NoError(t, err) + } + + err = ss.Post().PermanentDeleteByUser(rctx, userID) + var errLimitExceeded *store.ErrLimitExceeded + require.ErrorAs(t, err, &errLimitExceeded) +} + func testPostStoreGetWithChildren(t *testing.T, rctx request.CTX, ss store.Store) { teamID := model.NewId() channel1, err := ss.Channel().Save(rctx, &model.Channel{