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  }