summaryrefslogtreecommitdiffstats
path: root/store/sqlstore/channel_store.go
diff options
context:
space:
mode:
authorGeorge Goldberg <george@gberg.me>2018-05-14 15:59:04 +0100
committerGitHub <noreply@github.com>2018-05-14 15:59:04 +0100
commit51bd710ecdca6628461c9fa2679737073e4d5059 (patch)
treeb2a4837ced3ed515ee505728917a6630b0553f76 /store/sqlstore/channel_store.go
parent91557bbd978500388a11b99401783164e143a966 (diff)
downloadchat-51bd710ecdca6628461c9fa2679737073e4d5059.tar.gz
chat-51bd710ecdca6628461c9fa2679737073e4d5059.tar.bz2
chat-51bd710ecdca6628461c9fa2679737073e4d5059.zip
MM-9728: Online migration for advanced permissions phase 2 (#8744)
* MM-9728: Online migration for advanced permissions phase 2 * Add unit tests for new store functions. * Move migration specific code to own file. * Add migration state function test. * Style fixes. * Add i18n strings. * Fix mocks. * Add TestMain to migrations package tests. * Fix typo. * Fix review comments. * Fix up the "Check if migration is done" check to actually work.
Diffstat (limited to 'store/sqlstore/channel_store.go')
-rw-r--r--store/sqlstore/channel_store.go68
1 files changed, 68 insertions, 0 deletions
diff --git a/store/sqlstore/channel_store.go b/store/sqlstore/channel_store.go
index beef1be80..dceebc92e 100644
--- a/store/sqlstore/channel_store.go
+++ b/store/sqlstore/channel_store.go
@@ -1739,3 +1739,71 @@ func (s SqlChannelStore) GetChannelsByScheme(schemeId string, offset int, limit
}
})
}
+
+// This function does the Advanced Permissions Phase 2 migration for ChannelMember objects. It performs the migration
+// in batches as a single transaction per batch to ensure consistency but to also minimise execution time to avoid
+// causing unnecessary table locks. **THIS FUNCTION SHOULD NOT BE USED FOR ANY OTHER PURPOSE.** Executing this function
+// *after* the new Schemes functionality has been used on an installation will have unintended consequences.
+func (s SqlChannelStore) MigrateChannelMembers(fromChannelId string, fromUserId string) store.StoreChannel {
+ return store.Do(func(result *store.StoreResult) {
+ var transaction *gorp.Transaction
+ var err error
+
+ if transaction, err = s.GetMaster().Begin(); err != nil {
+ result.Err = model.NewAppError("SqlChannelStore.MigrateChannelMembers", "store.sql_channel.migrate_channel_members.open_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
+ return
+ }
+
+ var channelMembers []channelMember
+ if _, err := transaction.Select(&channelMembers, "SELECT * from ChannelMembers WHERE (ChannelId, UserId) > (:FromChannelId, :FromUserId) ORDER BY ChannelId, UserId LIMIT 100", map[string]interface{}{"FromChannelId": fromChannelId, "FromUserId": fromUserId}); err != nil {
+ result.Err = model.NewAppError("SqlChannelStore.MigrateChannelMembers", "store.sql_channel.migrate_channel_members.select.app_error", nil, err.Error(), http.StatusInternalServerError)
+ return
+ }
+
+ if len(channelMembers) == 0 {
+ // No more channel members in query result means that the migration has finished.
+ return
+ }
+
+ for _, member := range channelMembers {
+ roles := strings.Fields(member.Roles)
+ var newRoles []string
+ member.SchemeAdmin = sql.NullBool{Bool: false, Valid: true}
+ member.SchemeUser = sql.NullBool{Bool: false, Valid: true}
+ for _, role := range roles {
+ if role == model.CHANNEL_ADMIN_ROLE_ID {
+ member.SchemeAdmin = sql.NullBool{Bool: true, Valid: true}
+ } else if role == model.CHANNEL_USER_ROLE_ID {
+ member.SchemeUser = sql.NullBool{Bool: true, Valid: true}
+ } else {
+ newRoles = append(newRoles, role)
+ }
+ }
+ member.Roles = strings.Join(newRoles, " ")
+
+ if _, err := transaction.Update(&member); err != nil {
+ if err2 := transaction.Rollback(); err2 != nil {
+ result.Err = model.NewAppError("SqlChannelStore.MigrateChannelMembers", "store.sql_channel.migrate_channel_members.rollback_transaction.app_error", nil, err2.Error(), http.StatusInternalServerError)
+ return
+ }
+ result.Err = model.NewAppError("SqlChannelStore.MigrateChannelMembers", "store.sql_channel.migrate_channel_members.update.app_error", nil, err.Error(), http.StatusInternalServerError)
+ return
+ }
+
+ }
+
+ if err := transaction.Commit(); err != nil {
+ if err2 := transaction.Rollback(); err2 != nil {
+ result.Err = model.NewAppError("SqlChannelStore.MigrateChannelMembers", "store.sql_channel.migrate_channel_members.rollback_transaction.app_error", nil, err2.Error(), http.StatusInternalServerError)
+ return
+ }
+ result.Err = model.NewAppError("SqlChannelStore.MigrateChannelMembers", "store.sql_channel.migrate_channel_members.commit_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
+ return
+ }
+
+ data := make(map[string]string)
+ data["ChannelId"] = channelMembers[len(channelMembers)-1].ChannelId
+ data["UserId"] = channelMembers[len(channelMembers)-1].UserId
+ result.Data = data
+ })
+}