summaryrefslogtreecommitdiffstats
path: root/store
diff options
context:
space:
mode:
authorGeorge Goldberg <george@gberg.me>2018-10-08 16:39:03 +0100
committerGitHub <noreply@github.com>2018-10-08 16:39:03 +0100
commit9a4f3ce1e5b22a297eeb00b2aaff44f88304ae8c (patch)
tree8841d645463b21a175036399e78ecae647922e55 /store
parent7b338c161bce8bdede54d85a5df5a0efe34eb874 (diff)
downloadchat-9a4f3ce1e5b22a297eeb00b2aaff44f88304ae8c.tar.gz
chat-9a4f3ce1e5b22a297eeb00b2aaff44f88304ae8c.tar.bz2
chat-9a4f3ce1e5b22a297eeb00b2aaff44f88304ae8c.zip
MM-12251: Add flag to MoveChannel to remove all deactivated users. (#9515)
Diffstat (limited to 'store')
-rw-r--r--store/sqlstore/channel_store.go26
-rw-r--r--store/store.go1
-rw-r--r--store/storetest/channel_store.go73
-rw-r--r--store/storetest/mocks/ChannelStore.go16
4 files changed, 116 insertions, 0 deletions
diff --git a/store/sqlstore/channel_store.go b/store/sqlstore/channel_store.go
index 7a9e4e687..b1886c428 100644
--- a/store/sqlstore/channel_store.go
+++ b/store/sqlstore/channel_store.go
@@ -1478,6 +1478,32 @@ func (s SqlChannelStore) RemoveMember(channelId string, userId string) store.Sto
})
}
+func (s SqlChannelStore) RemoveAllDeactivatedMembers(channelId string) store.StoreChannel {
+ return store.Do(func(result *store.StoreResult) {
+ query := `
+ DELETE
+ FROM
+ ChannelMembers
+ WHERE
+ UserId IN (
+ SELECT
+ Id
+ FROM
+ Users
+ WHERE
+ Users.DeleteAt != 0
+ )
+ AND
+ ChannelMembers.ChannelId = :ChannelId
+ `
+
+ _, err := s.GetMaster().Exec(query, map[string]interface{}{"ChannelId": channelId})
+ if err != nil {
+ result.Err = model.NewAppError("SqlChannelStore.RemoveAllDeactivatedMembers", "store.sql_channel.remove_all_deactivated_members.app_error", nil, "channel_id="+channelId+", "+err.Error(), http.StatusInternalServerError)
+ }
+ })
+}
+
func (s SqlChannelStore) PermanentDeleteMembersByUser(userId string) store.StoreChannel {
return store.Do(func(result *store.StoreResult) {
if _, err := s.GetMaster().Exec("DELETE FROM ChannelMembers WHERE UserId = :UserId", map[string]interface{}{"UserId": userId}); err != nil {
diff --git a/store/store.go b/store/store.go
index dd49e0c97..8a2051527 100644
--- a/store/store.go
+++ b/store/store.go
@@ -184,6 +184,7 @@ type ChannelStore interface {
IsExperimentalPublicChannelsMaterializationEnabled() bool
GetAllChannelsForExportAfter(limit int, afterId string) StoreChannel
GetChannelMembersForExport(userId string, teamId string) StoreChannel
+ RemoveAllDeactivatedMembers(channelId string) StoreChannel
}
type ChannelMemberHistoryStore interface {
diff --git a/store/storetest/channel_store.go b/store/storetest/channel_store.go
index 7cb86242f..34efd810d 100644
--- a/store/storetest/channel_store.go
+++ b/store/storetest/channel_store.go
@@ -80,6 +80,7 @@ func TestChannelStore(t *testing.T, ss store.Store, s SqlSupplier) {
t.Run("MaterializedPublicChannels", func(t *testing.T) { testMaterializedPublicChannels(t, ss, s) })
t.Run("GetAllChannelsForExportAfter", func(t *testing.T) { testChannelStoreGetAllChannelsForExportAfter(t, ss) })
t.Run("GetChannelMembersForExport", func(t *testing.T) { testChannelStoreGetChannelMembersForExport(t, ss) })
+ t.Run("RemoveAllDeactivatedMembers", func(t *testing.T) { testChannelStoreRemoveAllDeactivatedMembers(t, ss) })
})
}
}
@@ -2806,3 +2807,75 @@ func testChannelStoreGetChannelMembersForExport(t *testing.T, ss store.Store) {
assert.Equal(t, c1.Id, cmfe1.ChannelId)
assert.Equal(t, u1.Id, cmfe1.UserId)
}
+
+func testChannelStoreRemoveAllDeactivatedMembers(t *testing.T, ss store.Store) {
+ // Set up all the objects needed in the store.
+ t1 := model.Team{}
+ t1.DisplayName = "Name"
+ t1.Name = model.NewId()
+ t1.Email = MakeEmail()
+ t1.Type = model.TEAM_OPEN
+ store.Must(ss.Team().Save(&t1))
+
+ c1 := model.Channel{}
+ c1.TeamId = t1.Id
+ c1.DisplayName = "Channel1"
+ c1.Name = "zz" + model.NewId() + "b"
+ c1.Type = model.CHANNEL_OPEN
+ store.Must(ss.Channel().Save(&c1, -1))
+
+ u1 := model.User{}
+ u1.Email = MakeEmail()
+ u1.Nickname = model.NewId()
+ store.Must(ss.User().Save(&u1))
+
+ u2 := model.User{}
+ u2.Email = MakeEmail()
+ u2.Nickname = model.NewId()
+ store.Must(ss.User().Save(&u2))
+
+ u3 := model.User{}
+ u3.Email = MakeEmail()
+ u3.Nickname = model.NewId()
+ store.Must(ss.User().Save(&u3))
+
+ m1 := model.ChannelMember{}
+ m1.ChannelId = c1.Id
+ m1.UserId = u1.Id
+ m1.NotifyProps = model.GetDefaultChannelNotifyProps()
+ store.Must(ss.Channel().SaveMember(&m1))
+
+ m2 := model.ChannelMember{}
+ m2.ChannelId = c1.Id
+ m2.UserId = u2.Id
+ m2.NotifyProps = model.GetDefaultChannelNotifyProps()
+ store.Must(ss.Channel().SaveMember(&m2))
+
+ m3 := model.ChannelMember{}
+ m3.ChannelId = c1.Id
+ m3.UserId = u3.Id
+ m3.NotifyProps = model.GetDefaultChannelNotifyProps()
+ store.Must(ss.Channel().SaveMember(&m3))
+
+ // Get all the channel members. Check there are 3.
+ r1 := <-ss.Channel().GetMembers(c1.Id, 0, 1000)
+ assert.Nil(t, r1.Err)
+ d1 := r1.Data.(*model.ChannelMembers)
+ assert.Len(t, *d1, 3)
+
+ // Deactivate users 1 & 2.
+ u1.DeleteAt = model.GetMillis()
+ u2.DeleteAt = model.GetMillis()
+ require.Nil(t, (<-ss.User().Update(&u1, true)).Err)
+ require.Nil(t, (<-ss.User().Update(&u2, true)).Err)
+
+ // Remove all deactivated users from the channel.
+ assert.Nil(t, (<-ss.Channel().RemoveAllDeactivatedMembers(c1.Id)).Err)
+
+ // Get all the channel members. Check there is now only 1: m3.
+ r2 := <-ss.Channel().GetMembers(c1.Id, 0, 1000)
+ assert.Nil(t, r1.Err)
+ d2 := r2.Data.(*model.ChannelMembers)
+ assert.Len(t, *d2, 1)
+ assert.Equal(t, (*d2)[0].UserId, u3.Id)
+}
diff --git a/store/storetest/mocks/ChannelStore.go b/store/storetest/mocks/ChannelStore.go
index 9db85eacf..1c3a2a8f2 100644
--- a/store/storetest/mocks/ChannelStore.go
+++ b/store/storetest/mocks/ChannelStore.go
@@ -779,6 +779,22 @@ func (_m *ChannelStore) PermanentDeleteMembersByUser(userId string) store.StoreC
return r0
}
+// RemoveAllDeactivatedMembers provides a mock function with given fields: channelId
+func (_m *ChannelStore) RemoveAllDeactivatedMembers(channelId string) store.StoreChannel {
+ ret := _m.Called(channelId)
+
+ var r0 store.StoreChannel
+ if rf, ok := ret.Get(0).(func(string) store.StoreChannel); ok {
+ r0 = rf(channelId)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(store.StoreChannel)
+ }
+ }
+
+ return r0
+}
+
// RemoveMember provides a mock function with given fields: channelId, userId
func (_m *ChannelStore) RemoveMember(channelId string, userId string) store.StoreChannel {
ret := _m.Called(channelId, userId)