Add system console settings for mobile security (#30456)

* Add config settings for additional security features on mobile

* Add system console settings for mobile security

* Update svg and link

* Fix strings

* Add test for the discovery feature

* Fix tests

* Add permission migrations

* Add relevant e2e tests

* Fix key alignment

* fix tests

* Fix lint

* Mock new migration

* Fix playwright prettier

* Add new section to delegated permissions

* Update snapshots

* Fix flakyness in playwright test

---------

Co-authored-by: Elias Nahum <nahumhbl@gmail.com>
Co-authored-by: Mattermost Build <build@mattermost.com>
Этот коммит содержится в:
Daniel Espino García
2025-03-27 13:13:20 +01:00
коммит произвёл GitHub
родитель 8ce78c302d
Коммит 7999239ccf
29 изменённых файлов: 2990 добавлений и 5 удалений

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

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

@@ -36,6 +36,8 @@ import {SystemUsersColumnToggleMenu} from './system_console/sections/system_user
import ChannelsPostEdit from '@e2e-support/ui/components/channels/post_edit';
import DeletePostConfirmationDialog from '@e2e-support/ui/components/channels/delete_post_confirmation_dialog';
import RestorePostConfirmationDialog from '@e2e-support/ui/components/channels/restore_post_confirmation_dialog';
import MobileSecurity from './system_console/sections/system_users/mobile_security';
import FeatureDiscovery from './system_console/sections/system_users/feature_discovery';
const components = {
GlobalHeader,
@@ -71,6 +73,8 @@ const components = {
UserProfilePopover,
DeletePostConfirmationDialog,
RestorePostConfirmationDialog,
MobileSecurity,
FeatureDiscovery,
};
export {

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

@@ -0,0 +1,25 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {expect, Locator} from '@playwright/test';
/**
* System Console -> Feature Discovery
*/
export default class FeatureDiscovery {
readonly container: Locator;
constructor(container: Locator) {
this.container = container;
}
async toBeVisible() {
await expect(this.container).toBeVisible();
}
async toHaveTitle(title: string) {
await expect(this.container.getByTestId('featureDiscovery_title')).toHaveText(title);
}
}
export {FeatureDiscovery};

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

@@ -0,0 +1,81 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {expect, Locator} from '@playwright/test';
/**
* System Console -> Environment -> Mobile Security
*/
export default class MobileSecurity {
readonly container: Locator;
readonly enableBiometricAuthenticationToggleTrue: Locator;
readonly enableBiometricAuthenticationToggleFalse: Locator;
readonly preventScreenCaptureToggleTrue: Locator;
readonly preventScreenCaptureToggleFalse: Locator;
readonly jailbreakProtectionToggleTrue: Locator;
readonly jailbreakProtectionToggleFalse: Locator;
readonly saveButton: Locator;
constructor(container: Locator) {
this.container = container;
this.enableBiometricAuthenticationToggleTrue = this.container.getByTestId(
'NativeAppSettings.MobileEnableBiometricstrue',
);
this.enableBiometricAuthenticationToggleFalse = this.container.getByTestId(
'NativeAppSettings.MobileEnableBiometricsfalse',
);
this.preventScreenCaptureToggleTrue = this.container.getByTestId(
'NativeAppSettings.MobilePreventScreenCapturetrue',
);
this.preventScreenCaptureToggleFalse = this.container.getByTestId(
'NativeAppSettings.MobilePreventScreenCapturefalse',
);
this.jailbreakProtectionToggleTrue = this.container.getByTestId(
'NativeAppSettings.MobileJailbreakProtectiontrue',
);
this.jailbreakProtectionToggleFalse = this.container.getByTestId(
'NativeAppSettings.MobileJailbreakProtectionfalse',
);
this.saveButton = this.container.getByRole('button', {name: 'Save'});
}
async toBeVisible() {
await expect(this.container).toBeVisible();
}
async clickEnableBiometricAuthenticationToggleTrue() {
await this.enableBiometricAuthenticationToggleTrue.click();
}
async clickEnableBiometricAuthenticationToggleFalse() {
await this.enableBiometricAuthenticationToggleFalse.click();
}
async clickPreventScreenCaptureToggleTrue() {
await this.preventScreenCaptureToggleTrue.click();
}
async clickPreventScreenCaptureToggleFalse() {
await this.preventScreenCaptureToggleFalse.click();
}
async clickJailbreakProtectionToggleTrue() {
await this.jailbreakProtectionToggleTrue.click();
}
async clickJailbreakProtectionToggleFalse() {
await this.jailbreakProtectionToggleFalse.click();
}
async clickSaveButton() {
await this.saveButton.click();
}
}
export {MobileSecurity};

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

@@ -21,6 +21,10 @@ class SystemConsolePage {
readonly systemUsersColumnToggleMenu;
readonly systemUsersActionMenus;
readonly mobileSecurity;
readonly featureDiscovery;
// modal
readonly confirmModal;
readonly exportModal;
@@ -35,6 +39,10 @@ class SystemConsolePage {
// Sections and sub-sections
this.systemUsers = new components.SystemUsers(page.getByTestId('systemUsersSection'));
this.mobileSecurity = new components.MobileSecurity(
page.getByTestId('sysconsole_section_MobileSecuritySettings'),
);
this.featureDiscovery = new components.FeatureDiscovery(page.getByTestId('featureDiscovery'));
// Menus & Popovers
this.systemUsersFilterPopover = new components.SystemUsersFilterPopover(

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

@@ -0,0 +1,126 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {waitUntil} from '@e2e-support/test_action';
import {expect, test} from '@e2e-support/test_fixture';
test('should be able to enable mobile security settings when licensed', async ({pw}) => {
const {adminUser, adminClient} = await pw.initSetup();
const license = await adminClient.getClientLicenseOld();
test.skip(license.SkuShortName !== 'enterprise', 'Skipping test - server has no enterprise license');
if (!adminUser) {
throw new Error('Failed to create admin user');
}
// # Log in as admin
const {systemConsolePage} = await pw.testBrowser.login(adminUser);
// # Visit system console
await systemConsolePage.goto();
await systemConsolePage.toBeVisible();
// # Go to Mobile Security section
await systemConsolePage.sidebar.goToItem('Mobile Security');
await systemConsolePage.mobileSecurity.toBeVisible();
// # Enable Biometric Authentication
await systemConsolePage.mobileSecurity.clickEnableBiometricAuthenticationToggleTrue();
// * Verify only Biometric Authentication is enabled
expect(await systemConsolePage.mobileSecurity.enableBiometricAuthenticationToggleTrue.isChecked()).toBe(true);
expect(await systemConsolePage.mobileSecurity.preventScreenCaptureToggleTrue.isChecked()).toBe(false);
expect(await systemConsolePage.mobileSecurity.jailbreakProtectionToggleTrue.isChecked()).toBe(false);
// # Save settings
await systemConsolePage.mobileSecurity.clickSaveButton();
// # Wait until the save button has settled
await waitUntil(async () => (await systemConsolePage.mobileSecurity.saveButton.textContent()) === 'Save');
// # Go to any other section and come back to Mobile Security
await systemConsolePage.sidebar.goToItem('Users');
await systemConsolePage.systemUsers.toBeVisible();
await systemConsolePage.sidebar.goToItem('Mobile Security');
// * Verify Biometric Authentication is still enabled
expect(await systemConsolePage.mobileSecurity.enableBiometricAuthenticationToggleTrue.isChecked()).toBe(true);
expect(await systemConsolePage.mobileSecurity.preventScreenCaptureToggleTrue.isChecked()).toBe(false);
expect(await systemConsolePage.mobileSecurity.jailbreakProtectionToggleTrue.isChecked()).toBe(false);
// # Enable Prevent Screen Capture
await systemConsolePage.mobileSecurity.clickPreventScreenCaptureToggleTrue();
// * Verify only Biometric Authentication and Prevent Screen Capture are enabled
expect(await systemConsolePage.mobileSecurity.enableBiometricAuthenticationToggleTrue.isChecked()).toBe(true);
expect(await systemConsolePage.mobileSecurity.preventScreenCaptureToggleTrue.isChecked()).toBe(true);
expect(await systemConsolePage.mobileSecurity.jailbreakProtectionToggleTrue.isChecked()).toBe(false);
// # Save settings
await systemConsolePage.mobileSecurity.clickSaveButton();
// # Wait until the save button has settled
await waitUntil(async () => (await systemConsolePage.mobileSecurity.saveButton.textContent()) === 'Save');
// # Go to any other section and come back to Mobile Security
await systemConsolePage.sidebar.goToItem('Users');
await systemConsolePage.systemUsers.toBeVisible();
await systemConsolePage.sidebar.goToItem('Mobile Security');
// * Verify Biometric Authentication and Prevent Screen Capture are still enabled
expect(await systemConsolePage.mobileSecurity.enableBiometricAuthenticationToggleTrue.isChecked()).toBe(true);
expect(await systemConsolePage.mobileSecurity.preventScreenCaptureToggleTrue.isChecked()).toBe(true);
expect(await systemConsolePage.mobileSecurity.jailbreakProtectionToggleTrue.isChecked()).toBe(false);
// # Enable Jailbreak Protection
await systemConsolePage.mobileSecurity.clickJailbreakProtectionToggleTrue();
// * Verify all toggles are enabled
expect(await systemConsolePage.mobileSecurity.enableBiometricAuthenticationToggleTrue.isChecked()).toBe(true);
expect(await systemConsolePage.mobileSecurity.preventScreenCaptureToggleTrue.isChecked()).toBe(true);
expect(await systemConsolePage.mobileSecurity.jailbreakProtectionToggleTrue.isChecked()).toBe(true);
// # Save settings
await systemConsolePage.mobileSecurity.clickSaveButton();
// # Wait until the save button has settled
await waitUntil(async () => (await systemConsolePage.mobileSecurity.saveButton.textContent()) === 'Save');
// # Go to any other section and come back to Mobile Security
await systemConsolePage.sidebar.goToItem('Users');
await systemConsolePage.systemUsers.toBeVisible();
await systemConsolePage.sidebar.goToItem('Mobile Security');
// * Verify all toggles are still enabled
expect(await systemConsolePage.mobileSecurity.enableBiometricAuthenticationToggleTrue.isChecked()).toBe(true);
expect(await systemConsolePage.mobileSecurity.preventScreenCaptureToggleTrue.isChecked()).toBe(true);
expect(await systemConsolePage.mobileSecurity.jailbreakProtectionToggleTrue.isChecked()).toBe(true);
});
test('should show mobile security upsell when not licensed', async ({pw}) => {
const {adminUser, adminClient} = await pw.initSetup();
const license = await adminClient.getClientLicenseOld();
test.skip(license.SkuShortName === 'enterprise', 'Skipping test - server has enterprise license');
if (!adminUser) {
throw new Error('Failed to create admin user');
}
// # Log in as admin
const {systemConsolePage} = await pw.testBrowser.login(adminUser);
// # Visit system console
await systemConsolePage.goto();
await systemConsolePage.toBeVisible();
// # Go to Mobile Security section
await systemConsolePage.sidebar.goToItem('Mobile Security');
await systemConsolePage.featureDiscovery.toBeVisible();
// * Verify title is correct
await systemConsolePage.featureDiscovery.toHaveTitle('Enhance mobile app security with Mattermost Enterprise');
});