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  }