@strapi/core 5.57.0 → 5.58.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Strapi.d.ts +28 -0
- package/dist/Strapi.d.ts.map +1 -1
- package/dist/Strapi.js +4 -0
- package/dist/Strapi.js.map +1 -1
- package/dist/Strapi.mjs +4 -0
- package/dist/Strapi.mjs.map +1 -1
- package/dist/ee/entitlements.d.ts +44 -0
- package/dist/ee/entitlements.d.ts.map +1 -0
- package/dist/ee/entitlements.js +54 -0
- package/dist/ee/entitlements.js.map +1 -0
- package/dist/ee/entitlements.mjs +51 -0
- package/dist/ee/entitlements.mjs.map +1 -0
- package/dist/ee/index.d.ts +33 -0
- package/dist/ee/index.d.ts.map +1 -1
- package/dist/ee/index.js +70 -3
- package/dist/ee/index.js.map +1 -1
- package/dist/ee/index.mjs +71 -4
- package/dist/ee/index.mjs.map +1 -1
- package/dist/ee/license.d.ts +10 -0
- package/dist/ee/license.d.ts.map +1 -1
- package/dist/ee/license.js +25 -1
- package/dist/ee/license.js.map +1 -1
- package/dist/ee/license.mjs +25 -2
- package/dist/ee/license.mjs.map +1 -1
- package/dist/package.json.js +16 -16
- package/dist/package.json.mjs +16 -16
- package/dist/services/document-service/transform/fields.d.ts.map +1 -1
- package/dist/services/document-service/transform/fields.js +7 -1
- package/dist/services/document-service/transform/fields.js.map +1 -1
- package/dist/services/document-service/transform/fields.mjs +7 -1
- package/dist/services/document-service/transform/fields.mjs.map +1 -1
- package/dist/services/document-service/transform/populate.d.ts.map +1 -1
- package/dist/services/document-service/transform/populate.js +8 -1
- package/dist/services/document-service/transform/populate.js.map +1 -1
- package/dist/services/document-service/transform/populate.mjs +8 -1
- package/dist/services/document-service/transform/populate.mjs.map +1 -1
- package/dist/services/document-service/transform/relations/utils/map-relation.d.ts.map +1 -1
- package/dist/services/document-service/transform/relations/utils/map-relation.js +10 -4
- package/dist/services/document-service/transform/relations/utils/map-relation.js.map +1 -1
- package/dist/services/document-service/transform/relations/utils/map-relation.mjs +10 -4
- package/dist/services/document-service/transform/relations/utils/map-relation.mjs.map +1 -1
- package/dist/utils/detect-customizations.d.ts +31 -0
- package/dist/utils/detect-customizations.d.ts.map +1 -0
- package/dist/utils/detect-customizations.js +173 -0
- package/dist/utils/detect-customizations.js.map +1 -0
- package/dist/utils/detect-customizations.mjs +165 -0
- package/dist/utils/detect-customizations.mjs.map +1 -0
- package/package.json +16 -16
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Effective entitlement limits registry.
|
|
3
|
+
*
|
|
4
|
+
* Feature modules register a live resolver for each numeric limit they enforce;
|
|
5
|
+
* the license endpoint and the support debug dump read the resolved, normalized
|
|
6
|
+
* values. A numeric string is read as its number. A resolved value that is nullish,
|
|
7
|
+
* non-numeric, or greater than or equal to UNLIMITED_ENTITLEMENT_THRESHOLD is reported
|
|
8
|
+
* as `null`, meaning "Unlimited".
|
|
9
|
+
*/ // The license registry ships a deliberately large number to mean "unlimited"
|
|
10
|
+
// (see the "a number that will never be reached like 9999" convention in
|
|
11
|
+
// content-releases validation). Kept server-side so the frontend never hard-codes it.
|
|
12
|
+
const UNLIMITED_ENTITLEMENT_THRESHOLD = 9999;
|
|
13
|
+
const normalize = (value)=>{
|
|
14
|
+
// License options are untyped JSON, and the registry has shipped some limits as numeric
|
|
15
|
+
// strings (`retentionDays: "90"`). Enforcement coerces those implicitly, so accepting only
|
|
16
|
+
// real numbers here showed a 90-day audit-logs cap as "Unlimited".
|
|
17
|
+
const limit = typeof value === 'string' && value.trim() !== '' ? Number(value) : value;
|
|
18
|
+
if (typeof limit !== 'number' || Number.isNaN(limit)) {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
return limit >= UNLIMITED_ENTITLEMENT_THRESHOLD ? null : limit;
|
|
22
|
+
};
|
|
23
|
+
const createEntitlementsRegistry = ()=>{
|
|
24
|
+
const registry = [];
|
|
25
|
+
const register = (input)=>{
|
|
26
|
+
const index = registry.findIndex((entry)=>entry.feature === input.feature);
|
|
27
|
+
if (index >= 0) {
|
|
28
|
+
registry[index] = input;
|
|
29
|
+
} else {
|
|
30
|
+
registry.push(input);
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
const list = (getFeature = ()=>undefined)=>registry.map((entry)=>{
|
|
34
|
+
const feature = getFeature(entry.feature);
|
|
35
|
+
return {
|
|
36
|
+
feature: entry.feature,
|
|
37
|
+
limits: entry.limits.map((limit)=>({
|
|
38
|
+
key: limit.key,
|
|
39
|
+
unit: limit.unit,
|
|
40
|
+
value: normalize(limit.get(feature))
|
|
41
|
+
}))
|
|
42
|
+
};
|
|
43
|
+
});
|
|
44
|
+
return {
|
|
45
|
+
register,
|
|
46
|
+
list
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export { UNLIMITED_ENTITLEMENT_THRESHOLD, createEntitlementsRegistry };
|
|
51
|
+
//# sourceMappingURL=entitlements.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entitlements.mjs","sources":["../../src/ee/entitlements.ts"],"sourcesContent":["/**\n * Effective entitlement limits registry.\n *\n * Feature modules register a live resolver for each numeric limit they enforce;\n * the license endpoint and the support debug dump read the resolved, normalized\n * values. A numeric string is read as its number. A resolved value that is nullish,\n * non-numeric, or greater than or equal to UNLIMITED_ENTITLEMENT_THRESHOLD is reported\n * as `null`, meaning \"Unlimited\".\n */\n\n// The license registry ships a deliberately large number to mean \"unlimited\"\n// (see the \"a number that will never be reached like 9999\" convention in\n// content-releases validation). Kept server-side so the frontend never hard-codes it.\nexport const UNLIMITED_ENTITLEMENT_THRESHOLD = 9999;\n\n/** A feature as a license lists it: a bare name, or `{ name, options }`. */\nexport type EntitlementFeature =\n | string\n | { name: string; options?: Record<string, unknown>; [key: string]: unknown }\n | undefined;\n\nexport interface EntitlementLimitInput {\n key: string;\n unit?: 'days' | 'count';\n /**\n * Resolves the limit the feature enforces from the feature as a license lists it. The same\n * resolver serves the live license and a lapsed license's retained snapshot, so it must read\n * options from the feature it is handed and apply its own defaults and clamps.\n */\n get: (feature?: EntitlementFeature) => unknown;\n}\n\nexport interface EntitlementInput {\n feature: string;\n limits: EntitlementLimitInput[];\n}\n\nexport interface EntitlementLimit {\n key: string;\n unit?: 'days' | 'count';\n value: number | null;\n}\n\nexport interface Entitlement {\n feature: string;\n limits: EntitlementLimit[];\n}\n\nconst normalize = (value: unknown): number | null => {\n // License options are untyped JSON, and the registry has shipped some limits as numeric\n // strings (`retentionDays: \"90\"`). Enforcement coerces those implicitly, so accepting only\n // real numbers here showed a 90-day audit-logs cap as \"Unlimited\".\n const limit = typeof value === 'string' && value.trim() !== '' ? Number(value) : value;\n\n if (typeof limit !== 'number' || Number.isNaN(limit)) {\n return null;\n }\n return limit >= UNLIMITED_ENTITLEMENT_THRESHOLD ? null : limit;\n};\n\nexport const createEntitlementsRegistry = () => {\n const registry: EntitlementInput[] = [];\n\n const register = (input: EntitlementInput): void => {\n const index = registry.findIndex((entry) => entry.feature === input.feature);\n if (index >= 0) {\n registry[index] = input;\n } else {\n registry.push(input);\n }\n };\n\n const list = (\n getFeature: (name: string) => EntitlementFeature = () => undefined\n ): Entitlement[] =>\n registry.map((entry) => {\n const feature = getFeature(entry.feature);\n\n return {\n feature: entry.feature,\n limits: entry.limits.map((limit) => ({\n key: limit.key,\n unit: limit.unit,\n value: normalize(limit.get(feature)),\n })),\n };\n });\n\n return { register, list };\n};\n"],"names":["UNLIMITED_ENTITLEMENT_THRESHOLD","normalize","value","limit","trim","Number","isNaN","createEntitlementsRegistry","registry","register","input","index","findIndex","entry","feature","push","list","getFeature","undefined","map","limits","key","unit","get"],"mappings":"AAAA;;;;;;;;AAQC;AAGD;AACA;AACO,MAAMA,kCAAkC;AAmC/C,MAAMC,YAAY,CAACC,KAAAA,GAAAA;;;;IAIjB,MAAMC,KAAAA,GAAQ,OAAOD,KAAAA,KAAU,QAAA,IAAYA,MAAME,IAAI,EAAA,KAAO,EAAA,GAAKC,MAAAA,CAAOH,KAAAA,CAAAA,GAASA,KAAAA;AAEjF,IAAA,IAAI,OAAOC,KAAAA,KAAU,QAAA,IAAYE,MAAAA,CAAOC,KAAK,CAACH,KAAAA,CAAAA,EAAQ;QACpD,OAAO,IAAA;AACT,IAAA;IACA,OAAOA,KAAAA,IAASH,kCAAkC,IAAA,GAAOG,KAAAA;AAC3D,CAAA;MAEaI,0BAAAA,GAA6B,IAAA;AACxC,IAAA,MAAMC,WAA+B,EAAE;AAEvC,IAAA,MAAMC,WAAW,CAACC,KAAAA,GAAAA;QAChB,MAAMC,KAAAA,GAAQH,QAAAA,CAASI,SAAS,CAAC,CAACC,QAAUA,KAAAA,CAAMC,OAAO,KAAKJ,KAAAA,CAAMI,OAAO,CAAA;AAC3E,QAAA,IAAIH,SAAS,CAAA,EAAG;YACdH,QAAQ,CAACG,MAAM,GAAGD,KAAAA;QACpB,CAAA,MAAO;AACLF,YAAAA,QAAAA,CAASO,IAAI,CAACL,KAAAA,CAAAA;AAChB,QAAA;AACF,IAAA,CAAA;IAEA,MAAMM,IAAAA,GAAO,CACXC,UAAAA,GAAmD,IAAMC,SAAS,GAElEV,QAAAA,CAASW,GAAG,CAAC,CAACN,KAAAA,GAAAA;YACZ,MAAMC,OAAAA,GAAUG,UAAAA,CAAWJ,KAAAA,CAAMC,OAAO,CAAA;YAExC,OAAO;AACLA,gBAAAA,OAAAA,EAASD,MAAMC,OAAO;AACtBM,gBAAAA,MAAAA,EAAQP,MAAMO,MAAM,CAACD,GAAG,CAAC,CAAChB,SAAW;AACnCkB,wBAAAA,GAAAA,EAAKlB,MAAMkB,GAAG;AACdC,wBAAAA,IAAAA,EAAMnB,MAAMmB,IAAI;wBAChBpB,KAAAA,EAAOD,SAAAA,CAAUE,KAAAA,CAAMoB,GAAG,CAACT,OAAAA,CAAAA;qBAC7B,CAAA;AACF,aAAA;AACF,QAAA,CAAA,CAAA;IAEF,OAAO;AAAEL,QAAAA,QAAAA;AAAUO,QAAAA;AAAK,KAAA;AAC1B;;;;"}
|
package/dist/ee/index.d.ts
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
import type { Logger } from '@strapi/logger';
|
|
2
2
|
import type { Core } from '@strapi/types';
|
|
3
|
+
interface LicenseInfoState {
|
|
4
|
+
licenseKey?: string;
|
|
5
|
+
features?: Array<{
|
|
6
|
+
name: string;
|
|
7
|
+
[key: string]: any;
|
|
8
|
+
} | string>;
|
|
9
|
+
expireAt?: string;
|
|
10
|
+
seats?: number;
|
|
11
|
+
type?: string;
|
|
12
|
+
isTrial: boolean;
|
|
13
|
+
subscriptionId?: string;
|
|
14
|
+
planPriceId?: string;
|
|
15
|
+
/** End of the subscription term, epoch milliseconds. */
|
|
16
|
+
renewalDate?: string | number;
|
|
17
|
+
}
|
|
18
|
+
type LicenseStatus = 'none' | 'active' | 'expired' | 'unknown';
|
|
3
19
|
declare const _default: Readonly<{
|
|
4
20
|
init: (licenseDir: string, logger?: Logger) => void;
|
|
5
21
|
checkLicense: ({ strapi }: {
|
|
@@ -11,8 +27,20 @@ declare const _default: Readonly<{
|
|
|
11
27
|
trialEndsAt: string;
|
|
12
28
|
} | null>;
|
|
13
29
|
readonly isEE: boolean;
|
|
30
|
+
readonly licenseStatus: LicenseStatus;
|
|
31
|
+
/** Display-only; see EE.retainedLicense. Never use for feature gating. */
|
|
32
|
+
readonly retainedLicense: Omit<LicenseInfoState, "licenseKey"> | null;
|
|
14
33
|
readonly seats: number | undefined;
|
|
15
34
|
readonly type: string | undefined;
|
|
35
|
+
readonly expireAt: string | undefined;
|
|
36
|
+
/** Null when the registry does not provide it yet; survives expiry via the retained snapshot. */
|
|
37
|
+
readonly renewalDate: string | number | null;
|
|
38
|
+
/**
|
|
39
|
+
* Every feature the current plan supports, in display order, regardless of whether this
|
|
40
|
+
* license includes it. Falls back to the retained license's type so an expired license
|
|
41
|
+
* still lists rows. See `PLAN_FEATURE_CATALOG` in `./license`.
|
|
42
|
+
*/
|
|
43
|
+
readonly planFeatureCatalog: string[];
|
|
16
44
|
readonly isTrial: boolean;
|
|
17
45
|
readonly planPriceId: string | undefined;
|
|
18
46
|
readonly subscriptionId: string | undefined;
|
|
@@ -27,6 +55,11 @@ declare const _default: Readonly<{
|
|
|
27
55
|
} | undefined;
|
|
28
56
|
isEnabled: (featureName: string) => boolean;
|
|
29
57
|
}>;
|
|
58
|
+
entitlements: Readonly<{
|
|
59
|
+
register: (input: import("./entitlements").EntitlementInput) => void;
|
|
60
|
+
list: () => import("./entitlements").Entitlement[];
|
|
61
|
+
listRetained(): import("./entitlements").Entitlement[];
|
|
62
|
+
}>;
|
|
30
63
|
}>;
|
|
31
64
|
export default _default;
|
|
32
65
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/ee/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ee/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ee/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAe1C,UAAU,gBAAgB;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;KAAE,GAAG,MAAM,CAAC,CAAC;IAChE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,wDAAwD;IACxD,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAC/B;AAED,KAAK,aAAa,GAAG,MAAM,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,CAAC;;uBAgFrC,MAAM,WAAW,MAAM;+BAsJT;QAAE,MAAM,EAAE,IAAI,CAAC,MAAM,CAAA;KAAE;mCA0B5D;QACD,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC;KACrB,KAAG,OAAO,CAAC;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;;;IAgDzC,0EAA0E;;;;;IAiB1E,iGAAiG;;IAKjG;;;;OAIG;iCACuB,MAAM,EAAE;;;;;;;kBAxVT,MAAM;;2BA4SP,MAAM;;kBA5SL,MAAM;;iCA8WJ,MAAM;;;;;;;;AA9DnC,wBAuFG"}
|
package/dist/ee/index.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
var _ = require('lodash');
|
|
4
4
|
var fetch = require('../utils/fetch.js');
|
|
5
5
|
var license = require('./license.js');
|
|
6
|
+
var entitlements$1 = require('./entitlements.js');
|
|
6
7
|
var cron = require('../utils/cron.js');
|
|
7
8
|
|
|
8
9
|
const ONE_MINUTE = 1000 * 60;
|
|
@@ -10,12 +11,30 @@ const ee = {
|
|
|
10
11
|
enabled: false,
|
|
11
12
|
licenseInfo: {
|
|
12
13
|
isTrial: false
|
|
13
|
-
}
|
|
14
|
+
},
|
|
15
|
+
retainedLicense: null,
|
|
16
|
+
licenseStatus: 'none'
|
|
14
17
|
};
|
|
15
|
-
const disable = (message)=>{
|
|
18
|
+
const disable = (message, status = 'unknown')=>{
|
|
16
19
|
// Prevent emitting ee.disable if it was already disabled
|
|
17
20
|
const shouldEmitEvent = ee.enabled !== false;
|
|
18
21
|
ee.logger?.warn(`${message} Switching to CE.`);
|
|
22
|
+
// Retain a display-only snapshot (never the key) BEFORE wiping, so the admin panel can
|
|
23
|
+
// still show which license this instance has and why it is unusable. Guarded on `type`
|
|
24
|
+
// so a repeat disable() call cannot overwrite the snapshot with an already-wiped one.
|
|
25
|
+
if (ee.licenseInfo.type) {
|
|
26
|
+
ee.retainedLicense = _.pick(ee.licenseInfo, [
|
|
27
|
+
'features',
|
|
28
|
+
'expireAt',
|
|
29
|
+
'seats',
|
|
30
|
+
'type',
|
|
31
|
+
'isTrial',
|
|
32
|
+
'subscriptionId',
|
|
33
|
+
'planPriceId',
|
|
34
|
+
'renewalDate'
|
|
35
|
+
]);
|
|
36
|
+
}
|
|
37
|
+
ee.licenseStatus = status;
|
|
19
38
|
// Only keep the license key and isTrial for potential re-enabling during a later check
|
|
20
39
|
ee.licenseInfo = _.pick(ee.licenseInfo, [
|
|
21
40
|
'licenseKey',
|
|
@@ -32,6 +51,8 @@ const enable = ()=>{
|
|
|
32
51
|
// Prevent emitting ee.enable if it was already enabled
|
|
33
52
|
const shouldEmitEvent = ee.enabled !== true;
|
|
34
53
|
ee.enabled = true;
|
|
54
|
+
ee.licenseStatus = 'active';
|
|
55
|
+
ee.retainedLicense = null;
|
|
35
56
|
if (shouldEmitEvent) {
|
|
36
57
|
// Notify EE features that they should be disabled
|
|
37
58
|
strapi.eventHub.emit('ee.enable');
|
|
@@ -79,8 +100,15 @@ let initialized = false;
|
|
|
79
100
|
lastCheckAt: Date.now()
|
|
80
101
|
};
|
|
81
102
|
const fallback = (error)=>{
|
|
103
|
+
// Whether the registry was unreachable or actually refused the license is only
|
|
104
|
+
// knowable here, from `shouldFallback`. Record it rather than letting the admin
|
|
105
|
+
// panel infer it from the presence of a cached license: an instance that has never
|
|
106
|
+
// reached the registry has no cache to fall back to, and would otherwise be told
|
|
107
|
+
// its license was refused when the registry was merely unreachable.
|
|
108
|
+
result.errorKind = error instanceof license.LicenseCheckError && error.shouldFallback ? 'unreachable' : 'rejected';
|
|
82
109
|
if (error instanceof license.LicenseCheckError && error.shouldFallback && storedInfo?.license) {
|
|
83
110
|
ee.logger?.warn(`${error.message} The last stored one will be used as a potential fallback.`);
|
|
111
|
+
result.error = error.message; // record why we fell back so usingCachedLicense is derivable
|
|
84
112
|
return storedInfo.license;
|
|
85
113
|
}
|
|
86
114
|
result.error = error.message;
|
|
@@ -144,7 +172,7 @@ const validateInfo = ()=>{
|
|
|
144
172
|
}
|
|
145
173
|
const expirationTime = new Date(ee.licenseInfo.expireAt).getTime();
|
|
146
174
|
if (expirationTime < new Date().getTime()) {
|
|
147
|
-
return disable('License expired.');
|
|
175
|
+
return disable('License expired.', 'expired');
|
|
148
176
|
}
|
|
149
177
|
enable();
|
|
150
178
|
};
|
|
@@ -191,6 +219,7 @@ const list = ()=>{
|
|
|
191
219
|
}) || [];
|
|
192
220
|
};
|
|
193
221
|
const get = (featureName)=>list().find((feature)=>feature.name === featureName);
|
|
222
|
+
const entitlements = entitlements$1.createEntitlementsRegistry();
|
|
194
223
|
var index = Object.freeze({
|
|
195
224
|
init,
|
|
196
225
|
checkLicense,
|
|
@@ -198,12 +227,32 @@ var index = Object.freeze({
|
|
|
198
227
|
get isEE () {
|
|
199
228
|
return ee.enabled;
|
|
200
229
|
},
|
|
230
|
+
get licenseStatus () {
|
|
231
|
+
return ee.licenseStatus;
|
|
232
|
+
},
|
|
233
|
+
/** Display-only; see EE.retainedLicense. Never use for feature gating. */ get retainedLicense () {
|
|
234
|
+
return ee.retainedLicense;
|
|
235
|
+
},
|
|
201
236
|
get seats () {
|
|
202
237
|
return ee.licenseInfo.seats;
|
|
203
238
|
},
|
|
204
239
|
get type () {
|
|
205
240
|
return ee.licenseInfo.type;
|
|
206
241
|
},
|
|
242
|
+
get expireAt () {
|
|
243
|
+
return ee.licenseInfo.expireAt;
|
|
244
|
+
},
|
|
245
|
+
/** Null when the registry does not provide it yet; survives expiry via the retained snapshot. */ get renewalDate () {
|
|
246
|
+
return ee.licenseInfo.renewalDate ?? ee.retainedLicense?.renewalDate ?? null;
|
|
247
|
+
},
|
|
248
|
+
/**
|
|
249
|
+
* Every feature the current plan supports, in display order, regardless of whether this
|
|
250
|
+
* license includes it. Falls back to the retained license's type so an expired license
|
|
251
|
+
* still lists rows. See `PLAN_FEATURE_CATALOG` in `./license`.
|
|
252
|
+
*/ get planFeatureCatalog () {
|
|
253
|
+
const type = ee.licenseInfo.type ?? ee.retainedLicense?.type;
|
|
254
|
+
return type && type in license.PLAN_FEATURE_CATALOG ? license.PLAN_FEATURE_CATALOG[type] : [];
|
|
255
|
+
},
|
|
207
256
|
get isTrial () {
|
|
208
257
|
return ee.licenseInfo.isTrial;
|
|
209
258
|
},
|
|
@@ -217,6 +266,24 @@ var index = Object.freeze({
|
|
|
217
266
|
list,
|
|
218
267
|
get,
|
|
219
268
|
isEnabled: (featureName)=>get(featureName) !== undefined
|
|
269
|
+
}),
|
|
270
|
+
entitlements: Object.freeze({
|
|
271
|
+
register: entitlements.register,
|
|
272
|
+
// Resolvers are registered during `register()`, before the license is validated, and each
|
|
273
|
+
// falls back to a built-in default when the feature is absent. Without this gate an
|
|
274
|
+
// instance whose license was disabled would still report generous limits, which reads as
|
|
275
|
+
// "these are your granted limits". No license, no entitlements.
|
|
276
|
+
list: ()=>ee.enabled ? entitlements.list(get) : [],
|
|
277
|
+
// A lapsed license's limits, from the same resolvers run against its retained feature list,
|
|
278
|
+
// so a lapsed Plan card and the debug dump carry the defaults and clamps the plan enforced
|
|
279
|
+
// instead of raw options. Only features the retained license listed are reported.
|
|
280
|
+
listRetained () {
|
|
281
|
+
const retainedFeatures = (ee.retainedLicense?.features ?? []).map((feature)=>typeof feature === 'object' ? feature : {
|
|
282
|
+
name: feature
|
|
283
|
+
});
|
|
284
|
+
const getRetained = (name)=>retainedFeatures.find((feature)=>feature.name === name);
|
|
285
|
+
return entitlements.list(getRetained).filter((entry)=>getRetained(entry.feature) !== undefined);
|
|
286
|
+
}
|
|
220
287
|
})
|
|
221
288
|
});
|
|
222
289
|
|
package/dist/ee/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../src/ee/index.ts"],"sourcesContent":["import { isEqual, pick } from 'lodash';\nimport type { Logger } from '@strapi/logger';\nimport type { Core } from '@strapi/types';\nimport { createStrapiFetch } from '../utils/fetch';\nimport {\n readLicense,\n verifyLicense,\n fetchLicense,\n LicenseCheckError,\n LICENSE_REGISTRY_URI,\n} from './license';\nimport { shiftCronExpression } from '../utils/cron';\n\nconst ONE_MINUTE = 1000 * 60;\n\ninterface EE {\n enabled: boolean;\n licenseInfo: {\n licenseKey?: string;\n features?: Array<{ name: string; [key: string]: any } | string>;\n expireAt?: string;\n seats?: number;\n type?: string;\n isTrial: boolean;\n subscriptionId?: string;\n planPriceId?: string;\n };\n logger?: Logger;\n}\n\nconst ee: EE = {\n enabled: false,\n licenseInfo: {\n isTrial: false,\n },\n};\n\nconst disable = (message: string) => {\n // Prevent emitting ee.disable if it was already disabled\n const shouldEmitEvent = ee.enabled !== false;\n\n ee.logger?.warn(`${message} Switching to CE.`);\n // Only keep the license key and isTrial for potential re-enabling during a later check\n ee.licenseInfo = pick(ee.licenseInfo, ['licenseKey', 'isTrial']);\n\n ee.licenseInfo.isTrial = false;\n\n ee.enabled = false;\n\n if (shouldEmitEvent) {\n // Notify EE features that they should be disabled\n strapi.eventHub.emit('ee.disable');\n }\n};\n\nconst enable = () => {\n // Prevent emitting ee.enable if it was already enabled\n const shouldEmitEvent = ee.enabled !== true;\n\n ee.enabled = true;\n\n if (shouldEmitEvent) {\n // Notify EE features that they should be disabled\n strapi.eventHub.emit('ee.enable');\n }\n};\n\nlet initialized = false;\n\n/**\n * Optimistically enable EE if the format of the license is valid, only run once.\n */\nconst init = (licenseDir: string, logger?: Logger) => {\n if (initialized) {\n return;\n }\n\n initialized = true;\n ee.logger = logger;\n\n if (process.env.STRAPI_DISABLE_EE?.toLowerCase() === 'true') {\n return;\n }\n\n try {\n const license = process.env.STRAPI_LICENSE || readLicense(licenseDir);\n\n if (license) {\n ee.licenseInfo = verifyLicense(license);\n enable();\n }\n } catch (error) {\n if (error instanceof Error) {\n disable(error.message);\n } else {\n disable('Invalid license.');\n }\n }\n};\n\n/**\n * Contact the license registry to update the license to its latest state.\n *\n * Store the result in database to avoid unecessary requests, and will fallback to that in case of a network failure.\n */\nconst onlineUpdate = async ({ strapi }: { strapi: Core.Strapi }) => {\n const { get, commit, rollback } = await strapi.db.transaction();\n const transaction = get();\n\n try {\n const storedInfo = await strapi.db\n ?.queryBuilder('strapi::core-store')\n .where({ key: 'ee_information' })\n .select('value')\n .first()\n .transacting(transaction)\n .forUpdate()\n .execute()\n .then((result: any) => (result ? JSON.parse(result.value) : result));\n\n const shouldContactRegistry = (storedInfo?.lastCheckAt ?? 0) < Date.now() - ONE_MINUTE;\n const result: {\n license?: string | null;\n error?: string;\n lastCheckAt?: number;\n } = { lastCheckAt: Date.now() };\n\n const fallback = (error: Error) => {\n if (error instanceof LicenseCheckError && error.shouldFallback && storedInfo?.license) {\n ee.logger?.warn(\n `${error.message} The last stored one will be used as a potential fallback.`\n );\n return storedInfo.license;\n }\n\n result.error = error.message;\n disable(error.message);\n };\n\n if (!ee?.licenseInfo?.licenseKey) {\n throw new Error('Missing license key.');\n }\n\n const license = shouldContactRegistry\n ? await fetchLicense({ strapi }, ee.licenseInfo.licenseKey, strapi.config.get('uuid')).catch(\n fallback\n )\n : storedInfo.license;\n\n if (license) {\n try {\n // Verify license and check if its info changed\n const newLicenseInfo = verifyLicense(license);\n const licenseInfoChanged =\n !isEqual(newLicenseInfo.features, ee.licenseInfo.features) ||\n newLicenseInfo.seats !== ee.licenseInfo.seats ||\n newLicenseInfo.type !== ee.licenseInfo.type;\n\n // Store the new license info\n ee.licenseInfo = newLicenseInfo;\n const wasEnabled = ee.enabled;\n validateInfo();\n\n // Notify EE features\n if (licenseInfoChanged && wasEnabled) {\n strapi.eventHub.emit('ee.update');\n }\n } catch (error) {\n if (error instanceof Error) {\n disable(error.message);\n } else {\n disable('Invalid license.');\n }\n }\n } else if (!shouldContactRegistry) {\n disable(storedInfo.error);\n }\n\n if (shouldContactRegistry) {\n result.license = license ?? null;\n const query = strapi.db.queryBuilder('strapi::core-store').transacting(transaction);\n\n if (!storedInfo) {\n query.insert({ key: 'ee_information', value: JSON.stringify(result) });\n } else {\n query.update({ value: JSON.stringify(result) }).where({ key: 'ee_information' });\n }\n\n await query.execute();\n }\n\n await commit();\n } catch {\n // Example of errors: SQLite does not support FOR UPDATE\n await rollback();\n }\n};\n\nconst validateInfo = () => {\n if (typeof ee.licenseInfo.expireAt === 'undefined') {\n throw new Error('Missing license key.');\n }\n\n const expirationTime = new Date(ee.licenseInfo.expireAt).getTime();\n\n if (expirationTime < new Date().getTime()) {\n return disable('License expired.');\n }\n\n enable();\n};\n\nconst checkLicense = async ({ strapi }: { strapi: Core.Strapi }) => {\n const shouldStayOffline =\n ee.licenseInfo.type === 'gold' &&\n // This env variable support is temporarily used to ease the migration between online vs offline\n process.env.STRAPI_DISABLE_LICENSE_PING?.toLowerCase() === 'true';\n\n if (!shouldStayOffline) {\n await onlineUpdate({ strapi });\n\n strapi.cron.add({\n onlineUpdate: {\n task: () => onlineUpdate({ strapi }),\n options: shiftCronExpression('0 0 */12 * * *'),\n },\n });\n } else {\n if (!ee.licenseInfo.expireAt) {\n return disable('Your license does not have offline support.');\n }\n\n validateInfo();\n }\n};\n\nconst getTrialEndDate = async ({\n strapi,\n}: {\n strapi: Core.Strapi;\n}): Promise<{ trialEndsAt: string } | null> => {\n const silentFetch = createStrapiFetch(strapi, {\n logs: false,\n });\n\n const res = await silentFetch(\n `${LICENSE_REGISTRY_URI}/api/licenses/${ee.licenseInfo.licenseKey}/trial-countdown`,\n {\n method: 'GET',\n headers: { 'Content-Type': 'application/json' },\n }\n ).catch(() => {\n throw new LicenseCheckError(\n 'Could not proceed to retrieve the trial time left for your license.',\n true\n );\n });\n\n const data = (await res.json()) as { trialEndsAt: string } | null;\n\n return data;\n};\n\nconst list = () => {\n return (\n ee.licenseInfo.features?.map((feature) =>\n typeof feature === 'object' ? feature : { name: feature }\n ) || []\n );\n};\n\nconst get = (featureName: string) => list().find((feature) => feature.name === featureName);\n\nexport default Object.freeze({\n init,\n checkLicense,\n getTrialEndDate,\n\n get isEE() {\n return ee.enabled;\n },\n\n get seats() {\n return ee.licenseInfo.seats;\n },\n\n get type() {\n return ee.licenseInfo.type;\n },\n\n get isTrial() {\n return ee.licenseInfo.isTrial;\n },\n\n get planPriceId() {\n return ee.licenseInfo.planPriceId;\n },\n\n get subscriptionId() {\n return ee.licenseInfo.subscriptionId;\n },\n\n features: Object.freeze({\n list,\n get,\n isEnabled: (featureName: string) => get(featureName) !== undefined,\n }),\n});\n"],"names":["ONE_MINUTE","ee","enabled","licenseInfo","isTrial","disable","message","shouldEmitEvent","logger","warn","pick","strapi","eventHub","emit","enable","initialized","init","licenseDir","process","env","STRAPI_DISABLE_EE","toLowerCase","license","STRAPI_LICENSE","readLicense","verifyLicense","error","Error","onlineUpdate","get","commit","rollback","db","transaction","storedInfo","queryBuilder","where","key","select","first","transacting","forUpdate","execute","then","result","JSON","parse","value","shouldContactRegistry","lastCheckAt","Date","now","fallback","LicenseCheckError","shouldFallback","licenseKey","fetchLicense","config","catch","newLicenseInfo","licenseInfoChanged","isEqual","features","seats","type","wasEnabled","validateInfo","query","insert","stringify","update","expireAt","expirationTime","getTime","checkLicense","shouldStayOffline","STRAPI_DISABLE_LICENSE_PING","cron","add","task","options","shiftCronExpression","getTrialEndDate","silentFetch","createStrapiFetch","logs","res","LICENSE_REGISTRY_URI","method","headers","data","json","list","map","feature","name","featureName","find","Object","freeze","isEE","planPriceId","subscriptionId","isEnabled","undefined"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../src/ee/index.ts"],"sourcesContent":["import { isEqual, pick } from 'lodash';\nimport type { Logger } from '@strapi/logger';\nimport type { Core } from '@strapi/types';\nimport { createStrapiFetch } from '../utils/fetch';\nimport {\n readLicense,\n verifyLicense,\n fetchLicense,\n LicenseCheckError,\n LICENSE_REGISTRY_URI,\n PLAN_FEATURE_CATALOG,\n} from './license';\nimport { createEntitlementsRegistry } from './entitlements';\nimport { shiftCronExpression } from '../utils/cron';\n\nconst ONE_MINUTE = 1000 * 60;\n\ninterface LicenseInfoState {\n licenseKey?: string;\n features?: Array<{ name: string; [key: string]: any } | string>;\n expireAt?: string;\n seats?: number;\n type?: string;\n isTrial: boolean;\n subscriptionId?: string;\n planPriceId?: string;\n /** End of the subscription term, epoch milliseconds. */\n renewalDate?: string | number;\n}\n\ntype LicenseStatus = 'none' | 'active' | 'expired' | 'unknown';\n\ninterface EE {\n enabled: boolean;\n licenseInfo: LicenseInfoState;\n /**\n * Display-only copy of the last known license, retained when a license exists but is\n * not usable (expired / could not be validated) so the admin panel can explain why.\n * NEVER read by enforcement paths (features.list/get/isEnabled, isEE) and never holds\n * the license key.\n */\n retainedLicense: Omit<LicenseInfoState, 'licenseKey'> | null;\n licenseStatus: LicenseStatus;\n logger?: Logger;\n}\n\nconst ee: EE = {\n enabled: false,\n licenseInfo: {\n isTrial: false,\n },\n retainedLicense: null,\n licenseStatus: 'none',\n};\n\nconst disable = (message: string, status: 'expired' | 'unknown' = 'unknown') => {\n // Prevent emitting ee.disable if it was already disabled\n const shouldEmitEvent = ee.enabled !== false;\n\n ee.logger?.warn(`${message} Switching to CE.`);\n\n // Retain a display-only snapshot (never the key) BEFORE wiping, so the admin panel can\n // still show which license this instance has and why it is unusable. Guarded on `type`\n // so a repeat disable() call cannot overwrite the snapshot with an already-wiped one.\n if (ee.licenseInfo.type) {\n ee.retainedLicense = pick(ee.licenseInfo, [\n 'features',\n 'expireAt',\n 'seats',\n 'type',\n 'isTrial',\n 'subscriptionId',\n 'planPriceId',\n 'renewalDate',\n ]);\n }\n ee.licenseStatus = status;\n\n // Only keep the license key and isTrial for potential re-enabling during a later check\n ee.licenseInfo = pick(ee.licenseInfo, ['licenseKey', 'isTrial']);\n\n ee.licenseInfo.isTrial = false;\n\n ee.enabled = false;\n\n if (shouldEmitEvent) {\n // Notify EE features that they should be disabled\n strapi.eventHub.emit('ee.disable');\n }\n};\n\nconst enable = () => {\n // Prevent emitting ee.enable if it was already enabled\n const shouldEmitEvent = ee.enabled !== true;\n\n ee.enabled = true;\n ee.licenseStatus = 'active';\n ee.retainedLicense = null;\n\n if (shouldEmitEvent) {\n // Notify EE features that they should be disabled\n strapi.eventHub.emit('ee.enable');\n }\n};\n\nlet initialized = false;\n\n/**\n * Optimistically enable EE if the format of the license is valid, only run once.\n */\nconst init = (licenseDir: string, logger?: Logger) => {\n if (initialized) {\n return;\n }\n\n initialized = true;\n ee.logger = logger;\n\n if (process.env.STRAPI_DISABLE_EE?.toLowerCase() === 'true') {\n return;\n }\n\n try {\n const license = process.env.STRAPI_LICENSE || readLicense(licenseDir);\n\n if (license) {\n ee.licenseInfo = verifyLicense(license);\n enable();\n }\n } catch (error) {\n if (error instanceof Error) {\n disable(error.message);\n } else {\n disable('Invalid license.');\n }\n }\n};\n\n/**\n * Contact the license registry to update the license to its latest state.\n *\n * Store the result in database to avoid unecessary requests, and will fallback to that in case of a network failure.\n */\nconst onlineUpdate = async ({ strapi }: { strapi: Core.Strapi }) => {\n const { get, commit, rollback } = await strapi.db.transaction();\n const transaction = get();\n\n try {\n const storedInfo = await strapi.db\n ?.queryBuilder('strapi::core-store')\n .where({ key: 'ee_information' })\n .select('value')\n .first()\n .transacting(transaction)\n .forUpdate()\n .execute()\n .then((result: any) => (result ? JSON.parse(result.value) : result));\n\n const shouldContactRegistry = (storedInfo?.lastCheckAt ?? 0) < Date.now() - ONE_MINUTE;\n const result: {\n license?: string | null;\n error?: string;\n errorKind?: 'unreachable' | 'rejected';\n lastCheckAt?: number;\n } = { lastCheckAt: Date.now() };\n\n const fallback = (error: Error) => {\n // Whether the registry was unreachable or actually refused the license is only\n // knowable here, from `shouldFallback`. Record it rather than letting the admin\n // panel infer it from the presence of a cached license: an instance that has never\n // reached the registry has no cache to fall back to, and would otherwise be told\n // its license was refused when the registry was merely unreachable.\n result.errorKind =\n error instanceof LicenseCheckError && error.shouldFallback ? 'unreachable' : 'rejected';\n\n if (error instanceof LicenseCheckError && error.shouldFallback && storedInfo?.license) {\n ee.logger?.warn(\n `${error.message} The last stored one will be used as a potential fallback.`\n );\n result.error = error.message; // record why we fell back so usingCachedLicense is derivable\n return storedInfo.license;\n }\n\n result.error = error.message;\n disable(error.message);\n };\n\n if (!ee?.licenseInfo?.licenseKey) {\n throw new Error('Missing license key.');\n }\n\n const license = shouldContactRegistry\n ? await fetchLicense({ strapi }, ee.licenseInfo.licenseKey, strapi.config.get('uuid')).catch(\n fallback\n )\n : storedInfo.license;\n\n if (license) {\n try {\n // Verify license and check if its info changed\n const newLicenseInfo = verifyLicense(license);\n const licenseInfoChanged =\n !isEqual(newLicenseInfo.features, ee.licenseInfo.features) ||\n newLicenseInfo.seats !== ee.licenseInfo.seats ||\n newLicenseInfo.type !== ee.licenseInfo.type;\n\n // Store the new license info\n ee.licenseInfo = newLicenseInfo;\n const wasEnabled = ee.enabled;\n validateInfo();\n\n // Notify EE features\n if (licenseInfoChanged && wasEnabled) {\n strapi.eventHub.emit('ee.update');\n }\n } catch (error) {\n if (error instanceof Error) {\n disable(error.message);\n } else {\n disable('Invalid license.');\n }\n }\n } else if (!shouldContactRegistry) {\n disable(storedInfo.error);\n }\n\n if (shouldContactRegistry) {\n result.license = license ?? null;\n const query = strapi.db.queryBuilder('strapi::core-store').transacting(transaction);\n\n if (!storedInfo) {\n query.insert({ key: 'ee_information', value: JSON.stringify(result) });\n } else {\n query.update({ value: JSON.stringify(result) }).where({ key: 'ee_information' });\n }\n\n await query.execute();\n }\n\n await commit();\n } catch {\n // Example of errors: SQLite does not support FOR UPDATE\n await rollback();\n }\n};\n\nconst validateInfo = () => {\n if (typeof ee.licenseInfo.expireAt === 'undefined') {\n throw new Error('Missing license key.');\n }\n\n const expirationTime = new Date(ee.licenseInfo.expireAt).getTime();\n\n if (expirationTime < new Date().getTime()) {\n return disable('License expired.', 'expired');\n }\n\n enable();\n};\n\nconst checkLicense = async ({ strapi }: { strapi: Core.Strapi }) => {\n const shouldStayOffline =\n ee.licenseInfo.type === 'gold' &&\n // This env variable support is temporarily used to ease the migration between online vs offline\n process.env.STRAPI_DISABLE_LICENSE_PING?.toLowerCase() === 'true';\n\n if (!shouldStayOffline) {\n await onlineUpdate({ strapi });\n\n strapi.cron.add({\n onlineUpdate: {\n task: () => onlineUpdate({ strapi }),\n options: shiftCronExpression('0 0 */12 * * *'),\n },\n });\n } else {\n if (!ee.licenseInfo.expireAt) {\n return disable('Your license does not have offline support.');\n }\n\n validateInfo();\n }\n};\n\nconst getTrialEndDate = async ({\n strapi,\n}: {\n strapi: Core.Strapi;\n}): Promise<{ trialEndsAt: string } | null> => {\n const silentFetch = createStrapiFetch(strapi, {\n logs: false,\n });\n\n const res = await silentFetch(\n `${LICENSE_REGISTRY_URI}/api/licenses/${ee.licenseInfo.licenseKey}/trial-countdown`,\n {\n method: 'GET',\n headers: { 'Content-Type': 'application/json' },\n }\n ).catch(() => {\n throw new LicenseCheckError(\n 'Could not proceed to retrieve the trial time left for your license.',\n true\n );\n });\n\n const data = (await res.json()) as { trialEndsAt: string } | null;\n\n return data;\n};\n\nconst list = () => {\n return (\n ee.licenseInfo.features?.map((feature) =>\n typeof feature === 'object' ? feature : { name: feature }\n ) || []\n );\n};\n\nconst get = (featureName: string) => list().find((feature) => feature.name === featureName);\n\nconst entitlements = createEntitlementsRegistry();\n\nexport default Object.freeze({\n init,\n checkLicense,\n getTrialEndDate,\n\n get isEE() {\n return ee.enabled;\n },\n\n get licenseStatus() {\n return ee.licenseStatus;\n },\n\n /** Display-only; see EE.retainedLicense. Never use for feature gating. */\n get retainedLicense() {\n return ee.retainedLicense;\n },\n\n get seats() {\n return ee.licenseInfo.seats;\n },\n\n get type() {\n return ee.licenseInfo.type;\n },\n\n get expireAt() {\n return ee.licenseInfo.expireAt;\n },\n\n /** Null when the registry does not provide it yet; survives expiry via the retained snapshot. */\n get renewalDate() {\n return ee.licenseInfo.renewalDate ?? ee.retainedLicense?.renewalDate ?? null;\n },\n\n /**\n * Every feature the current plan supports, in display order, regardless of whether this\n * license includes it. Falls back to the retained license's type so an expired license\n * still lists rows. See `PLAN_FEATURE_CATALOG` in `./license`.\n */\n get planFeatureCatalog(): string[] {\n const type = ee.licenseInfo.type ?? ee.retainedLicense?.type;\n return type && type in PLAN_FEATURE_CATALOG\n ? PLAN_FEATURE_CATALOG[type as keyof typeof PLAN_FEATURE_CATALOG]\n : [];\n },\n\n get isTrial() {\n return ee.licenseInfo.isTrial;\n },\n\n get planPriceId() {\n return ee.licenseInfo.planPriceId;\n },\n\n get subscriptionId() {\n return ee.licenseInfo.subscriptionId;\n },\n\n features: Object.freeze({\n list,\n get,\n isEnabled: (featureName: string) => get(featureName) !== undefined,\n }),\n\n entitlements: Object.freeze({\n register: entitlements.register,\n // Resolvers are registered during `register()`, before the license is validated, and each\n // falls back to a built-in default when the feature is absent. Without this gate an\n // instance whose license was disabled would still report generous limits, which reads as\n // \"these are your granted limits\". No license, no entitlements.\n list: () => (ee.enabled ? entitlements.list(get) : []),\n // A lapsed license's limits, from the same resolvers run against its retained feature list,\n // so a lapsed Plan card and the debug dump carry the defaults and clamps the plan enforced\n // instead of raw options. Only features the retained license listed are reported.\n listRetained() {\n const retainedFeatures = (ee.retainedLicense?.features ?? []).map((feature) =>\n typeof feature === 'object' ? feature : { name: feature }\n );\n const getRetained = (name: string) =>\n retainedFeatures.find((feature) => feature.name === name);\n\n return entitlements\n .list(getRetained)\n .filter((entry) => getRetained(entry.feature) !== undefined);\n },\n }),\n});\n"],"names":["ONE_MINUTE","ee","enabled","licenseInfo","isTrial","retainedLicense","licenseStatus","disable","message","status","shouldEmitEvent","logger","warn","type","pick","strapi","eventHub","emit","enable","initialized","init","licenseDir","process","env","STRAPI_DISABLE_EE","toLowerCase","license","STRAPI_LICENSE","readLicense","verifyLicense","error","Error","onlineUpdate","get","commit","rollback","db","transaction","storedInfo","queryBuilder","where","key","select","first","transacting","forUpdate","execute","then","result","JSON","parse","value","shouldContactRegistry","lastCheckAt","Date","now","fallback","errorKind","LicenseCheckError","shouldFallback","licenseKey","fetchLicense","config","catch","newLicenseInfo","licenseInfoChanged","isEqual","features","seats","wasEnabled","validateInfo","query","insert","stringify","update","expireAt","expirationTime","getTime","checkLicense","shouldStayOffline","STRAPI_DISABLE_LICENSE_PING","cron","add","task","options","shiftCronExpression","getTrialEndDate","silentFetch","createStrapiFetch","logs","res","LICENSE_REGISTRY_URI","method","headers","data","json","list","map","feature","name","featureName","find","entitlements","createEntitlementsRegistry","Object","freeze","isEE","renewalDate","planFeatureCatalog","PLAN_FEATURE_CATALOG","planPriceId","subscriptionId","isEnabled","undefined","register","listRetained","retainedFeatures","getRetained","filter","entry"],"mappings":"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"}
|
package/dist/ee/index.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { isEqual, pick } from 'lodash';
|
|
2
2
|
import { createStrapiFetch } from '../utils/fetch.mjs';
|
|
3
|
-
import { LICENSE_REGISTRY_URI, LicenseCheckError, readLicense, verifyLicense, fetchLicense } from './license.mjs';
|
|
3
|
+
import { PLAN_FEATURE_CATALOG, LICENSE_REGISTRY_URI, LicenseCheckError, readLicense, verifyLicense, fetchLicense } from './license.mjs';
|
|
4
|
+
import { createEntitlementsRegistry } from './entitlements.mjs';
|
|
4
5
|
import { shiftCronExpression } from '../utils/cron.mjs';
|
|
5
6
|
|
|
6
7
|
const ONE_MINUTE = 1000 * 60;
|
|
@@ -8,12 +9,30 @@ const ee = {
|
|
|
8
9
|
enabled: false,
|
|
9
10
|
licenseInfo: {
|
|
10
11
|
isTrial: false
|
|
11
|
-
}
|
|
12
|
+
},
|
|
13
|
+
retainedLicense: null,
|
|
14
|
+
licenseStatus: 'none'
|
|
12
15
|
};
|
|
13
|
-
const disable = (message)=>{
|
|
16
|
+
const disable = (message, status = 'unknown')=>{
|
|
14
17
|
// Prevent emitting ee.disable if it was already disabled
|
|
15
18
|
const shouldEmitEvent = ee.enabled !== false;
|
|
16
19
|
ee.logger?.warn(`${message} Switching to CE.`);
|
|
20
|
+
// Retain a display-only snapshot (never the key) BEFORE wiping, so the admin panel can
|
|
21
|
+
// still show which license this instance has and why it is unusable. Guarded on `type`
|
|
22
|
+
// so a repeat disable() call cannot overwrite the snapshot with an already-wiped one.
|
|
23
|
+
if (ee.licenseInfo.type) {
|
|
24
|
+
ee.retainedLicense = pick(ee.licenseInfo, [
|
|
25
|
+
'features',
|
|
26
|
+
'expireAt',
|
|
27
|
+
'seats',
|
|
28
|
+
'type',
|
|
29
|
+
'isTrial',
|
|
30
|
+
'subscriptionId',
|
|
31
|
+
'planPriceId',
|
|
32
|
+
'renewalDate'
|
|
33
|
+
]);
|
|
34
|
+
}
|
|
35
|
+
ee.licenseStatus = status;
|
|
17
36
|
// Only keep the license key and isTrial for potential re-enabling during a later check
|
|
18
37
|
ee.licenseInfo = pick(ee.licenseInfo, [
|
|
19
38
|
'licenseKey',
|
|
@@ -30,6 +49,8 @@ const enable = ()=>{
|
|
|
30
49
|
// Prevent emitting ee.enable if it was already enabled
|
|
31
50
|
const shouldEmitEvent = ee.enabled !== true;
|
|
32
51
|
ee.enabled = true;
|
|
52
|
+
ee.licenseStatus = 'active';
|
|
53
|
+
ee.retainedLicense = null;
|
|
33
54
|
if (shouldEmitEvent) {
|
|
34
55
|
// Notify EE features that they should be disabled
|
|
35
56
|
strapi.eventHub.emit('ee.enable');
|
|
@@ -77,8 +98,15 @@ let initialized = false;
|
|
|
77
98
|
lastCheckAt: Date.now()
|
|
78
99
|
};
|
|
79
100
|
const fallback = (error)=>{
|
|
101
|
+
// Whether the registry was unreachable or actually refused the license is only
|
|
102
|
+
// knowable here, from `shouldFallback`. Record it rather than letting the admin
|
|
103
|
+
// panel infer it from the presence of a cached license: an instance that has never
|
|
104
|
+
// reached the registry has no cache to fall back to, and would otherwise be told
|
|
105
|
+
// its license was refused when the registry was merely unreachable.
|
|
106
|
+
result.errorKind = error instanceof LicenseCheckError && error.shouldFallback ? 'unreachable' : 'rejected';
|
|
80
107
|
if (error instanceof LicenseCheckError && error.shouldFallback && storedInfo?.license) {
|
|
81
108
|
ee.logger?.warn(`${error.message} The last stored one will be used as a potential fallback.`);
|
|
109
|
+
result.error = error.message; // record why we fell back so usingCachedLicense is derivable
|
|
82
110
|
return storedInfo.license;
|
|
83
111
|
}
|
|
84
112
|
result.error = error.message;
|
|
@@ -142,7 +170,7 @@ const validateInfo = ()=>{
|
|
|
142
170
|
}
|
|
143
171
|
const expirationTime = new Date(ee.licenseInfo.expireAt).getTime();
|
|
144
172
|
if (expirationTime < new Date().getTime()) {
|
|
145
|
-
return disable('License expired.');
|
|
173
|
+
return disable('License expired.', 'expired');
|
|
146
174
|
}
|
|
147
175
|
enable();
|
|
148
176
|
};
|
|
@@ -189,6 +217,7 @@ const list = ()=>{
|
|
|
189
217
|
}) || [];
|
|
190
218
|
};
|
|
191
219
|
const get = (featureName)=>list().find((feature)=>feature.name === featureName);
|
|
220
|
+
const entitlements = createEntitlementsRegistry();
|
|
192
221
|
var index = Object.freeze({
|
|
193
222
|
init,
|
|
194
223
|
checkLicense,
|
|
@@ -196,12 +225,32 @@ var index = Object.freeze({
|
|
|
196
225
|
get isEE () {
|
|
197
226
|
return ee.enabled;
|
|
198
227
|
},
|
|
228
|
+
get licenseStatus () {
|
|
229
|
+
return ee.licenseStatus;
|
|
230
|
+
},
|
|
231
|
+
/** Display-only; see EE.retainedLicense. Never use for feature gating. */ get retainedLicense () {
|
|
232
|
+
return ee.retainedLicense;
|
|
233
|
+
},
|
|
199
234
|
get seats () {
|
|
200
235
|
return ee.licenseInfo.seats;
|
|
201
236
|
},
|
|
202
237
|
get type () {
|
|
203
238
|
return ee.licenseInfo.type;
|
|
204
239
|
},
|
|
240
|
+
get expireAt () {
|
|
241
|
+
return ee.licenseInfo.expireAt;
|
|
242
|
+
},
|
|
243
|
+
/** Null when the registry does not provide it yet; survives expiry via the retained snapshot. */ get renewalDate () {
|
|
244
|
+
return ee.licenseInfo.renewalDate ?? ee.retainedLicense?.renewalDate ?? null;
|
|
245
|
+
},
|
|
246
|
+
/**
|
|
247
|
+
* Every feature the current plan supports, in display order, regardless of whether this
|
|
248
|
+
* license includes it. Falls back to the retained license's type so an expired license
|
|
249
|
+
* still lists rows. See `PLAN_FEATURE_CATALOG` in `./license`.
|
|
250
|
+
*/ get planFeatureCatalog () {
|
|
251
|
+
const type = ee.licenseInfo.type ?? ee.retainedLicense?.type;
|
|
252
|
+
return type && type in PLAN_FEATURE_CATALOG ? PLAN_FEATURE_CATALOG[type] : [];
|
|
253
|
+
},
|
|
205
254
|
get isTrial () {
|
|
206
255
|
return ee.licenseInfo.isTrial;
|
|
207
256
|
},
|
|
@@ -215,6 +264,24 @@ var index = Object.freeze({
|
|
|
215
264
|
list,
|
|
216
265
|
get,
|
|
217
266
|
isEnabled: (featureName)=>get(featureName) !== undefined
|
|
267
|
+
}),
|
|
268
|
+
entitlements: Object.freeze({
|
|
269
|
+
register: entitlements.register,
|
|
270
|
+
// Resolvers are registered during `register()`, before the license is validated, and each
|
|
271
|
+
// falls back to a built-in default when the feature is absent. Without this gate an
|
|
272
|
+
// instance whose license was disabled would still report generous limits, which reads as
|
|
273
|
+
// "these are your granted limits". No license, no entitlements.
|
|
274
|
+
list: ()=>ee.enabled ? entitlements.list(get) : [],
|
|
275
|
+
// A lapsed license's limits, from the same resolvers run against its retained feature list,
|
|
276
|
+
// so a lapsed Plan card and the debug dump carry the defaults and clamps the plan enforced
|
|
277
|
+
// instead of raw options. Only features the retained license listed are reported.
|
|
278
|
+
listRetained () {
|
|
279
|
+
const retainedFeatures = (ee.retainedLicense?.features ?? []).map((feature)=>typeof feature === 'object' ? feature : {
|
|
280
|
+
name: feature
|
|
281
|
+
});
|
|
282
|
+
const getRetained = (name)=>retainedFeatures.find((feature)=>feature.name === name);
|
|
283
|
+
return entitlements.list(getRetained).filter((entry)=>getRetained(entry.feature) !== undefined);
|
|
284
|
+
}
|
|
218
285
|
})
|
|
219
286
|
});
|
|
220
287
|
|
package/dist/ee/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sources":["../../src/ee/index.ts"],"sourcesContent":["import { isEqual, pick } from 'lodash';\nimport type { Logger } from '@strapi/logger';\nimport type { Core } from '@strapi/types';\nimport { createStrapiFetch } from '../utils/fetch';\nimport {\n readLicense,\n verifyLicense,\n fetchLicense,\n LicenseCheckError,\n LICENSE_REGISTRY_URI,\n} from './license';\nimport { shiftCronExpression } from '../utils/cron';\n\nconst ONE_MINUTE = 1000 * 60;\n\ninterface EE {\n enabled: boolean;\n licenseInfo: {\n licenseKey?: string;\n features?: Array<{ name: string; [key: string]: any } | string>;\n expireAt?: string;\n seats?: number;\n type?: string;\n isTrial: boolean;\n subscriptionId?: string;\n planPriceId?: string;\n };\n logger?: Logger;\n}\n\nconst ee: EE = {\n enabled: false,\n licenseInfo: {\n isTrial: false,\n },\n};\n\nconst disable = (message: string) => {\n // Prevent emitting ee.disable if it was already disabled\n const shouldEmitEvent = ee.enabled !== false;\n\n ee.logger?.warn(`${message} Switching to CE.`);\n // Only keep the license key and isTrial for potential re-enabling during a later check\n ee.licenseInfo = pick(ee.licenseInfo, ['licenseKey', 'isTrial']);\n\n ee.licenseInfo.isTrial = false;\n\n ee.enabled = false;\n\n if (shouldEmitEvent) {\n // Notify EE features that they should be disabled\n strapi.eventHub.emit('ee.disable');\n }\n};\n\nconst enable = () => {\n // Prevent emitting ee.enable if it was already enabled\n const shouldEmitEvent = ee.enabled !== true;\n\n ee.enabled = true;\n\n if (shouldEmitEvent) {\n // Notify EE features that they should be disabled\n strapi.eventHub.emit('ee.enable');\n }\n};\n\nlet initialized = false;\n\n/**\n * Optimistically enable EE if the format of the license is valid, only run once.\n */\nconst init = (licenseDir: string, logger?: Logger) => {\n if (initialized) {\n return;\n }\n\n initialized = true;\n ee.logger = logger;\n\n if (process.env.STRAPI_DISABLE_EE?.toLowerCase() === 'true') {\n return;\n }\n\n try {\n const license = process.env.STRAPI_LICENSE || readLicense(licenseDir);\n\n if (license) {\n ee.licenseInfo = verifyLicense(license);\n enable();\n }\n } catch (error) {\n if (error instanceof Error) {\n disable(error.message);\n } else {\n disable('Invalid license.');\n }\n }\n};\n\n/**\n * Contact the license registry to update the license to its latest state.\n *\n * Store the result in database to avoid unecessary requests, and will fallback to that in case of a network failure.\n */\nconst onlineUpdate = async ({ strapi }: { strapi: Core.Strapi }) => {\n const { get, commit, rollback } = await strapi.db.transaction();\n const transaction = get();\n\n try {\n const storedInfo = await strapi.db\n ?.queryBuilder('strapi::core-store')\n .where({ key: 'ee_information' })\n .select('value')\n .first()\n .transacting(transaction)\n .forUpdate()\n .execute()\n .then((result: any) => (result ? JSON.parse(result.value) : result));\n\n const shouldContactRegistry = (storedInfo?.lastCheckAt ?? 0) < Date.now() - ONE_MINUTE;\n const result: {\n license?: string | null;\n error?: string;\n lastCheckAt?: number;\n } = { lastCheckAt: Date.now() };\n\n const fallback = (error: Error) => {\n if (error instanceof LicenseCheckError && error.shouldFallback && storedInfo?.license) {\n ee.logger?.warn(\n `${error.message} The last stored one will be used as a potential fallback.`\n );\n return storedInfo.license;\n }\n\n result.error = error.message;\n disable(error.message);\n };\n\n if (!ee?.licenseInfo?.licenseKey) {\n throw new Error('Missing license key.');\n }\n\n const license = shouldContactRegistry\n ? await fetchLicense({ strapi }, ee.licenseInfo.licenseKey, strapi.config.get('uuid')).catch(\n fallback\n )\n : storedInfo.license;\n\n if (license) {\n try {\n // Verify license and check if its info changed\n const newLicenseInfo = verifyLicense(license);\n const licenseInfoChanged =\n !isEqual(newLicenseInfo.features, ee.licenseInfo.features) ||\n newLicenseInfo.seats !== ee.licenseInfo.seats ||\n newLicenseInfo.type !== ee.licenseInfo.type;\n\n // Store the new license info\n ee.licenseInfo = newLicenseInfo;\n const wasEnabled = ee.enabled;\n validateInfo();\n\n // Notify EE features\n if (licenseInfoChanged && wasEnabled) {\n strapi.eventHub.emit('ee.update');\n }\n } catch (error) {\n if (error instanceof Error) {\n disable(error.message);\n } else {\n disable('Invalid license.');\n }\n }\n } else if (!shouldContactRegistry) {\n disable(storedInfo.error);\n }\n\n if (shouldContactRegistry) {\n result.license = license ?? null;\n const query = strapi.db.queryBuilder('strapi::core-store').transacting(transaction);\n\n if (!storedInfo) {\n query.insert({ key: 'ee_information', value: JSON.stringify(result) });\n } else {\n query.update({ value: JSON.stringify(result) }).where({ key: 'ee_information' });\n }\n\n await query.execute();\n }\n\n await commit();\n } catch {\n // Example of errors: SQLite does not support FOR UPDATE\n await rollback();\n }\n};\n\nconst validateInfo = () => {\n if (typeof ee.licenseInfo.expireAt === 'undefined') {\n throw new Error('Missing license key.');\n }\n\n const expirationTime = new Date(ee.licenseInfo.expireAt).getTime();\n\n if (expirationTime < new Date().getTime()) {\n return disable('License expired.');\n }\n\n enable();\n};\n\nconst checkLicense = async ({ strapi }: { strapi: Core.Strapi }) => {\n const shouldStayOffline =\n ee.licenseInfo.type === 'gold' &&\n // This env variable support is temporarily used to ease the migration between online vs offline\n process.env.STRAPI_DISABLE_LICENSE_PING?.toLowerCase() === 'true';\n\n if (!shouldStayOffline) {\n await onlineUpdate({ strapi });\n\n strapi.cron.add({\n onlineUpdate: {\n task: () => onlineUpdate({ strapi }),\n options: shiftCronExpression('0 0 */12 * * *'),\n },\n });\n } else {\n if (!ee.licenseInfo.expireAt) {\n return disable('Your license does not have offline support.');\n }\n\n validateInfo();\n }\n};\n\nconst getTrialEndDate = async ({\n strapi,\n}: {\n strapi: Core.Strapi;\n}): Promise<{ trialEndsAt: string } | null> => {\n const silentFetch = createStrapiFetch(strapi, {\n logs: false,\n });\n\n const res = await silentFetch(\n `${LICENSE_REGISTRY_URI}/api/licenses/${ee.licenseInfo.licenseKey}/trial-countdown`,\n {\n method: 'GET',\n headers: { 'Content-Type': 'application/json' },\n }\n ).catch(() => {\n throw new LicenseCheckError(\n 'Could not proceed to retrieve the trial time left for your license.',\n true\n );\n });\n\n const data = (await res.json()) as { trialEndsAt: string } | null;\n\n return data;\n};\n\nconst list = () => {\n return (\n ee.licenseInfo.features?.map((feature) =>\n typeof feature === 'object' ? feature : { name: feature }\n ) || []\n );\n};\n\nconst get = (featureName: string) => list().find((feature) => feature.name === featureName);\n\nexport default Object.freeze({\n init,\n checkLicense,\n getTrialEndDate,\n\n get isEE() {\n return ee.enabled;\n },\n\n get seats() {\n return ee.licenseInfo.seats;\n },\n\n get type() {\n return ee.licenseInfo.type;\n },\n\n get isTrial() {\n return ee.licenseInfo.isTrial;\n },\n\n get planPriceId() {\n return ee.licenseInfo.planPriceId;\n },\n\n get subscriptionId() {\n return ee.licenseInfo.subscriptionId;\n },\n\n features: Object.freeze({\n list,\n get,\n isEnabled: (featureName: string) => get(featureName) !== undefined,\n }),\n});\n"],"names":["ONE_MINUTE","ee","enabled","licenseInfo","isTrial","disable","message","shouldEmitEvent","logger","warn","pick","strapi","eventHub","emit","enable","initialized","init","licenseDir","process","env","STRAPI_DISABLE_EE","toLowerCase","license","STRAPI_LICENSE","readLicense","verifyLicense","error","Error","onlineUpdate","get","commit","rollback","db","transaction","storedInfo","queryBuilder","where","key","select","first","transacting","forUpdate","execute","then","result","JSON","parse","value","shouldContactRegistry","lastCheckAt","Date","now","fallback","LicenseCheckError","shouldFallback","licenseKey","fetchLicense","config","catch","newLicenseInfo","licenseInfoChanged","isEqual","features","seats","type","wasEnabled","validateInfo","query","insert","stringify","update","expireAt","expirationTime","getTime","checkLicense","shouldStayOffline","STRAPI_DISABLE_LICENSE_PING","cron","add","task","options","shiftCronExpression","getTrialEndDate","silentFetch","createStrapiFetch","logs","res","LICENSE_REGISTRY_URI","method","headers","data","json","list","map","feature","name","featureName","find","Object","freeze","isEE","planPriceId","subscriptionId","isEnabled","undefined"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../../src/ee/index.ts"],"sourcesContent":["import { isEqual, pick } from 'lodash';\nimport type { Logger } from '@strapi/logger';\nimport type { Core } from '@strapi/types';\nimport { createStrapiFetch } from '../utils/fetch';\nimport {\n readLicense,\n verifyLicense,\n fetchLicense,\n LicenseCheckError,\n LICENSE_REGISTRY_URI,\n PLAN_FEATURE_CATALOG,\n} from './license';\nimport { createEntitlementsRegistry } from './entitlements';\nimport { shiftCronExpression } from '../utils/cron';\n\nconst ONE_MINUTE = 1000 * 60;\n\ninterface LicenseInfoState {\n licenseKey?: string;\n features?: Array<{ name: string; [key: string]: any } | string>;\n expireAt?: string;\n seats?: number;\n type?: string;\n isTrial: boolean;\n subscriptionId?: string;\n planPriceId?: string;\n /** End of the subscription term, epoch milliseconds. */\n renewalDate?: string | number;\n}\n\ntype LicenseStatus = 'none' | 'active' | 'expired' | 'unknown';\n\ninterface EE {\n enabled: boolean;\n licenseInfo: LicenseInfoState;\n /**\n * Display-only copy of the last known license, retained when a license exists but is\n * not usable (expired / could not be validated) so the admin panel can explain why.\n * NEVER read by enforcement paths (features.list/get/isEnabled, isEE) and never holds\n * the license key.\n */\n retainedLicense: Omit<LicenseInfoState, 'licenseKey'> | null;\n licenseStatus: LicenseStatus;\n logger?: Logger;\n}\n\nconst ee: EE = {\n enabled: false,\n licenseInfo: {\n isTrial: false,\n },\n retainedLicense: null,\n licenseStatus: 'none',\n};\n\nconst disable = (message: string, status: 'expired' | 'unknown' = 'unknown') => {\n // Prevent emitting ee.disable if it was already disabled\n const shouldEmitEvent = ee.enabled !== false;\n\n ee.logger?.warn(`${message} Switching to CE.`);\n\n // Retain a display-only snapshot (never the key) BEFORE wiping, so the admin panel can\n // still show which license this instance has and why it is unusable. Guarded on `type`\n // so a repeat disable() call cannot overwrite the snapshot with an already-wiped one.\n if (ee.licenseInfo.type) {\n ee.retainedLicense = pick(ee.licenseInfo, [\n 'features',\n 'expireAt',\n 'seats',\n 'type',\n 'isTrial',\n 'subscriptionId',\n 'planPriceId',\n 'renewalDate',\n ]);\n }\n ee.licenseStatus = status;\n\n // Only keep the license key and isTrial for potential re-enabling during a later check\n ee.licenseInfo = pick(ee.licenseInfo, ['licenseKey', 'isTrial']);\n\n ee.licenseInfo.isTrial = false;\n\n ee.enabled = false;\n\n if (shouldEmitEvent) {\n // Notify EE features that they should be disabled\n strapi.eventHub.emit('ee.disable');\n }\n};\n\nconst enable = () => {\n // Prevent emitting ee.enable if it was already enabled\n const shouldEmitEvent = ee.enabled !== true;\n\n ee.enabled = true;\n ee.licenseStatus = 'active';\n ee.retainedLicense = null;\n\n if (shouldEmitEvent) {\n // Notify EE features that they should be disabled\n strapi.eventHub.emit('ee.enable');\n }\n};\n\nlet initialized = false;\n\n/**\n * Optimistically enable EE if the format of the license is valid, only run once.\n */\nconst init = (licenseDir: string, logger?: Logger) => {\n if (initialized) {\n return;\n }\n\n initialized = true;\n ee.logger = logger;\n\n if (process.env.STRAPI_DISABLE_EE?.toLowerCase() === 'true') {\n return;\n }\n\n try {\n const license = process.env.STRAPI_LICENSE || readLicense(licenseDir);\n\n if (license) {\n ee.licenseInfo = verifyLicense(license);\n enable();\n }\n } catch (error) {\n if (error instanceof Error) {\n disable(error.message);\n } else {\n disable('Invalid license.');\n }\n }\n};\n\n/**\n * Contact the license registry to update the license to its latest state.\n *\n * Store the result in database to avoid unecessary requests, and will fallback to that in case of a network failure.\n */\nconst onlineUpdate = async ({ strapi }: { strapi: Core.Strapi }) => {\n const { get, commit, rollback } = await strapi.db.transaction();\n const transaction = get();\n\n try {\n const storedInfo = await strapi.db\n ?.queryBuilder('strapi::core-store')\n .where({ key: 'ee_information' })\n .select('value')\n .first()\n .transacting(transaction)\n .forUpdate()\n .execute()\n .then((result: any) => (result ? JSON.parse(result.value) : result));\n\n const shouldContactRegistry = (storedInfo?.lastCheckAt ?? 0) < Date.now() - ONE_MINUTE;\n const result: {\n license?: string | null;\n error?: string;\n errorKind?: 'unreachable' | 'rejected';\n lastCheckAt?: number;\n } = { lastCheckAt: Date.now() };\n\n const fallback = (error: Error) => {\n // Whether the registry was unreachable or actually refused the license is only\n // knowable here, from `shouldFallback`. Record it rather than letting the admin\n // panel infer it from the presence of a cached license: an instance that has never\n // reached the registry has no cache to fall back to, and would otherwise be told\n // its license was refused when the registry was merely unreachable.\n result.errorKind =\n error instanceof LicenseCheckError && error.shouldFallback ? 'unreachable' : 'rejected';\n\n if (error instanceof LicenseCheckError && error.shouldFallback && storedInfo?.license) {\n ee.logger?.warn(\n `${error.message} The last stored one will be used as a potential fallback.`\n );\n result.error = error.message; // record why we fell back so usingCachedLicense is derivable\n return storedInfo.license;\n }\n\n result.error = error.message;\n disable(error.message);\n };\n\n if (!ee?.licenseInfo?.licenseKey) {\n throw new Error('Missing license key.');\n }\n\n const license = shouldContactRegistry\n ? await fetchLicense({ strapi }, ee.licenseInfo.licenseKey, strapi.config.get('uuid')).catch(\n fallback\n )\n : storedInfo.license;\n\n if (license) {\n try {\n // Verify license and check if its info changed\n const newLicenseInfo = verifyLicense(license);\n const licenseInfoChanged =\n !isEqual(newLicenseInfo.features, ee.licenseInfo.features) ||\n newLicenseInfo.seats !== ee.licenseInfo.seats ||\n newLicenseInfo.type !== ee.licenseInfo.type;\n\n // Store the new license info\n ee.licenseInfo = newLicenseInfo;\n const wasEnabled = ee.enabled;\n validateInfo();\n\n // Notify EE features\n if (licenseInfoChanged && wasEnabled) {\n strapi.eventHub.emit('ee.update');\n }\n } catch (error) {\n if (error instanceof Error) {\n disable(error.message);\n } else {\n disable('Invalid license.');\n }\n }\n } else if (!shouldContactRegistry) {\n disable(storedInfo.error);\n }\n\n if (shouldContactRegistry) {\n result.license = license ?? null;\n const query = strapi.db.queryBuilder('strapi::core-store').transacting(transaction);\n\n if (!storedInfo) {\n query.insert({ key: 'ee_information', value: JSON.stringify(result) });\n } else {\n query.update({ value: JSON.stringify(result) }).where({ key: 'ee_information' });\n }\n\n await query.execute();\n }\n\n await commit();\n } catch {\n // Example of errors: SQLite does not support FOR UPDATE\n await rollback();\n }\n};\n\nconst validateInfo = () => {\n if (typeof ee.licenseInfo.expireAt === 'undefined') {\n throw new Error('Missing license key.');\n }\n\n const expirationTime = new Date(ee.licenseInfo.expireAt).getTime();\n\n if (expirationTime < new Date().getTime()) {\n return disable('License expired.', 'expired');\n }\n\n enable();\n};\n\nconst checkLicense = async ({ strapi }: { strapi: Core.Strapi }) => {\n const shouldStayOffline =\n ee.licenseInfo.type === 'gold' &&\n // This env variable support is temporarily used to ease the migration between online vs offline\n process.env.STRAPI_DISABLE_LICENSE_PING?.toLowerCase() === 'true';\n\n if (!shouldStayOffline) {\n await onlineUpdate({ strapi });\n\n strapi.cron.add({\n onlineUpdate: {\n task: () => onlineUpdate({ strapi }),\n options: shiftCronExpression('0 0 */12 * * *'),\n },\n });\n } else {\n if (!ee.licenseInfo.expireAt) {\n return disable('Your license does not have offline support.');\n }\n\n validateInfo();\n }\n};\n\nconst getTrialEndDate = async ({\n strapi,\n}: {\n strapi: Core.Strapi;\n}): Promise<{ trialEndsAt: string } | null> => {\n const silentFetch = createStrapiFetch(strapi, {\n logs: false,\n });\n\n const res = await silentFetch(\n `${LICENSE_REGISTRY_URI}/api/licenses/${ee.licenseInfo.licenseKey}/trial-countdown`,\n {\n method: 'GET',\n headers: { 'Content-Type': 'application/json' },\n }\n ).catch(() => {\n throw new LicenseCheckError(\n 'Could not proceed to retrieve the trial time left for your license.',\n true\n );\n });\n\n const data = (await res.json()) as { trialEndsAt: string } | null;\n\n return data;\n};\n\nconst list = () => {\n return (\n ee.licenseInfo.features?.map((feature) =>\n typeof feature === 'object' ? feature : { name: feature }\n ) || []\n );\n};\n\nconst get = (featureName: string) => list().find((feature) => feature.name === featureName);\n\nconst entitlements = createEntitlementsRegistry();\n\nexport default Object.freeze({\n init,\n checkLicense,\n getTrialEndDate,\n\n get isEE() {\n return ee.enabled;\n },\n\n get licenseStatus() {\n return ee.licenseStatus;\n },\n\n /** Display-only; see EE.retainedLicense. Never use for feature gating. */\n get retainedLicense() {\n return ee.retainedLicense;\n },\n\n get seats() {\n return ee.licenseInfo.seats;\n },\n\n get type() {\n return ee.licenseInfo.type;\n },\n\n get expireAt() {\n return ee.licenseInfo.expireAt;\n },\n\n /** Null when the registry does not provide it yet; survives expiry via the retained snapshot. */\n get renewalDate() {\n return ee.licenseInfo.renewalDate ?? ee.retainedLicense?.renewalDate ?? null;\n },\n\n /**\n * Every feature the current plan supports, in display order, regardless of whether this\n * license includes it. Falls back to the retained license's type so an expired license\n * still lists rows. See `PLAN_FEATURE_CATALOG` in `./license`.\n */\n get planFeatureCatalog(): string[] {\n const type = ee.licenseInfo.type ?? ee.retainedLicense?.type;\n return type && type in PLAN_FEATURE_CATALOG\n ? PLAN_FEATURE_CATALOG[type as keyof typeof PLAN_FEATURE_CATALOG]\n : [];\n },\n\n get isTrial() {\n return ee.licenseInfo.isTrial;\n },\n\n get planPriceId() {\n return ee.licenseInfo.planPriceId;\n },\n\n get subscriptionId() {\n return ee.licenseInfo.subscriptionId;\n },\n\n features: Object.freeze({\n list,\n get,\n isEnabled: (featureName: string) => get(featureName) !== undefined,\n }),\n\n entitlements: Object.freeze({\n register: entitlements.register,\n // Resolvers are registered during `register()`, before the license is validated, and each\n // falls back to a built-in default when the feature is absent. Without this gate an\n // instance whose license was disabled would still report generous limits, which reads as\n // \"these are your granted limits\". No license, no entitlements.\n list: () => (ee.enabled ? entitlements.list(get) : []),\n // A lapsed license's limits, from the same resolvers run against its retained feature list,\n // so a lapsed Plan card and the debug dump carry the defaults and clamps the plan enforced\n // instead of raw options. Only features the retained license listed are reported.\n listRetained() {\n const retainedFeatures = (ee.retainedLicense?.features ?? []).map((feature) =>\n typeof feature === 'object' ? feature : { name: feature }\n );\n const getRetained = (name: string) =>\n retainedFeatures.find((feature) => feature.name === name);\n\n return entitlements\n .list(getRetained)\n .filter((entry) => getRetained(entry.feature) !== undefined);\n },\n }),\n});\n"],"names":["ONE_MINUTE","ee","enabled","licenseInfo","isTrial","retainedLicense","licenseStatus","disable","message","status","shouldEmitEvent","logger","warn","type","pick","strapi","eventHub","emit","enable","initialized","init","licenseDir","process","env","STRAPI_DISABLE_EE","toLowerCase","license","STRAPI_LICENSE","readLicense","verifyLicense","error","Error","onlineUpdate","get","commit","rollback","db","transaction","storedInfo","queryBuilder","where","key","select","first","transacting","forUpdate","execute","then","result","JSON","parse","value","shouldContactRegistry","lastCheckAt","Date","now","fallback","errorKind","LicenseCheckError","shouldFallback","licenseKey","fetchLicense","config","catch","newLicenseInfo","licenseInfoChanged","isEqual","features","seats","wasEnabled","validateInfo","query","insert","stringify","update","expireAt","expirationTime","getTime","checkLicense","shouldStayOffline","STRAPI_DISABLE_LICENSE_PING","cron","add","task","options","shiftCronExpression","getTrialEndDate","silentFetch","createStrapiFetch","logs","res","LICENSE_REGISTRY_URI","method","headers","data","json","list","map","feature","name","featureName","find","entitlements","createEntitlementsRegistry","Object","freeze","isEE","renewalDate","planFeatureCatalog","PLAN_FEATURE_CATALOG","planPriceId","subscriptionId","isEnabled","undefined","register","listRetained","retainedFeatures","getRetained","filter","entry"],"mappings":"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"}
|
package/dist/ee/license.d.ts
CHANGED
|
@@ -10,7 +10,17 @@ interface LicenseInfo {
|
|
|
10
10
|
}>;
|
|
11
11
|
subscriptionId?: string;
|
|
12
12
|
planPriceId?: string;
|
|
13
|
+
/** End of the subscription term, epoch milliseconds. */
|
|
14
|
+
renewalDate?: string | number;
|
|
15
|
+
licenseKey?: string;
|
|
16
|
+
customerId?: string;
|
|
13
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
* Features that can appear on a plan, in the order the admin panel lists them.
|
|
20
|
+
* Used to render entitlement rows for features a plan supports but this license
|
|
21
|
+
* does not include. `cms-ai` is deliberately absent: AI usage has its own panel.
|
|
22
|
+
*/
|
|
23
|
+
export declare const PLAN_FEATURE_CATALOG: Record<'bronze' | 'silver' | 'gold', string[]>;
|
|
14
24
|
declare const LICENSE_REGISTRY_URI = "https://license.strapi.io";
|
|
15
25
|
declare class LicenseCheckError extends Error {
|
|
16
26
|
shouldFallback: boolean;
|
package/dist/ee/license.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"license.d.ts","sourceRoot":"","sources":["../../src/ee/license.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAI1C,UAAU,WAAW;IACnB,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAC;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,CAAC,CAAC;IACtE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"license.d.ts","sourceRoot":"","sources":["../../src/ee/license.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAI1C,UAAU,WAAW;IACnB,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAC;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,CAAC,CAAC;IACtE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,wDAAwD;IAExD,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAE9B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAiBD;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,EAAE,MAAM,CAAC,QAAQ,GAAG,QAAQ,GAAG,MAAM,EAAE,MAAM,EAAE,CAW/E,CAAC;AAEF,QAAA,MAAM,oBAAoB,8BAA8B,CAAC;AAkBzD,cAAM,iBAAkB,SAAQ,KAAK;IACnC,cAAc,UAAS;gBAEX,OAAO,EAAE,MAAM,EAAE,cAAc,UAAQ;CAKpD;AAED,QAAA,MAAM,WAAW,GAAI,WAAW,MAAM,uBASrC,CAAC;AAEF,QAAA,MAAM,aAAa,GAAI,SAAS,MAAM,gBA+BrC,CAAC;AAUF,QAAA,MAAM,YAAY,GAChB,YAAY;IAAE,MAAM,EAAE,IAAI,CAAC,MAAM,CAAA;CAAE,EACnC,KAAK,MAAM,EACX,WAAW,MAAM,oBA0ClB,CAAC;AAEF,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,YAAY,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,CAAC"}
|