MM-63378: Test and fix permission issues with System Manager team access (#30672)

* test PermissionView semantics

* change required ancillary permissions

`PermissionSysconsoleReadReportingTeamStatistics` doesn't strictly need `PermissionViewTeam`, but can work with whatever teams the user has access to.

* remove unnecessary timeouts

* remove redundant comment

* update snapshots

* Update e2e-tests/playwright/specs/functional/system_console/permissions/team_access.spec.ts

Co-authored-by: Saturnino Abril <5334504+saturninoabril@users.noreply.github.com>

---------

Co-authored-by: Saturnino Abril <5334504+saturninoabril@users.noreply.github.com>
Co-authored-by: Mattermost Build <build@mattermost.com>
Этот коммит содержится в:
Jesse Hallam
2025-04-14 12:43:56 -03:00
коммит произвёл GitHub
родитель 848bac2bae
Коммит 6f33b721de
4 изменённых файлов: 179 добавлений и 1 удалений

Просмотреть файл

@@ -0,0 +1,177 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {UserProfile} from '@mattermost/types/users';
import {expect, PlaywrightExtended, test} from '@mattermost/playwright-lib';
// setupSystemManagerRole configures the system manager with the given permission ("Can Edit", "Read only", "No access")
// for the given section and subsection (e.g. "permission_section_reporting_site_statistics" and "permission_section_reporting_team_statistics").
//
// We do this via the system console and not the API because this page has multiple queries to build up the
// final API call that are all ultimately part of the spec, and we want to test the effects of those, not
// merely a hand-created version of the same.
const setupDefaultSystemManagerRole = async (
pw: PlaywrightExtended,
adminUser: UserProfile,
sectionTestId: string,
subsectionTestId: string,
permissionText: string,
) => {
// Login as admin and navigate to System Console
const {systemConsolePage: adminConsolePage} = await pw.testBrowser.login(adminUser);
// Go to System Console
await adminConsolePage.goto();
// Login to the System Console and navigate to Delegated Granular Administration
await adminConsolePage.sidebar.goToItem('Delegated Granular Administration');
// Find the System Manager row in the table
const systemManagerText = adminConsolePage.page.getByText('System Manager', {exact: true}).first();
await expect(systemManagerText).toBeVisible();
// Click on the System Manager text to go to its settings page
await systemManagerText.click();
// Expand the section
const sectionReporting = adminConsolePage.page.locator(`data-testid=${sectionTestId}`);
const hideSubsectionsLink = sectionReporting.getByRole('button').filter({hasText: 'Hide'}).first();
const showSubsectionsLink = sectionReporting.getByRole('button').filter({hasText: 'Show'}).first();
// Check which one is visible and click if needed
const isHideVisible = await hideSubsectionsLink.isVisible();
const isShowVisible = !isHideVisible && (await showSubsectionsLink.isVisible());
if (isShowVisible) {
// Need to expand
await showSubsectionsLink.click();
}
// Get the whole row
const rowReporting = adminConsolePage.page.locator('.PermissionRow').filter({has: sectionReporting});
await rowReporting.click();
// Find the sub section
const subsectionTeamStatistics = rowReporting.locator(`data-testid=${subsectionTestId}`);
await subsectionTeamStatistics.click();
// Look for dropdown button
const dropdownButton = subsectionTeamStatistics.locator('button').first();
// Click the button to open the dropdown menu
await dropdownButton.click();
// Click on the desired option in the dropdown
const permissionOption = subsectionTeamStatistics.locator('.dropdown-menu').getByText(permissionText).first();
await permissionOption.click();
// Click Save button
const saveButton = adminConsolePage.page.getByRole('button', {name: 'Save'}).first();
await saveButton.click();
// Wait for save operation to complete
await adminConsolePage.page.waitForLoadState('networkidle');
// Go back to the main console
await adminConsolePage.goto();
await adminConsolePage.page.waitForLoadState('networkidle');
};
test('MM-63378 System Manager without team access permissions cannot view team details', async ({pw}) => {
const {
adminUser,
adminClient,
user: systemManagerUser,
userClient: systemManagerClient,
team,
} = await pw.initSetup();
// Update user with system_manager role
await adminClient.updateUserRoles(systemManagerUser.id, 'system_user system_manager');
// Create another team of which the user is not a member.
const otherTeam = await adminClient.createTeam(pw.random.team());
// Login as the user
const {systemConsolePage} = await pw.testBrowser.login(systemManagerUser);
// Configure the system manager with the default permissions.
await setupDefaultSystemManagerRole(
pw,
adminUser,
'permission_section_reporting',
'permission_section_reporting_team_statistics',
'Can edit',
);
await setupDefaultSystemManagerRole(
pw,
adminUser,
'permission_section_user_management',
'permission_section_user_management_teams',
'Can edit',
);
// Verify the system manager has access to the site statistics for all teams
await systemConsolePage.goto();
// Navigate to Team Statistics
await systemConsolePage.sidebar.goToItem('Team Statistics');
// Wait for page to fully load
await systemConsolePage.page.waitForLoadState('networkidle');
// Find the team filter dropdown
let teamFilterSelect = systemConsolePage.page.getByTestId('teamFilter');
await expect(teamFilterSelect).toBeVisible();
// Select the team by value
await teamFilterSelect.selectOption({value: team.id});
// Verify the text shows "Team Statistics for <team name>"
let teamStatsHeading = systemConsolePage.page.getByText(`Team Statistics for ${team.display_name}`, {exact: true});
await expect(teamStatsHeading).toBeVisible();
// Select the other team by value
await teamFilterSelect.selectOption({value: otherTeam.id});
// Verify the text shows "Team Statistics for <team name>"
const otherTeamStatsHeading = systemConsolePage.page.getByText(`Team Statistics for ${otherTeam.display_name}`, {
exact: true,
});
await expect(otherTeamStatsHeading).toBeVisible();
// Verify the user has API access to the otherTeam.
const fetchedOtherTeam = await systemManagerClient.getTeam(otherTeam.id);
expect(fetchedOtherTeam.id).toEqual(otherTeam.id);
// Configure the system manager without access to team user management
await setupDefaultSystemManagerRole(
pw,
adminUser,
'permission_section_user_management',
'permission_section_user_management_teams',
'No access',
);
// Verify the system manager only has access to the site statistics for the team they belong to
await systemConsolePage.goto();
// Navigate to Team Statistics
await systemConsolePage.sidebar.goToItem('Team Statistics');
// Find the team filter dropdown
teamFilterSelect = systemConsolePage.page.getByTestId('teamFilter');
await expect(teamFilterSelect).toBeVisible();
// Select the team by value
await teamFilterSelect.selectOption({value: team.id});
// Verify the text shows "Team Statistics for <team name>"
teamStatsHeading = systemConsolePage.page.getByText(`Team Statistics for ${team.display_name}`, {exact: true});
await expect(teamStatsHeading).toBeVisible();
// Verify the user has no API access to the otherTeam.
await expect(systemManagerClient.getTeam(otherTeam.id)).rejects.toThrow();
});

Просмотреть файл

@@ -109,7 +109,6 @@ func init() {
PermissionGetAnalytics,
},
PermissionSysconsoleReadReportingTeamStatistics.Id: {
PermissionViewTeam,
PermissionGetAnalytics,
},
PermissionSysconsoleWriteUserManagementUsers.Id: {

Просмотреть файл

@@ -6,6 +6,7 @@ exports[`admin_console/system_role_permission should match snapshot 1`] = `
>
<div
className="PermissionSection"
data-testid="permission_section_environment"
key="environment"
>
<div

Просмотреть файл

@@ -84,6 +84,7 @@ export default class SystemRolePermission extends React.PureComponent<Props> {
return (
<div
key={section.name}
data-testid={`permission_section_${section.name}`}
className='PermissionSection'
>
<div className='PermissionSectionText'>