github.com/spline-fu/mattermost-server@v4.10.10+incompatible/app/permissions_migrations.go (about) 1 // Copyright (c) 2018-present Mattermost, Inc. All Rights Reserved. 2 // See License.txt for license information. 3 4 package app 5 6 import ( 7 "github.com/mattermost/mattermost-server/model" 8 ) 9 10 type permissionTransformation struct { 11 On func(string, map[string]map[string]bool) bool 12 Add []string 13 Remove []string 14 } 15 type permissionsMap []permissionTransformation 16 17 const ( 18 MIGRATION_KEY_APPLY_CHANNEL_MANAGE_DELETE_TO_CHANNEL_USER = "apply_channel_manage_delete_to_channel_user" 19 MIGRATION_KEY_REMOVE_CHANNEL_MANAGE_DELETE_FROM_TEAM_USER = "remove_channel_manage_delete_from_team_user" 20 21 PERMISSION_DELETE_PUBLIC_CHANNEL = "delete_public_channel" 22 PERMISSION_DELETE_PRIVATE_CHANNEL = "delete_private_channel" 23 PERMISSION_MANAGE_PUBLIC_CHANNEL_PROPERTIES = "manage_public_channel_properties" 24 PERMISSION_MANAGE_PRIVATE_CHANNEL_PROPERTIES = "manage_private_channel_properties" 25 ) 26 27 func isRole(role string) func(string, map[string]map[string]bool) bool { 28 return func(roleName string, permissionsMap map[string]map[string]bool) bool { 29 return roleName == role 30 } 31 } 32 33 func permissionExists(permission string) func(string, map[string]map[string]bool) bool { 34 return func(roleName string, permissionsMap map[string]map[string]bool) bool { 35 val, ok := permissionsMap[roleName][permission] 36 return ok && val 37 } 38 } 39 40 func permissionNotExists(permission string) func(string, map[string]map[string]bool) bool { 41 return func(roleName string, permissionsMap map[string]map[string]bool) bool { 42 val, ok := permissionsMap[roleName][permission] 43 return !(ok && val) 44 } 45 } 46 47 func onOtherRole(otherRole string, function func(string, map[string]map[string]bool) bool) func(string, map[string]map[string]bool) bool { 48 return func(roleName string, permissionsMap map[string]map[string]bool) bool { 49 return function(otherRole, permissionsMap) 50 } 51 } 52 53 func permissionOr(funcs ...func(string, map[string]map[string]bool) bool) func(string, map[string]map[string]bool) bool { 54 return func(roleName string, permissionsMap map[string]map[string]bool) bool { 55 for _, f := range funcs { 56 if f(roleName, permissionsMap) { 57 return true 58 } 59 } 60 return false 61 } 62 } 63 64 func permissionAnd(funcs ...func(string, map[string]map[string]bool) bool) func(string, map[string]map[string]bool) bool { 65 return func(roleName string, permissionsMap map[string]map[string]bool) bool { 66 for _, f := range funcs { 67 if !f(roleName, permissionsMap) { 68 return false 69 } 70 } 71 return true 72 } 73 } 74 75 func applyPermissionsMap(roleName string, roleMap map[string]map[string]bool, migrationMap permissionsMap) []string { 76 var result []string 77 78 for _, transformation := range migrationMap { 79 if transformation.On(roleName, roleMap) { 80 for _, permission := range transformation.Add { 81 roleMap[roleName][permission] = true 82 } 83 for _, permission := range transformation.Remove { 84 roleMap[roleName][permission] = false 85 } 86 } 87 } 88 89 for key, active := range roleMap[roleName] { 90 if active { 91 result = append(result, key) 92 } 93 } 94 return result 95 } 96 97 func (a *App) doPermissionsMigration(key string, migrationMap permissionsMap) *model.AppError { 98 if result := <-a.Srv.Store.System().GetByName(key); result.Err == nil { 99 return nil 100 } 101 102 roles, err := a.GetAllRoles() 103 if err != nil { 104 return err 105 } 106 107 roleMap := make(map[string]map[string]bool) 108 for _, role := range roles { 109 roleMap[role.Name] = make(map[string]bool) 110 for _, permission := range role.Permissions { 111 roleMap[role.Name][permission] = true 112 } 113 } 114 115 for _, role := range roles { 116 role.Permissions = applyPermissionsMap(role.Name, roleMap, migrationMap) 117 if result := <-a.Srv.Store.Role().Save(role); result.Err != nil { 118 return result.Err 119 } 120 } 121 122 if result := <-a.Srv.Store.System().Save(&model.System{Name: key, Value: "true"}); result.Err != nil { 123 return result.Err 124 } 125 return nil 126 } 127 128 func applyChannelManageDeleteToChannelUser() permissionsMap { 129 return permissionsMap{ 130 permissionTransformation{ 131 On: permissionAnd(isRole(model.CHANNEL_USER_ROLE_ID), onOtherRole(model.TEAM_USER_ROLE_ID, permissionExists(PERMISSION_MANAGE_PRIVATE_CHANNEL_PROPERTIES))), 132 Add: []string{PERMISSION_MANAGE_PRIVATE_CHANNEL_PROPERTIES}, 133 }, 134 permissionTransformation{ 135 On: permissionAnd(isRole(model.CHANNEL_USER_ROLE_ID), onOtherRole(model.TEAM_USER_ROLE_ID, permissionExists(PERMISSION_DELETE_PRIVATE_CHANNEL))), 136 Add: []string{PERMISSION_DELETE_PRIVATE_CHANNEL}, 137 }, 138 permissionTransformation{ 139 On: permissionAnd(isRole(model.CHANNEL_USER_ROLE_ID), onOtherRole(model.TEAM_USER_ROLE_ID, permissionExists(PERMISSION_MANAGE_PUBLIC_CHANNEL_PROPERTIES))), 140 Add: []string{PERMISSION_MANAGE_PUBLIC_CHANNEL_PROPERTIES}, 141 }, 142 permissionTransformation{ 143 On: permissionAnd(isRole(model.CHANNEL_USER_ROLE_ID), onOtherRole(model.TEAM_USER_ROLE_ID, permissionExists(PERMISSION_DELETE_PUBLIC_CHANNEL))), 144 Add: []string{PERMISSION_DELETE_PUBLIC_CHANNEL}, 145 }, 146 } 147 } 148 149 func removeChannelManageDeleteFromTeamUser() permissionsMap { 150 return permissionsMap{ 151 permissionTransformation{ 152 On: permissionAnd(isRole(model.TEAM_USER_ROLE_ID), permissionExists(PERMISSION_MANAGE_PRIVATE_CHANNEL_PROPERTIES)), 153 Remove: []string{PERMISSION_MANAGE_PRIVATE_CHANNEL_PROPERTIES}, 154 }, 155 permissionTransformation{ 156 On: permissionAnd(isRole(model.TEAM_USER_ROLE_ID), permissionExists(PERMISSION_DELETE_PRIVATE_CHANNEL)), 157 Remove: []string{model.PERMISSION_DELETE_PRIVATE_CHANNEL.Id}, 158 }, 159 permissionTransformation{ 160 On: permissionAnd(isRole(model.TEAM_USER_ROLE_ID), permissionExists(PERMISSION_MANAGE_PUBLIC_CHANNEL_PROPERTIES)), 161 Remove: []string{PERMISSION_MANAGE_PUBLIC_CHANNEL_PROPERTIES}, 162 }, 163 permissionTransformation{ 164 On: permissionAnd(isRole(model.TEAM_USER_ROLE_ID), permissionExists(PERMISSION_DELETE_PUBLIC_CHANNEL)), 165 Remove: []string{PERMISSION_DELETE_PUBLIC_CHANNEL}, 166 }, 167 } 168 } 169 170 // DoPermissionsMigrations execute all the permissions migrations need by the current version. 171 func (a *App) DoPermissionsMigrations() *model.AppError { 172 PermissionsMigrations := []struct { 173 Key string 174 Migration func() permissionsMap 175 }{ 176 {Key: MIGRATION_KEY_APPLY_CHANNEL_MANAGE_DELETE_TO_CHANNEL_USER, Migration: applyChannelManageDeleteToChannelUser}, 177 {Key: MIGRATION_KEY_REMOVE_CHANNEL_MANAGE_DELETE_FROM_TEAM_USER, Migration: removeChannelManageDeleteFromTeamUser}, 178 } 179 180 for _, migration := range PermissionsMigrations { 181 if err := a.doPermissionsMigration(migration.Key, migration.Migration()); err != nil { 182 return err 183 } 184 } 185 return nil 186 }