diff --git a/app/user.go b/app/user.go index 84c975a76d..03be3bd5ef 100644 --- a/app/user.go +++ b/app/user.go @@ -1463,8 +1463,8 @@ func (a *App) PermanentDeleteUser(user *model.User) *model.AppError { return result.Err } - if result := <-a.Srv.Store.Post().PermanentDeleteByUser(user.Id); result.Err != nil { - return result.Err + if err := a.Srv.Store.Post().PermanentDeleteByUser(user.Id); err != nil { + return err } infos, err := a.Srv.Store.FileInfo().GetForUser(user.Id) diff --git a/store/sqlstore/post_store.go b/store/sqlstore/post_store.go index 5337004abb..9fe4d937ee 100644 --- a/store/sqlstore/post_store.go +++ b/store/sqlstore/post_store.go @@ -382,62 +382,56 @@ func (s *SqlPostStore) Delete(postId string, time int64, deleteByID string) *mod return nil } -func (s *SqlPostStore) permanentDelete(postId string) store.StoreChannel { - return store.Do(func(result *store.StoreResult) { - _, err := s.GetMaster().Exec("DELETE FROM Posts WHERE Id = :Id OR RootId = :RootId", map[string]interface{}{"Id": postId, "RootId": postId}) - if err != nil { - result.Err = model.NewAppError("SqlPostStore.Delete", "store.sql_post.permanent_delete.app_error", nil, "id="+postId+", err="+err.Error(), http.StatusInternalServerError) - } - }) +func (s *SqlPostStore) permanentDelete(postId string) *model.AppError { + _, err := s.GetMaster().Exec("DELETE FROM Posts WHERE Id = :Id OR RootId = :RootId", map[string]interface{}{"Id": postId, "RootId": postId}) + if err != nil { + return model.NewAppError("SqlPostStore.Delete", "store.sql_post.permanent_delete.app_error", nil, "id="+postId+", err="+err.Error(), http.StatusInternalServerError) + } + return nil } -func (s *SqlPostStore) permanentDeleteAllCommentByUser(userId string) store.StoreChannel { - return store.Do(func(result *store.StoreResult) { - _, err := s.GetMaster().Exec("DELETE FROM Posts WHERE UserId = :UserId AND RootId != ''", map[string]interface{}{"UserId": userId}) - if err != nil { - result.Err = model.NewAppError("SqlPostStore.permanentDeleteAllCommentByUser", "store.sql_post.permanent_delete_all_comments_by_user.app_error", nil, "userId="+userId+", err="+err.Error(), http.StatusInternalServerError) - } - }) +func (s *SqlPostStore) permanentDeleteAllCommentByUser(userId string) *model.AppError { + _, err := s.GetMaster().Exec("DELETE FROM Posts WHERE UserId = :UserId AND RootId != ''", map[string]interface{}{"UserId": userId}) + if err != nil { + return model.NewAppError("SqlPostStore.permanentDeleteAllCommentByUser", "store.sql_post.permanent_delete_all_comments_by_user.app_error", nil, "userId="+userId+", err="+err.Error(), http.StatusInternalServerError) + } + return nil } -func (s *SqlPostStore) PermanentDeleteByUser(userId string) store.StoreChannel { - return store.Do(func(result *store.StoreResult) { - // First attempt to delete all the comments for a user - if r := <-s.permanentDeleteAllCommentByUser(userId); r.Err != nil { - result.Err = r.Err - return +func (s *SqlPostStore) PermanentDeleteByUser(userId string) *model.AppError { + // First attempt to delete all the comments for a user + if err := s.permanentDeleteAllCommentByUser(userId); err != nil { + return err + } + + // Now attempt to delete all the root posts for a user. This will also + // delete all the comments for each post + found := true + count := 0 + + for found { + var ids []string + _, err := s.GetMaster().Select(&ids, "SELECT Id FROM Posts WHERE UserId = :UserId LIMIT 1000", map[string]interface{}{"UserId": userId}) + if err != nil { + return model.NewAppError("SqlPostStore.PermanentDeleteByUser.select", "store.sql_post.permanent_delete_by_user.app_error", nil, "userId="+userId+", err="+err.Error(), http.StatusInternalServerError) } - // Now attempt to delete all the root posts for a user. This will also - // delete all the comments for each post. - found := true - count := 0 - - for found { - var ids []string - _, err := s.GetMaster().Select(&ids, "SELECT Id FROM Posts WHERE UserId = :UserId LIMIT 1000", map[string]interface{}{"UserId": userId}) - if err != nil { - result.Err = model.NewAppError("SqlPostStore.PermanentDeleteByUser.select", "store.sql_post.permanent_delete_by_user.app_error", nil, "userId="+userId+", err="+err.Error(), http.StatusInternalServerError) - return - } else { - found = false - for _, id := range ids { - found = true - if r := <-s.permanentDelete(id); r.Err != nil { - result.Err = r.Err - return - } - } - } - - // This is a fail safe, give up if more than 10K messages - count = count + 1 - if count >= 10 { - result.Err = model.NewAppError("SqlPostStore.PermanentDeleteByUser.toolarge", "store.sql_post.permanent_delete_by_user.too_many.app_error", nil, "userId="+userId, http.StatusInternalServerError) - return + found = false + for _, id := range ids { + found = true + if err := s.permanentDelete(id); err != nil { + return err } } - }) + + // This is a fail safe, give up if more than 10k messages + count++ + if count >= 10 { + return model.NewAppError("SqlPostStore.PermanentDeleteByUser.toolarge", "store.sql_post.permanent_delete_by_user.too_many.app_error", nil, "userId="+userId, http.StatusInternalServerError) + } + } + + return nil } func (s *SqlPostStore) PermanentDeleteByChannel(channelId string) *model.AppError { diff --git a/store/store.go b/store/store.go index f91666ffaf..2f908bdc81 100644 --- a/store/store.go +++ b/store/store.go @@ -215,7 +215,7 @@ type PostStore interface { Get(id string) (*model.PostList, *model.AppError) GetSingle(id string) (*model.Post, *model.AppError) Delete(postId string, time int64, deleteByID string) *model.AppError - PermanentDeleteByUser(userId string) StoreChannel + PermanentDeleteByUser(userId string) *model.AppError PermanentDeleteByChannel(channelId string) *model.AppError GetPosts(channelId string, offset int, limit int, allowFromCache bool) (*model.PostList, *model.AppError) GetFlaggedPosts(userId string, offset int, limit int) (*model.PostList, *model.AppError) diff --git a/store/storetest/mocks/PostStore.go b/store/storetest/mocks/PostStore.go index 949e3dbe10..be69509f92 100644 --- a/store/storetest/mocks/PostStore.go +++ b/store/storetest/mocks/PostStore.go @@ -589,15 +589,15 @@ func (_m *PostStore) PermanentDeleteByChannel(channelId string) *model.AppError } // PermanentDeleteByUser provides a mock function with given fields: userId -func (_m *PostStore) PermanentDeleteByUser(userId string) store.StoreChannel { +func (_m *PostStore) PermanentDeleteByUser(userId string) *model.AppError { ret := _m.Called(userId) - var r0 store.StoreChannel - if rf, ok := ret.Get(0).(func(string) store.StoreChannel); ok { + var r0 *model.AppError + if rf, ok := ret.Get(0).(func(string) *model.AppError); ok { r0 = rf(userId) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(store.StoreChannel) + r0 = ret.Get(0).(*model.AppError) } } diff --git a/store/storetest/post_store.go b/store/storetest/post_store.go index 7d138eaffa..97b1e392c8 100644 --- a/store/storetest/post_store.go +++ b/store/storetest/post_store.go @@ -468,8 +468,8 @@ func testPostStorePermDelete1Level(t *testing.T, ss store.Store) { o3.Message = "zz" + model.NewId() + "b" o3 = (<-ss.Post().Save(o3)).Data.(*model.Post) - if r2 := <-ss.Post().PermanentDeleteByUser(o2.UserId); r2.Err != nil { - t.Fatal(r2.Err) + if err2 := ss.Post().PermanentDeleteByUser(o2.UserId); err2 != nil { + t.Fatal(err2) } if _, err := ss.Post().Get(o1.Id); err != nil { @@ -510,8 +510,8 @@ func testPostStorePermDelete1Level2(t *testing.T, ss store.Store) { o3.Message = "zz" + model.NewId() + "b" o3 = (<-ss.Post().Save(o3)).Data.(*model.Post) - if r2 := <-ss.Post().PermanentDeleteByUser(o1.UserId); r2.Err != nil { - t.Fatal(r2.Err) + if err2 := ss.Post().PermanentDeleteByUser(o1.UserId); err2 != nil { + t.Fatal(err2) } if _, err := ss.Post().Get(o1.Id); err == nil {