github.com/demisto/mattermost-server@v4.9.0-rc3+incompatible/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 "encoding/json" 8 "os" 9 "strings" 10 "time" 11 12 l4g "github.com/alecthomas/log4go" 13 14 "github.com/mattermost/mattermost-server/model" 15 "github.com/mattermost/mattermost-server/utils" 16 ) 17 18 const ( 19 VERSION_4_9_0 = "4.9.0" 20 VERSION_4_8_1 = "4.8.1" 21 VERSION_4_8_0 = "4.8.0" 22 VERSION_4_7_2 = "4.7.2" 23 VERSION_4_7_1 = "4.7.1" 24 VERSION_4_7_0 = "4.7.0" 25 VERSION_4_6_0 = "4.6.0" 26 VERSION_4_5_0 = "4.5.0" 27 VERSION_4_4_0 = "4.4.0" 28 VERSION_4_3_0 = "4.3.0" 29 VERSION_4_2_0 = "4.2.0" 30 VERSION_4_1_0 = "4.1.0" 31 VERSION_4_0_0 = "4.0.0" 32 VERSION_3_10_0 = "3.10.0" 33 VERSION_3_9_0 = "3.9.0" 34 VERSION_3_8_0 = "3.8.0" 35 VERSION_3_7_0 = "3.7.0" 36 VERSION_3_6_0 = "3.6.0" 37 VERSION_3_5_0 = "3.5.0" 38 VERSION_3_4_0 = "3.4.0" 39 VERSION_3_3_0 = "3.3.0" 40 VERSION_3_2_0 = "3.2.0" 41 VERSION_3_1_0 = "3.1.0" 42 VERSION_3_0_0 = "3.0.0" 43 OLDEST_SUPPORTED_VERSION = VERSION_3_0_0 44 ) 45 46 const ( 47 EXIT_VERSION_SAVE_MISSING = 1001 48 EXIT_TOO_OLD = 1002 49 EXIT_VERSION_SAVE = 1003 50 EXIT_THEME_MIGRATION = 1004 51 ) 52 53 func UpgradeDatabase(sqlStore SqlStore) { 54 55 UpgradeDatabaseToVersion31(sqlStore) 56 UpgradeDatabaseToVersion32(sqlStore) 57 UpgradeDatabaseToVersion33(sqlStore) 58 UpgradeDatabaseToVersion34(sqlStore) 59 UpgradeDatabaseToVersion35(sqlStore) 60 UpgradeDatabaseToVersion36(sqlStore) 61 UpgradeDatabaseToVersion37(sqlStore) 62 UpgradeDatabaseToVersion38(sqlStore) 63 UpgradeDatabaseToVersion39(sqlStore) 64 UpgradeDatabaseToVersion310(sqlStore) 65 UpgradeDatabaseToVersion40(sqlStore) 66 UpgradeDatabaseToVersion41(sqlStore) 67 UpgradeDatabaseToVersion42(sqlStore) 68 UpgradeDatabaseToVersion43(sqlStore) 69 UpgradeDatabaseToVersion44(sqlStore) 70 UpgradeDatabaseToVersion45(sqlStore) 71 UpgradeDatabaseToVersion46(sqlStore) 72 UpgradeDatabaseToVersion47(sqlStore) 73 UpgradeDatabaseToVersion471(sqlStore) 74 UpgradeDatabaseToVersion472(sqlStore) 75 UpgradeDatabaseToVersion48(sqlStore) 76 UpgradeDatabaseToVersion481(sqlStore) 77 UpgradeDatabaseToVersion49(sqlStore) 78 79 // If the SchemaVersion is empty this this is the first time it has ran 80 // so lets set it to the current version. 81 if sqlStore.GetCurrentSchemaVersion() == "" { 82 if result := <-sqlStore.System().SaveOrUpdate(&model.System{Name: "Version", Value: model.CurrentVersion}); result.Err != nil { 83 l4g.Critical(result.Err.Error()) 84 time.Sleep(time.Second) 85 os.Exit(EXIT_VERSION_SAVE_MISSING) 86 } 87 88 l4g.Info(utils.T("store.sql.schema_set.info"), model.CurrentVersion) 89 } 90 91 // If we're not on the current version then it's too old to be upgraded 92 if sqlStore.GetCurrentSchemaVersion() != model.CurrentVersion { 93 l4g.Critical(utils.T("store.sql.schema_version.critical"), sqlStore.GetCurrentSchemaVersion(), OLDEST_SUPPORTED_VERSION, model.CurrentVersion, OLDEST_SUPPORTED_VERSION) 94 time.Sleep(time.Second) 95 os.Exit(EXIT_TOO_OLD) 96 } 97 } 98 99 func saveSchemaVersion(sqlStore SqlStore, version string) { 100 if result := <-sqlStore.System().Update(&model.System{Name: "Version", Value: version}); result.Err != nil { 101 l4g.Critical(result.Err.Error()) 102 time.Sleep(time.Second) 103 os.Exit(EXIT_VERSION_SAVE) 104 } 105 106 l4g.Warn(utils.T("store.sql.upgraded.warn"), version) 107 } 108 109 func shouldPerformUpgrade(sqlStore SqlStore, currentSchemaVersion string, expectedSchemaVersion string) bool { 110 if sqlStore.GetCurrentSchemaVersion() == currentSchemaVersion { 111 l4g.Warn(utils.T("store.sql.schema_out_of_date.warn"), currentSchemaVersion) 112 l4g.Warn(utils.T("store.sql.schema_upgrade_attempt.warn"), expectedSchemaVersion) 113 114 return true 115 } 116 117 return false 118 } 119 120 func UpgradeDatabaseToVersion31(sqlStore SqlStore) { 121 if shouldPerformUpgrade(sqlStore, VERSION_3_0_0, VERSION_3_1_0) { 122 sqlStore.CreateColumnIfNotExists("OutgoingWebhooks", "ContentType", "varchar(128)", "varchar(128)", "") 123 saveSchemaVersion(sqlStore, VERSION_3_1_0) 124 } 125 } 126 127 func UpgradeDatabaseToVersion32(sqlStore SqlStore) { 128 if shouldPerformUpgrade(sqlStore, VERSION_3_1_0, VERSION_3_2_0) { 129 sqlStore.CreateColumnIfNotExists("TeamMembers", "DeleteAt", "bigint(20)", "bigint", "0") 130 131 saveSchemaVersion(sqlStore, VERSION_3_2_0) 132 } 133 } 134 135 func themeMigrationFailed(err error) { 136 l4g.Critical(utils.T("store.sql_user.migrate_theme.critical"), err) 137 time.Sleep(time.Second) 138 os.Exit(EXIT_THEME_MIGRATION) 139 } 140 141 func UpgradeDatabaseToVersion33(sqlStore SqlStore) { 142 if shouldPerformUpgrade(sqlStore, VERSION_3_2_0, VERSION_3_3_0) { 143 if sqlStore.DoesColumnExist("Users", "ThemeProps") { 144 params := map[string]interface{}{ 145 "Category": model.PREFERENCE_CATEGORY_THEME, 146 "Name": "", 147 } 148 149 transaction, err := sqlStore.GetMaster().Begin() 150 if err != nil { 151 themeMigrationFailed(err) 152 } 153 154 // increase size of Value column of Preferences table to match the size of the ThemeProps column 155 if sqlStore.DriverName() == model.DATABASE_DRIVER_POSTGRES { 156 if _, err := transaction.Exec("ALTER TABLE Preferences ALTER COLUMN Value TYPE varchar(2000)"); err != nil { 157 themeMigrationFailed(err) 158 } 159 } else if sqlStore.DriverName() == model.DATABASE_DRIVER_MYSQL { 160 if _, err := transaction.Exec("ALTER TABLE Preferences MODIFY Value text"); err != nil { 161 themeMigrationFailed(err) 162 } 163 } 164 165 // copy data across 166 if _, err := transaction.Exec( 167 `INSERT INTO 168 Preferences(UserId, Category, Name, Value) 169 SELECT 170 Id, '`+model.PREFERENCE_CATEGORY_THEME+`', '', ThemeProps 171 FROM 172 Users 173 WHERE 174 Users.ThemeProps != 'null'`, params); err != nil { 175 themeMigrationFailed(err) 176 } 177 178 // delete old data 179 if _, err := transaction.Exec("ALTER TABLE Users DROP COLUMN ThemeProps"); err != nil { 180 themeMigrationFailed(err) 181 } 182 183 if err := transaction.Commit(); err != nil { 184 themeMigrationFailed(err) 185 } 186 187 // rename solarized_* code themes to solarized-* to match client changes in 3.0 188 var data model.Preferences 189 if _, err := sqlStore.GetMaster().Select(&data, "SELECT * FROM Preferences WHERE Category = '"+model.PREFERENCE_CATEGORY_THEME+"' AND Value LIKE '%solarized_%'"); err == nil { 190 for i := range data { 191 data[i].Value = strings.Replace(data[i].Value, "solarized_", "solarized-", -1) 192 } 193 194 sqlStore.Preference().Save(&data) 195 } 196 } 197 198 sqlStore.CreateColumnIfNotExists("OAuthApps", "IsTrusted", "tinyint(1)", "boolean", "0") 199 sqlStore.CreateColumnIfNotExists("OAuthApps", "IconURL", "varchar(512)", "varchar(512)", "") 200 sqlStore.CreateColumnIfNotExists("OAuthAccessData", "ClientId", "varchar(26)", "varchar(26)", "") 201 sqlStore.CreateColumnIfNotExists("OAuthAccessData", "UserId", "varchar(26)", "varchar(26)", "") 202 sqlStore.CreateColumnIfNotExists("OAuthAccessData", "ExpiresAt", "bigint", "bigint", "0") 203 204 if sqlStore.DoesColumnExist("OAuthAccessData", "AuthCode") { 205 sqlStore.RemoveIndexIfExists("idx_oauthaccessdata_auth_code", "OAuthAccessData") 206 sqlStore.RemoveColumnIfExists("OAuthAccessData", "AuthCode") 207 } 208 209 sqlStore.RemoveColumnIfExists("Users", "LastActivityAt") 210 sqlStore.RemoveColumnIfExists("Users", "LastPingAt") 211 212 sqlStore.CreateColumnIfNotExists("OutgoingWebhooks", "TriggerWhen", "tinyint", "integer", "0") 213 214 saveSchemaVersion(sqlStore, VERSION_3_3_0) 215 } 216 } 217 218 func UpgradeDatabaseToVersion34(sqlStore SqlStore) { 219 if shouldPerformUpgrade(sqlStore, VERSION_3_3_0, VERSION_3_4_0) { 220 sqlStore.CreateColumnIfNotExists("Status", "Manual", "BOOLEAN", "BOOLEAN", "0") 221 sqlStore.CreateColumnIfNotExists("Status", "ActiveChannel", "varchar(26)", "varchar(26)", "") 222 223 saveSchemaVersion(sqlStore, VERSION_3_4_0) 224 } 225 } 226 227 func UpgradeDatabaseToVersion35(sqlStore SqlStore) { 228 if shouldPerformUpgrade(sqlStore, VERSION_3_4_0, VERSION_3_5_0) { 229 sqlStore.GetMaster().Exec("UPDATE Users SET Roles = 'system_user' WHERE Roles = ''") 230 sqlStore.GetMaster().Exec("UPDATE Users SET Roles = 'system_user system_admin' WHERE Roles = 'system_admin'") 231 sqlStore.GetMaster().Exec("UPDATE TeamMembers SET Roles = 'team_user' WHERE Roles = ''") 232 sqlStore.GetMaster().Exec("UPDATE TeamMembers SET Roles = 'team_user team_admin' WHERE Roles = 'admin'") 233 sqlStore.GetMaster().Exec("UPDATE ChannelMembers SET Roles = 'channel_user' WHERE Roles = ''") 234 sqlStore.GetMaster().Exec("UPDATE ChannelMembers SET Roles = 'channel_user channel_admin' WHERE Roles = 'admin'") 235 236 // The rest of the migration from Filenames -> FileIds is done lazily in api.GetFileInfosForPost 237 sqlStore.CreateColumnIfNotExists("Posts", "FileIds", "varchar(150)", "varchar(150)", "[]") 238 239 // Increase maximum length of the Channel table Purpose column. 240 if sqlStore.GetMaxLengthOfColumnIfExists("Channels", "Purpose") != "250" { 241 sqlStore.AlterColumnTypeIfExists("Channels", "Purpose", "varchar(250)", "varchar(250)") 242 } 243 244 sqlStore.Session().RemoveAllSessions() 245 246 saveSchemaVersion(sqlStore, VERSION_3_5_0) 247 } 248 } 249 250 func UpgradeDatabaseToVersion36(sqlStore SqlStore) { 251 if shouldPerformUpgrade(sqlStore, VERSION_3_5_0, VERSION_3_6_0) { 252 sqlStore.CreateColumnIfNotExists("Posts", "HasReactions", "tinyint", "boolean", "0") 253 254 // Create Team Description column 255 sqlStore.CreateColumnIfNotExists("Teams", "Description", "varchar(255)", "varchar(255)", "") 256 257 // Add a Position column to users. 258 sqlStore.CreateColumnIfNotExists("Users", "Position", "varchar(64)", "varchar(64)", "") 259 260 // Remove ActiveChannel column from Status 261 sqlStore.RemoveColumnIfExists("Status", "ActiveChannel") 262 263 saveSchemaVersion(sqlStore, VERSION_3_6_0) 264 } 265 } 266 267 func UpgradeDatabaseToVersion37(sqlStore SqlStore) { 268 if shouldPerformUpgrade(sqlStore, VERSION_3_6_0, VERSION_3_7_0) { 269 // Add EditAt column to Posts 270 sqlStore.CreateColumnIfNotExists("Posts", "EditAt", " bigint", " bigint", "0") 271 272 saveSchemaVersion(sqlStore, VERSION_3_7_0) 273 } 274 } 275 276 func UpgradeDatabaseToVersion38(sqlStore SqlStore) { 277 if shouldPerformUpgrade(sqlStore, VERSION_3_7_0, VERSION_3_8_0) { 278 // Add the IsPinned column to posts. 279 sqlStore.CreateColumnIfNotExists("Posts", "IsPinned", "boolean", "boolean", "0") 280 281 saveSchemaVersion(sqlStore, VERSION_3_8_0) 282 } 283 } 284 285 func UpgradeDatabaseToVersion39(sqlStore SqlStore) { 286 if shouldPerformUpgrade(sqlStore, VERSION_3_8_0, VERSION_3_9_0) { 287 sqlStore.CreateColumnIfNotExists("OAuthAccessData", "Scope", "varchar(128)", "varchar(128)", model.DEFAULT_SCOPE) 288 sqlStore.RemoveTableIfExists("PasswordRecovery") 289 290 saveSchemaVersion(sqlStore, VERSION_3_9_0) 291 } 292 } 293 294 func UpgradeDatabaseToVersion310(sqlStore SqlStore) { 295 if shouldPerformUpgrade(sqlStore, VERSION_3_9_0, VERSION_3_10_0) { 296 saveSchemaVersion(sqlStore, VERSION_3_10_0) 297 } 298 } 299 300 func UpgradeDatabaseToVersion40(sqlStore SqlStore) { 301 if shouldPerformUpgrade(sqlStore, VERSION_3_10_0, VERSION_4_0_0) { 302 saveSchemaVersion(sqlStore, VERSION_4_0_0) 303 } 304 } 305 306 func UpgradeDatabaseToVersion41(sqlStore SqlStore) { 307 if shouldPerformUpgrade(sqlStore, VERSION_4_0_0, VERSION_4_1_0) { 308 // Increase maximum length of the Users table Roles column. 309 if sqlStore.GetMaxLengthOfColumnIfExists("Users", "Roles") != "256" { 310 sqlStore.AlterColumnTypeIfExists("Users", "Roles", "varchar(256)", "varchar(256)") 311 } 312 313 sqlStore.RemoveTableIfExists("JobStatuses") 314 315 saveSchemaVersion(sqlStore, VERSION_4_1_0) 316 } 317 } 318 319 func UpgradeDatabaseToVersion42(sqlStore SqlStore) { 320 if shouldPerformUpgrade(sqlStore, VERSION_4_1_0, VERSION_4_2_0) { 321 saveSchemaVersion(sqlStore, VERSION_4_2_0) 322 } 323 } 324 325 func UpgradeDatabaseToVersion43(sqlStore SqlStore) { 326 if shouldPerformUpgrade(sqlStore, VERSION_4_2_0, VERSION_4_3_0) { 327 saveSchemaVersion(sqlStore, VERSION_4_3_0) 328 } 329 } 330 331 func UpgradeDatabaseToVersion44(sqlStore SqlStore) { 332 if shouldPerformUpgrade(sqlStore, VERSION_4_3_0, VERSION_4_4_0) { 333 // Add the IsActive column to UserAccessToken. 334 sqlStore.CreateColumnIfNotExists("UserAccessTokens", "IsActive", "boolean", "boolean", "1") 335 336 saveSchemaVersion(sqlStore, VERSION_4_4_0) 337 } 338 } 339 340 func UpgradeDatabaseToVersion45(sqlStore SqlStore) { 341 if shouldPerformUpgrade(sqlStore, VERSION_4_4_0, VERSION_4_5_0) { 342 saveSchemaVersion(sqlStore, VERSION_4_5_0) 343 } 344 } 345 346 func UpgradeDatabaseToVersion46(sqlStore SqlStore) { 347 if shouldPerformUpgrade(sqlStore, VERSION_4_5_0, VERSION_4_6_0) { 348 sqlStore.CreateColumnIfNotExists("IncomingWebhooks", "Username", "varchar(64)", "varchar(64)", "") 349 sqlStore.CreateColumnIfNotExists("IncomingWebhooks", "IconURL", "varchar(1024)", "varchar(1024)", "") 350 saveSchemaVersion(sqlStore, VERSION_4_6_0) 351 } 352 } 353 354 func UpgradeDatabaseToVersion47(sqlStore SqlStore) { 355 if shouldPerformUpgrade(sqlStore, VERSION_4_6_0, VERSION_4_7_0) { 356 sqlStore.AlterColumnTypeIfExists("Users", "Position", "varchar(128)", "varchar(128)") 357 sqlStore.AlterColumnTypeIfExists("OAuthAuthData", "State", "varchar(1024)", "varchar(1024)") 358 sqlStore.RemoveColumnIfExists("ChannelMemberHistory", "Email") 359 sqlStore.RemoveColumnIfExists("ChannelMemberHistory", "Username") 360 saveSchemaVersion(sqlStore, VERSION_4_7_0) 361 } 362 } 363 364 // If any new instances started with 4.7, they would have the bad Email column on the 365 // ChannelMemberHistory table. So for those cases we need to do an upgrade between 366 // 4.7.0 and 4.7.1 367 func UpgradeDatabaseToVersion471(sqlStore SqlStore) { 368 if shouldPerformUpgrade(sqlStore, VERSION_4_7_0, VERSION_4_7_1) { 369 sqlStore.RemoveColumnIfExists("ChannelMemberHistory", "Email") 370 saveSchemaVersion(sqlStore, VERSION_4_7_1) 371 } 372 } 373 374 func UpgradeDatabaseToVersion472(sqlStore SqlStore) { 375 if shouldPerformUpgrade(sqlStore, VERSION_4_7_1, VERSION_4_7_2) { 376 sqlStore.RemoveIndexIfExists("idx_channels_displayname", "Channels") 377 saveSchemaVersion(sqlStore, VERSION_4_7_2) 378 } 379 } 380 381 func UpgradeDatabaseToVersion48(sqlStore SqlStore) { 382 if shouldPerformUpgrade(sqlStore, VERSION_4_7_2, VERSION_4_8_0) { 383 saveSchemaVersion(sqlStore, VERSION_4_8_0) 384 } 385 } 386 387 func UpgradeDatabaseToVersion481(sqlStore SqlStore) { 388 if shouldPerformUpgrade(sqlStore, VERSION_4_8_0, VERSION_4_8_1) { 389 sqlStore.RemoveIndexIfExists("idx_channels_displayname", "Channels") 390 saveSchemaVersion(sqlStore, VERSION_4_8_1) 391 } 392 } 393 394 func UpgradeDatabaseToVersion49(sqlStore SqlStore) { 395 // This version of Mattermost includes an App-Layer migration which migrates from hard-coded roles configured by 396 // a number of parameters in `config.json` to a `Roles` table in the database. The migration code can be seen 397 // in the file `app/app.go` in the function `DoAdvancedPermissionsMigration()`. 398 399 if shouldPerformUpgrade(sqlStore, VERSION_4_8_1, VERSION_4_9_0) { 400 sqlStore.CreateColumnIfNotExists("Teams", "LastTeamIconUpdate", "bigint", "bigint", "0") 401 defaultTimezone := model.DefaultUserTimezone() 402 defaultTimezoneValue, err := json.Marshal(defaultTimezone) 403 if err != nil { 404 l4g.Critical(err) 405 } 406 sqlStore.CreateColumnIfNotExists("Users", "Timezone", "varchar(256)", "varchar(256)", string(defaultTimezoneValue)) 407 sqlStore.RemoveIndexIfExists("idx_channels_displayname", "Channels") 408 saveSchemaVersion(sqlStore, VERSION_4_9_0) 409 } 410 }