github.com/xzl8028/xenia-server@v0.0.0-20190809101854-18450a97da63/app/permissions_migrations.go (about) 1 // Copyright (c) 2018-present Xenia, Inc. All Rights Reserved. 2 // See License.txt for license information. 3 4 package app 5 6 import ( 7 "github.com/xzl8028/xenia-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_EMOJI_PERMISSIONS_SPLIT = "emoji_permissions_split" 19 MIGRATION_KEY_WEBHOOK_PERMISSIONS_SPLIT = "webhook_permissions_split" 20 MIGRATION_KEY_LIST_JOIN_PUBLIC_PRIVATE_TEAMS = "list_join_public_private_teams" 21 MIGRATION_KEY_REMOVE_PERMANENT_DELETE_USER = "remove_permanent_delete_user" 22 MIGRATION_KEY_ADD_BOT_PERMISSIONS = "add_bot_permissions" 23 MIGRATION_KEY_APPLY_CHANNEL_MANAGE_DELETE_TO_CHANNEL_USER = "apply_channel_manage_delete_to_channel_user" 24 MIGRATION_KEY_REMOVE_CHANNEL_MANAGE_DELETE_FROM_TEAM_USER = "remove_channel_manage_delete_from_team_user" 25 MIGRATION_KEY_VIEW_MEMBERS_NEW_PERMISSION = "view_members_new_permission" 26 27 PERMISSION_MANAGE_SYSTEM = "manage_system" 28 PERMISSION_MANAGE_EMOJIS = "manage_emojis" 29 PERMISSION_MANAGE_OTHERS_EMOJIS = "manage_others_emojis" 30 PERMISSION_CREATE_EMOJIS = "create_emojis" 31 PERMISSION_DELETE_EMOJIS = "delete_emojis" 32 PERMISSION_DELETE_OTHERS_EMOJIS = "delete_others_emojis" 33 PERMISSION_MANAGE_WEBHOOKS = "manage_webhooks" 34 PERMISSION_MANAGE_OTHERS_WEBHOOKS = "manage_others_webhooks" 35 PERMISSION_MANAGE_INCOMING_WEBHOOKS = "manage_incoming_webhooks" 36 PERMISSION_MANAGE_OTHERS_INCOMING_WEBHOOKS = "manage_others_incoming_webhooks" 37 PERMISSION_MANAGE_OUTGOING_WEBHOOKS = "manage_outgoing_webhooks" 38 PERMISSION_MANAGE_OTHERS_OUTGOING_WEBHOOKS = "manage_others_outgoing_webhooks" 39 PERMISSION_LIST_PUBLIC_TEAMS = "list_public_teams" 40 PERMISSION_LIST_PRIVATE_TEAMS = "list_private_teams" 41 PERMISSION_JOIN_PUBLIC_TEAMS = "join_public_teams" 42 PERMISSION_JOIN_PRIVATE_TEAMS = "join_private_teams" 43 PERMISSION_PERMANENT_DELETE_USER = "permanent_delete_user" 44 PERMISSION_CREATE_BOT = "create_bot" 45 PERMISSION_READ_BOTS = "read_bots" 46 PERMISSION_READ_OTHERS_BOTS = "read_others_bots" 47 PERMISSION_MANAGE_BOTS = "manage_bots" 48 PERMISSION_MANAGE_OTHERS_BOTS = "manage_others_bots" 49 PERMISSION_DELETE_PUBLIC_CHANNEL = "delete_public_channel" 50 PERMISSION_DELETE_PRIVATE_CHANNEL = "delete_private_channel" 51 PERMISSION_MANAGE_PUBLIC_CHANNEL_PROPERTIES = "manage_public_channel_properties" 52 PERMISSION_MANAGE_PRIVATE_CHANNEL_PROPERTIES = "manage_private_channel_properties" 53 PERMISSION_VIEW_MEMBERS = "view_members" 54 ) 55 56 func isRole(role string) func(string, map[string]map[string]bool) bool { 57 return func(roleName string, permissionsMap map[string]map[string]bool) bool { 58 return roleName == role 59 } 60 } 61 62 func permissionExists(permission string) func(string, map[string]map[string]bool) bool { 63 return func(roleName string, permissionsMap map[string]map[string]bool) bool { 64 val, ok := permissionsMap[roleName][permission] 65 return ok && val 66 } 67 } 68 69 func permissionNotExists(permission string) func(string, map[string]map[string]bool) bool { 70 return func(roleName string, permissionsMap map[string]map[string]bool) bool { 71 val, ok := permissionsMap[roleName][permission] 72 return !(ok && val) 73 } 74 } 75 76 func onOtherRole(otherRole string, function func(string, map[string]map[string]bool) bool) func(string, map[string]map[string]bool) bool { 77 return func(roleName string, permissionsMap map[string]map[string]bool) bool { 78 return function(otherRole, permissionsMap) 79 } 80 } 81 82 func permissionOr(funcs ...func(string, map[string]map[string]bool) bool) func(string, map[string]map[string]bool) bool { 83 return func(roleName string, permissionsMap map[string]map[string]bool) bool { 84 for _, f := range funcs { 85 if f(roleName, permissionsMap) { 86 return true 87 } 88 } 89 return false 90 } 91 } 92 93 func permissionAnd(funcs ...func(string, map[string]map[string]bool) bool) func(string, map[string]map[string]bool) bool { 94 return func(roleName string, permissionsMap map[string]map[string]bool) bool { 95 for _, f := range funcs { 96 if !f(roleName, permissionsMap) { 97 return false 98 } 99 } 100 return true 101 } 102 } 103 104 func applyPermissionsMap(roleName string, roleMap map[string]map[string]bool, migrationMap permissionsMap) []string { 105 var result []string 106 107 for _, transformation := range migrationMap { 108 if transformation.On(roleName, roleMap) { 109 for _, permission := range transformation.Add { 110 roleMap[roleName][permission] = true 111 } 112 for _, permission := range transformation.Remove { 113 roleMap[roleName][permission] = false 114 } 115 } 116 } 117 118 for key, active := range roleMap[roleName] { 119 if active { 120 result = append(result, key) 121 } 122 } 123 return result 124 } 125 126 func (a *App) doPermissionsMigration(key string, migrationMap permissionsMap) *model.AppError { 127 if _, err := a.Srv.Store.System().GetByName(key); err == nil { 128 return nil 129 } 130 131 roles, err := a.GetAllRoles() 132 if err != nil { 133 return err 134 } 135 136 roleMap := make(map[string]map[string]bool) 137 for _, role := range roles { 138 roleMap[role.Name] = make(map[string]bool) 139 for _, permission := range role.Permissions { 140 roleMap[role.Name][permission] = true 141 } 142 } 143 144 for _, role := range roles { 145 role.Permissions = applyPermissionsMap(role.Name, roleMap, migrationMap) 146 if _, err := a.Srv.Store.Role().Save(role); err != nil { 147 return err 148 } 149 } 150 151 if err := a.Srv.Store.System().Save(&model.System{Name: key, Value: "true"}); err != nil { 152 return err 153 } 154 return nil 155 } 156 157 func getEmojisPermissionsSplitMigration() permissionsMap { 158 return permissionsMap{ 159 permissionTransformation{ 160 On: permissionExists(PERMISSION_MANAGE_EMOJIS), 161 Add: []string{PERMISSION_CREATE_EMOJIS, PERMISSION_DELETE_EMOJIS}, 162 Remove: []string{PERMISSION_MANAGE_EMOJIS}, 163 }, 164 permissionTransformation{ 165 On: permissionExists(PERMISSION_MANAGE_OTHERS_EMOJIS), 166 Add: []string{PERMISSION_DELETE_OTHERS_EMOJIS}, 167 Remove: []string{PERMISSION_MANAGE_OTHERS_EMOJIS}, 168 }, 169 } 170 } 171 172 func getWebhooksPermissionsSplitMigration() permissionsMap { 173 return permissionsMap{ 174 permissionTransformation{ 175 On: permissionExists(PERMISSION_MANAGE_WEBHOOKS), 176 Add: []string{PERMISSION_MANAGE_INCOMING_WEBHOOKS, PERMISSION_MANAGE_OUTGOING_WEBHOOKS}, 177 Remove: []string{PERMISSION_MANAGE_WEBHOOKS}, 178 }, 179 permissionTransformation{ 180 On: permissionExists(PERMISSION_MANAGE_OTHERS_WEBHOOKS), 181 Add: []string{PERMISSION_MANAGE_OTHERS_INCOMING_WEBHOOKS, PERMISSION_MANAGE_OTHERS_OUTGOING_WEBHOOKS}, 182 Remove: []string{PERMISSION_MANAGE_OTHERS_WEBHOOKS}, 183 }, 184 } 185 } 186 187 func getListJoinPublicPrivateTeamsPermissionsMigration() permissionsMap { 188 return permissionsMap{ 189 permissionTransformation{ 190 On: isRole(model.SYSTEM_ADMIN_ROLE_ID), 191 Add: []string{PERMISSION_LIST_PRIVATE_TEAMS, PERMISSION_JOIN_PRIVATE_TEAMS}, 192 Remove: []string{}, 193 }, 194 permissionTransformation{ 195 On: isRole(model.SYSTEM_USER_ROLE_ID), 196 Add: []string{PERMISSION_LIST_PUBLIC_TEAMS, PERMISSION_JOIN_PUBLIC_TEAMS}, 197 Remove: []string{}, 198 }, 199 } 200 } 201 202 func removePermanentDeleteUserMigration() permissionsMap { 203 return permissionsMap{ 204 permissionTransformation{ 205 On: permissionExists(PERMISSION_PERMANENT_DELETE_USER), 206 Remove: []string{PERMISSION_PERMANENT_DELETE_USER}, 207 }, 208 } 209 } 210 211 func getAddBotPermissionsMigration() permissionsMap { 212 return permissionsMap{ 213 permissionTransformation{ 214 On: isRole(model.SYSTEM_ADMIN_ROLE_ID), 215 Add: []string{PERMISSION_CREATE_BOT, PERMISSION_READ_BOTS, PERMISSION_READ_OTHERS_BOTS, PERMISSION_MANAGE_BOTS, PERMISSION_MANAGE_OTHERS_BOTS}, 216 Remove: []string{}, 217 }, 218 } 219 } 220 221 func applyChannelManageDeleteToChannelUser() permissionsMap { 222 return permissionsMap{ 223 permissionTransformation{ 224 On: permissionAnd(isRole(model.CHANNEL_USER_ROLE_ID), onOtherRole(model.TEAM_USER_ROLE_ID, permissionExists(PERMISSION_MANAGE_PRIVATE_CHANNEL_PROPERTIES))), 225 Add: []string{PERMISSION_MANAGE_PRIVATE_CHANNEL_PROPERTIES}, 226 }, 227 permissionTransformation{ 228 On: permissionAnd(isRole(model.CHANNEL_USER_ROLE_ID), onOtherRole(model.TEAM_USER_ROLE_ID, permissionExists(PERMISSION_DELETE_PRIVATE_CHANNEL))), 229 Add: []string{PERMISSION_DELETE_PRIVATE_CHANNEL}, 230 }, 231 permissionTransformation{ 232 On: permissionAnd(isRole(model.CHANNEL_USER_ROLE_ID), onOtherRole(model.TEAM_USER_ROLE_ID, permissionExists(PERMISSION_MANAGE_PUBLIC_CHANNEL_PROPERTIES))), 233 Add: []string{PERMISSION_MANAGE_PUBLIC_CHANNEL_PROPERTIES}, 234 }, 235 permissionTransformation{ 236 On: permissionAnd(isRole(model.CHANNEL_USER_ROLE_ID), onOtherRole(model.TEAM_USER_ROLE_ID, permissionExists(PERMISSION_DELETE_PUBLIC_CHANNEL))), 237 Add: []string{PERMISSION_DELETE_PUBLIC_CHANNEL}, 238 }, 239 } 240 } 241 242 func removeChannelManageDeleteFromTeamUser() permissionsMap { 243 return permissionsMap{ 244 permissionTransformation{ 245 On: permissionAnd(isRole(model.TEAM_USER_ROLE_ID), permissionExists(PERMISSION_MANAGE_PRIVATE_CHANNEL_PROPERTIES)), 246 Remove: []string{PERMISSION_MANAGE_PRIVATE_CHANNEL_PROPERTIES}, 247 }, 248 permissionTransformation{ 249 On: permissionAnd(isRole(model.TEAM_USER_ROLE_ID), permissionExists(PERMISSION_DELETE_PRIVATE_CHANNEL)), 250 Remove: []string{model.PERMISSION_DELETE_PRIVATE_CHANNEL.Id}, 251 }, 252 permissionTransformation{ 253 On: permissionAnd(isRole(model.TEAM_USER_ROLE_ID), permissionExists(PERMISSION_MANAGE_PUBLIC_CHANNEL_PROPERTIES)), 254 Remove: []string{PERMISSION_MANAGE_PUBLIC_CHANNEL_PROPERTIES}, 255 }, 256 permissionTransformation{ 257 On: permissionAnd(isRole(model.TEAM_USER_ROLE_ID), permissionExists(PERMISSION_DELETE_PUBLIC_CHANNEL)), 258 Remove: []string{PERMISSION_DELETE_PUBLIC_CHANNEL}, 259 }, 260 } 261 } 262 263 func getViewMembersPermissionMigration() permissionsMap { 264 return permissionsMap{ 265 permissionTransformation{ 266 On: isRole(model.SYSTEM_USER_ROLE_ID), 267 Add: []string{PERMISSION_VIEW_MEMBERS}, 268 }, 269 permissionTransformation{ 270 On: isRole(model.SYSTEM_ADMIN_ROLE_ID), 271 Add: []string{PERMISSION_VIEW_MEMBERS}, 272 }, 273 } 274 } 275 276 // DoPermissionsMigrations execute all the permissions migrations need by the current version. 277 func (a *App) DoPermissionsMigrations() *model.AppError { 278 PermissionsMigrations := []struct { 279 Key string 280 Migration func() permissionsMap 281 }{ 282 {Key: MIGRATION_KEY_EMOJI_PERMISSIONS_SPLIT, Migration: getEmojisPermissionsSplitMigration}, 283 {Key: MIGRATION_KEY_WEBHOOK_PERMISSIONS_SPLIT, Migration: getWebhooksPermissionsSplitMigration}, 284 {Key: MIGRATION_KEY_LIST_JOIN_PUBLIC_PRIVATE_TEAMS, Migration: getListJoinPublicPrivateTeamsPermissionsMigration}, 285 {Key: MIGRATION_KEY_REMOVE_PERMANENT_DELETE_USER, Migration: removePermanentDeleteUserMigration}, 286 {Key: MIGRATION_KEY_ADD_BOT_PERMISSIONS, Migration: getAddBotPermissionsMigration}, 287 {Key: MIGRATION_KEY_APPLY_CHANNEL_MANAGE_DELETE_TO_CHANNEL_USER, Migration: applyChannelManageDeleteToChannelUser}, 288 {Key: MIGRATION_KEY_REMOVE_CHANNEL_MANAGE_DELETE_FROM_TEAM_USER, Migration: removeChannelManageDeleteFromTeamUser}, 289 {Key: MIGRATION_KEY_VIEW_MEMBERS_NEW_PERMISSION, Migration: getViewMembersPermissionMigration}, 290 } 291 292 for _, migration := range PermissionsMigrations { 293 if err := a.doPermissionsMigration(migration.Key, migration.Migration()); err != nil { 294 return err 295 } 296 } 297 return nil 298 }