summaryrefslogtreecommitdiffstats
path: root/store
diff options
context:
space:
mode:
authorJoram Wilander <jwawilander@gmail.com>2015-11-18 12:48:45 -0500
committerJoram Wilander <jwawilander@gmail.com>2015-11-18 12:48:45 -0500
commite408d615c02ae3c863df3c7dc13d1b813c22fd28 (patch)
treea1c607b7721831c71aadbf89f018ed7b11a0e426 /store
parent9660adb00775aba822d2d684d215c55679a456c6 (diff)
parentc115191d6b5abdefda856c063e3f9048dc82f830 (diff)
downloadchat-e408d615c02ae3c863df3c7dc13d1b813c22fd28.tar.gz
chat-e408d615c02ae3c863df3c7dc13d1b813c22fd28.tar.bz2
chat-e408d615c02ae3c863df3c7dc13d1b813c22fd28.zip
Merge pull request #1448 from mattermost/PLT-975
PLT-975 adding delete to command line tool
Diffstat (limited to 'store')
-rw-r--r--store/sql_audit_store.go19
-rw-r--r--store/sql_audit_store_test.go4
-rw-r--r--store/sql_channel_store.go34
-rw-r--r--store/sql_channel_store_test.go57
-rw-r--r--store/sql_oauth_store.go18
-rw-r--r--store/sql_oauth_store_test.go14
-rw-r--r--store/sql_post_store.go93
-rw-r--r--store/sql_post_store_test.go70
-rw-r--r--store/sql_preference_store.go18
-rw-r--r--store/sql_preference_store_test.go40
-rw-r--r--store/sql_session_store.go18
-rw-r--r--store/sql_session_store_test.go23
-rw-r--r--store/sql_team_store.go17
-rw-r--r--store/sql_team_store_test.go23
-rw-r--r--store/sql_user_store.go18
-rw-r--r--store/sql_user_store_test.go13
-rw-r--r--store/sql_webhook_store.go36
-rw-r--r--store/sql_webhook_store_test.go57
-rw-r--r--store/store.go11
19 files changed, 583 insertions, 0 deletions
diff --git a/store/sql_audit_store.go b/store/sql_audit_store.go
index b3e2daea0..f4fd29aab 100644
--- a/store/sql_audit_store.go
+++ b/store/sql_audit_store.go
@@ -86,3 +86,22 @@ func (s SqlAuditStore) Get(user_id string, limit int) StoreChannel {
return storeChannel
}
+
+func (s SqlAuditStore) PermanentDeleteByUser(userId string) StoreChannel {
+
+ storeChannel := make(StoreChannel)
+
+ go func() {
+ result := StoreResult{}
+
+ if _, err := s.GetMaster().Exec("DELETE FROM Audits WHERE UserId = :userId",
+ map[string]interface{}{"userId": userId}); err != nil {
+ result.Err = model.NewAppError("SqlAuditStore.Delete", "We encountered an error deleting the audits", "user_id="+userId)
+ }
+
+ storeChannel <- result
+ close(storeChannel)
+ }()
+
+ return storeChannel
+}
diff --git a/store/sql_audit_store_test.go b/store/sql_audit_store_test.go
index e265db837..b395631f1 100644
--- a/store/sql_audit_store_test.go
+++ b/store/sql_audit_store_test.go
@@ -44,4 +44,8 @@ func TestSqlAuditStore(t *testing.T) {
if len(audits) != 0 {
t.Fatal("Should have returned empty because user_id is missing")
}
+
+ if r2 := <-store.Audit().PermanentDeleteByUser(audit.UserId); r2.Err != nil {
+ t.Fatal(r2.Err)
+ }
}
diff --git a/store/sql_channel_store.go b/store/sql_channel_store.go
index a9f99bd67..badaa4d13 100644
--- a/store/sql_channel_store.go
+++ b/store/sql_channel_store.go
@@ -279,6 +279,23 @@ func (s SqlChannelStore) Delete(channelId string, time int64) StoreChannel {
return storeChannel
}
+func (s SqlChannelStore) PermanentDeleteByTeam(teamId string) StoreChannel {
+ storeChannel := make(StoreChannel)
+
+ go func() {
+ result := StoreResult{}
+
+ if _, err := s.GetMaster().Exec("DELETE FROM Channels WHERE TeamId = :TeamId", map[string]interface{}{"TeamId": teamId}); err != nil {
+ result.Err = model.NewAppError("SqlChannelStore.PermanentDeleteByTeam", "We couldn't delete the channels", "teamId="+teamId+", "+err.Error())
+ }
+
+ storeChannel <- result
+ close(storeChannel)
+ }()
+
+ return storeChannel
+}
+
type channelWithMember struct {
model.Channel
model.ChannelMember
@@ -616,6 +633,23 @@ func (s SqlChannelStore) RemoveMember(channelId string, userId string) StoreChan
return storeChannel
}
+func (s SqlChannelStore) PermanentDeleteMembersByUser(userId string) StoreChannel {
+ storeChannel := make(StoreChannel)
+
+ go func() {
+ result := StoreResult{}
+
+ if _, err := s.GetMaster().Exec("DELETE FROM ChannelMembers WHERE UserId = :UserId", map[string]interface{}{"UserId": userId}); err != nil {
+ result.Err = model.NewAppError("SqlChannelStore.RemoveMember", "We couldn't remove the channel member", "user_id="+userId+", "+err.Error())
+ }
+
+ storeChannel <- result
+ close(storeChannel)
+ }()
+
+ return storeChannel
+}
+
func (s SqlChannelStore) CheckPermissionsTo(teamId string, channelId string, userId string) StoreChannel {
storeChannel := make(StoreChannel)
diff --git a/store/sql_channel_store_test.go b/store/sql_channel_store_test.go
index 8662fcbd3..695991bf7 100644
--- a/store/sql_channel_store_test.go
+++ b/store/sql_channel_store_test.go
@@ -379,6 +379,63 @@ func TestChannelMemberStore(t *testing.T) {
}
}
+func TestChannelDeleteMemberStore(t *testing.T) {
+ Setup()
+
+ c1 := model.Channel{}
+ c1.TeamId = model.NewId()
+ c1.DisplayName = "NameName"
+ c1.Name = "a" + model.NewId() + "b"
+ c1.Type = model.CHANNEL_OPEN
+ c1 = *Must(store.Channel().Save(&c1)).(*model.Channel)
+
+ c1t1 := (<-store.Channel().Get(c1.Id)).Data.(*model.Channel)
+ t1 := c1t1.ExtraUpdateAt
+
+ u1 := model.User{}
+ u1.TeamId = model.NewId()
+ u1.Email = model.NewId()
+ u1.Nickname = model.NewId()
+ Must(store.User().Save(&u1))
+
+ u2 := model.User{}
+ u2.TeamId = model.NewId()
+ u2.Email = model.NewId()
+ u2.Nickname = model.NewId()
+ Must(store.User().Save(&u2))
+
+ o1 := model.ChannelMember{}
+ o1.ChannelId = c1.Id
+ o1.UserId = u1.Id
+ o1.NotifyProps = model.GetDefaultChannelNotifyProps()
+ Must(store.Channel().SaveMember(&o1))
+
+ o2 := model.ChannelMember{}
+ o2.ChannelId = c1.Id
+ o2.UserId = u2.Id
+ o2.NotifyProps = model.GetDefaultChannelNotifyProps()
+ Must(store.Channel().SaveMember(&o2))
+
+ c1t2 := (<-store.Channel().Get(c1.Id)).Data.(*model.Channel)
+ t2 := c1t2.ExtraUpdateAt
+
+ if t2 <= t1 {
+ t.Fatal("Member update time incorrect")
+ }
+
+ count := (<-store.Channel().GetMemberCount(o1.ChannelId)).Data.(int64)
+ if count != 2 {
+ t.Fatal("should have saved 2 members")
+ }
+
+ Must(store.Channel().PermanentDeleteMembersByUser(o2.UserId))
+
+ count = (<-store.Channel().GetMemberCount(o1.ChannelId)).Data.(int64)
+ if count != 1 {
+ t.Fatal("should have removed 1 member")
+ }
+}
+
func TestChannelStorePermissionsTo(t *testing.T) {
Setup()
diff --git a/store/sql_oauth_store.go b/store/sql_oauth_store.go
index 751207b85..43a5bee31 100644
--- a/store/sql_oauth_store.go
+++ b/store/sql_oauth_store.go
@@ -332,3 +332,21 @@ func (as SqlOAuthStore) RemoveAuthData(code string) StoreChannel {
return storeChannel
}
+
+func (as SqlOAuthStore) PermanentDeleteAuthDataByUser(userId string) StoreChannel {
+ storeChannel := make(StoreChannel)
+
+ go func() {
+ result := StoreResult{}
+
+ _, err := as.GetMaster().Exec("DELETE FROM OAuthAuthData WHERE UserId = :UserId", map[string]interface{}{"UserId": userId})
+ if err != nil {
+ result.Err = model.NewAppError("SqlOAuthStore.RemoveAuthDataByUserId", "We couldn't remove the authorization code", "err="+err.Error())
+ }
+
+ storeChannel <- result
+ close(storeChannel)
+ }()
+
+ return storeChannel
+}
diff --git a/store/sql_oauth_store_test.go b/store/sql_oauth_store_test.go
index 3f05f1c92..c3f6ea7ac 100644
--- a/store/sql_oauth_store_test.go
+++ b/store/sql_oauth_store_test.go
@@ -180,3 +180,17 @@ func TestOAuthStoreRemoveAuthData(t *testing.T) {
t.Fatal("should have errored - auth code removed")
}
}
+
+func TestOAuthStoreRemoveAuthDataByUser(t *testing.T) {
+ Setup()
+
+ a1 := model.AuthData{}
+ a1.ClientId = model.NewId()
+ a1.UserId = model.NewId()
+ a1.Code = model.NewId()
+ Must(store.OAuth().SaveAuthData(&a1))
+
+ if err := (<-store.OAuth().PermanentDeleteAuthDataByUser(a1.UserId)).Err; err != nil {
+ t.Fatal(err)
+ }
+}
diff --git a/store/sql_post_store.go b/store/sql_post_store.go
index f800367cb..cc596074f 100644
--- a/store/sql_post_store.go
+++ b/store/sql_post_store.go
@@ -228,6 +228,99 @@ func (s SqlPostStore) Delete(postId string, time int64) StoreChannel {
return storeChannel
}
+func (s SqlPostStore) permanentDelete(postId string) StoreChannel {
+ storeChannel := make(StoreChannel)
+
+ go func() {
+ result := StoreResult{}
+
+ _, err := s.GetMaster().Exec("DELETE FROM Posts WHERE Id = :Id OR ParentId = :ParentId OR RootId = :RootId", map[string]interface{}{"Id": postId, "ParentId": postId, "RootId": postId})
+ if err != nil {
+ result.Err = model.NewAppError("SqlPostStore.Delete", "We couldn't delete the post", "id="+postId+", err="+err.Error())
+ }
+
+ storeChannel <- result
+ close(storeChannel)
+ }()
+
+ return storeChannel
+}
+
+func (s SqlPostStore) permanentDeleteAllCommentByUser(userId string) StoreChannel {
+ storeChannel := make(StoreChannel)
+
+ go func() {
+ result := 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", "We couldn't delete the comments for user", "userId="+userId+", err="+err.Error())
+ }
+
+ storeChannel <- result
+ close(storeChannel)
+ }()
+
+ return storeChannel
+}
+
+func (s SqlPostStore) PermanentDeleteByUser(userId string) StoreChannel {
+ storeChannel := make(StoreChannel)
+
+ go func() {
+ result := StoreResult{}
+
+ // First attempt to delete all the comments for a user
+ if r := <-s.permanentDeleteAllCommentByUser(userId); r.Err != nil {
+ result.Err = r.Err
+ storeChannel <- result
+ close(storeChannel)
+ return
+ }
+
+ // 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", "We couldn't select the posts to delete for the user", "userId="+userId+", err="+err.Error())
+ storeChannel <- result
+ close(storeChannel)
+ return
+ } else {
+ found = false
+ for _, id := range ids {
+ found = true
+ if r := <-s.permanentDelete(id); r.Err != nil {
+ result.Err = r.Err
+ storeChannel <- result
+ close(storeChannel)
+ 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", "We couldn't select the posts to delete for the user (too many), please re-run", "userId="+userId)
+ storeChannel <- result
+ close(storeChannel)
+ return
+ }
+ }
+
+ storeChannel <- result
+ close(storeChannel)
+ }()
+
+ return storeChannel
+}
+
func (s SqlPostStore) GetPosts(channelId string, offset int, limit int) StoreChannel {
storeChannel := make(StoreChannel)
diff --git a/store/sql_post_store_test.go b/store/sql_post_store_test.go
index fe7195a54..d9b087ea7 100644
--- a/store/sql_post_store_test.go
+++ b/store/sql_post_store_test.go
@@ -247,6 +247,76 @@ func TestPostStoreDelete2Level(t *testing.T) {
}
}
+func TestPostStorePermDelete1Level(t *testing.T) {
+ Setup()
+
+ o1 := &model.Post{}
+ o1.ChannelId = model.NewId()
+ o1.UserId = model.NewId()
+ o1.Message = "a" + model.NewId() + "b"
+ o1 = (<-store.Post().Save(o1)).Data.(*model.Post)
+
+ o2 := &model.Post{}
+ o2.ChannelId = o1.ChannelId
+ o2.UserId = model.NewId()
+ o2.Message = "a" + model.NewId() + "b"
+ o2.ParentId = o1.Id
+ o2.RootId = o1.Id
+ o2 = (<-store.Post().Save(o2)).Data.(*model.Post)
+
+ if r2 := <-store.Post().PermanentDeleteByUser(o2.UserId); r2.Err != nil {
+ t.Fatal(r2.Err)
+ }
+
+ if r3 := (<-store.Post().Get(o1.Id)); r3.Err != nil {
+ t.Fatal("Deleted id shouldn't have failed")
+ }
+
+ if r4 := (<-store.Post().Get(o2.Id)); r4.Err == nil {
+ t.Fatal("Deleted id should have failed")
+ }
+}
+
+func TestPostStorePermDelete1Level2(t *testing.T) {
+ Setup()
+
+ o1 := &model.Post{}
+ o1.ChannelId = model.NewId()
+ o1.UserId = model.NewId()
+ o1.Message = "a" + model.NewId() + "b"
+ o1 = (<-store.Post().Save(o1)).Data.(*model.Post)
+
+ o2 := &model.Post{}
+ o2.ChannelId = o1.ChannelId
+ o2.UserId = model.NewId()
+ o2.Message = "a" + model.NewId() + "b"
+ o2.ParentId = o1.Id
+ o2.RootId = o1.Id
+ o2 = (<-store.Post().Save(o2)).Data.(*model.Post)
+
+ o3 := &model.Post{}
+ o3.ChannelId = model.NewId()
+ o3.UserId = model.NewId()
+ o3.Message = "a" + model.NewId() + "b"
+ o3 = (<-store.Post().Save(o3)).Data.(*model.Post)
+
+ if r2 := <-store.Post().PermanentDeleteByUser(o1.UserId); r2.Err != nil {
+ t.Fatal(r2.Err)
+ }
+
+ if r3 := (<-store.Post().Get(o1.Id)); r3.Err == nil {
+ t.Fatal("Deleted id should have failed")
+ }
+
+ if r4 := (<-store.Post().Get(o2.Id)); r4.Err == nil {
+ t.Fatal("Deleted id should have failed")
+ }
+
+ if r5 := (<-store.Post().Get(o3.Id)); r5.Err != nil {
+ t.Fatal("Deleted id shouldn't have failed")
+ }
+}
+
func TestPostStoreGetWithChildren(t *testing.T) {
Setup()
diff --git a/store/sql_preference_store.go b/store/sql_preference_store.go
index f9f38b747..8454abcbd 100644
--- a/store/sql_preference_store.go
+++ b/store/sql_preference_store.go
@@ -239,3 +239,21 @@ func (s SqlPreferenceStore) GetAll(userId string) StoreChannel {
return storeChannel
}
+
+func (s SqlPreferenceStore) PermanentDeleteByUser(userId string) StoreChannel {
+ storeChannel := make(StoreChannel)
+
+ go func() {
+ result := StoreResult{}
+
+ if _, err := s.GetMaster().Exec(
+ `DELETE FROM Preferences WHERE UserId = :UserId`, map[string]interface{}{"UserId": userId}); err != nil {
+ result.Err = model.NewAppError("SqlPreferenceStore.Delete", "We encountered an error while deleteing preferences", err.Error())
+ }
+
+ storeChannel <- result
+ close(storeChannel)
+ }()
+
+ return storeChannel
+}
diff --git a/store/sql_preference_store_test.go b/store/sql_preference_store_test.go
index e68203cc3..77da71fd6 100644
--- a/store/sql_preference_store_test.go
+++ b/store/sql_preference_store_test.go
@@ -192,3 +192,43 @@ func TestPreferenceGetAll(t *testing.T) {
}
}
}
+
+func TestPreferenceDelete(t *testing.T) {
+ Setup()
+
+ userId := model.NewId()
+ category := model.PREFERENCE_CATEGORY_DIRECT_CHANNEL_SHOW
+ name := model.NewId()
+
+ preferences := model.Preferences{
+ {
+ UserId: userId,
+ Category: category,
+ Name: name,
+ },
+ // same user/category, different name
+ {
+ UserId: userId,
+ Category: category,
+ Name: model.NewId(),
+ },
+ // same user/name, different category
+ {
+ UserId: userId,
+ Category: model.NewId(),
+ Name: name,
+ },
+ // same name/category, different user
+ {
+ UserId: model.NewId(),
+ Category: category,
+ Name: name,
+ },
+ }
+
+ Must(store.Preference().Save(&preferences))
+
+ if result := <-store.Preference().PermanentDeleteByUser(userId); result.Err != nil {
+ t.Fatal(result.Err)
+ }
+}
diff --git a/store/sql_session_store.go b/store/sql_session_store.go
index 27b34ee39..86604b4fe 100644
--- a/store/sql_session_store.go
+++ b/store/sql_session_store.go
@@ -158,6 +158,24 @@ func (me SqlSessionStore) RemoveAllSessionsForTeam(teamId string) StoreChannel {
return storeChannel
}
+func (me SqlSessionStore) PermanentDeleteSessionsByUser(userId string) StoreChannel {
+ storeChannel := make(StoreChannel)
+
+ go func() {
+ result := StoreResult{}
+
+ _, err := me.GetMaster().Exec("DELETE FROM Sessions WHERE UserId = :UserId", map[string]interface{}{"UserId": userId})
+ if err != nil {
+ result.Err = model.NewAppError("SqlSessionStore.RemoveAllSessionsForUser", "We couldn't remove all the sessions for the user", "id="+userId+", err="+err.Error())
+ }
+
+ storeChannel <- result
+ close(storeChannel)
+ }()
+
+ return storeChannel
+}
+
func (me SqlSessionStore) CleanUpExpiredSessions(userId string) StoreChannel {
storeChannel := make(StoreChannel)
diff --git a/store/sql_session_store_test.go b/store/sql_session_store_test.go
index 068e5fc19..cec8e93b0 100644
--- a/store/sql_session_store_test.go
+++ b/store/sql_session_store_test.go
@@ -103,6 +103,29 @@ func TestSessionRemoveAll(t *testing.T) {
}
}
+func TestSessionRemoveByUser(t *testing.T) {
+ Setup()
+
+ s1 := model.Session{}
+ s1.UserId = model.NewId()
+ s1.TeamId = model.NewId()
+ Must(store.Session().Save(&s1))
+
+ if rs1 := (<-store.Session().Get(s1.Id)); rs1.Err != nil {
+ t.Fatal(rs1.Err)
+ } else {
+ if rs1.Data.(*model.Session).Id != s1.Id {
+ t.Fatal("should match")
+ }
+ }
+
+ Must(store.Session().PermanentDeleteSessionsByUser(s1.UserId))
+
+ if rs2 := (<-store.Session().Get(s1.Id)); rs2.Err == nil {
+ t.Fatal("should have been removed")
+ }
+}
+
func TestSessionRemoveToken(t *testing.T) {
Setup()
diff --git a/store/sql_team_store.go b/store/sql_team_store.go
index 1a0aeabde..9578549ca 100644
--- a/store/sql_team_store.go
+++ b/store/sql_team_store.go
@@ -300,3 +300,20 @@ func (s SqlTeamStore) GetAllTeamListing() StoreChannel {
return storeChannel
}
+
+func (s SqlTeamStore) PermanentDelete(teamId string) StoreChannel {
+ storeChannel := make(StoreChannel)
+
+ go func() {
+ result := StoreResult{}
+
+ if _, err := s.GetMaster().Exec("DELETE FROM Teams WHERE Id = :TeamId", map[string]interface{}{"TeamId": teamId}); err != nil {
+ result.Err = model.NewAppError("SqlTeamStore.Delete", "We couldn't delete the existing team", "teamId="+teamId+", "+err.Error())
+ }
+
+ storeChannel <- result
+ close(storeChannel)
+ }()
+
+ return storeChannel
+}
diff --git a/store/sql_team_store_test.go b/store/sql_team_store_test.go
index 71740f7e7..7dc31cbe2 100644
--- a/store/sql_team_store_test.go
+++ b/store/sql_team_store_test.go
@@ -238,3 +238,26 @@ func TestAllTeamListing(t *testing.T) {
}
}
}
+
+func TestDelete(t *testing.T) {
+ Setup()
+
+ o1 := model.Team{}
+ o1.DisplayName = "DisplayName"
+ o1.Name = "a" + model.NewId() + "b"
+ o1.Email = model.NewId() + "@nowhere.com"
+ o1.Type = model.TEAM_OPEN
+ o1.AllowTeamListing = true
+ Must(store.Team().Save(&o1))
+
+ o2 := model.Team{}
+ o2.DisplayName = "DisplayName"
+ o2.Name = "a" + model.NewId() + "b"
+ o2.Email = model.NewId() + "@nowhere.com"
+ o2.Type = model.TEAM_OPEN
+ Must(store.Team().Save(&o2))
+
+ if r1 := <-store.Team().PermanentDelete(o1.Id); r1.Err != nil {
+ t.Fatal(r1.Err)
+ }
+}
diff --git a/store/sql_user_store.go b/store/sql_user_store.go
index 77ff5bfab..d19135b64 100644
--- a/store/sql_user_store.go
+++ b/store/sql_user_store.go
@@ -554,3 +554,21 @@ func (us SqlUserStore) GetTotalActiveUsersCount() StoreChannel {
return storeChannel
}
+
+func (us SqlUserStore) PermanentDelete(userId string) StoreChannel {
+
+ storeChannel := make(StoreChannel)
+
+ go func() {
+ result := StoreResult{}
+
+ if _, err := us.GetMaster().Exec("DELETE FROM Users WHERE Id = :UserId", map[string]interface{}{"UserId": userId}); err != nil {
+ result.Err = model.NewAppError("SqlUserStore.GetByEmail", "We couldn't delete the existing account", "userId="+userId+", "+err.Error())
+ }
+
+ storeChannel <- result
+ close(storeChannel)
+ }()
+
+ return storeChannel
+}
diff --git a/store/sql_user_store_test.go b/store/sql_user_store_test.go
index 874baf634..dd08438f1 100644
--- a/store/sql_user_store_test.go
+++ b/store/sql_user_store_test.go
@@ -377,3 +377,16 @@ func TestUserStoreUpdatePassword(t *testing.T) {
}
}
}
+
+func TestUserStoreDelete(t *testing.T) {
+ Setup()
+
+ u1 := model.User{}
+ u1.TeamId = model.NewId()
+ u1.Email = model.NewId()
+ Must(store.User().Save(&u1))
+
+ if err := (<-store.User().PermanentDelete(u1.Id)).Err; err != nil {
+ t.Fatal(err)
+ }
+}
diff --git a/store/sql_webhook_store.go b/store/sql_webhook_store.go
index c758e2339..b7bf0615f 100644
--- a/store/sql_webhook_store.go
+++ b/store/sql_webhook_store.go
@@ -116,6 +116,24 @@ func (s SqlWebhookStore) DeleteIncoming(webhookId string, time int64) StoreChann
return storeChannel
}
+func (s SqlWebhookStore) PermanentDeleteIncomingByUser(userId string) StoreChannel {
+ storeChannel := make(StoreChannel)
+
+ go func() {
+ result := StoreResult{}
+
+ _, err := s.GetMaster().Exec("DELETE FROM IncomingWebhooks WHERE UserId = :UserId", map[string]interface{}{"UserId": userId})
+ if err != nil {
+ result.Err = model.NewAppError("SqlWebhookStore.DeleteIncomingByUser", "We couldn't delete the webhook", "id="+userId+", err="+err.Error())
+ }
+
+ storeChannel <- result
+ close(storeChannel)
+ }()
+
+ return storeChannel
+}
+
func (s SqlWebhookStore) GetIncomingByUser(userId string) StoreChannel {
storeChannel := make(StoreChannel)
@@ -294,6 +312,24 @@ func (s SqlWebhookStore) DeleteOutgoing(webhookId string, time int64) StoreChann
return storeChannel
}
+func (s SqlWebhookStore) PermanentDeleteOutgoingByUser(userId string) StoreChannel {
+ storeChannel := make(StoreChannel)
+
+ go func() {
+ result := StoreResult{}
+
+ _, err := s.GetMaster().Exec("DELETE FROM OutgoingWebhooks WHERE CreatorId = :UserId", map[string]interface{}{"UserId": userId})
+ if err != nil {
+ result.Err = model.NewAppError("SqlWebhookStore.DeleteOutgoingByUser", "We couldn't delete the webhook", "id="+userId+", err="+err.Error())
+ }
+
+ storeChannel <- result
+ close(storeChannel)
+ }()
+
+ return storeChannel
+}
+
func (s SqlWebhookStore) UpdateOutgoing(hook *model.OutgoingWebhook) StoreChannel {
storeChannel := make(StoreChannel)
diff --git a/store/sql_webhook_store_test.go b/store/sql_webhook_store_test.go
index 1fb990f3e..1a9d5be3b 100644
--- a/store/sql_webhook_store_test.go
+++ b/store/sql_webhook_store_test.go
@@ -103,6 +103,34 @@ func TestWebhookStoreDeleteIncoming(t *testing.T) {
}
}
+func TestWebhookStoreDeleteIncomingByUser(t *testing.T) {
+ Setup()
+
+ o1 := &model.IncomingWebhook{}
+ o1.ChannelId = model.NewId()
+ o1.UserId = model.NewId()
+ o1.TeamId = model.NewId()
+
+ o1 = (<-store.Webhook().SaveIncoming(o1)).Data.(*model.IncomingWebhook)
+
+ if r1 := <-store.Webhook().GetIncoming(o1.Id); r1.Err != nil {
+ t.Fatal(r1.Err)
+ } else {
+ if r1.Data.(*model.IncomingWebhook).CreateAt != o1.CreateAt {
+ t.Fatal("invalid returned webhook")
+ }
+ }
+
+ if r2 := <-store.Webhook().PermanentDeleteIncomingByUser(o1.UserId); r2.Err != nil {
+ t.Fatal(r2.Err)
+ }
+
+ if r3 := (<-store.Webhook().GetIncoming(o1.Id)); r3.Err == nil {
+ t.Log(r3.Data)
+ t.Fatal("Missing id should have failed")
+ }
+}
+
func TestWebhookStoreSaveOutgoing(t *testing.T) {
Setup()
@@ -258,6 +286,35 @@ func TestWebhookStoreDeleteOutgoing(t *testing.T) {
}
}
+func TestWebhookStoreDeleteOutgoingByUser(t *testing.T) {
+ Setup()
+
+ o1 := &model.OutgoingWebhook{}
+ o1.ChannelId = model.NewId()
+ o1.CreatorId = model.NewId()
+ o1.TeamId = model.NewId()
+ o1.CallbackURLs = []string{"http://nowhere.com/"}
+
+ o1 = (<-store.Webhook().SaveOutgoing(o1)).Data.(*model.OutgoingWebhook)
+
+ if r1 := <-store.Webhook().GetOutgoing(o1.Id); r1.Err != nil {
+ t.Fatal(r1.Err)
+ } else {
+ if r1.Data.(*model.OutgoingWebhook).CreateAt != o1.CreateAt {
+ t.Fatal("invalid returned webhook")
+ }
+ }
+
+ if r2 := <-store.Webhook().PermanentDeleteOutgoingByUser(o1.CreatorId); r2.Err != nil {
+ t.Fatal(r2.Err)
+ }
+
+ if r3 := (<-store.Webhook().GetOutgoing(o1.Id)); r3.Err == nil {
+ t.Log(r3.Data)
+ t.Fatal("Missing id should have failed")
+ }
+}
+
func TestWebhookStoreUpdateOutgoing(t *testing.T) {
Setup()
diff --git a/store/store.go b/store/store.go
index 13b59b582..338ae186f 100644
--- a/store/store.go
+++ b/store/store.go
@@ -52,6 +52,7 @@ type TeamStore interface {
GetAll() StoreChannel
GetAllTeamListing() StoreChannel
GetByInviteId(inviteId string) StoreChannel
+ PermanentDelete(teamId string) StoreChannel
}
type ChannelStore interface {
@@ -60,6 +61,7 @@ type ChannelStore interface {
Update(channel *model.Channel) StoreChannel
Get(id string) StoreChannel
Delete(channelId string, time int64) StoreChannel
+ PermanentDeleteByTeam(teamId string) StoreChannel
GetByName(team_id string, domain string) StoreChannel
GetChannels(teamId string, userId string) StoreChannel
GetMoreChannels(teamId string, userId string) StoreChannel
@@ -72,6 +74,7 @@ type ChannelStore interface {
GetMember(channelId string, userId string) StoreChannel
GetMemberCount(channelId string) StoreChannel
RemoveMember(channelId string, userId string) StoreChannel
+ PermanentDeleteMembersByUser(userId string) StoreChannel
GetExtraMembers(channelId string, limit int) StoreChannel
CheckPermissionsTo(teamId string, channelId string, userId string) StoreChannel
CheckOpenChannelPermissions(teamId string, channelId string) StoreChannel
@@ -86,6 +89,7 @@ type PostStore interface {
Update(post *model.Post, newMessage string, newHashtags string) StoreChannel
Get(id string) StoreChannel
Delete(postId string, time int64) StoreChannel
+ PermanentDeleteByUser(userId string) StoreChannel
GetPosts(channelId 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
@@ -118,6 +122,7 @@ type UserStore interface {
GetTotalUsersCount() StoreChannel
GetTotalActiveUsersCount() StoreChannel
GetSystemAdminProfiles() StoreChannel
+ PermanentDelete(userId string) StoreChannel
}
type SessionStore interface {
@@ -126,6 +131,7 @@ type SessionStore interface {
GetSessions(userId string) StoreChannel
Remove(sessionIdOrToken string) StoreChannel
RemoveAllSessionsForTeam(teamId string) StoreChannel
+ PermanentDeleteSessionsByUser(teamId string) StoreChannel
UpdateLastActivityAt(sessionId string, time int64) StoreChannel
UpdateRoles(userId string, roles string) StoreChannel
}
@@ -133,6 +139,7 @@ type SessionStore interface {
type AuditStore interface {
Save(audit *model.Audit) StoreChannel
Get(user_id string, limit int) StoreChannel
+ PermanentDeleteByUser(userId string) StoreChannel
}
type OAuthStore interface {
@@ -143,6 +150,7 @@ type OAuthStore interface {
SaveAuthData(authData *model.AuthData) StoreChannel
GetAuthData(code string) StoreChannel
RemoveAuthData(code string) StoreChannel
+ PermanentDeleteAuthDataByUser(userId string) StoreChannel
SaveAccessData(accessData *model.AccessData) StoreChannel
GetAccessData(token string) StoreChannel
GetAccessDataByAuthCode(authCode string) StoreChannel
@@ -161,12 +169,14 @@ type WebhookStore interface {
GetIncomingByUser(userId string) StoreChannel
GetIncomingByChannel(channelId string) StoreChannel
DeleteIncoming(webhookId string, time int64) StoreChannel
+ PermanentDeleteIncomingByUser(userId string) StoreChannel
SaveOutgoing(webhook *model.OutgoingWebhook) StoreChannel
GetOutgoing(id string) StoreChannel
GetOutgoingByCreator(userId string) StoreChannel
GetOutgoingByChannel(channelId string) StoreChannel
GetOutgoingByTeam(teamId string) StoreChannel
DeleteOutgoing(webhookId string, time int64) StoreChannel
+ PermanentDeleteOutgoingByUser(userId string) StoreChannel
UpdateOutgoing(hook *model.OutgoingWebhook) StoreChannel
}
@@ -175,4 +185,5 @@ type PreferenceStore interface {
Get(userId string, category string, name string) StoreChannel
GetCategory(userId string, category string) StoreChannel
GetAll(userId string) StoreChannel
+ PermanentDeleteByUser(userId string) StoreChannel
}