[MM-23019] Create use_group_mentions permission and migrate existing roles (#13987)

* MM-22962 Create use_group_mentions permission and give to all non guest roles that can create post

* Add use_group_mentions to team admin role for test

* Trigger CI

* MM-22962 Remove old migration keys
Этот коммит содержится в:
Farhan Munshi
2020-03-30 23:08:48 -04:00
коммит произвёл GitHub
родитель bf1d9b0ae9
Коммит ab338e8417
6 изменённых файлов: 67 добавлений и 23 удалений

Просмотреть файл

@@ -563,6 +563,7 @@ func TestDoEmojisPermissionsMigration(t *testing.T) {
model.PERMISSION_DELETE_OTHERS_EMOJIS.Id, model.PERMISSION_DELETE_OTHERS_EMOJIS.Id,
model.PERMISSION_VIEW_MEMBERS.Id, model.PERMISSION_VIEW_MEMBERS.Id,
model.PERMISSION_USE_CHANNEL_MENTIONS.Id, model.PERMISSION_USE_CHANNEL_MENTIONS.Id,
model.PERMISSION_USE_GROUP_MENTIONS.Id,
} }
sort.Strings(expectedSystemAdmin) sort.Strings(expectedSystemAdmin)
@@ -602,6 +603,7 @@ func TestDoEmojisPermissionsMigration(t *testing.T) {
model.PERMISSION_MANAGE_PRIVATE_CHANNEL_MEMBERS.Id, model.PERMISSION_MANAGE_PRIVATE_CHANNEL_MEMBERS.Id,
model.PERMISSION_REMOVE_REACTION.Id, model.PERMISSION_REMOVE_REACTION.Id,
model.PERMISSION_USE_CHANNEL_MENTIONS.Id, model.PERMISSION_USE_CHANNEL_MENTIONS.Id,
model.PERMISSION_USE_GROUP_MENTIONS.Id,
} }
sort.Strings(expected2) sort.Strings(expected2)
sort.Strings(role2.Permissions) sort.Strings(role2.Permissions)

Просмотреть файл

@@ -4,11 +4,13 @@
package app package app
import ( import (
"strings"
"github.com/mattermost/mattermost-server/v5/model" "github.com/mattermost/mattermost-server/v5/model"
) )
type permissionTransformation struct { type permissionTransformation struct {
On func(string, map[string]map[string]bool) bool On func(*model.Role, map[string]map[string]bool) bool
Add []string Add []string
Remove []string Remove []string
} }
@@ -49,42 +51,55 @@ const (
PERMISSION_USE_CHANNEL_MENTIONS = "use_channel_mentions" PERMISSION_USE_CHANNEL_MENTIONS = "use_channel_mentions"
PERMISSION_CREATE_POST = "create_post" PERMISSION_CREATE_POST = "create_post"
PERMISSION_CREATE_POST_PUBLIC = "create_post_public" PERMISSION_CREATE_POST_PUBLIC = "create_post_public"
PERMISSION_USE_GROUP_MENTIONS = "use_group_mentions"
PERMISSION_ADD_REACTION = "add_reaction" PERMISSION_ADD_REACTION = "add_reaction"
PERMISSION_REMOVE_REACTION = "remove_reaction" PERMISSION_REMOVE_REACTION = "remove_reaction"
PERMISSION_MANAGE_PUBLIC_CHANNEL_MEMBERS = "manage_public_channel_members" PERMISSION_MANAGE_PUBLIC_CHANNEL_MEMBERS = "manage_public_channel_members"
PERMISSION_MANAGE_PRIVATE_CHANNEL_MEMBERS = "manage_private_channel_members" PERMISSION_MANAGE_PRIVATE_CHANNEL_MEMBERS = "manage_private_channel_members"
) )
func isRole(role string) func(string, map[string]map[string]bool) bool { func isRole(roleName string) func(*model.Role, map[string]map[string]bool) bool {
return func(roleName string, permissionsMap map[string]map[string]bool) bool { return func(role *model.Role, permissionsMap map[string]map[string]bool) bool {
return roleName == role return role.Name == roleName
} }
} }
func permissionExists(permission string) func(string, map[string]map[string]bool) bool { func isNotRole(roleName string) func(*model.Role, map[string]map[string]bool) bool {
return func(roleName string, permissionsMap map[string]map[string]bool) bool { return func(role *model.Role, permissionsMap map[string]map[string]bool) bool {
val, ok := permissionsMap[roleName][permission] return role.Name != roleName
}
}
func isNotSchemeRole(roleName string) func(*model.Role, map[string]map[string]bool) bool {
return func(role *model.Role, permissionsMap map[string]map[string]bool) bool {
return !strings.Contains(role.DisplayName, roleName)
}
}
func permissionExists(permission string) func(*model.Role, map[string]map[string]bool) bool {
return func(role *model.Role, permissionsMap map[string]map[string]bool) bool {
val, ok := permissionsMap[role.Name][permission]
return ok && val return ok && val
} }
} }
func permissionNotExists(permission string) func(string, map[string]map[string]bool) bool { func permissionNotExists(permission string) func(*model.Role, map[string]map[string]bool) bool {
return func(roleName string, permissionsMap map[string]map[string]bool) bool { return func(role *model.Role, permissionsMap map[string]map[string]bool) bool {
val, ok := permissionsMap[roleName][permission] val, ok := permissionsMap[role.Name][permission]
return !(ok && val) return !(ok && val)
} }
} }
func onOtherRole(otherRole string, function func(string, map[string]map[string]bool) bool) func(string, map[string]map[string]bool) bool { func onOtherRole(otherRole string, function func(*model.Role, map[string]map[string]bool) bool) func(*model.Role, map[string]map[string]bool) bool {
return func(roleName string, permissionsMap map[string]map[string]bool) bool { return func(role *model.Role, permissionsMap map[string]map[string]bool) bool {
return function(otherRole, permissionsMap) return function(&model.Role{Name: otherRole}, permissionsMap)
} }
} }
func permissionOr(funcs ...func(string, map[string]map[string]bool) bool) func(string, map[string]map[string]bool) bool { func permissionOr(funcs ...func(*model.Role, map[string]map[string]bool) bool) func(*model.Role, map[string]map[string]bool) bool {
return func(roleName string, permissionsMap map[string]map[string]bool) bool { return func(role *model.Role, permissionsMap map[string]map[string]bool) bool {
for _, f := range funcs { for _, f := range funcs {
if f(roleName, permissionsMap) { if f(role, permissionsMap) {
return true return true
} }
} }
@@ -92,10 +107,10 @@ func permissionOr(funcs ...func(string, map[string]map[string]bool) bool) func(s
} }
} }
func permissionAnd(funcs ...func(string, map[string]map[string]bool) bool) func(string, map[string]map[string]bool) bool { func permissionAnd(funcs ...func(*model.Role, map[string]map[string]bool) bool) func(*model.Role, map[string]map[string]bool) bool {
return func(roleName string, permissionsMap map[string]map[string]bool) bool { return func(role *model.Role, permissionsMap map[string]map[string]bool) bool {
for _, f := range funcs { for _, f := range funcs {
if !f(roleName, permissionsMap) { if !f(role, permissionsMap) {
return false return false
} }
} }
@@ -103,11 +118,12 @@ func permissionAnd(funcs ...func(string, map[string]map[string]bool) bool) func(
} }
} }
func applyPermissionsMap(roleName string, roleMap map[string]map[string]bool, migrationMap permissionsMap) []string { func applyPermissionsMap(role *model.Role, roleMap map[string]map[string]bool, migrationMap permissionsMap) []string {
var result []string var result []string
roleName := role.Name
for _, transformation := range migrationMap { for _, transformation := range migrationMap {
if transformation.On(roleName, roleMap) { if transformation.On(role, roleMap) {
for _, permission := range transformation.Add { for _, permission := range transformation.Add {
roleMap[roleName][permission] = true roleMap[roleName][permission] = true
} }
@@ -144,7 +160,7 @@ func (a *App) doPermissionsMigration(key string, migrationMap permissionsMap) *m
} }
for _, role := range roles { for _, role := range roles {
role.Permissions = applyPermissionsMap(role.Name, roleMap, migrationMap) role.Permissions = applyPermissionsMap(role, roleMap, migrationMap)
if _, err := a.Srv().Store.Role().Save(role); err != nil { if _, err := a.Srv().Store.Role().Save(role); err != nil {
return err return err
} }
@@ -396,6 +412,19 @@ func (a *App) channelModerationPermissionsMigration() (permissionsMap, error) {
return transformations, nil return transformations, nil
} }
func (a *App) getAddUseGroupMentionsPermissionMigration() (permissionsMap, error) {
return permissionsMap{
permissionTransformation{
On: permissionAnd(
isNotRole(model.CHANNEL_GUEST_ROLE_ID),
isNotSchemeRole("Channel Guest Role for Scheme"),
permissionOr(permissionExists(PERMISSION_CREATE_POST), permissionExists(PERMISSION_CREATE_POST_PUBLIC)),
),
Add: []string{PERMISSION_USE_GROUP_MENTIONS},
},
}, nil
}
// DoPermissionsMigrations execute all the permissions migrations need by the current version. // DoPermissionsMigrations execute all the permissions migrations need by the current version.
func (a *App) DoPermissionsMigrations() error { func (a *App) DoPermissionsMigrations() error {
PermissionsMigrations := []struct { PermissionsMigrations := []struct {
@@ -412,6 +441,7 @@ func (a *App) DoPermissionsMigrations() error {
{Key: model.MIGRATION_KEY_VIEW_MEMBERS_NEW_PERMISSION, Migration: a.getViewMembersPermissionMigration}, {Key: model.MIGRATION_KEY_VIEW_MEMBERS_NEW_PERMISSION, Migration: a.getViewMembersPermissionMigration},
{Key: model.MIGRATION_KEY_ADD_MANAGE_GUESTS_PERMISSIONS, Migration: a.getAddManageGuestsPermissionsMigration}, {Key: model.MIGRATION_KEY_ADD_MANAGE_GUESTS_PERMISSIONS, Migration: a.getAddManageGuestsPermissionsMigration},
{Key: model.MIGRATION_KEY_CHANNEL_MODERATIONS_PERMISSIONS, Migration: a.channelModerationPermissionsMigration}, {Key: model.MIGRATION_KEY_CHANNEL_MODERATIONS_PERMISSIONS, Migration: a.channelModerationPermissionsMigration},
{Key: model.MIGRATION_KEY_ADD_USE_GROUP_MENTIONS_PERMISSION, Migration: a.getAddUseGroupMentionsPermissionMigration},
} }
for _, migration := range PermissionsMigrations { for _, migration := range PermissionsMigrations {

Просмотреть файл

@@ -7,6 +7,7 @@ import (
"sort" "sort"
"testing" "testing"
"github.com/mattermost/mattermost-server/v5/model"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@@ -195,7 +196,7 @@ func TestApplyPermissionsMap(t *testing.T) {
for _, tc := range tt { for _, tc := range tt {
t.Run(tc.Name, func(t *testing.T) { t.Run(tc.Name, func(t *testing.T) {
result := applyPermissionsMap("system_admin", tc.RoleMap, tc.TranslationMap) result := applyPermissionsMap(&model.Role{Name: "system_admin"}, tc.RoleMap, tc.TranslationMap)
sort.Strings(result) sort.Strings(result)
assert.Equal(t, tc.ExpectedResult, result) assert.Equal(t, tc.ExpectedResult, result)
}) })

Просмотреть файл

@@ -16,4 +16,5 @@ const (
MIGRATION_KEY_VIEW_MEMBERS_NEW_PERMISSION = "view_members_new_permission" MIGRATION_KEY_VIEW_MEMBERS_NEW_PERMISSION = "view_members_new_permission"
MIGRATION_KEY_ADD_MANAGE_GUESTS_PERMISSIONS = "add_manage_guests_permissions" MIGRATION_KEY_ADD_MANAGE_GUESTS_PERMISSIONS = "add_manage_guests_permissions"
MIGRATION_KEY_CHANNEL_MODERATIONS_PERMISSIONS = "channel_moderations_permissions" MIGRATION_KEY_CHANNEL_MODERATIONS_PERMISSIONS = "channel_moderations_permissions"
MIGRATION_KEY_ADD_USE_GROUP_MENTIONS_PERMISSION = "add_use_group_mentions_permission"
) )

Просмотреть файл

@@ -91,6 +91,7 @@ var PERMISSION_INVITE_GUEST *Permission
var PERMISSION_PROMOTE_GUEST *Permission var PERMISSION_PROMOTE_GUEST *Permission
var PERMISSION_DEMOTE_TO_GUEST *Permission var PERMISSION_DEMOTE_TO_GUEST *Permission
var PERMISSION_USE_CHANNEL_MENTIONS *Permission var PERMISSION_USE_CHANNEL_MENTIONS *Permission
var PERMISSION_USE_GROUP_MENTIONS *Permission
// General permission that encompasses all system admin functions // General permission that encompasses all system admin functions
// in the future this could be broken up to allow access to some // in the future this could be broken up to allow access to some
@@ -567,6 +568,13 @@ func initializePermissions() {
PERMISSION_SCOPE_CHANNEL, PERMISSION_SCOPE_CHANNEL,
} }
PERMISSION_USE_GROUP_MENTIONS = &Permission{
"use_group_mentions",
"authentication.permissions.use_group_mentions.name",
"authentication.permissions.use_group_mentions.description",
PERMISSION_SCOPE_CHANNEL,
}
ALL_PERMISSIONS = []*Permission{ ALL_PERMISSIONS = []*Permission{
PERMISSION_INVITE_USER, PERMISSION_INVITE_USER,
PERMISSION_ADD_USER_TO_TEAM, PERMISSION_ADD_USER_TO_TEAM,
@@ -643,6 +651,7 @@ func initializePermissions() {
PERMISSION_PROMOTE_GUEST, PERMISSION_PROMOTE_GUEST,
PERMISSION_DEMOTE_TO_GUEST, PERMISSION_DEMOTE_TO_GUEST,
PERMISSION_USE_CHANNEL_MENTIONS, PERMISSION_USE_CHANNEL_MENTIONS,
PERMISSION_USE_GROUP_MENTIONS,
} }
CHANNEL_MODERATED_PERMISSIONS = []string{ CHANNEL_MODERATED_PERMISSIONS = []string{

Просмотреть файл

@@ -40,6 +40,7 @@ func GetMockStoreForSetupFunctions() *mocks.Store {
systemStore.On("GetByName", model.MIGRATION_KEY_VIEW_MEMBERS_NEW_PERMISSION).Return(&model.System{Name: model.MIGRATION_KEY_VIEW_MEMBERS_NEW_PERMISSION, Value: "true"}, nil) systemStore.On("GetByName", model.MIGRATION_KEY_VIEW_MEMBERS_NEW_PERMISSION).Return(&model.System{Name: model.MIGRATION_KEY_VIEW_MEMBERS_NEW_PERMISSION, Value: "true"}, nil)
systemStore.On("GetByName", model.MIGRATION_KEY_ADD_MANAGE_GUESTS_PERMISSIONS).Return(&model.System{Name: model.MIGRATION_KEY_ADD_MANAGE_GUESTS_PERMISSIONS, Value: "true"}, nil) systemStore.On("GetByName", model.MIGRATION_KEY_ADD_MANAGE_GUESTS_PERMISSIONS).Return(&model.System{Name: model.MIGRATION_KEY_ADD_MANAGE_GUESTS_PERMISSIONS, Value: "true"}, nil)
systemStore.On("GetByName", model.MIGRATION_KEY_CHANNEL_MODERATIONS_PERMISSIONS).Return(&model.System{Name: model.MIGRATION_KEY_CHANNEL_MODERATIONS_PERMISSIONS, Value: "true"}, nil) systemStore.On("GetByName", model.MIGRATION_KEY_CHANNEL_MODERATIONS_PERMISSIONS).Return(&model.System{Name: model.MIGRATION_KEY_CHANNEL_MODERATIONS_PERMISSIONS, Value: "true"}, nil)
systemStore.On("GetByName", model.MIGRATION_KEY_ADD_USE_GROUP_MENTIONS_PERMISSION).Return(&model.System{Name: model.MIGRATION_KEY_ADD_USE_GROUP_MENTIONS_PERMISSION, Value: "true"}, nil)
systemStore.On("Get").Return(make(model.StringMap), nil) systemStore.On("Get").Return(make(model.StringMap), nil)
systemStore.On("Save", mock.AnythingOfType("*model.System")).Return(nil) systemStore.On("Save", mock.AnythingOfType("*model.System")).Return(nil)