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