System console tiered license check (#30916)

* Make the Mobile Security settings available on Enterprise Advance

* rename to minLicenseTier

* used license tier checks in system console

* lint fix

* renamed license in test

* Made license name display in single line

---------

Co-authored-by: Elias Nahum <nahumhbl@gmail.com>
Этот коммит содержится в:
Harshil Sharma
2025-05-05 14:18:48 +05:30
коммит произвёл GitHub
родитель ea4ab9aa90
Коммит b7ff54acee
5 изменённых файлов: 1243 добавлений и 48 удалений

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

@@ -232,7 +232,7 @@ func GenerateClientConfig(c *model.Config, telemetryID string, license *model.Li
props["ScheduledPosts"] = strconv.FormatBool(*c.ServiceSettings.ScheduledPosts) props["ScheduledPosts"] = strconv.FormatBool(*c.ServiceSettings.ScheduledPosts)
} }
if license.SkuShortName == model.LicenseShortSkuEnterprise { if model.MinimumEnterpriseLicense(license) {
props["MobileEnableBiometrics"] = strconv.FormatBool(*c.NativeAppSettings.MobileEnableBiometrics) props["MobileEnableBiometrics"] = strconv.FormatBool(*c.NativeAppSettings.MobileEnableBiometrics)
props["MobilePreventScreenCapture"] = strconv.FormatBool(*c.NativeAppSettings.MobilePreventScreenCapture) props["MobilePreventScreenCapture"] = strconv.FormatBool(*c.NativeAppSettings.MobilePreventScreenCapture)
props["MobileJailbreakProtection"] = strconv.FormatBool(*c.NativeAppSettings.MobileJailbreakProtection) props["MobileJailbreakProtection"] = strconv.FormatBool(*c.NativeAppSettings.MobileJailbreakProtection)
@@ -402,7 +402,7 @@ func GenerateLimitedClientConfig(c *model.Config, telemetryID string, license *m
props["OpenIdButtonText"] = *c.OpenIdSettings.ButtonText props["OpenIdButtonText"] = *c.OpenIdSettings.ButtonText
} }
if license.SkuShortName == model.LicenseShortSkuEnterprise { if model.MinimumEnterpriseLicense(license) {
props["MobileEnableBiometrics"] = strconv.FormatBool(*c.NativeAppSettings.MobileEnableBiometrics) props["MobileEnableBiometrics"] = strconv.FormatBool(*c.NativeAppSettings.MobileEnableBiometrics)
props["MobilePreventScreenCapture"] = strconv.FormatBool(*c.NativeAppSettings.MobilePreventScreenCapture) props["MobilePreventScreenCapture"] = strconv.FormatBool(*c.NativeAppSettings.MobilePreventScreenCapture)
props["MobileJailbreakProtection"] = strconv.FormatBool(*c.NativeAppSettings.MobileJailbreakProtection) props["MobileJailbreakProtection"] = strconv.FormatBool(*c.NativeAppSettings.MobileJailbreakProtection)

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

@@ -36,7 +36,7 @@ import {searchableStrings as teamAnalyticsSearchableStrings} from 'components/an
import ExternalLink from 'components/external_link'; import ExternalLink from 'components/external_link';
import RestrictedIndicator from 'components/widgets/menu/menu_items/restricted_indicator'; import RestrictedIndicator from 'components/widgets/menu/menu_items/restricted_indicator';
import {Constants, CloudProducts, LicenseSkus, AboutLinks, DocLinks, DeveloperLinks, CacheTypes} from 'utils/constants'; import {Constants, CloudProducts, LicenseSkus, AboutLinks, DocLinks, DeveloperLinks, CacheTypes, getLicenseTier} from 'utils/constants';
import {isCloudLicense} from 'utils/license_utils'; import {isCloudLicense} from 'utils/license_utils';
import {ID_PATH_PATTERN} from 'utils/path'; import {ID_PATH_PATTERN} from 'utils/path';
import {getSiteURL} from 'utils/url'; import {getSiteURL} from 'utils/url';
@@ -228,6 +228,7 @@ export const it = {
cloudLicensed: (config: Partial<AdminConfig>, state: any, license?: ClientLicense) => Boolean(license?.IsLicensed && isCloudLicense(license)), cloudLicensed: (config: Partial<AdminConfig>, state: any, license?: ClientLicense) => Boolean(license?.IsLicensed && isCloudLicense(license)),
licensedForFeature: (feature: string) => (config: Partial<AdminConfig>, state: any, license?: ClientLicense) => Boolean(license?.IsLicensed && license[feature] === 'true'), licensedForFeature: (feature: string) => (config: Partial<AdminConfig>, state: any, license?: ClientLicense) => Boolean(license?.IsLicensed && license[feature] === 'true'),
licensedForSku: (skuName: string) => (config: Partial<AdminConfig>, state: any, license?: ClientLicense) => Boolean(license?.IsLicensed && license.SkuShortName === skuName), licensedForSku: (skuName: string) => (config: Partial<AdminConfig>, state: any, license?: ClientLicense) => Boolean(license?.IsLicensed && license.SkuShortName === skuName),
minLicenseTier: (skuName: string) => (config: Partial<AdminConfig>, state: any, license?: ClientLicense) => Boolean(license?.IsLicensed && getLicenseTier(license.SkuShortName) >= getLicenseTier(skuName)),
licensedForCloudStarter: (config: Partial<AdminConfig>, state: any, license?: ClientLicense) => Boolean(license?.IsLicensed && isCloudLicense(license) && license.SkuShortName === LicenseSkus.Starter), licensedForCloudStarter: (config: Partial<AdminConfig>, state: any, license?: ClientLicense) => Boolean(license?.IsLicensed && isCloudLicense(license) && license.SkuShortName === LicenseSkus.Starter),
hidePaymentInfo: (config: Partial<AdminConfig>, state: any, license?: ClientLicense, enterpriseReady?: boolean, consoleAccess?: ConsoleAccess, cloud?: CloudState) => { hidePaymentInfo: (config: Partial<AdminConfig>, state: any, license?: ClientLicense, enterpriseReady?: boolean, consoleAccess?: ConsoleAccess, cloud?: CloudState) => {
if (!cloud) { if (!cloud) {
@@ -1156,7 +1157,7 @@ const AdminDefinition: AdminDefinitionType = {
title: defineMessage({id: 'admin.sidebar.exportStorage', defaultMessage: 'Export Storage'}), title: defineMessage({id: 'admin.sidebar.exportStorage', defaultMessage: 'Export Storage'}),
isHidden: it.any( isHidden: it.any(
it.not(it.licensedForFeature('Cloud')), it.not(it.licensedForFeature('Cloud')),
it.not(it.licensedForSku(LicenseSkus.Enterprise)), it.not(it.minLicenseTier(LicenseSkus.Enterprise)),
it.configIsFalse('FeatureFlags', 'CloudDedicatedExportUI'), it.configIsFalse('FeatureFlags', 'CloudDedicatedExportUI'),
), ),
schema: { schema: {
@@ -2047,7 +2048,7 @@ const AdminDefinition: AdminDefinitionType = {
title: defineMessage({id: 'admin.sidebar.mobileSecurity', defaultMessage: 'Mobile Security'}), title: defineMessage({id: 'admin.sidebar.mobileSecurity', defaultMessage: 'Mobile Security'}),
isHidden: it.any( isHidden: it.any(
it.not(it.userHasReadPermissionOnResource(RESOURCE_KEYS.ENVIRONMENT.MOBILE_SECURITY)), it.not(it.userHasReadPermissionOnResource(RESOURCE_KEYS.ENVIRONMENT.MOBILE_SECURITY)),
it.not(it.licensedForSku(LicenseSkus.Enterprise)), it.not(it.minLicenseTier(LicenseSkus.Enterprise)),
), ),
schema: { schema: {
id: 'MobileSecuritySettings', id: 'MobileSecuritySettings',
@@ -2080,7 +2081,7 @@ const AdminDefinition: AdminDefinitionType = {
title: defineMessage({id: 'admin.sidebar.mobileSecurity', defaultMessage: 'Mobile Security'}), title: defineMessage({id: 'admin.sidebar.mobileSecurity', defaultMessage: 'Mobile Security'}),
isHidden: it.any( isHidden: it.any(
it.not(it.userHasReadPermissionOnResource(RESOURCE_KEYS.ENVIRONMENT.MOBILE_SECURITY)), it.not(it.userHasReadPermissionOnResource(RESOURCE_KEYS.ENVIRONMENT.MOBILE_SECURITY)),
it.licensedForSku(LicenseSkus.Enterprise), it.minLicenseTier(LicenseSkus.Enterprise),
it.not(it.enterpriseReady), it.not(it.enterpriseReady),
), ),
schema: { schema: {
@@ -2337,7 +2338,7 @@ const AdminDefinition: AdminDefinitionType = {
title: defineMessage({id: 'admin.sidebar.system_properties', defaultMessage: 'System Properties'}), title: defineMessage({id: 'admin.sidebar.system_properties', defaultMessage: 'System Properties'}),
searchableStrings: systemPropertiesSearchableStrings, searchableStrings: systemPropertiesSearchableStrings,
isHidden: it.not(it.all( isHidden: it.not(it.all(
it.licensedForSku(LicenseSkus.Enterprise), it.minLicenseTier(LicenseSkus.Enterprise),
it.configIsTrue('FeatureFlags', 'CustomProfileAttributes'), it.configIsTrue('FeatureFlags', 'CustomProfileAttributes'),
)), )),
schema: { schema: {
@@ -2521,8 +2522,7 @@ const AdminDefinition: AdminDefinitionType = {
help_text: defineMessage({id: 'admin.team.customUserGroupsDescription', defaultMessage: 'When true, users with appropriate permissions can create custom user groups and enables at-mentions for those groups.'}), help_text: defineMessage({id: 'admin.team.customUserGroupsDescription', defaultMessage: 'When true, users with appropriate permissions can create custom user groups and enables at-mentions for those groups.'}),
isDisabled: it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.SITE.USERS_AND_TEAMS)), isDisabled: it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.SITE.USERS_AND_TEAMS)),
isHidden: it.not(it.any( isHidden: it.not(it.any(
it.licensedForSku(LicenseSkus.Enterprise), it.minLicenseTier(LicenseSkus.Professional),
it.licensedForSku(LicenseSkus.Professional),
)), )),
}, },
{ {
@@ -3348,7 +3348,7 @@ const AdminDefinition: AdminDefinitionType = {
ip_filtering: { ip_filtering: {
url: 'site_config/ip_filtering', url: 'site_config/ip_filtering',
title: adminDefinitionMessages.ip_filtering_title, title: adminDefinitionMessages.ip_filtering_title,
isHidden: it.not(it.all(it.configIsTrue('FeatureFlags', 'CloudIPFiltering'), it.licensedForSku('enterprise'))), isHidden: it.not(it.all(it.configIsTrue('FeatureFlags', 'CloudIPFiltering'), it.minLicenseTier(LicenseSkus.Enterprise))),
isDisabled: it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.SITE.IP_FILTERING)), isDisabled: it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.SITE.IP_FILTERING)),
searchableStrings: [adminDefinitionMessages.ip_filtering_title], searchableStrings: [adminDefinitionMessages.ip_filtering_title],
schema: { schema: {
@@ -4008,7 +4008,7 @@ const AdminDefinition: AdminDefinitionType = {
key: 'LdapSettings.CustomProfileAttributes', key: 'LdapSettings.CustomProfileAttributes',
component: CustomProfileAttributes, component: CustomProfileAttributes,
isHidden: it.not(it.all( isHidden: it.not(it.all(
it.licensedForSku(LicenseSkus.Enterprise), it.minLicenseTier(LicenseSkus.Enterprise),
it.configIsTrue('FeatureFlags', 'CustomProfileAttributes'), it.configIsTrue('FeatureFlags', 'CustomProfileAttributes'),
)), )),
}, },
@@ -4720,7 +4720,7 @@ const AdminDefinition: AdminDefinitionType = {
key: 'SamlSettings.CustomProfileAttributes', key: 'SamlSettings.CustomProfileAttributes',
component: CustomProfileAttributes, component: CustomProfileAttributes,
isHidden: it.not(it.all( isHidden: it.not(it.all(
it.licensedForSku(LicenseSkus.Enterprise), it.minLicenseTier(LicenseSkus.Enterprise),
it.configIsTrue('FeatureFlags', 'CustomProfileAttributes'), it.configIsTrue('FeatureFlags', 'CustomProfileAttributes'),
)), )),
}, },
@@ -6413,9 +6413,7 @@ const AdminDefinition: AdminDefinitionType = {
), ),
}, },
help_text_markdown: false, help_text_markdown: false,
isHidden: it.not(it.any( isHidden: it.not(it.minLicenseTier(LicenseSkus.Enterprise)),
it.licensedForSku(LicenseSkus.Enterprise),
it.licensedForSku(LicenseSkus.E20))),
isDisabled: it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.EXPERIMENTAL.FEATURES)), isDisabled: it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.EXPERIMENTAL.FEATURES)),
}, },
{ {
@@ -6434,9 +6432,7 @@ const AdminDefinition: AdminDefinitionType = {
display_name: defineMessage({id: 'admin.experimental.clientSideCertCheck.options.secondary', defaultMessage: 'secondary'}), display_name: defineMessage({id: 'admin.experimental.clientSideCertCheck.options.secondary', defaultMessage: 'secondary'}),
}, },
], ],
isHidden: it.not(it.any( isHidden: it.not(it.minLicenseTier(LicenseSkus.Enterprise)),
it.licensedForSku(LicenseSkus.Enterprise),
it.licensedForSku(LicenseSkus.E20))),
isDisabled: it.any( isDisabled: it.any(
it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.EXPERIMENTAL.FEATURES)), it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.EXPERIMENTAL.FEATURES)),
it.stateIsFalse('ExperimentalSettings.ClientSideCertEnable'), it.stateIsFalse('ExperimentalSettings.ClientSideCertEnable'),
@@ -6699,7 +6695,11 @@ const AdminDefinition: AdminDefinitionType = {
audit_logging: { audit_logging: {
url: 'experimental/audit_logging', url: 'experimental/audit_logging',
title: defineMessage({id: 'admin.sidebar.audit_logging_experimental', defaultMessage: 'Audit Logging'}), title: defineMessage({id: 'admin.sidebar.audit_logging_experimental', defaultMessage: 'Audit Logging'}),
isHidden: it.any(it.not(it.userHasReadPermissionOnResource(RESOURCE_KEYS.EXPERIMENTAL.FEATURES)), it.configIsFalse('FeatureFlags', 'ExperimentalAuditSettingsSystemConsoleUI'), it.not(it.licensedForSku('enterprise'))), isHidden: it.any(
it.not(it.userHasReadPermissionOnResource(RESOURCE_KEYS.EXPERIMENTAL.FEATURES)),
it.configIsFalse('FeatureFlags', 'ExperimentalAuditSettingsSystemConsoleUI'),
it.not(it.minLicenseTier(LicenseSkus.Enterprise)),
),
schema: { schema: {
id: 'ExperimentalAuditSettings', id: 'ExperimentalAuditSettings',
name: 'Audit Log Settings (Experimental)', name: 'Audit Log Settings (Experimental)',

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@@ -359,6 +359,7 @@ describe('components/AdminSidebar', () => {
license: { license: {
IsLicensed: 'true', IsLicensed: 'true',
SkuShortName: 'enterprise', SkuShortName: 'enterprise',
Cloud: 'true',
}, },
config: { config: {
...defaultProps.config, ...defaultProps.config,
@@ -384,6 +385,12 @@ describe('components/AdminSidebar', () => {
Secret: 'office365Secret', Secret: 'office365Secret',
Scope: 'scope', Scope: 'scope',
} as Office365Settings, } as Office365Settings,
FeatureFlags: {
CustomProfileAttributes: true,
CloudDedicatedExportUI: true,
CloudIPFiltering: true,
ExperimentalAuditSettingsSystemConsoleUI: true,
},
}, },
adminDefinition: AdminDefinition, adminDefinition: AdminDefinition,
buildEnterpriseReady: true, buildEnterpriseReady: true,
@@ -482,6 +489,77 @@ describe('components/AdminSidebar', () => {
expect(wrapper).toMatchSnapshot(); expect(wrapper).toMatchSnapshot();
}); });
test('should match snapshot with license with enterprise advanced SKU', () => {
const props: Props = {
license: {
IsLicensed: 'true',
SkuShortName: 'advanced',
Cloud: 'true',
},
config: {
...defaultProps.config,
ExperimentalSettings: {
RestrictSystemAdmin: false,
} as ExperimentalSettings,
PluginSettings: {
Enable: true,
EnableUploads: true,
} as PluginSettings,
GoogleSettings: {
Id: 'googleID',
Secret: 'googleSecret',
Scope: 'scope',
} as SSOSettings,
GitLabSettings: {
Id: 'gitlabID',
Secret: 'gitlabSecret',
Scope: 'scope',
} as SSOSettings,
Office365Settings: {
Id: 'office365ID',
Secret: 'office365Secret',
Scope: 'scope',
} as Office365Settings,
FeatureFlags: {
CustomProfileAttributes: true,
CloudDedicatedExportUI: true,
CloudIPFiltering: true,
ExperimentalAuditSettingsSystemConsoleUI: true,
},
},
adminDefinition: AdminDefinition,
buildEnterpriseReady: true,
navigationBlocked: false,
siteName: 'test snap',
subscriptionProduct: undefined,
plugins: {
plugin_0: {
active: false,
description: 'The plugin 0.',
id: 'plugin_0',
name: 'Plugin 0',
version: '0.1.0',
settings_schema: {
footer: '',
header: '',
settings: [],
},
webapp: {bundle_path: 'webapp/dist/main.js'},
},
},
onSearchChange: jest.fn(),
actions: {
getPlugins: jest.fn(),
},
consoleAccess: {...defaultProps.consoleAccess},
cloud: {...defaultProps.cloud},
showTaskList: false,
};
const wrapper = shallowWithIntl(<AdminSidebar {...props}/>);
expect(wrapper).toMatchSnapshot();
});
describe('generateIndex', () => { describe('generateIndex', () => {
const props: Props = { const props: Props = {
license: {}, license: {},

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

@@ -60,9 +60,7 @@
font-family: Metropolis; font-family: Metropolis;
&__Grid { &__Grid {
display: grid; display: flex;
grid-template-columns: repeat(2, 1fr);
grid-template-rows: 1fr;
} }
.PlanDetails__viewPlansButton { .PlanDetails__viewPlansButton {