diff --git a/packages/x-data-grid-premium/src/tests/license.DataGridPremium.test.tsx b/packages/x-data-grid-premium/src/tests/license.DataGridPremium.test.tsx index 9879b1d182603..1b6d15e194f20 100644 --- a/packages/x-data-grid-premium/src/tests/license.DataGridPremium.test.tsx +++ b/packages/x-data-grid-premium/src/tests/license.DataGridPremium.test.tsx @@ -13,7 +13,7 @@ describe(' - License', () => { generateLicense({ expiryDate: addYears(new Date(), 1), orderNumber: 'Test', - licensingModel: 'subscription', + licenseModel: 'subscription', scope: 'pro', planVersion: 'initial', }), diff --git a/packages/x-license/src/generateLicense/generateLicense.test.ts b/packages/x-license/src/generateLicense/generateLicense.test.ts index 90ea9768276d2..d09584737fd7f 100644 --- a/packages/x-license/src/generateLicense/generateLicense.test.ts +++ b/packages/x-license/src/generateLicense/generateLicense.test.ts @@ -7,8 +7,8 @@ describe('License: generateLicense', () => { generateLicense({ expiryDate: new Date(1591723879062), orderNumber: 'MUI-123', - scope: 'pro', - licensingModel: 'subscription', + planScope: 'pro', + licenseModel: 'subscription', planVersion: 'initial', }), ).to.equal( @@ -21,8 +21,8 @@ describe('License: generateLicense', () => { generateLicense({ expiryDate: new Date(1591723879062), orderNumber: 'MUI-123', - scope: 'premium', - licensingModel: 'subscription', + planScope: 'premium', + licenseModel: 'subscription', planVersion: 'initial', }), ).to.equal( @@ -30,13 +30,13 @@ describe('License: generateLicense', () => { ); }); - it('should generate annual license when `licensingModel: "subscription"`', () => { + it('should generate annual license when `licenseModel: "subscription"`', () => { expect( generateLicense({ expiryDate: new Date(1591723879062), orderNumber: 'MUI-123', - scope: 'pro', - licensingModel: 'subscription', + planScope: 'pro', + licenseModel: 'subscription', planVersion: 'initial', }), ).to.equal( @@ -44,13 +44,13 @@ describe('License: generateLicense', () => { ); }); - it('should generate perpetual license when `licensingModel: "perpetual"`', () => { + it('should generate perpetual license when `licenseModel: "perpetual"`', () => { expect( generateLicense({ expiryDate: new Date(1591723879062), orderNumber: 'MUI-123', - scope: 'pro', - licensingModel: 'perpetual', + planScope: 'pro', + licenseModel: 'perpetual', planVersion: 'initial', }), ).to.equal( @@ -63,8 +63,8 @@ describe('License: generateLicense', () => { generateLicense({ expiryDate: new Date(1591723879062), orderNumber: 'MUI-123', - scope: 'pro', - licensingModel: 'subscription', + planScope: 'pro', + licenseModel: 'subscription', planVersion: 'Q3-2024', }), ).to.equal( @@ -77,8 +77,8 @@ describe('License: generateLicense', () => { generateLicense({ expiryDate: new Date(1591723879062), orderNumber: 'MUI-123', - scope: 'premium', - licensingModel: 'subscription', + planScope: 'premium', + licenseModel: 'subscription', planVersion: 'Q3-2024', }), ).to.equal( diff --git a/packages/x-license/src/generateLicense/generateLicense.ts b/packages/x-license/src/generateLicense/generateLicense.ts index 107b510888d0a..dc2b64d5bd834 100644 --- a/packages/x-license/src/generateLicense/generateLicense.ts +++ b/packages/x-license/src/generateLicense/generateLicense.ts @@ -1,17 +1,23 @@ import { md5 } from '../encoding/md5'; import { base64Encode } from '../encoding/base64'; -import { LICENSE_SCOPES, LicenseScope, PlanVersion } from '../utils/licenseScope'; -import { LICENSING_MODELS, LicensingModel } from '../utils/licensingModel'; +import { PLAN_SCOPES, PlanScope, PlanVersion } from '../utils/plan'; +import { LICENSE_MODELS, LicenseModel } from '../utils/licenseModel'; const licenseVersion = '2'; export interface LicenseDetails { orderNumber: string; expiryDate: Date; - scope?: LicenseScope; - planScope?: LicenseScope; // TODO deprecate - licenseModel?: LicensingModel; - licensingModel?: LicensingModel; // TODO deprecate + /** + * @deprecated Use planScope instead. + */ + scope?: PlanScope; + planScope?: PlanScope; + /** + * @deprecated Use licenseModel instead. + */ + licensingModel?: LicenseModel; // TODO deprecate + licenseModel?: LicenseModel; planVersion: PlanVersion; } @@ -25,11 +31,11 @@ function getClearLicenseString(details: LicenseDetails) { details.planScope = details.scope; } - if (details.planScope && !LICENSE_SCOPES.includes(details.planScope)) { + if (details.planScope && !PLAN_SCOPES.includes(details.planScope)) { throw new Error('MUI X: Invalid scope'); } - if (details.licenseModel && !LICENSING_MODELS.includes(details.licenseModel)) { + if (details.licenseModel && !LICENSE_MODELS.includes(details.licenseModel)) { throw new Error('MUI X: Invalid licensing model'); } diff --git a/packages/x-license/src/useLicenseVerifier/useLicenseVerifier.test.tsx b/packages/x-license/src/useLicenseVerifier/useLicenseVerifier.test.tsx index 25a4aaa6f27c1..7605292c6acd8 100644 --- a/packages/x-license/src/useLicenseVerifier/useLicenseVerifier.test.tsx +++ b/packages/x-license/src/useLicenseVerifier/useLicenseVerifier.test.tsx @@ -61,9 +61,9 @@ describe('useLicenseVerifier', function test() { it('should detect an override of a valid license key in the context', () => { const key = generateLicense({ expiryDate: new Date(3001, 0, 0, 0, 0, 0, 0), - licensingModel: 'perpetual', + licenseModel: 'perpetual', orderNumber: '12345', - scope: 'pro', + planScope: 'pro', planVersion: 'initial', }); @@ -88,8 +88,8 @@ describe('useLicenseVerifier', function test() { const expiredLicenseKey = generateLicense({ expiryDate: new Date(new Date().getTime() - oneDayInMS * 30), orderNumber: 'MUI-123', - scope: 'pro', - licensingModel: 'subscription', + planScope: 'pro', + licenseModel: 'subscription', planVersion: 'initial', }); LicenseInfo.setLicenseKey(expiredLicenseKey); @@ -117,8 +117,8 @@ describe('useLicenseVerifier', function test() { const licenseKey = generateLicense({ expiryDate: new Date(3001, 0, 0, 0, 0, 0, 0), orderNumber: 'MUI-123', - scope: 'pro', - licensingModel: 'subscription', + planScope: 'pro', + licenseModel: 'subscription', planVersion: 'initial', }); @@ -141,8 +141,8 @@ describe('useLicenseVerifier', function test() { const licenseKey = generateLicense({ expiryDate: new Date(3001, 0, 0, 0, 0, 0, 0), orderNumber: 'MUI-123', - scope: 'pro', - licensingModel: 'subscription', + planScope: 'pro', + licenseModel: 'subscription', planVersion: 'Q3-2024', }); @@ -165,8 +165,8 @@ describe('useLicenseVerifier', function test() { const licenseKey = generateLicense({ expiryDate: new Date(3001, 0, 0, 0, 0, 0, 0), orderNumber: 'MUI-123', - scope: 'premium', - licensingModel: 'subscription', + planScope: 'premium', + licenseModel: 'subscription', planVersion: 'Q3-2024', }); diff --git a/packages/x-license/src/utils/index.ts b/packages/x-license/src/utils/index.ts index 7197239c1e953..f63e9b2033eb6 100644 --- a/packages/x-license/src/utils/index.ts +++ b/packages/x-license/src/utils/index.ts @@ -1,6 +1,6 @@ export * from './licenseErrorMessageUtils'; export * from './licenseInfo'; export * from './licenseStatus'; -export type { LicenseScope } from './licenseScope'; -export type { LicensingModel } from './licensingModel'; +export type { PlanScope } from './plan'; +export type { LicenseModel } from './licenseModel'; export type { MuiCommercialPackageName } from './commercialPackages'; diff --git a/packages/x-license/src/utils/licensingModel.ts b/packages/x-license/src/utils/licenseModel.ts similarity index 78% rename from packages/x-license/src/utils/licensingModel.ts rename to packages/x-license/src/utils/licenseModel.ts index 5ba1d0394d325..c9d7ebe170f85 100644 --- a/packages/x-license/src/utils/licensingModel.ts +++ b/packages/x-license/src/utils/licenseModel.ts @@ -1,4 +1,4 @@ -export const LICENSING_MODELS = [ +export const LICENSE_MODELS = [ /** * A license is outdated if the current version of the software was released after the expiry date of the license. * But the license can be used indefinitely with an older version of the software. @@ -10,9 +10,9 @@ export const LICENSING_MODELS = [ */ 'annual', /** - * TODO 2025 remove, legacy name of annual. + * TODO 2026 remove, legacy name of annual. */ 'subscription', ] as const; -export type LicensingModel = (typeof LICENSING_MODELS)[number]; +export type LicenseModel = (typeof LICENSE_MODELS)[number]; diff --git a/packages/x-license/src/utils/licenseScope.ts b/packages/x-license/src/utils/plan.ts similarity index 50% rename from packages/x-license/src/utils/licenseScope.ts rename to packages/x-license/src/utils/plan.ts index f998b354f7b0a..15933a3cd606c 100644 --- a/packages/x-license/src/utils/licenseScope.ts +++ b/packages/x-license/src/utils/plan.ts @@ -1,5 +1,5 @@ -export const LICENSE_SCOPES = ['pro', 'premium'] as const; +export const PLAN_SCOPES = ['pro', 'premium'] as const; export const PLAN_VERSIONS = ['initial', 'Q3-2024'] as const; -export type LicenseScope = (typeof LICENSE_SCOPES)[number]; +export type PlanScope = (typeof PLAN_SCOPES)[number]; export type PlanVersion = (typeof PLAN_VERSIONS)[number]; diff --git a/packages/x-license/src/verifyLicense/verifyLicense.test.ts b/packages/x-license/src/verifyLicense/verifyLicense.test.ts index 3b096e31abae1..6876193cabd23 100644 --- a/packages/x-license/src/verifyLicense/verifyLicense.test.ts +++ b/packages/x-license/src/verifyLicense/verifyLicense.test.ts @@ -50,8 +50,8 @@ describe('License: verifyLicense', () => { process.env.NODE_ENV = 'production'; const expiredLicenseKey = generateLicense({ expiryDate: new Date(releaseDate.getTime() - oneDayInMS), - scope: 'pro', - licensingModel: 'perpetual', + planScope: 'pro', + licenseModel: 'perpetual', orderNumber: 'MUI-123', planVersion: 'initial', }); @@ -82,16 +82,16 @@ describe('License: verifyLicense', () => { const licenseKeyPro = generateLicense({ expiryDate: new Date(releaseDate.getTime() + oneDayInMS), orderNumber: 'MUI-123', - scope: 'pro', - licensingModel: 'subscription', + planScope: 'pro', + licenseModel: 'subscription', planVersion: 'initial', }); const licenseKeyPremium = generateLicense({ expiryDate: new Date(releaseDate.getTime() + oneDayInMS), orderNumber: 'MUI-123', - scope: 'premium', - licensingModel: 'subscription', + planScope: 'premium', + licenseModel: 'subscription', planVersion: 'initial', }); @@ -148,8 +148,8 @@ describe('License: verifyLicense', () => { const expiredLicenseKey = generateLicense({ expiryDate: new Date(releaseDate.getTime() + oneDayInMS), orderNumber: 'MUI-123', - scope: 'pro', - licensingModel: 'subscription', + planScope: 'pro', + licenseModel: 'subscription', planVersion: 'initial', }); @@ -166,8 +166,8 @@ describe('License: verifyLicense', () => { const expiredLicenseKey = generateLicense({ expiryDate: new Date(new Date().getTime() - oneDayInMS), orderNumber: 'MUI-123', - scope: 'pro', - licensingModel: 'subscription', + planScope: 'pro', + licenseModel: 'subscription', planVersion: 'initial', }); @@ -185,8 +185,8 @@ describe('License: verifyLicense', () => { const expiredLicenseKey = generateLicense({ expiryDate: new Date(new Date().getTime() - oneDayInMS * 30), orderNumber: 'MUI-123', - scope: 'pro', - licensingModel: 'subscription', + planScope: 'pro', + licenseModel: 'subscription', planVersion: 'initial', }); @@ -203,8 +203,8 @@ describe('License: verifyLicense', () => { const expiredLicenseKey = generateLicense({ expiryDate: new Date(releaseDate.getTime() + oneDayInMS), orderNumber: 'MUI-123', - scope: 'pro', - licensingModel: 'perpetual', + planScope: 'pro', + licenseModel: 'perpetual', planVersion: 'initial', }); @@ -235,12 +235,12 @@ describe('License: verifyLicense', () => { const licenseKeyPro = generateLicense({ expiryDate: new Date(releaseDate.getTime() + oneDayInMS), orderNumber: 'MUI-123', - scope: 'pro', - licensingModel: 'annual', + planScope: 'pro', + licenseModel: 'annual', planVersion: 'initial', }); - it('should accept licensingModel="annual"', () => { + it('should accept licenseModel="annual"', () => { process.env.NODE_ENV = 'production'; expect( verifyLicense({ @@ -256,24 +256,24 @@ describe('License: verifyLicense', () => { const proLicenseKeyInitial = generateLicense({ expiryDate: new Date(releaseDate.getTime() + oneDayInMS), orderNumber: 'MUI-123', - scope: 'pro', - licensingModel: 'annual', + planScope: 'pro', + licenseModel: 'annual', planVersion: 'initial', }); const premiumLicenseKeyInitial = generateLicense({ expiryDate: new Date(releaseDate.getTime() + oneDayInMS), orderNumber: 'MUI-123', - scope: 'premium', - licensingModel: 'annual', + planScope: 'premium', + licenseModel: 'annual', planVersion: 'initial', }); const proLicenseKeyQ32024 = generateLicense({ expiryDate: new Date(releaseDate.getTime() + oneDayInMS), orderNumber: 'MUI-123', - scope: 'pro', - licensingModel: 'annual', + planScope: 'pro', + licenseModel: 'annual', planVersion: 'Q3-2024', }); diff --git a/packages/x-license/src/verifyLicense/verifyLicense.ts b/packages/x-license/src/verifyLicense/verifyLicense.ts index 8aa5d8915d5ac..9043999cc06e6 100644 --- a/packages/x-license/src/verifyLicense/verifyLicense.ts +++ b/packages/x-license/src/verifyLicense/verifyLicense.ts @@ -1,8 +1,8 @@ import { base64Decode, base64Encode } from '../encoding/base64'; import { md5 } from '../encoding/md5'; import { LICENSE_STATUS, LicenseStatus } from '../utils/licenseStatus'; -import { LicenseScope, LICENSE_SCOPES, PlanVersion } from '../utils/licenseScope'; -import { LicensingModel, LICENSING_MODELS } from '../utils/licensingModel'; +import { PlanScope, PLAN_SCOPES, PlanVersion } from '../utils/plan'; +import { LicenseModel, LICENSE_MODELS } from '../utils/licenseModel'; import { MuiCommercialPackageName } from '../utils/commercialPackages'; const getDefaultReleaseDate = () => { @@ -16,11 +16,8 @@ export function generateReleaseInfo(releaseDate = getDefaultReleaseDate()) { return base64Encode(releaseDate.getTime().toString()); } -function isLicenseScopeSufficient( - packageName: MuiCommercialPackageName, - licenseScope: LicenseScope, -) { - let acceptedScopes: LicenseScope[]; +function isPlanScopeSufficient(packageName: MuiCommercialPackageName, planScope: PlanScope) { + let acceptedScopes: PlanScope[]; if (packageName.includes('-pro')) { acceptedScopes = ['pro', 'premium']; } else if (packageName.includes('-premium')) { @@ -29,14 +26,14 @@ function isLicenseScopeSufficient( acceptedScopes = []; } - return acceptedScopes.includes(licenseScope); + return acceptedScopes.includes(planScope); } const expiryReg = /^.*EXPIRY=([0-9]+),.*$/; interface MuiLicense { - licensingModel: LicensingModel | null; - scope: LicenseScope | null; + licenseModel: LicenseModel | null; + planScope: PlanScope | null; expiryTimestamp: number | null; planVersion: PlanVersion; } @@ -61,20 +58,20 @@ const decodeLicenseVersion1 = (license: string): MuiLicense => { } return { - scope: 'pro', - licensingModel: 'perpetual', + planScope: 'pro', + licenseModel: 'perpetual', expiryTimestamp, planVersion: 'initial', }; }; /** - * Format: O=${orderNumber},E=${expiryTimestamp},S=${scope},LM=${licensingModel},PV=${planVersion},KV=2`; + * Format: O=${orderNumber},E=${expiryTimestamp},S=${planScope},LM=${licenseModel},PV=${planVersion},KV=2`; */ const decodeLicenseVersion2 = (license: string): MuiLicense => { const licenseInfo: MuiLicense = { - scope: null, - licensingModel: null, + planScope: null, + licenseModel: null, expiryTimestamp: null, planVersion: 'initial', }; @@ -85,11 +82,11 @@ const decodeLicenseVersion2 = (license: string): MuiLicense => { .filter((el) => el.length === 2) .forEach(([key, value]) => { if (key === 'S') { - licenseInfo.scope = value as LicenseScope; + licenseInfo.planScope = value as PlanScope; } if (key === 'LM') { - licenseInfo.licensingModel = value as LicensingModel; + licenseInfo.licenseModel = value as LicenseModel; } if (key === 'E') { @@ -155,7 +152,7 @@ export function verifyLicense({ return { status: LICENSE_STATUS.Invalid }; } - if (license.licensingModel == null || !LICENSING_MODELS.includes(license.licensingModel)) { + if (license.licenseModel == null || !LICENSE_MODELS.includes(license.licenseModel)) { console.error('MUI X: Error checking license. Licensing model not found or invalid!'); return { status: LICENSE_STATUS.Invalid }; } @@ -165,7 +162,7 @@ export function verifyLicense({ return { status: LICENSE_STATUS.Invalid }; } - if (license.licensingModel === 'perpetual' || process.env.NODE_ENV === 'production') { + if (license.licenseModel === 'perpetual' || process.env.NODE_ENV === 'production') { const pkgTimestamp = parseInt(base64Decode(releaseInfo), 10); if (Number.isNaN(pkgTimestamp)) { throw new Error('MUI X: The release information is invalid. Not able to validate license.'); @@ -174,7 +171,7 @@ export function verifyLicense({ if (license.expiryTimestamp < pkgTimestamp) { return { status: LICENSE_STATUS.ExpiredVersion }; } - } else if (license.licensingModel === 'subscription' || license.licensingModel === 'annual') { + } else if (license.licenseModel === 'subscription' || license.licenseModel === 'annual') { if (new Date().getTime() > license.expiryTimestamp) { if ( // 30 days grace @@ -193,19 +190,19 @@ export function verifyLicense({ } } - if (license.scope == null || !LICENSE_SCOPES.includes(license.scope)) { - console.error('MUI X: Error checking license. scope not found or invalid!'); + if (license.planScope == null || !PLAN_SCOPES.includes(license.planScope)) { + console.error('MUI X: Error checking license. planScope not found or invalid!'); return { status: LICENSE_STATUS.Invalid }; } - if (!isLicenseScopeSufficient(packageName, license.scope)) { + if (!isPlanScopeSufficient(packageName, license.planScope)) { return { status: LICENSE_STATUS.OutOfScope }; } // 'charts-pro' or 'tree-view-pro' can only be used with a newer Pro license if ( license.planVersion === 'initial' && - license.scope === 'pro' && + license.planScope === 'pro' && !PRO_PACKAGES_AVAILABLE_IN_INITIAL_PRO_PLAN.includes(packageName) ) { return { status: LICENSE_STATUS.NotAvailableInInitialProPlan }; diff --git a/scripts/x-license.exports.json b/scripts/x-license.exports.json index 257e49906393c..142052e831d4d 100644 --- a/scripts/x-license.exports.json +++ b/scripts/x-license.exports.json @@ -4,11 +4,11 @@ { "name": "LICENSE_STATUS", "kind": "Enum" }, { "name": "LicenseDetails", "kind": "Interface" }, { "name": "LicenseInfo", "kind": "Class" }, - { "name": "LicenseScope", "kind": "TypeAlias" }, + { "name": "LicenseModel", "kind": "TypeAlias" }, { "name": "LicenseStatus", "kind": "TypeAlias" }, - { "name": "LicensingModel", "kind": "TypeAlias" }, { "name": "MuiCommercialPackageName", "kind": "TypeAlias" }, { "name": "MuiLicenseInfo", "kind": "Interface" }, + { "name": "PlanScope", "kind": "TypeAlias" }, { "name": "showExpiredAnnualGraceLicenseKeyError", "kind": "Function" }, { "name": "showExpiredAnnualLicenseKeyError", "kind": "Function" }, { "name": "showExpiredPackageVersionError", "kind": "Function" }, diff --git a/test/utils/testLicense.js b/test/utils/testLicense.js index bf3064751157b..15e9e679f3111 100644 --- a/test/utils/testLicense.js +++ b/test/utils/testLicense.js @@ -6,8 +6,8 @@ export function generateTestLicenseKey() { // Tests usually take up to 15 minutes to run on CI. expiryDate.setHours(expiryDate.getHours() + 1); return generateLicense({ - licensingModel: 'subscription', - scope: 'premium', + licenseModel: 'subscription', + planScope: 'premium', orderNumber: 'MUI X tests', expiryDate, planVersion: 'Q3-2024',