github.com/crspeller/mattermost-server@v0.0.0-20190328001957-a200beb3d111/store/sqlstore/upgrade.go (about)

     1  // Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
     2  // See License.txt for license information.
     3  
     4  package sqlstore
     5  
     6  import (
     7  	"database/sql"
     8  	"encoding/json"
     9  	"fmt"
    10  	"os"
    11  	"strings"
    12  	"time"
    13  
    14  	"github.com/pkg/errors"
    15  
    16  	"github.com/crspeller/mattermost-server/mlog"
    17  	"github.com/crspeller/mattermost-server/model"
    18  	"github.com/crspeller/mattermost-server/services/timezones"
    19  )
    20  
    21  const (
    22  	VERSION_5_11_0           = "5.11.0"
    23  	VERSION_5_10_0           = "5.10.0"
    24  	VERSION_5_9_0            = "5.9.0"
    25  	VERSION_5_8_0            = "5.8.0"
    26  	VERSION_5_7_0            = "5.7.0"
    27  	VERSION_5_6_0            = "5.6.0"
    28  	VERSION_5_5_0            = "5.5.0"
    29  	VERSION_5_4_0            = "5.4.0"
    30  	VERSION_5_3_0            = "5.3.0"
    31  	VERSION_5_2_0            = "5.2.0"
    32  	VERSION_5_1_0            = "5.1.0"
    33  	VERSION_5_0_0            = "5.0.0"
    34  	VERSION_4_10_0           = "4.10.0"
    35  	VERSION_4_9_0            = "4.9.0"
    36  	VERSION_4_8_1            = "4.8.1"
    37  	VERSION_4_8_0            = "4.8.0"
    38  	VERSION_4_7_2            = "4.7.2"
    39  	VERSION_4_7_1            = "4.7.1"
    40  	VERSION_4_7_0            = "4.7.0"
    41  	VERSION_4_6_0            = "4.6.0"
    42  	VERSION_4_5_0            = "4.5.0"
    43  	VERSION_4_4_0            = "4.4.0"
    44  	VERSION_4_3_0            = "4.3.0"
    45  	VERSION_4_2_0            = "4.2.0"
    46  	VERSION_4_1_0            = "4.1.0"
    47  	VERSION_4_0_0            = "4.0.0"
    48  	VERSION_3_10_0           = "3.10.0"
    49  	VERSION_3_9_0            = "3.9.0"
    50  	VERSION_3_8_0            = "3.8.0"
    51  	VERSION_3_7_0            = "3.7.0"
    52  	VERSION_3_6_0            = "3.6.0"
    53  	VERSION_3_5_0            = "3.5.0"
    54  	VERSION_3_4_0            = "3.4.0"
    55  	VERSION_3_3_0            = "3.3.0"
    56  	VERSION_3_2_0            = "3.2.0"
    57  	VERSION_3_1_0            = "3.1.0"
    58  	VERSION_3_0_0            = "3.0.0"
    59  	OLDEST_SUPPORTED_VERSION = VERSION_3_0_0
    60  )
    61  
    62  const (
    63  	EXIT_VERSION_SAVE_MISSING  = 1001
    64  	EXIT_TOO_OLD               = 1002
    65  	EXIT_VERSION_SAVE          = 1003
    66  	EXIT_THEME_MIGRATION       = 1004
    67  	EXIT_ROLE_MIGRATION_FAILED = 1005
    68  )
    69  
    70  func UpgradeDatabase(sqlStore SqlStore) {
    71  
    72  	UpgradeDatabaseToVersion31(sqlStore)
    73  	UpgradeDatabaseToVersion32(sqlStore)
    74  	UpgradeDatabaseToVersion33(sqlStore)
    75  	UpgradeDatabaseToVersion34(sqlStore)
    76  	UpgradeDatabaseToVersion35(sqlStore)
    77  	UpgradeDatabaseToVersion36(sqlStore)
    78  	UpgradeDatabaseToVersion37(sqlStore)
    79  	UpgradeDatabaseToVersion38(sqlStore)
    80  	UpgradeDatabaseToVersion39(sqlStore)
    81  	UpgradeDatabaseToVersion310(sqlStore)
    82  	UpgradeDatabaseToVersion40(sqlStore)
    83  	UpgradeDatabaseToVersion41(sqlStore)
    84  	UpgradeDatabaseToVersion42(sqlStore)
    85  	UpgradeDatabaseToVersion43(sqlStore)
    86  	UpgradeDatabaseToVersion44(sqlStore)
    87  	UpgradeDatabaseToVersion45(sqlStore)
    88  	UpgradeDatabaseToVersion46(sqlStore)
    89  	UpgradeDatabaseToVersion47(sqlStore)
    90  	UpgradeDatabaseToVersion471(sqlStore)
    91  	UpgradeDatabaseToVersion472(sqlStore)
    92  	UpgradeDatabaseToVersion48(sqlStore)
    93  	UpgradeDatabaseToVersion481(sqlStore)
    94  	UpgradeDatabaseToVersion49(sqlStore)
    95  	UpgradeDatabaseToVersion410(sqlStore)
    96  	UpgradeDatabaseToVersion50(sqlStore)
    97  	UpgradeDatabaseToVersion51(sqlStore)
    98  	UpgradeDatabaseToVersion52(sqlStore)
    99  	UpgradeDatabaseToVersion53(sqlStore)
   100  	UpgradeDatabaseToVersion54(sqlStore)
   101  	UpgradeDatabaseToVersion55(sqlStore)
   102  	UpgradeDatabaseToVersion56(sqlStore)
   103  	UpgradeDatabaseToVersion57(sqlStore)
   104  	UpgradeDatabaseToVersion58(sqlStore)
   105  	UpgradeDatabaseToVersion59(sqlStore)
   106  	UpgradeDatabaseToVersion510(sqlStore)
   107  	UpgradeDatabaseToVersion511(sqlStore)
   108  
   109  	// If the SchemaVersion is empty this this is the first time it has ran
   110  	// so lets set it to the current version.
   111  	if sqlStore.GetCurrentSchemaVersion() == "" {
   112  		if result := <-sqlStore.System().SaveOrUpdate(&model.System{Name: "Version", Value: model.CurrentVersion}); result.Err != nil {
   113  			mlog.Critical(result.Err.Error())
   114  			time.Sleep(time.Second)
   115  			os.Exit(EXIT_VERSION_SAVE_MISSING)
   116  		}
   117  
   118  		mlog.Info(fmt.Sprintf("The database schema has been set to version %v", model.CurrentVersion))
   119  	}
   120  
   121  	// If we're not on the current version then it's too old to be upgraded
   122  	if sqlStore.GetCurrentSchemaVersion() != model.CurrentVersion {
   123  		mlog.Critical(fmt.Sprintf("Database schema version %v is no longer supported. This Mattermost server supports automatic upgrades from schema version %v through schema version %v. Downgrades are not supported. Please manually upgrade to at least version %v before continuing", sqlStore.GetCurrentSchemaVersion(), OLDEST_SUPPORTED_VERSION, model.CurrentVersion, OLDEST_SUPPORTED_VERSION))
   124  		time.Sleep(time.Second)
   125  		os.Exit(EXIT_TOO_OLD)
   126  	}
   127  }
   128  
   129  func saveSchemaVersion(sqlStore SqlStore, version string) {
   130  	if result := <-sqlStore.System().Update(&model.System{Name: "Version", Value: version}); result.Err != nil {
   131  		mlog.Critical(result.Err.Error())
   132  		time.Sleep(time.Second)
   133  		os.Exit(EXIT_VERSION_SAVE)
   134  	}
   135  
   136  	mlog.Warn(fmt.Sprintf("The database schema has been upgraded to version %v", version))
   137  }
   138  
   139  func shouldPerformUpgrade(sqlStore SqlStore, currentSchemaVersion string, expectedSchemaVersion string) bool {
   140  	if sqlStore.GetCurrentSchemaVersion() == currentSchemaVersion {
   141  		mlog.Warn(fmt.Sprintf("The database schema version of %v appears to be out of date", currentSchemaVersion))
   142  		mlog.Warn(fmt.Sprintf("Attempting to upgrade the database schema version to %v", expectedSchemaVersion))
   143  
   144  		return true
   145  	}
   146  
   147  	return false
   148  }
   149  
   150  func UpgradeDatabaseToVersion31(sqlStore SqlStore) {
   151  	if shouldPerformUpgrade(sqlStore, VERSION_3_0_0, VERSION_3_1_0) {
   152  		sqlStore.CreateColumnIfNotExists("OutgoingWebhooks", "ContentType", "varchar(128)", "varchar(128)", "")
   153  		saveSchemaVersion(sqlStore, VERSION_3_1_0)
   154  	}
   155  }
   156  
   157  func UpgradeDatabaseToVersion32(sqlStore SqlStore) {
   158  	if shouldPerformUpgrade(sqlStore, VERSION_3_1_0, VERSION_3_2_0) {
   159  		sqlStore.CreateColumnIfNotExists("TeamMembers", "DeleteAt", "bigint(20)", "bigint", "0")
   160  
   161  		saveSchemaVersion(sqlStore, VERSION_3_2_0)
   162  	}
   163  }
   164  
   165  func themeMigrationFailed(err error) {
   166  	mlog.Critical(fmt.Sprintf("Failed to migrate User.ThemeProps to Preferences table %v", err))
   167  	time.Sleep(time.Second)
   168  	os.Exit(EXIT_THEME_MIGRATION)
   169  }
   170  
   171  func UpgradeDatabaseToVersion33(sqlStore SqlStore) {
   172  	if shouldPerformUpgrade(sqlStore, VERSION_3_2_0, VERSION_3_3_0) {
   173  		if sqlStore.DoesColumnExist("Users", "ThemeProps") {
   174  			params := map[string]interface{}{
   175  				"Category": model.PREFERENCE_CATEGORY_THEME,
   176  				"Name":     "",
   177  			}
   178  
   179  			transaction, err := sqlStore.GetMaster().Begin()
   180  			if err != nil {
   181  				themeMigrationFailed(err)
   182  			}
   183  			defer finalizeTransaction(transaction)
   184  
   185  			// increase size of Value column of Preferences table to match the size of the ThemeProps column
   186  			if sqlStore.DriverName() == model.DATABASE_DRIVER_POSTGRES {
   187  				if _, err := transaction.Exec("ALTER TABLE Preferences ALTER COLUMN Value TYPE varchar(2000)"); err != nil {
   188  					themeMigrationFailed(err)
   189  					return
   190  				}
   191  			} else if sqlStore.DriverName() == model.DATABASE_DRIVER_MYSQL {
   192  				if _, err := transaction.Exec("ALTER TABLE Preferences MODIFY Value text"); err != nil {
   193  					themeMigrationFailed(err)
   194  					return
   195  				}
   196  			}
   197  
   198  			// copy data across
   199  			if _, err := transaction.Exec(
   200  				`INSERT INTO
   201  					Preferences(UserId, Category, Name, Value)
   202  				SELECT
   203  					Id, '`+model.PREFERENCE_CATEGORY_THEME+`', '', ThemeProps
   204  				FROM
   205  					Users
   206  				WHERE
   207  					Users.ThemeProps != 'null'`, params); err != nil {
   208  				themeMigrationFailed(err)
   209  				return
   210  			}
   211  
   212  			// delete old data
   213  			if _, err := transaction.Exec("ALTER TABLE Users DROP COLUMN ThemeProps"); err != nil {
   214  				themeMigrationFailed(err)
   215  				return
   216  			}
   217  
   218  			if err := transaction.Commit(); err != nil {
   219  				themeMigrationFailed(err)
   220  				return
   221  			}
   222  
   223  			// rename solarized_* code themes to solarized-* to match client changes in 3.0
   224  			var data model.Preferences
   225  			if _, err := sqlStore.GetMaster().Select(&data, "SELECT * FROM Preferences WHERE Category = '"+model.PREFERENCE_CATEGORY_THEME+"' AND Value LIKE '%solarized_%'"); err == nil {
   226  				for i := range data {
   227  					data[i].Value = strings.Replace(data[i].Value, "solarized_", "solarized-", -1)
   228  				}
   229  
   230  				sqlStore.Preference().Save(&data)
   231  			}
   232  		}
   233  
   234  		sqlStore.CreateColumnIfNotExists("OAuthApps", "IsTrusted", "tinyint(1)", "boolean", "0")
   235  		sqlStore.CreateColumnIfNotExists("OAuthApps", "IconURL", "varchar(512)", "varchar(512)", "")
   236  		sqlStore.CreateColumnIfNotExists("OAuthAccessData", "ClientId", "varchar(26)", "varchar(26)", "")
   237  		sqlStore.CreateColumnIfNotExists("OAuthAccessData", "UserId", "varchar(26)", "varchar(26)", "")
   238  		sqlStore.CreateColumnIfNotExists("OAuthAccessData", "ExpiresAt", "bigint", "bigint", "0")
   239  
   240  		if sqlStore.DoesColumnExist("OAuthAccessData", "AuthCode") {
   241  			sqlStore.RemoveIndexIfExists("idx_oauthaccessdata_auth_code", "OAuthAccessData")
   242  			sqlStore.RemoveColumnIfExists("OAuthAccessData", "AuthCode")
   243  		}
   244  
   245  		sqlStore.RemoveColumnIfExists("Users", "LastActivityAt")
   246  		sqlStore.RemoveColumnIfExists("Users", "LastPingAt")
   247  
   248  		sqlStore.CreateColumnIfNotExists("OutgoingWebhooks", "TriggerWhen", "tinyint", "integer", "0")
   249  
   250  		saveSchemaVersion(sqlStore, VERSION_3_3_0)
   251  	}
   252  }
   253  
   254  func UpgradeDatabaseToVersion34(sqlStore SqlStore) {
   255  	if shouldPerformUpgrade(sqlStore, VERSION_3_3_0, VERSION_3_4_0) {
   256  		sqlStore.CreateColumnIfNotExists("Status", "Manual", "BOOLEAN", "BOOLEAN", "0")
   257  		sqlStore.CreateColumnIfNotExists("Status", "ActiveChannel", "varchar(26)", "varchar(26)", "")
   258  
   259  		saveSchemaVersion(sqlStore, VERSION_3_4_0)
   260  	}
   261  }
   262  
   263  func UpgradeDatabaseToVersion35(sqlStore SqlStore) {
   264  	if shouldPerformUpgrade(sqlStore, VERSION_3_4_0, VERSION_3_5_0) {
   265  		sqlStore.GetMaster().Exec("UPDATE Users SET Roles = 'system_user' WHERE Roles = ''")
   266  		sqlStore.GetMaster().Exec("UPDATE Users SET Roles = 'system_user system_admin' WHERE Roles = 'system_admin'")
   267  		sqlStore.GetMaster().Exec("UPDATE TeamMembers SET Roles = 'team_user' WHERE Roles = ''")
   268  		sqlStore.GetMaster().Exec("UPDATE TeamMembers SET Roles = 'team_user team_admin' WHERE Roles = 'admin'")
   269  		sqlStore.GetMaster().Exec("UPDATE ChannelMembers SET Roles = 'channel_user' WHERE Roles = ''")
   270  		sqlStore.GetMaster().Exec("UPDATE ChannelMembers SET Roles = 'channel_user channel_admin' WHERE Roles = 'admin'")
   271  
   272  		// The rest of the migration from Filenames -> FileIds is done lazily in api.GetFileInfosForPost
   273  		sqlStore.CreateColumnIfNotExists("Posts", "FileIds", "varchar(150)", "varchar(150)", "[]")
   274  
   275  		// Increase maximum length of the Channel table Purpose column.
   276  		if sqlStore.GetMaxLengthOfColumnIfExists("Channels", "Purpose") != "250" {
   277  			sqlStore.AlterColumnTypeIfExists("Channels", "Purpose", "varchar(250)", "varchar(250)")
   278  		}
   279  
   280  		sqlStore.Session().RemoveAllSessions()
   281  
   282  		saveSchemaVersion(sqlStore, VERSION_3_5_0)
   283  	}
   284  }
   285  
   286  func UpgradeDatabaseToVersion36(sqlStore SqlStore) {
   287  	if shouldPerformUpgrade(sqlStore, VERSION_3_5_0, VERSION_3_6_0) {
   288  		sqlStore.CreateColumnIfNotExists("Posts", "HasReactions", "tinyint", "boolean", "0")
   289  
   290  		// Create Team Description column
   291  		sqlStore.CreateColumnIfNotExists("Teams", "Description", "varchar(255)", "varchar(255)", "")
   292  
   293  		// Add a Position column to users.
   294  		sqlStore.CreateColumnIfNotExists("Users", "Position", "varchar(64)", "varchar(64)", "")
   295  
   296  		// Remove ActiveChannel column from Status
   297  		sqlStore.RemoveColumnIfExists("Status", "ActiveChannel")
   298  
   299  		saveSchemaVersion(sqlStore, VERSION_3_6_0)
   300  	}
   301  }
   302  
   303  func UpgradeDatabaseToVersion37(sqlStore SqlStore) {
   304  	if shouldPerformUpgrade(sqlStore, VERSION_3_6_0, VERSION_3_7_0) {
   305  		// Add EditAt column to Posts
   306  		sqlStore.CreateColumnIfNotExists("Posts", "EditAt", " bigint", " bigint", "0")
   307  
   308  		saveSchemaVersion(sqlStore, VERSION_3_7_0)
   309  	}
   310  }
   311  
   312  func UpgradeDatabaseToVersion38(sqlStore SqlStore) {
   313  	if shouldPerformUpgrade(sqlStore, VERSION_3_7_0, VERSION_3_8_0) {
   314  		// Add the IsPinned column to posts.
   315  		sqlStore.CreateColumnIfNotExists("Posts", "IsPinned", "boolean", "boolean", "0")
   316  
   317  		saveSchemaVersion(sqlStore, VERSION_3_8_0)
   318  	}
   319  }
   320  
   321  func UpgradeDatabaseToVersion39(sqlStore SqlStore) {
   322  	if shouldPerformUpgrade(sqlStore, VERSION_3_8_0, VERSION_3_9_0) {
   323  		sqlStore.CreateColumnIfNotExists("OAuthAccessData", "Scope", "varchar(128)", "varchar(128)", model.DEFAULT_SCOPE)
   324  		sqlStore.RemoveTableIfExists("PasswordRecovery")
   325  
   326  		saveSchemaVersion(sqlStore, VERSION_3_9_0)
   327  	}
   328  }
   329  
   330  func UpgradeDatabaseToVersion310(sqlStore SqlStore) {
   331  	if shouldPerformUpgrade(sqlStore, VERSION_3_9_0, VERSION_3_10_0) {
   332  		saveSchemaVersion(sqlStore, VERSION_3_10_0)
   333  	}
   334  }
   335  
   336  func UpgradeDatabaseToVersion40(sqlStore SqlStore) {
   337  	if shouldPerformUpgrade(sqlStore, VERSION_3_10_0, VERSION_4_0_0) {
   338  		saveSchemaVersion(sqlStore, VERSION_4_0_0)
   339  	}
   340  }
   341  
   342  func UpgradeDatabaseToVersion41(sqlStore SqlStore) {
   343  	if shouldPerformUpgrade(sqlStore, VERSION_4_0_0, VERSION_4_1_0) {
   344  		// Increase maximum length of the Users table Roles column.
   345  		if sqlStore.GetMaxLengthOfColumnIfExists("Users", "Roles") != "256" {
   346  			sqlStore.AlterColumnTypeIfExists("Users", "Roles", "varchar(256)", "varchar(256)")
   347  		}
   348  
   349  		sqlStore.RemoveTableIfExists("JobStatuses")
   350  
   351  		saveSchemaVersion(sqlStore, VERSION_4_1_0)
   352  	}
   353  }
   354  
   355  func UpgradeDatabaseToVersion42(sqlStore SqlStore) {
   356  	if shouldPerformUpgrade(sqlStore, VERSION_4_1_0, VERSION_4_2_0) {
   357  		saveSchemaVersion(sqlStore, VERSION_4_2_0)
   358  	}
   359  }
   360  
   361  func UpgradeDatabaseToVersion43(sqlStore SqlStore) {
   362  	if shouldPerformUpgrade(sqlStore, VERSION_4_2_0, VERSION_4_3_0) {
   363  		saveSchemaVersion(sqlStore, VERSION_4_3_0)
   364  	}
   365  }
   366  
   367  func UpgradeDatabaseToVersion44(sqlStore SqlStore) {
   368  	if shouldPerformUpgrade(sqlStore, VERSION_4_3_0, VERSION_4_4_0) {
   369  		// Add the IsActive column to UserAccessToken.
   370  		sqlStore.CreateColumnIfNotExists("UserAccessTokens", "IsActive", "boolean", "boolean", "1")
   371  
   372  		saveSchemaVersion(sqlStore, VERSION_4_4_0)
   373  	}
   374  }
   375  
   376  func UpgradeDatabaseToVersion45(sqlStore SqlStore) {
   377  	if shouldPerformUpgrade(sqlStore, VERSION_4_4_0, VERSION_4_5_0) {
   378  		saveSchemaVersion(sqlStore, VERSION_4_5_0)
   379  	}
   380  }
   381  
   382  func UpgradeDatabaseToVersion46(sqlStore SqlStore) {
   383  	if shouldPerformUpgrade(sqlStore, VERSION_4_5_0, VERSION_4_6_0) {
   384  		sqlStore.CreateColumnIfNotExists("IncomingWebhooks", "Username", "varchar(64)", "varchar(64)", "")
   385  		sqlStore.CreateColumnIfNotExists("IncomingWebhooks", "IconURL", "varchar(1024)", "varchar(1024)", "")
   386  		saveSchemaVersion(sqlStore, VERSION_4_6_0)
   387  	}
   388  }
   389  
   390  func UpgradeDatabaseToVersion47(sqlStore SqlStore) {
   391  	if shouldPerformUpgrade(sqlStore, VERSION_4_6_0, VERSION_4_7_0) {
   392  		sqlStore.AlterColumnTypeIfExists("Users", "Position", "varchar(128)", "varchar(128)")
   393  		sqlStore.AlterColumnTypeIfExists("OAuthAuthData", "State", "varchar(1024)", "varchar(1024)")
   394  		sqlStore.RemoveColumnIfExists("ChannelMemberHistory", "Email")
   395  		sqlStore.RemoveColumnIfExists("ChannelMemberHistory", "Username")
   396  		saveSchemaVersion(sqlStore, VERSION_4_7_0)
   397  	}
   398  }
   399  
   400  // If any new instances started with 4.7, they would have the bad Email column on the
   401  // ChannelMemberHistory table. So for those cases we need to do an upgrade between
   402  // 4.7.0 and 4.7.1
   403  func UpgradeDatabaseToVersion471(sqlStore SqlStore) {
   404  	if shouldPerformUpgrade(sqlStore, VERSION_4_7_0, VERSION_4_7_1) {
   405  		sqlStore.RemoveColumnIfExists("ChannelMemberHistory", "Email")
   406  		saveSchemaVersion(sqlStore, VERSION_4_7_1)
   407  	}
   408  }
   409  
   410  func UpgradeDatabaseToVersion472(sqlStore SqlStore) {
   411  	if shouldPerformUpgrade(sqlStore, VERSION_4_7_1, VERSION_4_7_2) {
   412  		sqlStore.RemoveIndexIfExists("idx_channels_displayname", "Channels")
   413  		saveSchemaVersion(sqlStore, VERSION_4_7_2)
   414  	}
   415  }
   416  
   417  func UpgradeDatabaseToVersion48(sqlStore SqlStore) {
   418  	if shouldPerformUpgrade(sqlStore, VERSION_4_7_2, VERSION_4_8_0) {
   419  		saveSchemaVersion(sqlStore, VERSION_4_8_0)
   420  	}
   421  }
   422  
   423  func UpgradeDatabaseToVersion481(sqlStore SqlStore) {
   424  	if shouldPerformUpgrade(sqlStore, VERSION_4_8_0, VERSION_4_8_1) {
   425  		sqlStore.RemoveIndexIfExists("idx_channels_displayname", "Channels")
   426  		saveSchemaVersion(sqlStore, VERSION_4_8_1)
   427  	}
   428  }
   429  
   430  func UpgradeDatabaseToVersion49(sqlStore SqlStore) {
   431  	// This version of Mattermost includes an App-Layer migration which migrates from hard-coded roles configured by
   432  	// a number of parameters in `config.json` to a `Roles` table in the database. The migration code can be seen
   433  	// in the file `app/app.go` in the function `DoAdvancedPermissionsMigration()`.
   434  
   435  	if shouldPerformUpgrade(sqlStore, VERSION_4_8_1, VERSION_4_9_0) {
   436  		sqlStore.CreateColumnIfNotExists("Teams", "LastTeamIconUpdate", "bigint", "bigint", "0")
   437  		defaultTimezone := timezones.DefaultUserTimezone()
   438  		defaultTimezoneValue, err := json.Marshal(defaultTimezone)
   439  		if err != nil {
   440  			mlog.Critical(fmt.Sprint(err))
   441  		}
   442  		sqlStore.CreateColumnIfNotExists("Users", "Timezone", "varchar(256)", "varchar(256)", string(defaultTimezoneValue))
   443  		sqlStore.RemoveIndexIfExists("idx_channels_displayname", "Channels")
   444  		saveSchemaVersion(sqlStore, VERSION_4_9_0)
   445  	}
   446  }
   447  
   448  func UpgradeDatabaseToVersion410(sqlStore SqlStore) {
   449  	if shouldPerformUpgrade(sqlStore, VERSION_4_9_0, VERSION_4_10_0) {
   450  
   451  		sqlStore.RemoveIndexIfExists("Name_2", "Channels")
   452  		sqlStore.RemoveIndexIfExists("Name_2", "Emoji")
   453  		sqlStore.RemoveIndexIfExists("ClientId_2", "OAuthAccessData")
   454  
   455  		saveSchemaVersion(sqlStore, VERSION_4_10_0)
   456  		sqlStore.GetMaster().Exec("UPDATE Users SET AuthData=LOWER(AuthData) WHERE AuthService = 'saml'")
   457  	}
   458  }
   459  
   460  func UpgradeDatabaseToVersion50(sqlStore SqlStore) {
   461  	// This version of Mattermost includes an App-Layer migration which migrates from hard-coded emojis configured
   462  	// in `config.json` to a `Permission` in the database. The migration code can be seen
   463  	// in the file `app/app.go` in the function `DoEmojisPermissionsMigration()`.
   464  
   465  	// This version of Mattermost also includes a online-migration which migrates some roles from the `Roles` columns of
   466  	// TeamMember and ChannelMember rows to the new SchemeAdmin and SchemeUser columns. If you need to downgrade to a
   467  	// version of Mattermost prior to 5.0, you should take your server offline and run the following SQL statements
   468  	// prior to launching the downgraded version:
   469  	//
   470  	//    UPDATE Teams SET SchemeId = NULL;
   471  	//    UPDATE Channels SET SchemeId = NULL;
   472  	//    UPDATE TeamMembers SET Roles = CONCAT(Roles, ' team_user'), SchemeUser = NULL where SchemeUser = 1;
   473  	//    UPDATE TeamMembers SET Roles = CONCAT(Roles, ' team_admin'), SchemeAdmin = NULL where SchemeAdmin = 1;
   474  	//    UPDATE ChannelMembers SET Roles = CONCAT(Roles, ' channel_user'), SchemeUser = NULL where SchemeUser = 1;
   475  	//    UPDATE ChannelMembers SET Roles = CONCAT(Roles, ' channel_admin'), SchemeAdmin = NULL where SchemeAdmin = 1;
   476  	//    DELETE from Systems WHERE Name = 'migration_advanced_permissions_phase_2';
   477  
   478  	if shouldPerformUpgrade(sqlStore, VERSION_4_10_0, VERSION_5_0_0) {
   479  
   480  		sqlStore.CreateColumnIfNotExistsNoDefault("Teams", "SchemeId", "varchar(26)", "varchar(26)")
   481  		sqlStore.CreateColumnIfNotExistsNoDefault("Channels", "SchemeId", "varchar(26)", "varchar(26)")
   482  
   483  		sqlStore.CreateColumnIfNotExistsNoDefault("TeamMembers", "SchemeUser", "boolean", "boolean")
   484  		sqlStore.CreateColumnIfNotExistsNoDefault("TeamMembers", "SchemeAdmin", "boolean", "boolean")
   485  		sqlStore.CreateColumnIfNotExistsNoDefault("ChannelMembers", "SchemeUser", "boolean", "boolean")
   486  		sqlStore.CreateColumnIfNotExistsNoDefault("ChannelMembers", "SchemeAdmin", "boolean", "boolean")
   487  
   488  		sqlStore.CreateColumnIfNotExists("Roles", "BuiltIn", "boolean", "boolean", "0")
   489  		sqlStore.GetMaster().Exec("UPDATE Roles SET BuiltIn=true")
   490  		sqlStore.GetMaster().Exec("UPDATE Roles SET SchemeManaged=false WHERE Name NOT IN ('system_user', 'system_admin', 'team_user', 'team_admin', 'channel_user', 'channel_admin')")
   491  		sqlStore.CreateColumnIfNotExists("IncomingWebhooks", "ChannelLocked", "boolean", "boolean", "0")
   492  
   493  		sqlStore.RemoveIndexIfExists("idx_channels_txt", "Channels")
   494  
   495  		saveSchemaVersion(sqlStore, VERSION_5_0_0)
   496  	}
   497  }
   498  
   499  func UpgradeDatabaseToVersion51(sqlStore SqlStore) {
   500  	if shouldPerformUpgrade(sqlStore, VERSION_5_0_0, VERSION_5_1_0) {
   501  		saveSchemaVersion(sqlStore, VERSION_5_1_0)
   502  	}
   503  }
   504  
   505  func UpgradeDatabaseToVersion52(sqlStore SqlStore) {
   506  	if shouldPerformUpgrade(sqlStore, VERSION_5_1_0, VERSION_5_2_0) {
   507  		sqlStore.CreateColumnIfNotExists("OutgoingWebhooks", "Username", "varchar(64)", "varchar(64)", "")
   508  		sqlStore.CreateColumnIfNotExists("OutgoingWebhooks", "IconURL", "varchar(1024)", "varchar(1024)", "")
   509  		saveSchemaVersion(sqlStore, VERSION_5_2_0)
   510  	}
   511  }
   512  
   513  func UpgradeDatabaseToVersion53(sqlStore SqlStore) {
   514  	if shouldPerformUpgrade(sqlStore, VERSION_5_2_0, VERSION_5_3_0) {
   515  		saveSchemaVersion(sqlStore, VERSION_5_3_0)
   516  	}
   517  }
   518  
   519  func UpgradeDatabaseToVersion54(sqlStore SqlStore) {
   520  	if shouldPerformUpgrade(sqlStore, VERSION_5_3_0, VERSION_5_4_0) {
   521  		sqlStore.AlterColumnTypeIfExists("OutgoingWebhooks", "Description", "varchar(500)", "varchar(500)")
   522  		sqlStore.AlterColumnTypeIfExists("IncomingWebhooks", "Description", "varchar(500)", "varchar(500)")
   523  		if err := sqlStore.Channel().MigratePublicChannels(); err != nil {
   524  			mlog.Critical("Failed to migrate PublicChannels table", mlog.Err(err))
   525  			time.Sleep(time.Second)
   526  			os.Exit(EXIT_GENERIC_FAILURE)
   527  		}
   528  		saveSchemaVersion(sqlStore, VERSION_5_4_0)
   529  	}
   530  }
   531  
   532  func UpgradeDatabaseToVersion55(sqlStore SqlStore) {
   533  	if shouldPerformUpgrade(sqlStore, VERSION_5_4_0, VERSION_5_5_0) {
   534  		saveSchemaVersion(sqlStore, VERSION_5_5_0)
   535  	}
   536  }
   537  
   538  func UpgradeDatabaseToVersion56(sqlStore SqlStore) {
   539  	if shouldPerformUpgrade(sqlStore, VERSION_5_5_0, VERSION_5_6_0) {
   540  		sqlStore.CreateColumnIfNotExists("PluginKeyValueStore", "ExpireAt", "bigint(20)", "bigint", "0")
   541  
   542  		// migrating user's accepted terms of service data into the new table
   543  		sqlStore.GetMaster().Exec("INSERT INTO UserTermsOfService SELECT Id, AcceptedTermsOfServiceId as TermsOfServiceId, :CreateAt FROM Users WHERE AcceptedTermsOfServiceId != \"\" AND AcceptedTermsOfServiceId IS NOT NULL", map[string]interface{}{"CreateAt": model.GetMillis()})
   544  
   545  		if sqlStore.DriverName() == model.DATABASE_DRIVER_POSTGRES {
   546  			sqlStore.RemoveIndexIfExists("idx_users_email_lower", "lower(Email)")
   547  			sqlStore.RemoveIndexIfExists("idx_users_username_lower", "lower(Username)")
   548  			sqlStore.RemoveIndexIfExists("idx_users_nickname_lower", "lower(Nickname)")
   549  			sqlStore.RemoveIndexIfExists("idx_users_firstname_lower", "lower(FirstName)")
   550  			sqlStore.RemoveIndexIfExists("idx_users_lastname_lower", "lower(LastName)")
   551  		}
   552  
   553  		saveSchemaVersion(sqlStore, VERSION_5_6_0)
   554  	}
   555  
   556  }
   557  
   558  func UpgradeDatabaseToVersion57(sqlStore SqlStore) {
   559  	if shouldPerformUpgrade(sqlStore, VERSION_5_6_0, VERSION_5_7_0) {
   560  		saveSchemaVersion(sqlStore, VERSION_5_7_0)
   561  	}
   562  }
   563  
   564  func getRole(sqlStore SqlStore, name string) (*model.Role, error) {
   565  	var dbRole Role
   566  
   567  	if err := sqlStore.GetReplica().SelectOne(&dbRole, "SELECT * from Roles WHERE Name = :Name", map[string]interface{}{"Name": name}); err != nil {
   568  		if err == sql.ErrNoRows {
   569  			return nil, errors.Wrapf(err, "failed to find role %s", name)
   570  		} else {
   571  			return nil, errors.Wrapf(err, "failed to query role %s", name)
   572  		}
   573  	}
   574  
   575  	return dbRole.ToModel(), nil
   576  }
   577  
   578  func saveRole(sqlStore SqlStore, role *model.Role) error {
   579  	dbRole := NewRoleFromModel(role)
   580  
   581  	dbRole.UpdateAt = model.GetMillis()
   582  	if rowsChanged, err := sqlStore.GetMaster().Update(dbRole); err != nil {
   583  		return errors.Wrap(err, "failed to update role")
   584  	} else if rowsChanged != 1 {
   585  		return errors.New("found no role to update")
   586  	}
   587  
   588  	return nil
   589  }
   590  
   591  func UpgradeDatabaseToVersion58(sqlStore SqlStore) {
   592  	if shouldPerformUpgrade(sqlStore, VERSION_5_7_0, VERSION_5_8_0) {
   593  		// idx_channels_txt was removed in `UpgradeDatabaseToVersion50`, but merged as part of
   594  		// v5.1, so the migration wouldn't apply to anyone upgrading from v5.0. Remove it again to
   595  		// bring the upgraded (from v5.0) and fresh install schemas back in sync.
   596  		sqlStore.RemoveIndexIfExists("idx_channels_txt", "Channels")
   597  
   598  		// Fix column types and defaults where gorp converged on a different schema value than the
   599  		// original migration.
   600  		sqlStore.AlterColumnTypeIfExists("OutgoingWebhooks", "Description", "text", "VARCHAR(500)")
   601  		sqlStore.AlterColumnTypeIfExists("IncomingWebhooks", "Description", "text", "VARCHAR(500)")
   602  		sqlStore.AlterColumnTypeIfExists("OutgoingWebhooks", "IconURL", "text", "VARCHAR(1024)")
   603  		sqlStore.AlterColumnDefaultIfExists("OutgoingWebhooks", "Username", model.NewString("NULL"), model.NewString(""))
   604  		sqlStore.AlterColumnDefaultIfExists("OutgoingWebhooks", "IconURL", nil, model.NewString(""))
   605  		sqlStore.AlterColumnDefaultIfExists("PluginKeyValueStore", "ExpireAt", model.NewString("NULL"), model.NewString("NULL"))
   606  
   607  		saveSchemaVersion(sqlStore, VERSION_5_8_0)
   608  	}
   609  }
   610  
   611  func UpgradeDatabaseToVersion59(sqlStore SqlStore) {
   612  	if shouldPerformUpgrade(sqlStore, VERSION_5_8_0, VERSION_5_9_0) {
   613  		saveSchemaVersion(sqlStore, VERSION_5_9_0)
   614  	}
   615  }
   616  
   617  func UpgradeDatabaseToVersion510(sqlStore SqlStore) {
   618  	if shouldPerformUpgrade(sqlStore, VERSION_5_9_0, VERSION_5_10_0) {
   619  
   620  		// Grant new bot permissions to the system admin. Ideally we'd use the RoleStore directly,
   621  		// but it uses the new supplier model, which isn't initialized in the UpgradeDatabase code
   622  		// path. Also, the role won't exist for new servers, so don't fail on fetch, and don't
   623  		// bother inserting since it will be created with the new permissions anyway.
   624  		if role, err := getRole(sqlStore, model.SYSTEM_ADMIN_ROLE_ID); err != nil {
   625  			mlog.Warn("Failed to find role " + model.SYSTEM_ADMIN_ROLE_ID + " for upgrade: " + err.Error())
   626  		} else {
   627  			role.Permissions = append(role.Permissions, model.PERMISSION_CREATE_BOT.Id)
   628  			role.Permissions = append(role.Permissions, model.PERMISSION_READ_BOTS.Id)
   629  			role.Permissions = append(role.Permissions, model.PERMISSION_READ_OTHERS_BOTS.Id)
   630  			role.Permissions = append(role.Permissions, model.PERMISSION_MANAGE_BOTS.Id)
   631  			role.Permissions = append(role.Permissions, model.PERMISSION_MANAGE_OTHERS_BOTS.Id)
   632  
   633  			if err := saveRole(sqlStore, role); err != nil {
   634  				mlog.Critical(err.Error())
   635  				time.Sleep(time.Second)
   636  				os.Exit(EXIT_ROLE_MIGRATION_FAILED)
   637  			}
   638  		}
   639  
   640  		sqlStore.CreateColumnIfNotExistsNoDefault("Channels", "GroupConstrained", "tinyint(4)", "boolean")
   641  		sqlStore.CreateColumnIfNotExistsNoDefault("Teams", "GroupConstrained", "tinyint(4)", "boolean")
   642  
   643  		saveSchemaVersion(sqlStore, VERSION_5_10_0)
   644  	}
   645  }
   646  
   647  func UpgradeDatabaseToVersion511(sqlStore SqlStore) {
   648  	// TODO: Uncomment following condition when version 5.11.0 is released
   649  	// if shouldPerformUpgrade(sqlStore, VERSION_5_10_0, VERSION_5_11_0) {
   650  
   651  	// 	saveSchemaVersion(sqlStore, VERSION_5_11_0)
   652  	// }
   653  }