summaryrefslogtreecommitdiffstats
path: root/store
diff options
context:
space:
mode:
authorDaniel Schalla <daniel@schalla.me>2018-06-25 18:12:59 +0200
committerHarrison Healey <harrisonmhealey@gmail.com>2018-06-25 12:12:59 -0400
commitecefa6cdd1e7376046bbec82c1b47f7756fea646 (patch)
treed1cb2486e344c1bb93353020713b9eb2146a5b6f /store
parentfc158fce907b602bbde3babfadfd1a04d1dde31e (diff)
downloadchat-ecefa6cdd1e7376046bbec82c1b47f7756fea646.tar.gz
chat-ecefa6cdd1e7376046bbec82c1b47f7756fea646.tar.bz2
chat-ecefa6cdd1e7376046bbec82c1b47f7756fea646.zip
Implementation of File Exists Function; Delete FileInfos upon Permanent User Delete (#8958)
Check if file was deleted on FS Warning message if file couldnt be removed
Diffstat (limited to 'store')
-rw-r--r--store/sqlstore/file_info_store.go43
-rw-r--r--store/store.go2
-rw-r--r--store/storetest/file_info_store.go65
-rw-r--r--store/storetest/mocks/FileInfoStore.go32
4 files changed, 142 insertions, 0 deletions
diff --git a/store/sqlstore/file_info_store.go b/store/sqlstore/file_info_store.go
index 7559640c8..824e41583 100644
--- a/store/sqlstore/file_info_store.go
+++ b/store/sqlstore/file_info_store.go
@@ -177,6 +177,30 @@ func (fs SqlFileInfoStore) GetForPost(postId string, readFromMaster bool, allowF
})
}
+func (fs SqlFileInfoStore) GetForUser(userId string) store.StoreChannel {
+ return store.Do(func(result *store.StoreResult) {
+ var infos []*model.FileInfo
+
+ dbmap := fs.GetReplica()
+
+ if _, err := dbmap.Select(&infos,
+ `SELECT
+ *
+ FROM
+ FileInfo
+ WHERE
+ CreatorId = :CreatorId
+ AND DeleteAt = 0
+ ORDER BY
+ CreateAt`, map[string]interface{}{"CreatorId": userId}); err != nil {
+ result.Err = model.NewAppError("SqlFileInfoStore.GetForPost",
+ "store.sql_file_info.get_for_user_id.app_error", nil, "creator_id="+userId+", "+err.Error(), http.StatusInternalServerError)
+ } else {
+ result.Data = infos
+ }
+ })
+}
+
func (fs SqlFileInfoStore) AttachToPost(fileId, postId string) store.StoreChannel {
return store.Do(func(result *store.StoreResult) {
if _, err := fs.GetMaster().Exec(
@@ -246,3 +270,22 @@ func (s SqlFileInfoStore) PermanentDeleteBatch(endTime int64, limit int64) store
}
})
}
+
+func (s SqlFileInfoStore) PermanentDeleteByUser(userId string) store.StoreChannel {
+ return store.Do(func(result *store.StoreResult) {
+ query := "DELETE from FileInfo WHERE CreatorId = :CreatorId"
+
+ sqlResult, err := s.GetMaster().Exec(query, map[string]interface{}{"CreatorId": userId})
+ if err != nil {
+ result.Err = model.NewAppError("SqlFileInfoStore.PermanentDeleteByUser", "store.sql_file_info.PermanentDeleteByUser.app_error", nil, ""+err.Error(), http.StatusInternalServerError)
+ } else {
+ rowsAffected, err1 := sqlResult.RowsAffected()
+ if err1 != nil {
+ result.Err = model.NewAppError("SqlFileInfoStore.PermanentDeleteByUser", "store.sql_file_info.PermanentDeleteByUser.app_error", nil, ""+err.Error(), http.StatusInternalServerError)
+ result.Data = int64(0)
+ } else {
+ result.Data = rowsAffected
+ }
+ }
+ })
+}
diff --git a/store/store.go b/store/store.go
index 3ec136f0b..bb967e614 100644
--- a/store/store.go
+++ b/store/store.go
@@ -430,11 +430,13 @@ type FileInfoStore interface {
Get(id string) StoreChannel
GetByPath(path string) StoreChannel
GetForPost(postId string, readFromMaster bool, allowFromCache bool) StoreChannel
+ GetForUser(userId string) StoreChannel
InvalidateFileInfosForPostCache(postId string)
AttachToPost(fileId string, postId string) StoreChannel
DeleteForPost(postId string) StoreChannel
PermanentDelete(fileId string) StoreChannel
PermanentDeleteBatch(endTime int64, limit int64) StoreChannel
+ PermanentDeleteByUser(userId string) StoreChannel
ClearCaches()
}
diff --git a/store/storetest/file_info_store.go b/store/storetest/file_info_store.go
index 9b3388db5..50b5cf059 100644
--- a/store/storetest/file_info_store.go
+++ b/store/storetest/file_info_store.go
@@ -15,10 +15,12 @@ func TestFileInfoStore(t *testing.T, ss store.Store) {
t.Run("FileInfoSaveGet", func(t *testing.T) { testFileInfoSaveGet(t, ss) })
t.Run("FileInfoSaveGetByPath", func(t *testing.T) { testFileInfoSaveGetByPath(t, ss) })
t.Run("FileInfoGetForPost", func(t *testing.T) { testFileInfoGetForPost(t, ss) })
+ t.Run("FileInfoGetForUser", func(t *testing.T) { testFileInfoGetForUser(t, ss) })
t.Run("FileInfoAttachToPost", func(t *testing.T) { testFileInfoAttachToPost(t, ss) })
t.Run("FileInfoDeleteForPost", func(t *testing.T) { testFileInfoDeleteForPost(t, ss) })
t.Run("FileInfoPermanentDelete", func(t *testing.T) { testFileInfoPermanentDelete(t, ss) })
t.Run("FileInfoPermanentDeleteBatch", func(t *testing.T) { testFileInfoPermanentDeleteBatch(t, ss) })
+ t.Run("FileInfoPermanentDeleteByUser", func(t *testing.T) { testFileInfoPermanentDeleteByUser(t, ss) })
}
func testFileInfoSaveGet(t *testing.T, ss store.Store) {
@@ -153,6 +155,54 @@ func testFileInfoGetForPost(t *testing.T, ss store.Store) {
}
}
+func testFileInfoGetForUser(t *testing.T, ss store.Store) {
+ userId := model.NewId()
+ userId2 := model.NewId()
+ postId := model.NewId()
+
+ infos := []*model.FileInfo{
+ {
+ PostId: postId,
+ CreatorId: userId,
+ Path: "file.txt",
+ },
+ {
+ PostId: postId,
+ CreatorId: userId,
+ Path: "file.txt",
+ },
+ {
+ PostId: postId,
+ CreatorId: userId,
+ Path: "file.txt",
+ },
+ {
+ PostId: model.NewId(),
+ CreatorId: userId2,
+ Path: "file.txt",
+ },
+ }
+
+ for i, info := range infos {
+ infos[i] = store.Must(ss.FileInfo().Save(info)).(*model.FileInfo)
+ defer func(id string) {
+ <-ss.FileInfo().PermanentDelete(id)
+ }(infos[i].Id)
+ }
+
+ if result := <-ss.FileInfo().GetForUser(userId); result.Err != nil {
+ t.Fatal(result.Err)
+ } else if returned := result.Data.([]*model.FileInfo); len(returned) != 3 {
+ t.Fatal("should've returned exactly 3 file infos")
+ }
+
+ if result := <-ss.FileInfo().GetForUser(userId2); result.Err != nil {
+ t.Fatal(result.Err)
+ } else if returned := result.Data.([]*model.FileInfo); len(returned) != 1 {
+ t.Fatal("should've returned exactly 1 file infos")
+ }
+}
+
func testFileInfoAttachToPost(t *testing.T, ss store.Store) {
userId := model.NewId()
postId := model.NewId()
@@ -294,3 +344,18 @@ func testFileInfoPermanentDeleteBatch(t *testing.T, ss store.Store) {
t.Fatal("Expected 3 fileInfos")
}
}
+
+func testFileInfoPermanentDeleteByUser(t *testing.T, ss store.Store) {
+ userId := model.NewId()
+ postId := model.NewId()
+
+ store.Must(ss.FileInfo().Save(&model.FileInfo{
+ PostId: postId,
+ CreatorId: userId,
+ Path: "file.txt",
+ }))
+
+ if result := <-ss.FileInfo().PermanentDeleteByUser(userId); result.Err != nil {
+ t.Fatal(result.Err)
+ }
+}
diff --git a/store/storetest/mocks/FileInfoStore.go b/store/storetest/mocks/FileInfoStore.go
index 4dddf0bd7..a33ca0453 100644
--- a/store/storetest/mocks/FileInfoStore.go
+++ b/store/storetest/mocks/FileInfoStore.go
@@ -98,6 +98,22 @@ func (_m *FileInfoStore) GetForPost(postId string, readFromMaster bool, allowFro
return r0
}
+// GetForUser provides a mock function with given fields: userId
+func (_m *FileInfoStore) GetForUser(userId string) store.StoreChannel {
+ ret := _m.Called(userId)
+
+ var r0 store.StoreChannel
+ if rf, ok := ret.Get(0).(func(string) store.StoreChannel); ok {
+ r0 = rf(userId)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(store.StoreChannel)
+ }
+ }
+
+ return r0
+}
+
// InvalidateFileInfosForPostCache provides a mock function with given fields: postId
func (_m *FileInfoStore) InvalidateFileInfosForPostCache(postId string) {
_m.Called(postId)
@@ -135,6 +151,22 @@ func (_m *FileInfoStore) PermanentDeleteBatch(endTime int64, limit int64) store.
return r0
}
+// PermanentDeleteByUser provides a mock function with given fields: userId
+func (_m *FileInfoStore) PermanentDeleteByUser(userId string) store.StoreChannel {
+ ret := _m.Called(userId)
+
+ var r0 store.StoreChannel
+ if rf, ok := ret.Get(0).(func(string) store.StoreChannel); ok {
+ r0 = rf(userId)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(store.StoreChannel)
+ }
+ }
+
+ return r0
+}
+
// Save provides a mock function with given fields: info
func (_m *FileInfoStore) Save(info *model.FileInfo) store.StoreChannel {
ret := _m.Called(info)