github.com/mattermosttest/mattermost-server/v5@v5.0.0-20200917143240-9dfa12e121f9/app/role_test.go (about)

     1  // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
     2  // See LICENSE.txt for license information.
     3  
     4  package app
     5  
     6  import (
     7  	"encoding/csv"
     8  	"io/ioutil"
     9  	"os"
    10  	"strconv"
    11  	"strings"
    12  	"testing"
    13  
    14  	"github.com/mattermost/mattermost-server/v5/model"
    15  	"github.com/mattermost/mattermost-server/v5/utils"
    16  	"github.com/stretchr/testify/require"
    17  )
    18  
    19  type permissionInheritanceTestData struct {
    20  	channelRole          *model.Role
    21  	permission           *model.Permission
    22  	shouldHavePermission bool
    23  	channel              *model.Channel
    24  	higherScopedRole     *model.Role
    25  	truthTableRow        []string
    26  }
    27  
    28  func TestGetRolesByNames(t *testing.T) {
    29  	testPermissionInheritance(t, func(t *testing.T, th *TestHelper, testData permissionInheritanceTestData) {
    30  		actualRoles, err := th.App.GetRolesByNames([]string{testData.channelRole.Name})
    31  		require.Nil(t, err)
    32  		require.Len(t, actualRoles, 1)
    33  
    34  		actualRole := actualRoles[0]
    35  		require.NotNil(t, actualRole)
    36  		require.Equal(t, testData.channelRole.Name, actualRole.Name)
    37  
    38  		require.Equal(t, testData.shouldHavePermission, utils.StringInSlice(testData.permission.Id, actualRole.Permissions))
    39  	})
    40  }
    41  
    42  func TestGetRoleByName(t *testing.T) {
    43  	testPermissionInheritance(t, func(t *testing.T, th *TestHelper, testData permissionInheritanceTestData) {
    44  		actualRole, err := th.App.GetRoleByName(testData.channelRole.Name)
    45  		require.Nil(t, err)
    46  		require.NotNil(t, actualRole)
    47  		require.Equal(t, testData.channelRole.Name, actualRole.Name)
    48  		require.Equal(t, testData.shouldHavePermission, utils.StringInSlice(testData.permission.Id, actualRole.Permissions), "row: %+v", testData.truthTableRow)
    49  	})
    50  }
    51  
    52  // testPermissionInheritance tests 48 combinations of scheme, permission, role data.
    53  func testPermissionInheritance(t *testing.T, testCallback func(t *testing.T, th *TestHelper, testData permissionInheritanceTestData)) {
    54  	th := Setup(t).InitBasic()
    55  	defer th.TearDown()
    56  
    57  	th.App.Srv().SetLicense(model.NewTestLicense(""))
    58  	th.App.SetPhase2PermissionsMigrationStatus(true)
    59  
    60  	permissionsDefault := []string{
    61  		model.PERMISSION_MANAGE_CHANNEL_ROLES.Id,
    62  		model.PERMISSION_MANAGE_PUBLIC_CHANNEL_MEMBERS.Id,
    63  	}
    64  
    65  	// Defer resetting the system scheme permissions
    66  	systemSchemeRoles, err := th.App.GetRolesByNames([]string{
    67  		model.CHANNEL_GUEST_ROLE_ID,
    68  		model.CHANNEL_USER_ROLE_ID,
    69  		model.CHANNEL_ADMIN_ROLE_ID,
    70  	})
    71  	require.Nil(t, err)
    72  	require.Len(t, systemSchemeRoles, 3)
    73  
    74  	// defer resetting the system role permissions
    75  	for _, systemRole := range systemSchemeRoles {
    76  		defer th.App.PatchRole(systemRole, &model.RolePatch{
    77  			Permissions: &systemRole.Permissions,
    78  		})
    79  	}
    80  
    81  	// Make a channel scheme, clear its permissions
    82  	channelScheme, err := th.App.CreateScheme(&model.Scheme{
    83  		Name:        model.NewId(),
    84  		DisplayName: model.NewId(),
    85  		Scope:       model.SCHEME_SCOPE_CHANNEL,
    86  	})
    87  	require.Nil(t, err)
    88  	defer th.App.DeleteScheme(channelScheme.Id)
    89  
    90  	team := th.CreateTeam()
    91  	defer th.App.PermanentDeleteTeamId(team.Id)
    92  
    93  	// Make a channel
    94  	channel := th.CreateChannel(team)
    95  	defer th.App.PermanentDeleteChannel(channel)
    96  
    97  	// Set the channel scheme
    98  	channel.SchemeId = &channelScheme.Id
    99  	channel, err = th.App.UpdateChannelScheme(channel)
   100  	require.Nil(t, err)
   101  
   102  	// Get the truth table from CSV
   103  	file, e := os.Open("tests/channel-role-has-permission.csv")
   104  	require.Nil(t, e)
   105  	defer file.Close()
   106  
   107  	b, e := ioutil.ReadAll(file)
   108  	require.Nil(t, e)
   109  
   110  	r := csv.NewReader(strings.NewReader(string(b)))
   111  	records, e := r.ReadAll()
   112  	require.Nil(t, e)
   113  
   114  	test := func(higherScopedGuest, higherScopedUser, higherScopedAdmin string) {
   115  		for _, roleNameUnderTest := range []string{higherScopedGuest, higherScopedUser, higherScopedAdmin} {
   116  			for i, row := range records {
   117  				// skip csv header
   118  				if i == 0 {
   119  					continue
   120  				}
   121  
   122  				higherSchemeHasPermission, e := strconv.ParseBool(row[0])
   123  				require.Nil(t, e)
   124  
   125  				permissionIsModerated, e := strconv.ParseBool(row[1])
   126  				require.Nil(t, e)
   127  
   128  				channelSchemeHasPermission, e := strconv.ParseBool(row[2])
   129  				require.Nil(t, e)
   130  
   131  				channelRoleIsChannelAdmin, e := strconv.ParseBool(row[3])
   132  				require.Nil(t, e)
   133  
   134  				shouldHavePermission, e := strconv.ParseBool(row[4])
   135  				require.Nil(t, e)
   136  
   137  				// skip some invalid combinations because of the outer loop iterating all 3 channel roles
   138  				if (channelRoleIsChannelAdmin && roleNameUnderTest != higherScopedAdmin) || (!channelRoleIsChannelAdmin && roleNameUnderTest == higherScopedAdmin) {
   139  					continue
   140  				}
   141  
   142  				// select the permission to test (moderated or non-moderated)
   143  				var permission *model.Permission
   144  				if permissionIsModerated {
   145  					permission = model.PERMISSION_CREATE_POST // moderated
   146  				} else {
   147  					permission = model.PERMISSION_READ_CHANNEL // non-moderated
   148  				}
   149  
   150  				// add or remove the permission from the higher-scoped scheme
   151  				higherScopedRole, testErr := th.App.GetRoleByName(roleNameUnderTest)
   152  				require.Nil(t, testErr)
   153  
   154  				var higherScopedPermissions []string
   155  				if higherSchemeHasPermission {
   156  					higherScopedPermissions = []string{permission.Id}
   157  				} else {
   158  					higherScopedPermissions = permissionsDefault
   159  				}
   160  				higherScopedRole, testErr = th.App.PatchRole(higherScopedRole, &model.RolePatch{Permissions: &higherScopedPermissions})
   161  				require.Nil(t, testErr)
   162  
   163  				// get channel role
   164  				var channelRoleName string
   165  				switch roleNameUnderTest {
   166  				case higherScopedGuest:
   167  					channelRoleName = channelScheme.DefaultChannelGuestRole
   168  				case higherScopedUser:
   169  					channelRoleName = channelScheme.DefaultChannelUserRole
   170  				case higherScopedAdmin:
   171  					channelRoleName = channelScheme.DefaultChannelAdminRole
   172  				}
   173  				channelRole, testErr := th.App.GetRoleByName(channelRoleName)
   174  				require.Nil(t, testErr)
   175  
   176  				// add or remove the permission from the channel scheme
   177  				var channelSchemePermissions []string
   178  				if channelSchemeHasPermission {
   179  					channelSchemePermissions = []string{permission.Id}
   180  				} else {
   181  					channelSchemePermissions = permissionsDefault
   182  				}
   183  				channelRole, testErr = th.App.PatchRole(channelRole, &model.RolePatch{Permissions: &channelSchemePermissions})
   184  				require.Nil(t, testErr)
   185  
   186  				testCallback(t, th, permissionInheritanceTestData{
   187  					channelRole:          channelRole,
   188  					permission:           permission,
   189  					shouldHavePermission: shouldHavePermission,
   190  					channel:              channel,
   191  					higherScopedRole:     higherScopedRole,
   192  					truthTableRow:        row,
   193  				})
   194  			}
   195  		}
   196  	}
   197  
   198  	// test 24 combinations where the higher-scoped scheme is the SYSTEM scheme
   199  	test(model.CHANNEL_GUEST_ROLE_ID, model.CHANNEL_USER_ROLE_ID, model.CHANNEL_ADMIN_ROLE_ID)
   200  
   201  	// create a team scheme
   202  	teamScheme, err := th.App.CreateScheme(&model.Scheme{
   203  		Name:        model.NewId(),
   204  		DisplayName: model.NewId(),
   205  		Scope:       model.SCHEME_SCOPE_TEAM,
   206  	})
   207  	require.Nil(t, err)
   208  	defer th.App.DeleteScheme(teamScheme.Id)
   209  
   210  	// assign the scheme to the team
   211  	team.SchemeId = &teamScheme.Id
   212  	team, err = th.App.UpdateTeamScheme(team)
   213  	require.Nil(t, err)
   214  
   215  	// test 24 combinations where the higher-scoped scheme is a TEAM scheme
   216  	test(teamScheme.DefaultChannelGuestRole, teamScheme.DefaultChannelUserRole, teamScheme.DefaultChannelAdminRole)
   217  }