From 6331c9fda52eb5eead486fd79e51762b63fecf1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Espino?= Date: Mon, 28 May 2018 10:06:46 +0200 Subject: [PATCH] Create emojis migration --- api4/apitestlib.go | 1 + app/app.go | 123 ++++++++++++++--------------- app/app_test.go | 127 +++++++++++++++++++++++++++++- app/apptestlib.go | 13 +++ app/permissions.go | 1 + cmd/mattermost/commands/init.go | 1 + cmd/mattermost/commands/server.go | 1 + migrations/migrationstestlib.go | 1 + model/role.go | 2 - store/sqlstore/upgrade.go | 4 + web/web_test.go | 1 + 11 files changed, 207 insertions(+), 68 deletions(-) diff --git a/api4/apitestlib.go b/api4/apitestlib.go index 952c21df3b7..22084a1d639 100644 --- a/api4/apitestlib.go +++ b/api4/apitestlib.go @@ -125,6 +125,7 @@ func setupTestHelper(enterprise bool) *TestHelper { wsapi.Init(th.App, th.App.Srv.WebSocketRouter) th.App.Srv.Store.MarkSystemRanUnitTests() th.App.DoAdvancedPermissionsMigration() + th.App.DoEmojisPermissionsMigration() th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.EnableOpenServer = true }) diff --git a/app/app.go b/app/app.go index 012cb532636..2fbc5e307b9 100644 --- a/app/app.go +++ b/app/app.go @@ -30,6 +30,7 @@ import ( ) const ADVANCED_PERMISSIONS_MIGRATION_KEY = "AdvancedPermissionsMigrationComplete" +const EMOJIS_PERMISSIONS_MIGRATION_KEY = "EmojisPermissionsMigrationComplete" type App struct { goroutineCount int32 @@ -594,67 +595,61 @@ func (a *App) SetPhase2PermissionsMigrationStatus(isComplete bool) error { return nil } -// func (a *App) DoEmojisPermissionsMigration() { -// // If the migration is already marked as completed, don't do it again. -// if result := <-a.Srv.Store.System().GetByName(EMOJIS_PERMISSIONS_MIGRATION_KEY); result.Err == nil { -// return -// } -// -// mlog.Info("Migrating emojisto database.") -// if a.Config().ServiceSettings.RestrictCustomEmojiCreation == model.RESTRICT_EMOJI_CREATION_ALL { -// } -// if a.Config().ServiceSettings.RestrictCustomEmojiCreation == model.RESTRICT_EMOJI_CREATION_ALL { -// } -// roles := model.MakeDefaultRoles() -// roles = utils.SetRolePermiemojisssionsFromConfig(roles, a.Config(), a.License() != nil) -// -// allSucceeded := true -// -// for _, role := range roles { -// if result := <-a.Srv.Store.Role().Save(role); result.Err != nil { -// // If this failed for reasons other than the role already existing, don't mark the migration as done. -// if result2 := <-a.Srv.Store.Role().GetByName(role.Name); result2.Err != nil { -// mlog.Critical("Failed to migrate role to database.") -// mlog.Critical(fmt.Sprint(result.Err)) -// allSucceeded = false -// } else { -// // If the role already existed, check it is the same and update if not. -// fetchedRole := result.Data.(*model.Role) -// if !reflect.DeepEqual(fetchedRole.Permissions, role.Permissions) || -// fetchedRole.DisplayName != role.DisplayName || -// fetchedRole.Description != role.Description || -// fetchedRole.SchemeManaged != role.SchemeManaged { -// role.Id = fetchedRole.Id -// if result := <-a.Srv.Store.Role().Save(role); result.Err != nil { -// // Role is not the same, but failed to update. -// mlog.Critical("Failed to migrate role to database.") -// mlog.Critical(fmt.Sprint(result.Err)) -// allSucceeded = false -// } -// } -// } -// } -// } -// -// if !allSucceeded { -// return -// } -// -// config := a.Config() -// if *config.ServiceSettings.AllowEditPost == model.ALLOW_EDIT_POST_ALWAYS { -// *config.ServiceSettings.PostEditTimeLimit = -1 -// if err := a.SaveConfig(config, true); err != nil { -// mlog.Error("Failed to update config in Advanced Permissions Phase 1 Migration.", mlog.String("error", err.Error())) -// } -// } -// -// system := model.System{ -// Name: ADVANCED_PERMISSIONS_MIGRATION_KEY, -// Value: "true", -// } -// -// if result := <-a.Srv.Store.System().Save(&system); result.Err != nil { -// mlog.Critical("Failed to mark advanced permissions migration as completed.") -// mlog.Critical(fmt.Sprint(result.Err)) -// } -//} +func (a *App) DoEmojisPermissionsMigration() { + // If the migration is already marked as completed, don't do it again. + if result := <-a.Srv.Store.System().GetByName(EMOJIS_PERMISSIONS_MIGRATION_KEY); result.Err == nil { + return + } + + var role *model.Role = nil + var err *model.AppError = nil + + mlog.Info("Migrating emojis config to database.") + switch *a.Config().ServiceSettings.RestrictCustomEmojiCreation { + case model.RESTRICT_EMOJI_CREATION_ALL: + role, err = a.GetRoleByName(model.SYSTEM_USER_ROLE_ID) + if err != nil { + mlog.Critical("Failed to migrate emojis creation permissions from mattermost config.") + mlog.Critical(err.Error()) + return + } + break + case model.RESTRICT_EMOJI_CREATION_ADMIN: + role, err = a.GetRoleByName(model.TEAM_ADMIN_ROLE_ID) + if err != nil { + mlog.Critical("Failed to migrate emojis creation permissions from mattermost config.") + mlog.Critical(err.Error()) + return + } + break + case model.RESTRICT_EMOJI_CREATION_SYSTEM_ADMIN: + role, err = a.GetRoleByName(model.SYSTEM_ADMIN_ROLE_ID) + if err != nil { + mlog.Critical("Failed to migrate emojis creation permissions from mattermost config.") + mlog.Critical(err.Error()) + return + } + break + default: + mlog.Critical("Failed to migrate emojis creation permissions from mattermost config.") + mlog.Critical("Invalid restrict emoji creation setting") + return + } + + role.Permissions = append(role.Permissions, model.PERMISSION_MANAGE_EMOJIS.Id) + if result := <-a.Srv.Store.Role().Save(role); result.Err != nil { + mlog.Critical("Failed to migrate emojis creation permissions from mattermost config.") + mlog.Critical(result.Err.Error()) + return + } + + system := model.System{ + Name: EMOJIS_PERMISSIONS_MIGRATION_KEY, + Value: "true", + } + + if result := <-a.Srv.Store.System().Save(&system); result.Err != nil { + mlog.Critical("Failed to mark emojis permissions migration as completed.") + mlog.Critical(fmt.Sprint(result.Err)) + } +} diff --git a/app/app_test.go b/app/app_test.go index 7494fdf8506..38805cf6e63 100644 --- a/app/app_test.go +++ b/app/app_test.go @@ -169,7 +169,6 @@ func TestDoAdvancedPermissionsMigration(t *testing.T) { model.PERMISSION_CREATE_GROUP_CHANNEL.Id, model.PERMISSION_PERMANENT_DELETE_USER.Id, model.PERMISSION_CREATE_TEAM.Id, - model.PERMISSION_MANAGE_EMOJIS.Id, }, "system_post_all": []string{ model.PERMISSION_CREATE_POST.Id, @@ -335,7 +334,6 @@ func TestDoAdvancedPermissionsMigration(t *testing.T) { model.PERMISSION_CREATE_GROUP_CHANNEL.Id, model.PERMISSION_PERMANENT_DELETE_USER.Id, model.PERMISSION_CREATE_TEAM.Id, - model.PERMISSION_MANAGE_EMOJIS.Id, }, "system_post_all": []string{ model.PERMISSION_CREATE_POST.Id, @@ -457,3 +455,128 @@ func TestDoAdvancedPermissionsMigration(t *testing.T) { *config.ServiceSettings.PostEditTimeLimit = 300 th.App.SaveConfig(config, false) } + +func TestDoEmojisPermissionsMigration(t *testing.T) { + th := Setup() + defer th.TearDown() + + if testStoreSqlSupplier == nil { + t.Skip("This test requires a TestStore to be run.") + } + + // Add a license and change the policy config. + restrictCustomEmojiCreation := *th.App.Config().ServiceSettings.RestrictCustomEmojiCreation + + defer func() { + th.App.UpdateConfig(func(cfg *model.Config) { + *cfg.ServiceSettings.RestrictCustomEmojiCreation = restrictCustomEmojiCreation + }) + }() + + th.App.UpdateConfig(func(cfg *model.Config) { + *cfg.ServiceSettings.RestrictCustomEmojiCreation = model.RESTRICT_EMOJI_CREATION_SYSTEM_ADMIN + }) + + th.ResetEmojisMigration() + th.App.DoEmojisPermissionsMigration() + + role1, err1 := th.App.GetRoleByName(model.SYSTEM_ADMIN_ROLE_ID) + assert.Nil(t, err1) + expected1 := []string{ + model.PERMISSION_ASSIGN_SYSTEM_ADMIN_ROLE.Id, + model.PERMISSION_MANAGE_SYSTEM.Id, + model.PERMISSION_MANAGE_ROLES.Id, + model.PERMISSION_MANAGE_PUBLIC_CHANNEL_PROPERTIES.Id, + model.PERMISSION_MANAGE_PUBLIC_CHANNEL_MEMBERS.Id, + model.PERMISSION_MANAGE_PRIVATE_CHANNEL_MEMBERS.Id, + model.PERMISSION_DELETE_PUBLIC_CHANNEL.Id, + model.PERMISSION_CREATE_PUBLIC_CHANNEL.Id, + model.PERMISSION_MANAGE_PRIVATE_CHANNEL_PROPERTIES.Id, + model.PERMISSION_DELETE_PRIVATE_CHANNEL.Id, + model.PERMISSION_CREATE_PRIVATE_CHANNEL.Id, + model.PERMISSION_MANAGE_SYSTEM_WIDE_OAUTH.Id, + model.PERMISSION_MANAGE_OTHERS_WEBHOOKS.Id, + model.PERMISSION_EDIT_OTHER_USERS.Id, + model.PERMISSION_MANAGE_OAUTH.Id, + model.PERMISSION_INVITE_USER.Id, + model.PERMISSION_DELETE_POST.Id, + model.PERMISSION_DELETE_OTHERS_POSTS.Id, + model.PERMISSION_CREATE_TEAM.Id, + model.PERMISSION_ADD_USER_TO_TEAM.Id, + model.PERMISSION_LIST_USERS_WITHOUT_TEAM.Id, + model.PERMISSION_MANAGE_JOBS.Id, + model.PERMISSION_CREATE_POST_PUBLIC.Id, + model.PERMISSION_CREATE_POST_EPHEMERAL.Id, + model.PERMISSION_CREATE_USER_ACCESS_TOKEN.Id, + model.PERMISSION_READ_USER_ACCESS_TOKEN.Id, + model.PERMISSION_REVOKE_USER_ACCESS_TOKEN.Id, + model.PERMISSION_REMOVE_OTHERS_REACTIONS.Id, + model.PERMISSION_LIST_TEAM_CHANNELS.Id, + model.PERMISSION_JOIN_PUBLIC_CHANNELS.Id, + model.PERMISSION_READ_PUBLIC_CHANNEL.Id, + model.PERMISSION_VIEW_TEAM.Id, + model.PERMISSION_READ_CHANNEL.Id, + model.PERMISSION_ADD_REACTION.Id, + model.PERMISSION_REMOVE_REACTION.Id, + model.PERMISSION_UPLOAD_FILE.Id, + model.PERMISSION_GET_PUBLIC_LINK.Id, + model.PERMISSION_CREATE_POST.Id, + model.PERMISSION_USE_SLASH_COMMANDS.Id, + model.PERMISSION_EDIT_OTHERS_POSTS.Id, + model.PERMISSION_REMOVE_USER_FROM_TEAM.Id, + model.PERMISSION_MANAGE_TEAM.Id, + model.PERMISSION_IMPORT_TEAM.Id, + model.PERMISSION_MANAGE_TEAM_ROLES.Id, + model.PERMISSION_MANAGE_CHANNEL_ROLES.Id, + model.PERMISSION_MANAGE_SLASH_COMMANDS.Id, + model.PERMISSION_MANAGE_OTHERS_SLASH_COMMANDS.Id, + model.PERMISSION_MANAGE_WEBHOOKS.Id, + model.PERMISSION_EDIT_POST.Id, + model.PERMISSION_MANAGE_EMOJIS.Id, + } + assert.Equal(t, expected1, role1.Permissions, fmt.Sprintf("'%v' did not have expected permissions", model.SYSTEM_ADMIN_ROLE_ID)) + + th.App.UpdateConfig(func(cfg *model.Config) { + *cfg.ServiceSettings.RestrictCustomEmojiCreation = model.RESTRICT_EMOJI_CREATION_ADMIN + }) + + th.ResetEmojisMigration() + th.App.DoEmojisPermissionsMigration() + + role2, err2 := th.App.GetRoleByName(model.TEAM_ADMIN_ROLE_ID) + assert.Nil(t, err2) + expected2 := []string{ + model.PERMISSION_EDIT_OTHERS_POSTS.Id, + model.PERMISSION_REMOVE_USER_FROM_TEAM.Id, + model.PERMISSION_MANAGE_TEAM.Id, + model.PERMISSION_IMPORT_TEAM.Id, + model.PERMISSION_MANAGE_TEAM_ROLES.Id, + model.PERMISSION_MANAGE_CHANNEL_ROLES.Id, + model.PERMISSION_MANAGE_OTHERS_WEBHOOKS.Id, + model.PERMISSION_MANAGE_SLASH_COMMANDS.Id, + model.PERMISSION_MANAGE_OTHERS_SLASH_COMMANDS.Id, + model.PERMISSION_MANAGE_WEBHOOKS.Id, + model.PERMISSION_DELETE_POST.Id, + model.PERMISSION_DELETE_OTHERS_POSTS.Id, + model.PERMISSION_MANAGE_EMOJIS.Id, + } + assert.Equal(t, expected2, role2.Permissions, fmt.Sprintf("'%v' did not have expected permissions", model.TEAM_ADMIN_ROLE_ID)) + + th.App.UpdateConfig(func(cfg *model.Config) { + *cfg.ServiceSettings.RestrictCustomEmojiCreation = model.RESTRICT_EMOJI_CREATION_ALL + }) + + th.ResetEmojisMigration() + th.App.DoEmojisPermissionsMigration() + + role3, err3 := th.App.GetRoleByName(model.SYSTEM_USER_ROLE_ID) + assert.Nil(t, err3) + expected3 := []string{ + model.PERMISSION_CREATE_DIRECT_CHANNEL.Id, + model.PERMISSION_CREATE_GROUP_CHANNEL.Id, + model.PERMISSION_PERMANENT_DELETE_USER.Id, + model.PERMISSION_CREATE_TEAM.Id, + model.PERMISSION_MANAGE_EMOJIS.Id, + } + assert.Equal(t, expected3, role3.Permissions, fmt.Sprintf("'%v' did not have expected permissions", model.SYSTEM_USER_ROLE_ID)) +} diff --git a/app/apptestlib.go b/app/apptestlib.go index ec4992a753c..d4a79bdcc37 100644 --- a/app/apptestlib.go +++ b/app/apptestlib.go @@ -110,6 +110,7 @@ func setupTestHelper(enterprise bool) *TestHelper { th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.ListenAddress = prevListenAddress }) th.App.DoAdvancedPermissionsMigration() + th.App.DoEmojisPermissionsMigration() th.App.Srv.Store.MarkSystemRanUnitTests() @@ -433,6 +434,18 @@ func (me *TestHelper) ResetRoleMigration() { } } +func (me *TestHelper) ResetEmojisMigration() { + if _, err := testStoreSqlSupplier.GetMaster().Exec("UPDATE Roles SET Permissions=REPLACE(Permissions, ', manage_emojis', '') WHERE builtin=True"); err != nil { + panic(err) + } + + testClusterInterface.sendClearRoleCacheMessage() + + if _, err := testStoreSqlSupplier.GetMaster().Exec("DELETE from Systems where Name = :Name", map[string]interface{}{"Name": EMOJIS_PERMISSIONS_MIGRATION_KEY}); err != nil { + panic(err) + } +} + type FakeClusterInterface struct { clusterMessageHandler einterfaces.ClusterMessageHandler } diff --git a/app/permissions.go b/app/permissions.go index 70b8cc689be..46090070ef7 100644 --- a/app/permissions.go +++ b/app/permissions.go @@ -43,6 +43,7 @@ func (a *App) ResetPermissionsSystem() *model.AppError { // Now that the permissions system has been reset, re-run the migration to reinitialise it. a.DoAdvancedPermissionsMigration() + a.DoEmojisPermissionsMigration() return nil } diff --git a/cmd/mattermost/commands/init.go b/cmd/mattermost/commands/init.go index aea2b123070..ea7e8ec8409 100644 --- a/cmd/mattermost/commands/init.go +++ b/cmd/mattermost/commands/init.go @@ -23,6 +23,7 @@ func InitDBCommandContextCobra(command *cobra.Command) (*app.App, error) { } a.DoAdvancedPermissionsMigration() + a.DoEmojisPermissionsMigration() return a, nil } diff --git a/cmd/mattermost/commands/server.go b/cmd/mattermost/commands/server.go index 299005b6a0b..67e2f69c535 100644 --- a/cmd/mattermost/commands/server.go +++ b/cmd/mattermost/commands/server.go @@ -92,6 +92,7 @@ func runServer(configFileLocation string, disableConfigWatch bool, usedPlatform } a.DoAdvancedPermissionsMigration() + a.DoEmojisPermissionsMigration() a.InitPlugins(*a.Config().PluginSettings.Directory, *a.Config().PluginSettings.ClientDirectory, nil) a.AddConfigListener(func(prevCfg, cfg *model.Config) { diff --git a/migrations/migrationstestlib.go b/migrations/migrationstestlib.go index 1b9110425e2..b501291b044 100644 --- a/migrations/migrationstestlib.go +++ b/migrations/migrationstestlib.go @@ -111,6 +111,7 @@ func setupTestHelper(enterprise bool) *TestHelper { th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.ListenAddress = prevListenAddress }) th.App.DoAdvancedPermissionsMigration() + th.App.DoEmojisPermissionsMigration() th.App.Srv.Store.MarkSystemRanUnitTests() diff --git a/model/role.go b/model/role.go index 89f0e5f4d9b..80ae1ae34aa 100644 --- a/model/role.go +++ b/model/role.go @@ -266,7 +266,6 @@ func MakeDefaultRoles() map[string]*Role { PERMISSION_CREATE_DIRECT_CHANNEL.Id, PERMISSION_CREATE_GROUP_CHANNEL.Id, PERMISSION_PERMANENT_DELETE_USER.Id, - PERMISSION_MANAGE_EMOJIS.Id, }, SchemeManaged: true, BuiltIn: true, @@ -347,7 +346,6 @@ func MakeDefaultRoles() map[string]*Role { PERMISSION_READ_USER_ACCESS_TOKEN.Id, PERMISSION_REVOKE_USER_ACCESS_TOKEN.Id, PERMISSION_REMOVE_OTHERS_REACTIONS.Id, - PERMISSION_MANAGE_OTHERS_EMOJIS.Id, }, roles[TEAM_USER_ROLE_ID].Permissions..., ), diff --git a/store/sqlstore/upgrade.go b/store/sqlstore/upgrade.go index 93399d7d97d..98a89f36d68 100644 --- a/store/sqlstore/upgrade.go +++ b/store/sqlstore/upgrade.go @@ -425,6 +425,10 @@ func UpgradeDatabaseToVersion410(sqlStore SqlStore) { } func UpgradeDatabaseToVersion50(sqlStore SqlStore) { + // This version of Mattermost includes an App-Layer migration which migrates from hard-coded emojis configured + // in `config.json` to a `Permission` in the database. The migration code can be seen + // in the file `app/app.go` in the function `DoEmojisPermissionsMigration()`. + // TODO: Uncomment following condition when version 5.0.0 is released //if shouldPerformUpgrade(sqlStore, VERSION_4_10_0, VERSION_5_0_0) { diff --git a/web/web_test.go b/web/web_test.go index 9b6230013e8..b53ed96188e 100644 --- a/web/web_test.go +++ b/web/web_test.go @@ -61,6 +61,7 @@ func Setup() *TestHelper { ApiClient = model.NewAPIv4Client(URL) a.DoAdvancedPermissionsMigration() + a.DoEmojisPermissionsMigration() a.Srv.Store.MarkSystemRanUnitTests()