summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesús Espino <jespinog@gmail.com>2018-05-29 16:58:12 +0200
committerGeorge Goldberg <george@gberg.me>2018-05-29 15:58:12 +0100
commite88fe4bb1dea4918284ee3c6e5aee5a8497ff2b8 (patch)
tree480a5b91b37e2728ea151e3b7ad521aaf4402697
parentbf4cefc3496686850757b2d44219ea2425871dda (diff)
downloadchat-e88fe4bb1dea4918284ee3c6e5aee5a8497ff2b8.tar.gz
chat-e88fe4bb1dea4918284ee3c6e5aee5a8497ff2b8.tar.bz2
chat-e88fe4bb1dea4918284ee3c6e5aee5a8497ff2b8.zip
MM-8853: Adding MANAGE_EMOJIS and MANAGE_OTHERS_EMOJIS permissions (#8860)
* MM-8853: Adding MANAGE_EMOJIS and MANAGE_OTHERS_EMOJIS permissions * MM-8853: Removing unnecesary emoji enterprise feature * Create emojis migration * Adding MANAGE_EMOJIS and MANAGE_OTHERS_EMOJIS always to system admins * Simplifing permissions checks * Revert "Simplifing permissions checks" This reverts commit e2cafc1905fc9e20125dd9a1552d2d0c7340ae59.
-rw-r--r--api4/apitestlib.go1
-rw-r--r--api4/emoji.go66
-rw-r--r--api4/emoji_test.go124
-rw-r--r--api4/role.go1
-rw-r--r--app/app.go83
-rw-r--r--app/app_test.go135
-rw-r--r--app/apptestlib.go13
-rw-r--r--app/permissions.go1
-rw-r--r--cmd/mattermost/commands/init.go1
-rw-r--r--cmd/mattermost/commands/server.go1
-rw-r--r--einterfaces/emoji.go12
-rw-r--r--i18n/en.json4
-rw-r--r--migrations/migrationstestlib.go1
-rw-r--r--model/permission.go16
-rw-r--r--store/sqlstore/upgrade.go4
-rw-r--r--web/web_test.go1
16 files changed, 427 insertions, 37 deletions
diff --git a/api4/apitestlib.go b/api4/apitestlib.go
index 952c21df3..22084a1d6 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/api4/emoji.go b/api4/emoji.go
index cfb5dd6ab..42f66a22a 100644
--- a/api4/emoji.go
+++ b/api4/emoji.go
@@ -33,12 +33,6 @@ func createEmoji(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if emojiInterface := c.App.Emoji; emojiInterface != nil &&
- !emojiInterface.CanUserCreateEmoji(c.Session.Roles, c.Session.TeamMembers) {
- c.Err = model.NewAppError("getEmoji", "api.emoji.disabled.app_error", nil, "user_id="+c.Session.UserId, http.StatusUnauthorized)
- return
- }
-
if len(*c.App.Config().FileSettings.DriverName) == 0 {
c.Err = model.NewAppError("createEmoji", "api.emoji.storage.app_error", nil, "", http.StatusNotImplemented)
return
@@ -54,6 +48,28 @@ func createEmoji(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
+ // Allow any user with MANAGE_EMOJIS permission at Team level to manage emojis at system level
+ memberships, err := c.App.GetTeamMembersForUser(c.Session.UserId)
+
+ if err != nil {
+ c.Err = err
+ return
+ }
+
+ if !c.App.SessionHasPermissionTo(c.Session, model.PERMISSION_MANAGE_EMOJIS) {
+ hasPermission := false
+ for _, membership := range memberships {
+ if c.App.SessionHasPermissionToTeam(c.Session, membership.TeamId, model.PERMISSION_MANAGE_EMOJIS) {
+ hasPermission = true
+ break
+ }
+ }
+ if !hasPermission {
+ c.SetPermissionError(model.PERMISSION_MANAGE_EMOJIS)
+ return
+ }
+ }
+
m := r.MultipartForm
props := m.Value
@@ -110,11 +126,45 @@ func deleteEmoji(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if c.Session.UserId != emoji.CreatorId && !c.App.SessionHasPermissionTo(c.Session, model.PERMISSION_MANAGE_SYSTEM) {
- c.Err = model.NewAppError("deleteImage", "api.emoji.delete.permissions.app_error", nil, "user_id="+c.Session.UserId, http.StatusUnauthorized)
+ // Allow any user with MANAGE_EMOJIS permission at Team level to manage emojis at system level
+ memberships, err := c.App.GetTeamMembersForUser(c.Session.UserId)
+
+ if err != nil {
+ c.Err = err
return
}
+ if !c.App.SessionHasPermissionTo(c.Session, model.PERMISSION_MANAGE_EMOJIS) {
+ hasPermission := false
+ for _, membership := range memberships {
+ if c.App.SessionHasPermissionToTeam(c.Session, membership.TeamId, model.PERMISSION_MANAGE_EMOJIS) {
+ hasPermission = true
+ break
+ }
+ }
+ if !hasPermission {
+ c.SetPermissionError(model.PERMISSION_MANAGE_EMOJIS)
+ return
+ }
+ }
+
+ if c.Session.UserId != emoji.CreatorId {
+ if !c.App.SessionHasPermissionTo(c.Session, model.PERMISSION_MANAGE_OTHERS_EMOJIS) {
+ hasPermission := false
+ for _, membership := range memberships {
+ if c.App.SessionHasPermissionToTeam(c.Session, membership.TeamId, model.PERMISSION_MANAGE_OTHERS_EMOJIS) {
+ hasPermission = true
+ break
+ }
+ }
+
+ if !hasPermission {
+ c.SetPermissionError(model.PERMISSION_MANAGE_OTHERS_EMOJIS)
+ return
+ }
+ }
+ }
+
err = c.App.DeleteEmoji(emoji)
if err != nil {
c.Err = err
diff --git a/api4/emoji_test.go b/api4/emoji_test.go
index 39da4aaef..cb6398312 100644
--- a/api4/emoji_test.go
+++ b/api4/emoji_test.go
@@ -26,6 +26,11 @@ func TestCreateEmoji(t *testing.T) {
}()
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCustomEmoji = false })
+ defaultRolePermissions := th.SaveDefaultRolePermissions()
+ defer func() {
+ th.RestoreDefaultRolePermissions(defaultRolePermissions)
+ }()
+
emoji := &model.Emoji{
CreatorId: th.BasicUser.Id,
Name: model.NewId(),
@@ -141,6 +146,28 @@ func TestCreateEmoji(t *testing.T) {
_, resp = Client.CreateEmoji(emoji, utils.CreateTestGif(t, 10, 10), "image.gif")
CheckForbiddenStatus(t, resp)
+
+ // try to create an emoji without permissions
+ th.RemovePermissionFromRole(model.PERMISSION_MANAGE_EMOJIS.Id, model.SYSTEM_USER_ROLE_ID)
+
+ emoji = &model.Emoji{
+ CreatorId: th.BasicUser.Id,
+ Name: model.NewId(),
+ }
+
+ _, resp = Client.CreateEmoji(emoji, utils.CreateTestGif(t, 10, 10), "image.gif")
+ CheckForbiddenStatus(t, resp)
+
+ // create an emoji with permissions in one team
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_EMOJIS.Id, model.TEAM_USER_ROLE_ID)
+
+ emoji = &model.Emoji{
+ CreatorId: th.BasicUser.Id,
+ Name: model.NewId(),
+ }
+
+ _, resp = Client.CreateEmoji(emoji, utils.CreateTestGif(t, 10, 10), "image.gif")
+ CheckNoError(t, resp)
}
func TestGetEmojiList(t *testing.T) {
@@ -186,7 +213,7 @@ func TestGetEmojiList(t *testing.T) {
}
}
if !found {
- t.Fatalf("failed to get emoji with id %v", emoji.Id)
+ t.Fatalf("failed to get emoji with id %v, %v", emoji.Id, len(listEmoji))
}
}
@@ -231,6 +258,11 @@ func TestDeleteEmoji(t *testing.T) {
}()
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCustomEmoji = true })
+ defaultRolePermissions := th.SaveDefaultRolePermissions()
+ defer func() {
+ th.RestoreDefaultRolePermissions(defaultRolePermissions)
+ }()
+
emoji := &model.Emoji{
CreatorId: th.BasicUser.Id,
Name: model.NewId(),
@@ -277,14 +309,100 @@ func TestDeleteEmoji(t *testing.T) {
_, resp = Client.DeleteEmoji("")
CheckNotFoundStatus(t, resp)
- //Try to delete other user's custom emoji
+ //Try to delete my custom emoji without permissions
+ newEmoji, resp = Client.CreateEmoji(emoji, utils.CreateTestGif(t, 10, 10), "image.gif")
+ CheckNoError(t, resp)
+
+ th.RemovePermissionFromRole(model.PERMISSION_MANAGE_EMOJIS.Id, model.SYSTEM_USER_ROLE_ID)
+ _, resp = Client.DeleteEmoji(newEmoji.Id)
+ CheckForbiddenStatus(t, resp)
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_EMOJIS.Id, model.SYSTEM_USER_ROLE_ID)
+
+ //Try to delete other user's custom emoji without MANAGE_EMOJIS permissions
+ emoji = &model.Emoji{
+ CreatorId: th.BasicUser.Id,
+ Name: model.NewId(),
+ }
+
newEmoji, resp = Client.CreateEmoji(emoji, utils.CreateTestGif(t, 10, 10), "image.gif")
CheckNoError(t, resp)
+ th.RemovePermissionFromRole(model.PERMISSION_MANAGE_EMOJIS.Id, model.SYSTEM_USER_ROLE_ID)
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_OTHERS_EMOJIS.Id, model.SYSTEM_USER_ROLE_ID)
Client.Logout()
th.LoginBasic2()
ok, resp = Client.DeleteEmoji(newEmoji.Id)
- CheckUnauthorizedStatus(t, resp)
+ CheckForbiddenStatus(t, resp)
+ th.RemovePermissionFromRole(model.PERMISSION_MANAGE_OTHERS_EMOJIS.Id, model.SYSTEM_USER_ROLE_ID)
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_EMOJIS.Id, model.SYSTEM_USER_ROLE_ID)
+ Client.Logout()
+ th.LoginBasic()
+
+ //Try to delete other user's custom emoji without MANAGE_OTHERS_EMOJIS permissions
+ emoji = &model.Emoji{
+ CreatorId: th.BasicUser.Id,
+ Name: model.NewId(),
+ }
+
+ newEmoji, resp = Client.CreateEmoji(emoji, utils.CreateTestGif(t, 10, 10), "image.gif")
+ CheckNoError(t, resp)
+
+ Client.Logout()
+ th.LoginBasic2()
+ ok, resp = Client.DeleteEmoji(newEmoji.Id)
+ CheckForbiddenStatus(t, resp)
+ Client.Logout()
+ th.LoginBasic()
+
+ //Try to delete other user's custom emoji with permissions
+ emoji = &model.Emoji{
+ CreatorId: th.BasicUser.Id,
+ Name: model.NewId(),
+ }
+
+ newEmoji, resp = Client.CreateEmoji(emoji, utils.CreateTestGif(t, 10, 10), "image.gif")
+ CheckNoError(t, resp)
+
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_EMOJIS.Id, model.SYSTEM_USER_ROLE_ID)
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_OTHERS_EMOJIS.Id, model.SYSTEM_USER_ROLE_ID)
+ Client.Logout()
+ th.LoginBasic2()
+ ok, resp = Client.DeleteEmoji(newEmoji.Id)
+ CheckNoError(t, resp)
+
+ Client.Logout()
+ th.LoginBasic()
+
+ //Try to delete my custom emoji with permissions at team level
+ newEmoji, resp = Client.CreateEmoji(emoji, utils.CreateTestGif(t, 10, 10), "image.gif")
+ CheckNoError(t, resp)
+
+ th.RemovePermissionFromRole(model.PERMISSION_MANAGE_EMOJIS.Id, model.SYSTEM_USER_ROLE_ID)
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_EMOJIS.Id, model.TEAM_USER_ROLE_ID)
+ _, resp = Client.DeleteEmoji(newEmoji.Id)
+ CheckNoError(t, resp)
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_EMOJIS.Id, model.SYSTEM_USER_ROLE_ID)
+ th.RemovePermissionFromRole(model.PERMISSION_MANAGE_EMOJIS.Id, model.TEAM_USER_ROLE_ID)
+
+ //Try to delete other user's custom emoji with permissions at team level
+ emoji = &model.Emoji{
+ CreatorId: th.BasicUser.Id,
+ Name: model.NewId(),
+ }
+
+ newEmoji, resp = Client.CreateEmoji(emoji, utils.CreateTestGif(t, 10, 10), "image.gif")
+ CheckNoError(t, resp)
+
+ th.RemovePermissionFromRole(model.PERMISSION_MANAGE_EMOJIS.Id, model.SYSTEM_USER_ROLE_ID)
+ th.RemovePermissionFromRole(model.PERMISSION_MANAGE_OTHERS_EMOJIS.Id, model.SYSTEM_USER_ROLE_ID)
+
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_EMOJIS.Id, model.TEAM_USER_ROLE_ID)
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_OTHERS_EMOJIS.Id, model.TEAM_USER_ROLE_ID)
+
+ Client.Logout()
+ th.LoginBasic2()
+ ok, resp = Client.DeleteEmoji(newEmoji.Id)
+ CheckNoError(t, resp)
}
func TestGetEmoji(t *testing.T) {
diff --git a/api4/role.go b/api4/role.go
index c4203137b..2c0465891 100644
--- a/api4/role.go
+++ b/api4/role.go
@@ -100,6 +100,7 @@ func patchRole(c *Context, w http.ResponseWriter, r *http.Request) {
model.PERMISSION_MANAGE_SLASH_COMMANDS.Id,
model.PERMISSION_MANAGE_OAUTH.Id,
model.PERMISSION_MANAGE_SYSTEM_WIDE_OAUTH.Id,
+ model.PERMISSION_MANAGE_EMOJIS.Id,
}
changedPermissions := model.PermissionsChangedByPatch(oldRole, patch)
diff --git a/app/app.go b/app/app.go
index e5a496c6b..bda56ca1a 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
@@ -57,7 +58,6 @@ type App struct {
Compliance einterfaces.ComplianceInterface
DataRetention einterfaces.DataRetentionInterface
Elasticsearch einterfaces.ElasticsearchInterface
- Emoji einterfaces.EmojiInterface
Ldap einterfaces.LdapInterface
MessageExport einterfaces.MessageExportInterface
Metrics einterfaces.MetricsInterface
@@ -288,12 +288,6 @@ func RegisterElasticsearchInterface(f func(*App) einterfaces.ElasticsearchInterf
elasticsearchInterface = f
}
-var emojiInterface func(*App) einterfaces.EmojiInterface
-
-func RegisterEmojiInterface(f func(*App) einterfaces.EmojiInterface) {
- emojiInterface = f
-}
-
var jobsDataRetentionJobInterface func(*App) ejobs.DataRetentionJobInterface
func RegisterJobsDataRetentionJobInterface(f func(*App) ejobs.DataRetentionJobInterface) {
@@ -376,9 +370,6 @@ func (a *App) initEnterprise() {
if elasticsearchInterface != nil {
a.Elasticsearch = elasticsearchInterface(a)
}
- if emojiInterface != nil {
- a.Emoji = emojiInterface(a)
- }
if ldapInterface != nil {
a.Ldap = ldapInterface(a)
a.AddConfigListener(func(_, cfg *model.Config) {
@@ -603,3 +594,75 @@ func (a *App) SetPhase2PermissionsMigrationStatus(isComplete bool) error {
a.phase2PermissionsMigrationComplete = isComplete
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
+ }
+
+ var role *model.Role = nil
+ var systemAdminRole *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 = nil
+ break
+ default:
+ mlog.Critical("Failed to migrate emojis creation permissions from mattermost config.")
+ mlog.Critical("Invalid restrict emoji creation setting")
+ return
+ }
+
+ if role != nil {
+ 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
+ }
+ }
+
+ systemAdminRole, 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
+ }
+
+ systemAdminRole.Permissions = append(systemAdminRole.Permissions, model.PERMISSION_MANAGE_EMOJIS.Id)
+ systemAdminRole.Permissions = append(systemAdminRole.Permissions, model.PERMISSION_MANAGE_OTHERS_EMOJIS.Id)
+ if result := <-a.Srv.Store.Role().Save(systemAdminRole); 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 cb6917073..dd6f0b593 100644
--- a/app/app_test.go
+++ b/app/app_test.go
@@ -455,3 +455,138 @@ 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()
+
+ expectedSystemAdmin := []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,
+ model.PERMISSION_MANAGE_OTHERS_EMOJIS.Id,
+ }
+
+ role1, err1 := th.App.GetRoleByName(model.SYSTEM_ADMIN_ROLE_ID)
+ assert.Nil(t, err1)
+ assert.Equal(t, expectedSystemAdmin, 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))
+
+ systemAdmin1, systemAdminErr1 := th.App.GetRoleByName(model.SYSTEM_ADMIN_ROLE_ID)
+ assert.Nil(t, systemAdminErr1)
+ assert.Equal(t, expectedSystemAdmin, systemAdmin1.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_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))
+
+ systemAdmin2, systemAdminErr2 := th.App.GetRoleByName(model.SYSTEM_ADMIN_ROLE_ID)
+ assert.Nil(t, systemAdminErr2)
+ assert.Equal(t, expectedSystemAdmin, systemAdmin2.Permissions, fmt.Sprintf("'%v' did not have expected permissions", model.SYSTEM_ADMIN_ROLE_ID))
+}
diff --git a/app/apptestlib.go b/app/apptestlib.go
index ec4992a75..d4a79bdcc 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 70b8cc689..46090070e 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 aea2b1230..ea7e8ec84 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 299005b6a..67e2f69c5 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/einterfaces/emoji.go b/einterfaces/emoji.go
deleted file mode 100644
index b8d61e748..000000000
--- a/einterfaces/emoji.go
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
-// See License.txt for license information.
-
-package einterfaces
-
-import (
- "github.com/mattermost/mattermost-server/model"
-)
-
-type EmojiInterface interface {
- CanUserCreateEmoji(string, []*model.TeamMember) bool
-}
diff --git a/i18n/en.json b/i18n/en.json
index d631e7e1d..0fc9a733f 100644
--- a/i18n/en.json
+++ b/i18n/en.json
@@ -1337,10 +1337,6 @@
"translation": "Unable to delete reactions when deleting emoji with emoji name %v"
},
{
- "id": "api.emoji.delete.permissions.app_error",
- "translation": "Invalid permissions to delete emoji."
- },
- {
"id": "api.emoji.disabled.app_error",
"translation": "Custom emoji have been disabled by the system admin."
},
diff --git a/migrations/migrationstestlib.go b/migrations/migrationstestlib.go
index 1b9110425..b501291b0 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/permission.go b/model/permission.go
index 792c7d42e..737321cc7 100644
--- a/model/permission.go
+++ b/model/permission.go
@@ -50,6 +50,8 @@ var PERMISSION_MANAGE_WEBHOOKS *Permission
var PERMISSION_MANAGE_OTHERS_WEBHOOKS *Permission
var PERMISSION_MANAGE_OAUTH *Permission
var PERMISSION_MANAGE_SYSTEM_WIDE_OAUTH *Permission
+var PERMISSION_MANAGE_EMOJIS *Permission
+var PERMISSION_MANAGE_OTHERS_EMOJIS *Permission
var PERMISSION_CREATE_POST *Permission
var PERMISSION_CREATE_POST_PUBLIC *Permission
var PERMISSION_CREATE_POST_EPHEMERAL *Permission
@@ -286,6 +288,18 @@ func initializePermissions() {
"authentication.permissions.manage_system_wide_oauth.description",
PERMISSION_SCOPE_SYSTEM,
}
+ PERMISSION_MANAGE_EMOJIS = &Permission{
+ "manage_emojis",
+ "authentication.permissions.manage_emojis.name",
+ "authentication.permissions.manage_emojis.description",
+ PERMISSION_SCOPE_TEAM,
+ }
+ PERMISSION_MANAGE_OTHERS_EMOJIS = &Permission{
+ "manage_others_emojis",
+ "authentication.permissions.manage_others_emojis.name",
+ "authentication.permissions.manage_others_emojis.description",
+ PERMISSION_SCOPE_TEAM,
+ }
PERMISSION_CREATE_POST = &Permission{
"create_post",
"authentication.permissions.create_post.name",
@@ -424,6 +438,8 @@ func initializePermissions() {
PERMISSION_MANAGE_OTHERS_WEBHOOKS,
PERMISSION_MANAGE_OAUTH,
PERMISSION_MANAGE_SYSTEM_WIDE_OAUTH,
+ PERMISSION_MANAGE_EMOJIS,
+ PERMISSION_MANAGE_OTHERS_EMOJIS,
PERMISSION_CREATE_POST,
PERMISSION_CREATE_POST_PUBLIC,
PERMISSION_CREATE_POST_EPHEMERAL,
diff --git a/store/sqlstore/upgrade.go b/store/sqlstore/upgrade.go
index 93399d7d9..98a89f36d 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 9b6230013..b53ed9618 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()