Premium SKU (#30396)
* Added premium SKU * removed duplicate enterprise license check functions * Added license check on API layer * lint fix * lint fix * refactured signature: * test: Add comprehensive tests for license tier check functions * fixed test * text update * optimised license checks * fixedf test * Updated license valid function * webapp license checks * handling prekium SKU in webappp: * added plugin api method and general refactoring * Updated tests --------- Co-authored-by: Mattermost Build <build@mattermost.com>
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
21ca303b5e
Коммит
a9f09cadc2
@@ -9,7 +9,7 @@ import type {ClientLicense} from '@mattermost/types/config';
|
||||
import ContactUsButton from 'components/announcement_bar/contact_sales/contact_us';
|
||||
import SetupSystemSvg from 'components/common/svg_images_components/setup_system';
|
||||
|
||||
import {isEnterpriseOrE20License} from 'utils/license_utils';
|
||||
import {isEnterpriseLicense} from 'utils/license_utils';
|
||||
|
||||
export interface EnterpriseEditionProps {
|
||||
isTrialLicense: boolean;
|
||||
@@ -29,7 +29,7 @@ const EnterpriseEditionRightPanel = ({
|
||||
'And more...',
|
||||
];
|
||||
|
||||
const isEnterpriseOrE20 = isEnterpriseOrE20License(license);
|
||||
const isEnterpriseOrE20 = isEnterpriseLicense(license);
|
||||
|
||||
const contactSalesBtn = (
|
||||
<div className='purchase-card'>
|
||||
|
||||
@@ -18,7 +18,7 @@ import ExternalLink from 'components/external_link';
|
||||
import AdminHeader from 'components/widgets/admin_console/admin_header';
|
||||
|
||||
import {AboutLinks, CloudLinks, ModalIdentifiers} from 'utils/constants';
|
||||
import {isLicenseExpired, isLicenseExpiring, isTrialLicense, isEnterpriseOrE20License, licenseSKUWithFirstLetterCapitalized} from 'utils/license_utils';
|
||||
import {isLicenseExpired, isLicenseExpiring, isTrialLicense, licenseSKUWithFirstLetterCapitalized, isEnterpriseLicense} from 'utils/license_utils';
|
||||
|
||||
import type {ModalData} from 'types/actions';
|
||||
|
||||
@@ -384,7 +384,7 @@ export default class LicenseSettings extends React.PureComponent<Props, State> {
|
||||
<div className='panel-card'>
|
||||
{rightPanel}
|
||||
</div>
|
||||
{!isEnterpriseOrE20License(license) && this.comparePlans}
|
||||
{!isEnterpriseLicense(license) && this.comparePlans}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -20,13 +20,15 @@ import {getAdminConsoleUserManagementTableProperties} from 'selectors/views/admi
|
||||
|
||||
import WithTooltip from 'components/with_tooltip';
|
||||
|
||||
import {LicenseSkus, ModalIdentifiers} from 'utils/constants';
|
||||
import {ModalIdentifiers} from 'utils/constants';
|
||||
import {isMinimumProfessionalLicense} from 'utils/license_utils';
|
||||
|
||||
import {ExportErrorModal} from './export_error_modal';
|
||||
import {ExportUserDataModal} from './export_user_data_modal';
|
||||
import {UpgradeExportDataModal} from './upgrade_export_data_modal';
|
||||
|
||||
import {convertTableOptionsToUserReportOptions} from '../utils';
|
||||
|
||||
import './system_users_export.scss';
|
||||
|
||||
interface Props {
|
||||
@@ -47,7 +49,7 @@ export function SystemUsersExport(props: Props) {
|
||||
}
|
||||
|
||||
const license = useSelector(getLicense);
|
||||
const isLicensed = license.IsLicensed === 'true' && (license.SkuShortName === LicenseSkus.Professional || license.SkuShortName === LicenseSkus.Enterprise);
|
||||
const isLicensed = license.IsLicensed === 'true' && isMinimumProfessionalLicense(license);
|
||||
|
||||
async function doExport(checked?: boolean) {
|
||||
const {error} = await dispatch(startUsersBatchExport(tableOptionsToUserReport));
|
||||
|
||||
@@ -36,7 +36,7 @@ import {getTeam} from 'mattermost-redux/selectors/entities/teams';
|
||||
|
||||
import {setNavigationBlocked} from 'actions/admin_actions';
|
||||
|
||||
import {LicenseSkus} from 'utils/constants';
|
||||
import {isMinimumEnterpriseLicense, isMinimumProfessionalLicense} from 'utils/license_utils';
|
||||
|
||||
import ChannelDetails from './channel_details';
|
||||
|
||||
@@ -54,11 +54,11 @@ function mapStateToProps(state: GlobalState, ownProps: OwnProps) {
|
||||
|
||||
const isLicensed = license?.IsLicensed === 'true';
|
||||
|
||||
// Channel Moderation is only available for Professional, Enterprise and backward compatible with E20
|
||||
const channelModerationEnabled = isLicensed && (license.SkuShortName === LicenseSkus.Professional || license.SkuShortName === LicenseSkus.Enterprise || license.SkuShortName === LicenseSkus.E20);
|
||||
// Channel Moderation is only available for Professional and above
|
||||
const channelModerationEnabled = isLicensed && isMinimumProfessionalLicense(license);
|
||||
|
||||
// Channel Groups is only available for Enterprise and backward compatible with E20
|
||||
const channelGroupsEnabled = isLicensed && (license.SkuShortName === LicenseSkus.Enterprise || license.SkuShortName === LicenseSkus.E20);
|
||||
// Channel Groups is only available for Enterprise and above
|
||||
const channelGroupsEnabled = isLicensed && isMinimumEnterpriseLicense(license);
|
||||
|
||||
const guestAccountsEnabled = config.EnableGuestAccounts === 'true';
|
||||
const channelID = ownProps.match.params.channel_id;
|
||||
|
||||
@@ -31,7 +31,7 @@ import {runEaseOfUseChecks} from './dashboard_checks/easy_management';
|
||||
import {runPerformanceChecks} from './dashboard_checks/performance';
|
||||
import {runUpdateChecks} from './dashboard_checks/updates';
|
||||
|
||||
import {daysToLicenseExpire, isEnterpriseOrE20License, getIsStarterLicense} from '../../../utils/license_utils';
|
||||
import {daysToLicenseExpire, getIsStarterLicense, isEnterpriseLicense} from '../../../utils/license_utils';
|
||||
|
||||
export const impactModifiers: Record<ItemStatus, number> = {
|
||||
[ItemStatus.NONE]: 1,
|
||||
@@ -232,7 +232,7 @@ const useMetricsData = (
|
||||
const isLicensed = license?.IsLicensed === 'true' && daysUntilExpiration >= 0;
|
||||
|
||||
const isCloud = license?.Cloud === 'true';
|
||||
const isEnterpriseLicense = isEnterpriseOrE20License(license);
|
||||
const isEnterprise = isEnterpriseLicense(license);
|
||||
const isStarterLicense = getIsStarterLicense(license);
|
||||
|
||||
const [, contactSalesLink] = useOpenSalesLink();
|
||||
@@ -244,13 +244,13 @@ const useMetricsData = (
|
||||
|
||||
const options: Options = useMemo(() => ({
|
||||
isLicensed,
|
||||
isEnterpriseLicense,
|
||||
isEnterpriseLicense: isEnterprise,
|
||||
trialOrEnterpriseCtaConfig,
|
||||
isStarterLicense,
|
||||
isCloud,
|
||||
analytics,
|
||||
installedVersion,
|
||||
}), [isLicensed, isEnterpriseLicense, trialOrEnterpriseCtaConfig, isStarterLicense, isCloud, analytics, installedVersion]);
|
||||
}), [isLicensed, isEnterprise, trialOrEnterpriseCtaConfig, isStarterLicense, isCloud, analytics, installedVersion]);
|
||||
|
||||
useEffect(() => {
|
||||
setLoading(true);
|
||||
|
||||
@@ -34,7 +34,7 @@ describe('components/ConfigurationBar', () => {
|
||||
};
|
||||
|
||||
test('should match snapshot, expired, in grace period', () => {
|
||||
const props = {...baseProps, license: {Id: '1234', IsLicensed: 'true', ExpiresAt: Date.now() - millisPerDay}};
|
||||
const props = {...baseProps, license: {Id: '1234', IsLicensed: 'true', ExpiresAt: Date.now() - millisPerDay, SkuShortName: 'enterprise'}};
|
||||
const wrapper = shallowWithIntl(
|
||||
<ConfigurationBar {...props}/>,
|
||||
);
|
||||
@@ -43,7 +43,7 @@ describe('components/ConfigurationBar', () => {
|
||||
});
|
||||
|
||||
test('should match snapshot, expired', () => {
|
||||
const props = {...baseProps, license: {Id: '1234', IsLicensed: 'true', ExpiresAt: Date.now() - (11 * millisPerDay)}};
|
||||
const props = {...baseProps, license: {Id: '1234', IsLicensed: 'true', ExpiresAt: Date.now() - (11 * millisPerDay), SkuShortName: 'enterprise'}};
|
||||
const wrapper = shallowWithIntl(
|
||||
<ConfigurationBar {...props}/>,
|
||||
);
|
||||
@@ -52,7 +52,7 @@ describe('components/ConfigurationBar', () => {
|
||||
});
|
||||
|
||||
test('should match snapshot, expired, regular user', () => {
|
||||
const props = {...baseProps, canViewSystemErrors: false, license: {Id: '1234', IsLicensed: 'true', ExpiresAt: Date.now() - (11 * millisPerDay)}};
|
||||
const props = {...baseProps, canViewSystemErrors: false, license: {Id: '1234', IsLicensed: 'true', ExpiresAt: Date.now() - (11 * millisPerDay), SkuShortName: 'enterprise'}};
|
||||
const wrapper = shallowWithIntl(
|
||||
<ConfigurationBar {...props}/>,
|
||||
);
|
||||
|
||||
@@ -11,7 +11,7 @@ import {getMySystemPermissions, haveISystemPermission} from 'mattermost-redux/se
|
||||
|
||||
import AdminDefinition from 'components/admin_console/admin_definition';
|
||||
|
||||
import {isEnterpriseOrE20License} from '../utils/license_utils';
|
||||
import {isEnterpriseLicense} from '../utils/license_utils';
|
||||
|
||||
export const getAdminDefinition = createSelector(
|
||||
'getAdminDefinition',
|
||||
@@ -64,7 +64,7 @@ export const getShowManageUserSettings = createSelector(
|
||||
(license, state) => {
|
||||
const hasWriteUserManagementPermission = haveISystemPermission(state, {permission: Permissions.SYSCONSOLE_WRITE_USERMANAGEMENT_USERS});
|
||||
|
||||
const isEnterprise = isEnterpriseOrE20License(license);
|
||||
const isEnterprise = isEnterpriseLicense(license);
|
||||
|
||||
return hasWriteUserManagementPermission && isEnterprise;
|
||||
},
|
||||
@@ -77,7 +77,7 @@ export const getShowLockedManageUserSettings = createSelector(
|
||||
(license, state) => {
|
||||
const hasWriteUserManagementPermission = haveISystemPermission(state, {permission: Permissions.SYSCONSOLE_WRITE_USERMANAGEMENT_USERS});
|
||||
|
||||
const isEnterprise = isEnterpriseOrE20License(license);
|
||||
const isEnterprise = isEnterpriseLicense(license);
|
||||
|
||||
return hasWriteUserManagementPermission && !isEnterprise;
|
||||
},
|
||||
|
||||
@@ -539,6 +539,20 @@ export enum LicenseSkus {
|
||||
Starter = 'starter',
|
||||
Professional = 'professional',
|
||||
Enterprise = 'enterprise',
|
||||
Premium = 'premium',
|
||||
}
|
||||
|
||||
export function getLicenseTier(licenseSku: string): number {
|
||||
switch (licenseSku) {
|
||||
case LicenseSkus.Professional:
|
||||
return 10;
|
||||
case LicenseSkus.Enterprise:
|
||||
return 20;
|
||||
case LicenseSkus.Premium:
|
||||
return 30;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
export const CloudProductToSku = {
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {LicenseSkus} from 'utils/constants';
|
||||
import {isLicenseExpired, isLicenseExpiring, isLicensePastGracePeriod, isEnterpriseOrE20License} from 'utils/license_utils';
|
||||
import {isLicenseExpired, isLicenseExpiring, isLicensePastGracePeriod} from 'utils/license_utils';
|
||||
|
||||
describe('license_utils', () => {
|
||||
const millisPerDay = 24 * 60 * 60 * 1000;
|
||||
@@ -46,24 +45,4 @@ describe('license_utils', () => {
|
||||
expect(isLicensePastGracePeriod(license)).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('isEnterpriseOrE20License', () => {
|
||||
it('should return False if not Enterprise or E20', () => {
|
||||
const license = {Id: '1234', IsLicensed: 'true', Cloud: 'false', SkuShortName: LicenseSkus.Starter};
|
||||
|
||||
expect(isEnterpriseOrE20License(license)).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should return True if Enterprise', () => {
|
||||
const license = {Id: '1234', IsLicensed: 'true', Cloud: 'false', SkuShortName: LicenseSkus.Enterprise};
|
||||
|
||||
expect(isEnterpriseOrE20License(license)).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should return True if E20', () => {
|
||||
const license = {Id: '1234', IsLicensed: 'true', Cloud: 'false', SkuShortName: LicenseSkus.E20};
|
||||
|
||||
expect(isEnterpriseOrE20License(license)).toBeTruthy();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -6,7 +6,7 @@ import moment from 'moment';
|
||||
import type {Product} from '@mattermost/types/cloud';
|
||||
import type {ClientLicense} from '@mattermost/types/config';
|
||||
|
||||
import {CloudProducts, LicenseSkus, SelfHostedProducts} from 'utils/constants';
|
||||
import {CloudProducts, getLicenseTier, LicenseSkus, SelfHostedProducts} from 'utils/constants';
|
||||
|
||||
const LICENSE_EXPIRY_NOTIFICATION = 1000 * 60 * 60 * 24 * 60; // 60 days
|
||||
const LICENSE_GRACE_PERIOD = 1000 * 60 * 60 * 24 * 10; // 10 days
|
||||
@@ -84,14 +84,11 @@ export function getIsGovSku(license: ClientLicense) {
|
||||
return license?.IsGovSku === 'true';
|
||||
}
|
||||
|
||||
export function isEnterpriseOrE20License(license: ClientLicense) {
|
||||
return license?.SkuShortName === LicenseSkus.Enterprise || license?.SkuShortName === LicenseSkus.E20;
|
||||
}
|
||||
|
||||
export const isEnterpriseLicense = (license?: ClientLicense) => {
|
||||
switch (license?.SkuShortName) {
|
||||
case LicenseSkus.Enterprise:
|
||||
case LicenseSkus.E20:
|
||||
case LicenseSkus.Premium:
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -115,3 +112,19 @@ export function isEnterpriseOrCloudOrSKUStarterFree(license: ClientLicense, subs
|
||||
|
||||
return isCloudStarterFree || isSelfHostedStarter || isStarterSKULicense;
|
||||
}
|
||||
|
||||
export function isMinimumProfessionalLicense(license: ClientLicense): boolean {
|
||||
if (!license) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return getLicenseTier(license.SkuShortName) >= getLicenseTier(LicenseSkus.Professional);
|
||||
}
|
||||
|
||||
export function isMinimumEnterpriseLicense(license: ClientLicense): boolean {
|
||||
if (!license) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return getLicenseTier(license.SkuShortName) >= getLicenseTier(LicenseSkus.Enterprise);
|
||||
}
|
||||
|
||||
@@ -18,9 +18,12 @@ export const getSkuDisplayName = (skuShortName: string, isGovSku: boolean): stri
|
||||
case LicenseSkus.Starter:
|
||||
skuName = 'Starter';
|
||||
break;
|
||||
default:
|
||||
case LicenseSkus.Enterprise:
|
||||
skuName = 'Enterprise';
|
||||
break;
|
||||
default:
|
||||
skuName = 'Premium';
|
||||
break;
|
||||
}
|
||||
|
||||
skuName += isGovSku ? ' Gov' : '';
|
||||
|
||||
Ссылка в новой задаче
Block a user