@strapi/admin 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.
Files changed (190) hide show
  1. package/dist/admin/admin/src/components/FormInputs/Boolean.js +3 -2
  2. package/dist/admin/admin/src/components/FormInputs/Boolean.js.map +1 -1
  3. package/dist/admin/admin/src/components/FormInputs/Boolean.mjs +3 -2
  4. package/dist/admin/admin/src/components/FormInputs/Boolean.mjs.map +1 -1
  5. package/dist/admin/admin/src/constants.js +14 -0
  6. package/dist/admin/admin/src/constants.js.map +1 -1
  7. package/dist/admin/admin/src/constants.mjs +14 -0
  8. package/dist/admin/admin/src/constants.mjs.map +1 -1
  9. package/dist/admin/admin/src/pages/Auth/components/ResetPassword.js +6 -12
  10. package/dist/admin/admin/src/pages/Auth/components/ResetPassword.js.map +1 -1
  11. package/dist/admin/admin/src/pages/Auth/components/ResetPassword.mjs +6 -12
  12. package/dist/admin/admin/src/pages/Auth/components/ResetPassword.mjs.map +1 -1
  13. package/dist/admin/admin/src/pages/Settings/components/SettingsNav.js +10 -2
  14. package/dist/admin/admin/src/pages/Settings/components/SettingsNav.js.map +1 -1
  15. package/dist/admin/admin/src/pages/Settings/components/SettingsNav.mjs +10 -2
  16. package/dist/admin/admin/src/pages/Settings/components/SettingsNav.mjs.map +1 -1
  17. package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/ApplicationInfoPage.js +6 -56
  18. package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/ApplicationInfoPage.js.map +1 -1
  19. package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/ApplicationInfoPage.mjs +6 -56
  20. package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/ApplicationInfoPage.mjs.map +1 -1
  21. package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/components/DiagnosticSnapshotModal.js +217 -0
  22. package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/components/DiagnosticSnapshotModal.js.map +1 -0
  23. package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/components/DiagnosticSnapshotModal.mjs +195 -0
  24. package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/components/DiagnosticSnapshotModal.mjs.map +1 -0
  25. package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/components/PlanCard.js +185 -0
  26. package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/components/PlanCard.js.map +1 -0
  27. package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/components/PlanCard.mjs +162 -0
  28. package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/components/PlanCard.mjs.map +1 -0
  29. package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/components/SupportCard.js +342 -0
  30. package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/components/SupportCard.js.map +1 -0
  31. package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/components/SupportCard.mjs +320 -0
  32. package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/components/SupportCard.mjs.map +1 -0
  33. package/dist/admin/admin/src/services/admin.js +11 -1
  34. package/dist/admin/admin/src/services/admin.js.map +1 -1
  35. package/dist/admin/admin/src/services/admin.mjs +11 -2
  36. package/dist/admin/admin/src/services/admin.mjs.map +1 -1
  37. package/dist/admin/admin/src/translations/en.json.js +71 -4
  38. package/dist/admin/admin/src/translations/en.json.js.map +1 -1
  39. package/dist/admin/admin/src/translations/en.json.mjs +71 -4
  40. package/dist/admin/admin/src/translations/en.json.mjs.map +1 -1
  41. package/dist/admin/admin/src/utils/browserStrapi.js +1 -1
  42. package/dist/admin/admin/src/utils/browserStrapi.js.map +1 -1
  43. package/dist/admin/admin/src/utils/browserStrapi.mjs +1 -1
  44. package/dist/admin/admin/src/utils/browserStrapi.mjs.map +1 -1
  45. package/dist/admin/admin/src/utils/getFetchClient.js +24 -0
  46. package/dist/admin/admin/src/utils/getFetchClient.js.map +1 -1
  47. package/dist/admin/admin/src/utils/getFetchClient.mjs +24 -1
  48. package/dist/admin/admin/src/utils/getFetchClient.mjs.map +1 -1
  49. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/ApplicationInfoPage/components/AIUsage.js +52 -22
  50. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/ApplicationInfoPage/components/AIUsage.js.map +1 -1
  51. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/ApplicationInfoPage/components/AIUsage.mjs +53 -23
  52. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/ApplicationInfoPage/components/AIUsage.mjs.map +1 -1
  53. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/ApplicationInfoPage/components/AdminSeatInfo.js +16 -29
  54. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/ApplicationInfoPage/components/AdminSeatInfo.js.map +1 -1
  55. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/ApplicationInfoPage/components/AdminSeatInfo.mjs +18 -31
  56. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/ApplicationInfoPage/components/AdminSeatInfo.mjs.map +1 -1
  57. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/ApplicationInfoPage/components/LicenseInfo.js +473 -0
  58. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/ApplicationInfoPage/components/LicenseInfo.js.map +1 -0
  59. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/ApplicationInfoPage/components/LicenseInfo.mjs +471 -0
  60. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/ApplicationInfoPage/components/LicenseInfo.mjs.map +1 -0
  61. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/utils/getActionTypesDefaultMessages.js +2 -0
  62. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/utils/getActionTypesDefaultMessages.js.map +1 -1
  63. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/utils/getActionTypesDefaultMessages.mjs +2 -0
  64. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/utils/getActionTypesDefaultMessages.mjs.map +1 -1
  65. package/dist/admin/index.js +1 -0
  66. package/dist/admin/index.js.map +1 -1
  67. package/dist/admin/index.mjs +1 -1
  68. package/dist/admin/shared/utils/get-project-type.js +49 -0
  69. package/dist/admin/shared/utils/get-project-type.js.map +1 -0
  70. package/dist/admin/shared/utils/get-project-type.mjs +46 -0
  71. package/dist/admin/shared/utils/get-project-type.mjs.map +1 -0
  72. package/dist/admin/src/constants.d.ts +10 -0
  73. package/dist/admin/src/pages/Settings/pages/ApplicationInfo/ApplicationInfoPage.d.ts +1 -1
  74. package/dist/admin/src/pages/Settings/pages/ApplicationInfo/components/DiagnosticSnapshotModal.d.ts +12 -0
  75. package/dist/admin/src/pages/Settings/pages/ApplicationInfo/components/PlanCard.d.ts +14 -0
  76. package/dist/admin/src/pages/Settings/pages/ApplicationInfo/components/SupportCard.d.ts +2 -0
  77. package/dist/admin/src/services/admin.d.ts +2 -2
  78. package/dist/admin/src/types/permissions.d.ts +1 -0
  79. package/dist/admin/src/utils/getFetchClient.d.ts +25 -0
  80. package/dist/ee/admin/src/hooks/useLicenseLimits.d.ts +29 -0
  81. package/dist/ee/admin/src/pages/SettingsPage/pages/ApplicationInfoPage/components/AIUsage.d.ts +6 -1
  82. package/dist/ee/admin/src/pages/SettingsPage/pages/ApplicationInfoPage/components/LicenseInfo.d.ts +2 -0
  83. package/dist/ee/admin/src/pages/SettingsPage/pages/AuditLogs/utils/getActionTypesDefaultMessages.d.ts +2 -0
  84. package/dist/ee/server/src/audit-logs/entitlements.d.ts +8 -0
  85. package/dist/ee/server/src/audit-logs/entitlements.d.ts.map +1 -0
  86. package/dist/ee/server/src/audit-logs/services/lifecycles.d.ts +16 -0
  87. package/dist/ee/server/src/audit-logs/services/lifecycles.d.ts.map +1 -1
  88. package/dist/ee/server/src/controllers/admin.d.ts +36 -10
  89. package/dist/ee/server/src/controllers/admin.d.ts.map +1 -1
  90. package/dist/ee/server/src/controllers/authentication-utils/middlewares.d.ts.map +1 -1
  91. package/dist/ee/server/src/controllers/index.d.ts +36 -10
  92. package/dist/ee/server/src/controllers/index.d.ts.map +1 -1
  93. package/dist/ee/server/src/index.d.ts +36 -10
  94. package/dist/ee/server/src/index.d.ts.map +1 -1
  95. package/dist/server/ee/server/src/audit-logs/entitlements.js +25 -0
  96. package/dist/server/ee/server/src/audit-logs/entitlements.js.map +1 -0
  97. package/dist/server/ee/server/src/audit-logs/entitlements.mjs +23 -0
  98. package/dist/server/ee/server/src/audit-logs/entitlements.mjs.map +1 -0
  99. package/dist/server/ee/server/src/audit-logs/services/lifecycles.js +20 -8
  100. package/dist/server/ee/server/src/audit-logs/services/lifecycles.js.map +1 -1
  101. package/dist/server/ee/server/src/audit-logs/services/lifecycles.mjs +19 -9
  102. package/dist/server/ee/server/src/audit-logs/services/lifecycles.mjs.map +1 -1
  103. package/dist/server/ee/server/src/controllers/admin.js +76 -3
  104. package/dist/server/ee/server/src/controllers/admin.js.map +1 -1
  105. package/dist/server/ee/server/src/controllers/admin.mjs +76 -3
  106. package/dist/server/ee/server/src/controllers/admin.mjs.map +1 -1
  107. package/dist/server/ee/server/src/controllers/authentication-utils/middlewares.js +28 -10
  108. package/dist/server/ee/server/src/controllers/authentication-utils/middlewares.js.map +1 -1
  109. package/dist/server/ee/server/src/controllers/authentication-utils/middlewares.mjs +28 -10
  110. package/dist/server/ee/server/src/controllers/authentication-utils/middlewares.mjs.map +1 -1
  111. package/dist/server/ee/server/src/index.js +2 -0
  112. package/dist/server/ee/server/src/index.js.map +1 -1
  113. package/dist/server/ee/server/src/index.mjs +2 -0
  114. package/dist/server/ee/server/src/index.mjs.map +1 -1
  115. package/dist/server/server/src/audit-logs/auth.js +72 -0
  116. package/dist/server/server/src/audit-logs/auth.js.map +1 -0
  117. package/dist/server/server/src/audit-logs/auth.mjs +67 -0
  118. package/dist/server/server/src/audit-logs/auth.mjs.map +1 -0
  119. package/dist/server/server/src/config/admin-actions.js +7 -0
  120. package/dist/server/server/src/config/admin-actions.js.map +1 -1
  121. package/dist/server/server/src/config/admin-actions.mjs +7 -0
  122. package/dist/server/server/src/config/admin-actions.mjs.map +1 -1
  123. package/dist/server/server/src/controllers/admin.js +6 -0
  124. package/dist/server/server/src/controllers/admin.js.map +1 -1
  125. package/dist/server/server/src/controllers/admin.mjs +6 -0
  126. package/dist/server/server/src/controllers/admin.mjs.map +1 -1
  127. package/dist/server/server/src/controllers/authentication.js +34 -8
  128. package/dist/server/server/src/controllers/authentication.js.map +1 -1
  129. package/dist/server/server/src/controllers/authentication.mjs +34 -8
  130. package/dist/server/server/src/controllers/authentication.mjs.map +1 -1
  131. package/dist/server/server/src/register.js +4 -0
  132. package/dist/server/server/src/register.js.map +1 -1
  133. package/dist/server/server/src/register.mjs +4 -0
  134. package/dist/server/server/src/register.mjs.map +1 -1
  135. package/dist/server/server/src/routes/admin.js +18 -0
  136. package/dist/server/server/src/routes/admin.js.map +1 -1
  137. package/dist/server/server/src/routes/admin.mjs +18 -0
  138. package/dist/server/server/src/routes/admin.mjs.map +1 -1
  139. package/dist/server/server/src/services/auth.js +4 -2
  140. package/dist/server/server/src/services/auth.js.map +1 -1
  141. package/dist/server/server/src/services/auth.mjs +4 -3
  142. package/dist/server/server/src/services/auth.mjs.map +1 -1
  143. package/dist/server/server/src/services/debug-dump.js +173 -0
  144. package/dist/server/server/src/services/debug-dump.js.map +1 -0
  145. package/dist/server/server/src/services/debug-dump.mjs +166 -0
  146. package/dist/server/server/src/services/debug-dump.mjs.map +1 -0
  147. package/dist/server/server/src/services/index.js +3 -1
  148. package/dist/server/server/src/services/index.js.map +1 -1
  149. package/dist/server/server/src/services/index.mjs +3 -1
  150. package/dist/server/server/src/services/index.mjs.map +1 -1
  151. package/dist/server/server/src/utils/debug-dump/redact.js +197 -0
  152. package/dist/server/server/src/utils/debug-dump/redact.js.map +1 -0
  153. package/dist/server/server/src/utils/debug-dump/redact.mjs +194 -0
  154. package/dist/server/server/src/utils/debug-dump/redact.mjs.map +1 -0
  155. package/dist/server/shared/utils/get-project-type.js +49 -0
  156. package/dist/server/shared/utils/get-project-type.js.map +1 -0
  157. package/dist/server/shared/utils/get-project-type.mjs +46 -0
  158. package/dist/server/shared/utils/get-project-type.mjs.map +1 -0
  159. package/dist/server/src/audit-logs/auth.d.ts +72 -0
  160. package/dist/server/src/audit-logs/auth.d.ts.map +1 -0
  161. package/dist/server/src/config/admin-actions.d.ts.map +1 -1
  162. package/dist/server/src/controllers/admin.d.ts +3 -0
  163. package/dist/server/src/controllers/admin.d.ts.map +1 -1
  164. package/dist/server/src/controllers/authentication.d.ts.map +1 -1
  165. package/dist/server/src/controllers/index.d.ts +3 -0
  166. package/dist/server/src/controllers/index.d.ts.map +1 -1
  167. package/dist/server/src/index.d.ts +8 -0
  168. package/dist/server/src/index.d.ts.map +1 -1
  169. package/dist/server/src/register.d.ts.map +1 -1
  170. package/dist/server/src/routes/admin.d.ts.map +1 -1
  171. package/dist/server/src/services/auth.d.ts +6 -0
  172. package/dist/server/src/services/auth.d.ts.map +1 -1
  173. package/dist/server/src/services/debug-dump.d.ts +9 -0
  174. package/dist/server/src/services/debug-dump.d.ts.map +1 -0
  175. package/dist/server/src/services/index.d.ts +5 -0
  176. package/dist/server/src/services/index.d.ts.map +1 -1
  177. package/dist/server/src/utils/debug-dump/redact.d.ts +8 -0
  178. package/dist/server/src/utils/debug-dump/redact.d.ts.map +1 -0
  179. package/dist/shared/contracts/admin.d.ts +106 -0
  180. package/dist/shared/contracts/admin.d.ts.map +1 -1
  181. package/dist/shared/utils/__tests__/get-project-type.test.d.ts +1 -0
  182. package/dist/shared/utils/__tests__/get-project-type.test.d.ts.map +1 -0
  183. package/dist/shared/utils/get-project-type.d.ts +37 -0
  184. package/dist/shared/utils/get-project-type.d.ts.map +1 -0
  185. package/package.json +8 -8
  186. package/dist/admin/admin/src/utils/getProjectType.js +0 -22
  187. package/dist/admin/admin/src/utils/getProjectType.js.map +0 -1
  188. package/dist/admin/admin/src/utils/getProjectType.mjs +0 -20
  189. package/dist/admin/admin/src/utils/getProjectType.mjs.map +0 -1
  190. package/dist/admin/src/utils/getProjectType.d.ts +0 -16
@@ -27,19 +27,45 @@ declare const getAdminEE: () => {
27
27
  getProjectType(): Promise<import("../../../shared/contracts/admin").GetProjectType.Response>;
28
28
  licenseLimitInformation(): Promise<{
29
29
  data: {
30
- enforcementUserCount: any;
31
- currentActiveUserCount: any;
32
- permittedSeats: number | null | undefined;
30
+ currentActiveUserCount: number;
31
+ enforcementUserCount: number;
32
+ features: (import("../../../shared/contracts/admin").SSOFeature | import("../../../shared/contracts/admin").AuditLogsFeature | import("../../../shared/contracts/admin").ReviewWorkflowsFeature | import("../../../shared/contracts/admin").ContentReleasesFeature | import("../../../shared/contracts/admin").ContentHistoryFeature)[];
33
+ isHostedOnStrapiCloud: boolean;
34
+ licenseLimitStatus: unknown;
35
+ permittedSeats: number;
33
36
  shouldNotify: boolean;
34
37
  shouldStopCreate: boolean;
35
- licenseLimitStatus: string | null;
36
- isHostedOnStrapiCloud: boolean;
37
- type: string | null | undefined;
38
+ type: string;
38
39
  isTrial: boolean;
39
- features: {
40
- [key: string]: any;
41
- name: string;
42
- }[];
40
+ seats: number | null;
41
+ subscriptionId: string | null;
42
+ expireAt: string | null;
43
+ licenseStatus: "none" | "active" | "expired" | "unknown";
44
+ planPriceId: string | null;
45
+ renewalDate: string | number | null;
46
+ planEntitlements: Array<{
47
+ feature: string;
48
+ available: boolean;
49
+ limits: Array<{
50
+ key: string;
51
+ unit?: "days" | "count";
52
+ value: number | null;
53
+ }>;
54
+ }>;
55
+ licenseMode: "online" | "offline";
56
+ lastRegistrySyncAt: number | null;
57
+ nextRegistrySyncAt: number | null;
58
+ usingCachedLicense: boolean;
59
+ registrySyncError: string | null;
60
+ registrySyncErrorKind: "unreachable" | "rejected" | null;
61
+ entitlements: Array<{
62
+ feature: string;
63
+ limits: Array<{
64
+ key: string;
65
+ unit?: "days" | "count";
66
+ value: number | null;
67
+ }>;
68
+ }>;
43
69
  };
44
70
  }>;
45
71
  };
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../ee/server/src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAkB1C,QAAA,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBA4Be;QAAE,MAAM,EAAE,IAAI,CAAC,MAAM,CAAA;KAAE;wBA0BxB;QAAE,MAAM,EAAE,IAAI,CAAC,MAAM,CAAA;KAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAOpD,CAAC;AAEF,eAAe,UAAU,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../ee/server/src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAmB1C,QAAA,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gCAiE2/F,CAAC;;;;;;;;;;;;;;gCAA4wB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBArC1vH;QAAE,MAAM,EAAE,IAAI,CAAC,MAAM,CAAA;KAAE;wBA2BxB;QAAE,MAAM,EAAE,IAAI,CAAC,MAAM,CAAA;KAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAOpD,CAAC;AAEF,eAAe,UAAU,CAAC"}
@@ -0,0 +1,25 @@
1
+ 'use strict';
2
+
3
+ var lifecycles = require('./services/lifecycles.js');
4
+
5
+ /**
6
+ * Reports the audit-log retention the daily delete job uses, admin override included, for the
7
+ * Plan card and the debug dump. Registered whatever the boot-time license says, so a license
8
+ * that lapsed before boot still resolves its retained limits, and a later renewal needs no restart.
9
+ */ const registerAuditLogsEntitlements = (strapi)=>{
10
+ strapi.ee.entitlements.register({
11
+ feature: 'audit-logs',
12
+ limits: [
13
+ {
14
+ key: 'retentionDays',
15
+ unit: 'days',
16
+ get (feature) {
17
+ return lifecycles.computeRetentionDays(typeof feature === 'object' ? feature.options?.retentionDays : undefined, strapi.config.get('admin.auditLogs.retentionDays'));
18
+ }
19
+ }
20
+ ]
21
+ });
22
+ };
23
+
24
+ exports.registerAuditLogsEntitlements = registerAuditLogsEntitlements;
25
+ //# sourceMappingURL=entitlements.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entitlements.js","sources":["../../../../../../ee/server/src/audit-logs/entitlements.ts"],"sourcesContent":["import type { Core } from '@strapi/types';\n\nimport { computeRetentionDays } from './services/lifecycles';\n\n/**\n * Reports the audit-log retention the daily delete job uses, admin override included, for the\n * Plan card and the debug dump. Registered whatever the boot-time license says, so a license\n * that lapsed before boot still resolves its retained limits, and a later renewal needs no restart.\n */\nexport const registerAuditLogsEntitlements = (strapi: Core.Strapi) => {\n strapi.ee.entitlements.register({\n feature: 'audit-logs',\n limits: [\n {\n key: 'retentionDays',\n unit: 'days',\n get(feature) {\n return computeRetentionDays(\n typeof feature === 'object' ? feature.options?.retentionDays : undefined,\n strapi.config.get('admin.auditLogs.retentionDays')\n );\n },\n },\n ],\n });\n};\n"],"names":["registerAuditLogsEntitlements","strapi","ee","entitlements","register","feature","limits","key","unit","get","computeRetentionDays","options","retentionDays","undefined","config"],"mappings":";;;;AAIA;;;;IAKO,MAAMA,6BAAAA,GAAgC,CAACC,MAAAA,GAAAA;AAC5CA,IAAAA,MAAAA,CAAOC,EAAE,CAACC,YAAY,CAACC,QAAQ,CAAC;QAC9BC,OAAAA,EAAS,YAAA;QACTC,MAAAA,EAAQ;AACN,YAAA;gBACEC,GAAAA,EAAK,eAAA;gBACLC,IAAAA,EAAM,MAAA;AACNC,gBAAAA,GAAAA,CAAAA,CAAIJ,OAAO,EAAA;AACT,oBAAA,OAAOK,+BAAAA,CACL,OAAOL,OAAAA,KAAY,QAAA,GAAWA,OAAAA,CAAQM,OAAO,EAAEC,aAAAA,GAAgBC,SAAAA,EAC/DZ,MAAAA,CAAOa,MAAM,CAACL,GAAG,CAAC,+BAAA,CAAA,CAAA;AAEtB,gBAAA;AACF;AACD;AACH,KAAA,CAAA;AACF;;;;"}
@@ -0,0 +1,23 @@
1
+ import { computeRetentionDays } from './services/lifecycles.mjs';
2
+
3
+ /**
4
+ * Reports the audit-log retention the daily delete job uses, admin override included, for the
5
+ * Plan card and the debug dump. Registered whatever the boot-time license says, so a license
6
+ * that lapsed before boot still resolves its retained limits, and a later renewal needs no restart.
7
+ */ const registerAuditLogsEntitlements = (strapi)=>{
8
+ strapi.ee.entitlements.register({
9
+ feature: 'audit-logs',
10
+ limits: [
11
+ {
12
+ key: 'retentionDays',
13
+ unit: 'days',
14
+ get (feature) {
15
+ return computeRetentionDays(typeof feature === 'object' ? feature.options?.retentionDays : undefined, strapi.config.get('admin.auditLogs.retentionDays'));
16
+ }
17
+ }
18
+ ]
19
+ });
20
+ };
21
+
22
+ export { registerAuditLogsEntitlements };
23
+ //# sourceMappingURL=entitlements.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entitlements.mjs","sources":["../../../../../../ee/server/src/audit-logs/entitlements.ts"],"sourcesContent":["import type { Core } from '@strapi/types';\n\nimport { computeRetentionDays } from './services/lifecycles';\n\n/**\n * Reports the audit-log retention the daily delete job uses, admin override included, for the\n * Plan card and the debug dump. Registered whatever the boot-time license says, so a license\n * that lapsed before boot still resolves its retained limits, and a later renewal needs no restart.\n */\nexport const registerAuditLogsEntitlements = (strapi: Core.Strapi) => {\n strapi.ee.entitlements.register({\n feature: 'audit-logs',\n limits: [\n {\n key: 'retentionDays',\n unit: 'days',\n get(feature) {\n return computeRetentionDays(\n typeof feature === 'object' ? feature.options?.retentionDays : undefined,\n strapi.config.get('admin.auditLogs.retentionDays')\n );\n },\n },\n ],\n });\n};\n"],"names":["registerAuditLogsEntitlements","strapi","ee","entitlements","register","feature","limits","key","unit","get","computeRetentionDays","options","retentionDays","undefined","config"],"mappings":";;AAIA;;;;IAKO,MAAMA,6BAAAA,GAAgC,CAACC,MAAAA,GAAAA;AAC5CA,IAAAA,MAAAA,CAAOC,EAAE,CAACC,YAAY,CAACC,QAAQ,CAAC;QAC9BC,OAAAA,EAAS,YAAA;QACTC,MAAAA,EAAQ;AACN,YAAA;gBACEC,GAAAA,EAAK,eAAA;gBACLC,IAAAA,EAAM,MAAA;AACNC,gBAAAA,GAAAA,CAAAA,CAAIJ,OAAO,EAAA;AACT,oBAAA,OAAOK,oBAAAA,CACL,OAAOL,OAAAA,KAAY,QAAA,GAAWA,OAAAA,CAAQM,OAAO,EAAEC,aAAAA,GAAgBC,SAAAA,EAC/DZ,MAAAA,CAAOa,MAAM,CAACL,GAAG,CAAC,+BAAA,CAAA,CAAA;AAEtB,gBAAA;AACF;AACD;AACH,KAAA,CAAA;AACF;;;;"}
@@ -66,20 +66,26 @@ const getActor = (systemOrigin, user)=>{
66
66
  }
67
67
  };
68
68
  };
69
- const getRetentionDays = (strapi)=>{
70
- const featureConfig = strapi.ee.features.get('audit-logs');
71
- const licenseRetentionDays = typeof featureConfig === 'object' && featureConfig?.options?.retentionDays;
72
- const userRetentionDays = strapi.config.get('admin.auditLogs.retentionDays');
69
+ /**
70
+ * The retention the daily delete job applies, from the license's value and the admin override.
71
+ * Shared with the Plan card's resolver (../entitlements.ts) so the card shows this same figure.
72
+ */ const computeRetentionDays = (licenseRetentionDays, userRetentionDays)=>{
73
73
  // For enterprise plans, use 90 days by default, but allow users to override it
74
74
  if (licenseRetentionDays == null) {
75
75
  return userRetentionDays ?? DEFAULT_RETENTION_DAYS;
76
76
  }
77
+ // The registry can ship the value as a numeric string
78
+ const licenseDays = Number(licenseRetentionDays);
77
79
  // Allow users to override the license retention days, but not to increase it
78
- if (userRetentionDays && userRetentionDays <= licenseRetentionDays) {
80
+ if (userRetentionDays && userRetentionDays <= licenseDays) {
79
81
  return userRetentionDays;
80
82
  }
81
83
  // User didn't provide a retention days value, use the license one
82
- return licenseRetentionDays;
84
+ return licenseDays;
85
+ };
86
+ const getRetentionDays = (strapi)=>{
87
+ const featureConfig = strapi.ee.features.get('audit-logs');
88
+ return computeRetentionDays(typeof featureConfig === 'object' ? featureConfig?.options?.retentionDays : undefined, strapi.config.get('admin.auditLogs.retentionDays'));
83
89
  };
84
90
  /**
85
91
  * @description
@@ -107,15 +113,19 @@ const getRetentionDays = (strapi)=>{
107
113
  const isUsingAdminAuth = requestState?.route?.info?.type === 'admin';
108
114
  const auditSource = requestState?.auditSource;
109
115
  const isMcpAdminAction = auditSource === 'mcp';
110
- const user = requestState?.user;
116
+ const options = registration.kind === 'standard' ? registration.options : {};
117
+ const user = options.alwaysUnknownActor ? undefined : requestState?.user;
111
118
  const systemOrigin = auditSource && SYSTEM_ORIGINS.includes(auditSource) ? auditSource : undefined;
112
119
  if (!systemOrigin && !isUsingAdminAuth && !isMcpAdminAction) {
113
120
  return null;
114
121
  }
115
- const allowsUnknownActor = registration.kind === 'standard' && registration.options.allowUnknownActor === true;
122
+ const allowsUnknownActor = options.allowUnknownActor === true || options.alwaysUnknownActor === true;
116
123
  if (!systemOrigin && !user && !allowsUnknownActor) {
117
124
  return null;
118
125
  }
126
+ if (options.shouldRecord?.(...args) === false) {
127
+ return null;
128
+ }
119
129
  const origin = systemOrigin ?? auditSource ?? 'admin-panel';
120
130
  const date = new Date().toISOString();
121
131
  // Scheduled actions have no user, so a null user is expected. The earlier audit
@@ -267,5 +277,7 @@ const getRetentionDays = (strapi)=>{
267
277
  };
268
278
  };
269
279
 
280
+ exports.DEFAULT_RETENTION_DAYS = DEFAULT_RETENTION_DAYS;
281
+ exports.computeRetentionDays = computeRetentionDays;
270
282
  exports.createAuditLogsLifecycleService = createAuditLogsLifecycleService;
271
283
  //# sourceMappingURL=lifecycles.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"lifecycles.js","sources":["../../../../../../../ee/server/src/audit-logs/services/lifecycles.ts"],"sourcesContent":["import type { Core, Modules } from '@strapi/types';\n\nimport { getDisplayName } from '../utils';\n\nconst DEFAULT_RETENTION_DAYS = 90;\n\n/**\n * Events audited before the payload standard; their stored shape is frozen for\n * compatibility. Do not add events here: new events come through registerEvent().\n * The event hub still emits user.create, user.update and user.delete; the audit log\n * records them as admin-user.* (server/src/audit-logs/admin-users.ts).\n * TODO: migrate the rest to the standard.\n */\nconst defaultEvents = [\n 'entry.create',\n 'entry.update',\n 'entry.delete',\n 'entry.publish',\n 'entry.unpublish',\n 'media.create',\n 'media.update',\n 'media.delete',\n 'media-folder.create',\n 'media-folder.update',\n 'media-folder.delete',\n 'admin.auth.success',\n 'admin.logout',\n 'content-type.create',\n 'content-type.update',\n 'content-type.delete',\n 'component.create',\n 'component.update',\n 'component.delete',\n 'role.create',\n 'role.update',\n 'role.delete',\n 'permission.create',\n 'permission.update',\n 'permission.delete',\n];\n\n/**\n * Legacy events store the first emitted argument as-is; registered events store the\n * standard shape built by their transformer.\n */\ntype EventRegistration =\n | { kind: 'legacy' }\n | {\n kind: 'standard';\n transform: Modules.AuditLogs.EventTransformer;\n options: RegisterEventOptions;\n };\n\nexport interface RegisterEventOptions {\n /**\n * Records the event when the request has no authenticated user, with an\n * `unknown` actor and no user column. For actions taken from public admin\n * forms (password reset, invitation). Off by default: an event with no user\n * is dropped.\n */\n allowUnknownActor?: boolean;\n}\n\nconst getEventMap = (events: string[]) => {\n return events.reduce(\n (acc, event) => {\n acc[event] = { kind: 'legacy' };\n return acc;\n },\n {} as Record<string, EventRegistration>\n );\n};\n\nconst getActor = (\n systemOrigin: Modules.AuditLogs.SystemOrigin | undefined,\n user: { id: string | number; email: string; firstname?: string; lastname?: string } | undefined\n): Modules.AuditLogs.Actor => {\n if (systemOrigin) {\n return { type: 'system' };\n }\n\n if (!user) {\n return { type: 'unknown' };\n }\n\n // We copy the user data into the row so the history stays unchanged if the user\n // changes later\n return {\n type: 'admin-user',\n user: { id: user.id, email: user.email, name: getDisplayName(user) },\n };\n};\n\nconst getRetentionDays = (strapi: Core.Strapi) => {\n const featureConfig = strapi.ee.features.get('audit-logs');\n const licenseRetentionDays =\n typeof featureConfig === 'object' && featureConfig?.options?.retentionDays;\n const userRetentionDays = strapi.config.get('admin.auditLogs.retentionDays');\n\n // For enterprise plans, use 90 days by default, but allow users to override it\n if (licenseRetentionDays == null) {\n return userRetentionDays ?? DEFAULT_RETENTION_DAYS;\n }\n\n // Allow users to override the license retention days, but not to increase it\n if (userRetentionDays && userRetentionDays <= licenseRetentionDays) {\n return userRetentionDays;\n }\n\n // User didn't provide a retention days value, use the license one\n return licenseRetentionDays;\n};\n\n/**\n * @description\n * Manages the lifecycle of audit logs. Accessible via strapi.get('audit-logs-lifecycle')\n */\nconst createAuditLogsLifecycleService = (strapi: Core.Strapi) => {\n // Manage internal service state privately\n const state = {} as any;\n const auditLogsService = strapi.get('audit-logs');\n\n const eventMap = getEventMap(defaultEvents);\n\n /**\n * The system origins accepted from the execution context; anything else needs a\n * user. Keyed on the type, so extending SystemOrigin without gating it here fails\n * to compile.\n */\n const SYSTEM_ORIGIN_FLAGS: Record<Modules.AuditLogs.SystemOrigin, true> = {\n scheduler: true,\n };\n const SYSTEM_ORIGINS = Object.keys(SYSTEM_ORIGIN_FLAGS);\n\n const processEvent = async (name: string, ...args: any) => {\n const registration = eventMap[name];\n\n if (!registration) {\n return null;\n }\n\n const rawEvent = args[0];\n\n const requestState = strapi.requestContext.get()?.state;\n\n const isUsingAdminAuth = requestState?.route?.info?.type === 'admin';\n const auditSource = requestState?.auditSource;\n const isMcpAdminAction = auditSource === 'mcp';\n const user = requestState?.user;\n\n const systemOrigin =\n auditSource && SYSTEM_ORIGINS.includes(auditSource)\n ? (auditSource as Modules.AuditLogs.SystemOrigin)\n : undefined;\n\n if (!systemOrigin && !isUsingAdminAuth && !isMcpAdminAction) {\n return null;\n }\n\n const allowsUnknownActor =\n registration.kind === 'standard' && registration.options.allowUnknownActor === true;\n\n if (!systemOrigin && !user && !allowsUnknownActor) {\n return null;\n }\n\n const origin: Modules.AuditLogs.AuditSource = systemOrigin ?? auditSource ?? 'admin-panel';\n const date = new Date().toISOString();\n // Scheduled actions have no user, so a null user is expected. The earlier audit\n // entry that set the schedule records who did it. Events allowing an unknown actor\n // have no user either.\n const userId = user ? user.id : null;\n\n if (registration.kind === 'legacy') {\n // TODO: What does this ignore in upload? Why would we want to ignore anything?\n const ignoredUids = ['plugin::upload.file', 'plugin::upload.folder'];\n if (ignoredUids.includes(rawEvent?.uid)) {\n return null;\n }\n\n return {\n action: name,\n date,\n payload: { ...rawEvent, origin },\n userId,\n };\n }\n\n const actor = getActor(systemOrigin, user);\n\n let shape: Modules.AuditLogs.EventShape | null = null;\n\n try {\n shape = await registration.transform(...args);\n } catch (error) {\n // If the transformer fails, we still keep the audit event: the row is saved\n // with the subscriber's fields only.\n strapi.log.error(`Failed to build the audit log payload for ${name}`, { error });\n }\n\n const {\n action: _action,\n date: _date,\n actor: _actor,\n origin: _origin,\n ...rest\n } = (shape ?? {}) as Record<string, unknown>;\n const payload = shape\n ? ({ action: name, date, actor, origin, ...rest } as Modules.AuditLogs.StoredPayload)\n : { action: name, date, actor, origin };\n\n return { action: name, date, payload, userId };\n };\n\n const handleEvent = async (name: string, ...args: any) => {\n try {\n const processedEvent = await processEvent(name, ...args);\n\n if (processedEvent) {\n await auditLogsService.saveEvent(processedEvent);\n }\n } catch (error) {\n // Logged, not propagated: most emitters fire and forget (the document service\n // emits entry.* from an unawaited onCommit callback), and a rejection with no\n // one awaiting it takes the process down. Audit logging is therefore fail-open:\n // the entry is lost and only this line records it.\n strapi.log.error(`Failed to save the audit log entry for ${name}`, { error });\n }\n };\n\n return {\n /**\n * Adds an event to the list of audited events. Plugins register their own from\n * their bootstrap; the transformer builds the audited shape\n * ({resource, details, outcome}) from the arguments passed to eventHub.emit().\n */\n registerEvent<TDetails = unknown>(\n name: string,\n transform: Modules.AuditLogs.EventTransformer<TDetails>,\n options: RegisterEventOptions = {}\n ) {\n if (eventMap[name]?.kind === 'legacy') {\n throw new Error(\n `Cannot register the audit log event \"${name}\": it is one of the built-in events, whose stored shape is frozen.`\n );\n }\n\n if (eventMap[name]) {\n strapi.log.warn(`The audit log event \"${name}\" was already registered and is replaced.`);\n }\n\n eventMap[name] = {\n kind: 'standard',\n transform: transform as Modules.AuditLogs.EventTransformer,\n options,\n };\n },\n\n async register() {\n // Handle license being enabled\n if (!state.eeEnableUnsubscribe) {\n // @ts-expect-error- update event hub to receive callback argument\n state.eeEnableUnsubscribe = strapi.eventHub.on('ee.enable', () => {\n // Recreate the service to use the new license info\n this.destroy();\n this.register();\n });\n }\n\n // Handle license being updated\n if (!state.eeUpdateUnsubscribe) {\n // @ts-expect-error- update event hub to receive callback argument\n state.eeUpdateUnsubscribe = strapi.eventHub.on('ee.update', () => {\n // Recreate the service to use the new license info\n this.destroy();\n this.register();\n });\n }\n\n // Handle license being disabled\n // @ts-expect-error- update event hub to receive callback argument\n state.eeDisableUnsubscribe = strapi.eventHub.on('ee.disable', () => {\n // Turn off service when the license gets disabled\n // Only ee.enable and ee.update listeners remain active to recreate the service\n this.destroy();\n });\n\n // Check current state of license\n if (!strapi.ee.features.isEnabled('audit-logs')) {\n return this;\n }\n\n // Start saving events\n state.eventHubUnsubscribe = strapi.eventHub.subscribe(handleEvent);\n\n // Manage audit logs auto deletion\n const retentionDays = getRetentionDays(strapi);\n\n strapi.cron.add({\n deleteExpiredAuditLogs: {\n async task() {\n const expirationDate = new Date(Date.now() - retentionDays * 24 * 60 * 60 * 1000);\n await auditLogsService.deleteExpiredEvents(expirationDate);\n },\n options: '0 0 * * *',\n },\n });\n\n return this;\n },\n\n unsubscribe() {\n if (state.eeDisableUnsubscribe) {\n state.eeDisableUnsubscribe();\n }\n\n if (state.eventHubUnsubscribe) {\n state.eventHubUnsubscribe();\n }\n\n strapi.cron.remove('deleteExpiredAuditLogs');\n\n return this;\n },\n\n destroy() {\n return this.unsubscribe();\n },\n };\n};\n\nexport { createAuditLogsLifecycleService };\n"],"names":["DEFAULT_RETENTION_DAYS","defaultEvents","getEventMap","events","reduce","acc","event","kind","getActor","systemOrigin","user","type","id","email","name","getDisplayName","getRetentionDays","strapi","featureConfig","ee","features","get","licenseRetentionDays","options","retentionDays","userRetentionDays","config","createAuditLogsLifecycleService","state","auditLogsService","eventMap","SYSTEM_ORIGIN_FLAGS","scheduler","SYSTEM_ORIGINS","Object","keys","processEvent","args","registration","rawEvent","requestState","requestContext","isUsingAdminAuth","route","info","auditSource","isMcpAdminAction","includes","undefined","allowsUnknownActor","allowUnknownActor","origin","date","Date","toISOString","userId","ignoredUids","uid","action","payload","actor","shape","transform","error","log","_action","_date","_actor","_origin","rest","handleEvent","processedEvent","saveEvent","registerEvent","Error","warn","register","eeEnableUnsubscribe","eventHub","on","destroy","eeUpdateUnsubscribe","eeDisableUnsubscribe","isEnabled","eventHubUnsubscribe","subscribe","cron","add","deleteExpiredAuditLogs","task","expirationDate","now","deleteExpiredEvents","unsubscribe","remove"],"mappings":"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"}
1
+ {"version":3,"file":"lifecycles.js","sources":["../../../../../../../ee/server/src/audit-logs/services/lifecycles.ts"],"sourcesContent":["import type { Core, Modules } from '@strapi/types';\n\nimport { getDisplayName } from '../utils';\n\nexport const DEFAULT_RETENTION_DAYS = 90;\n\n/**\n * Events audited before the payload standard; their stored shape is frozen for\n * compatibility. Do not add events here: new events come through registerEvent().\n * The event hub still emits user.create, user.update and user.delete; the audit log\n * records them as admin-user.* (server/src/audit-logs/admin-users.ts).\n * TODO: migrate the rest to the standard.\n */\nconst defaultEvents = [\n 'entry.create',\n 'entry.update',\n 'entry.delete',\n 'entry.publish',\n 'entry.unpublish',\n 'media.create',\n 'media.update',\n 'media.delete',\n 'media-folder.create',\n 'media-folder.update',\n 'media-folder.delete',\n 'admin.auth.success',\n 'admin.logout',\n 'content-type.create',\n 'content-type.update',\n 'content-type.delete',\n 'component.create',\n 'component.update',\n 'component.delete',\n 'role.create',\n 'role.update',\n 'role.delete',\n 'permission.create',\n 'permission.update',\n 'permission.delete',\n];\n\n/**\n * Legacy events store the first emitted argument as-is; registered events store the\n * standard shape built by their transformer.\n */\ntype EventRegistration =\n | { kind: 'legacy' }\n | {\n kind: 'standard';\n transform: Modules.AuditLogs.EventTransformer;\n options: RegisterEventOptions;\n };\n\nexport interface RegisterEventOptions {\n /**\n * Records the event when the request has no authenticated user, with an\n * `unknown` actor and no user column. For actions taken from public admin\n * forms (password reset, invitation). Off by default: an event with no user\n * is dropped.\n */\n allowUnknownActor?: boolean;\n /**\n * Records the event with an `unknown` actor and no user column even when the request\n * has an authenticated user. For events about a login that did not complete.\n */\n alwaysUnknownActor?: boolean;\n /**\n * Receives the arguments passed to eventHub.emit(); returning false keeps the\n * event out of the audit log. Listeners on the event hub still receive it.\n */\n shouldRecord?: (...args: any[]) => boolean;\n}\n\nconst getEventMap = (events: string[]) => {\n return events.reduce(\n (acc, event) => {\n acc[event] = { kind: 'legacy' };\n return acc;\n },\n {} as Record<string, EventRegistration>\n );\n};\n\nconst getActor = (\n systemOrigin: Modules.AuditLogs.SystemOrigin | undefined,\n user: { id: string | number; email: string; firstname?: string; lastname?: string } | undefined\n): Modules.AuditLogs.Actor => {\n if (systemOrigin) {\n return { type: 'system' };\n }\n\n if (!user) {\n return { type: 'unknown' };\n }\n\n // We copy the user data into the row so the history stays unchanged if the user\n // changes later\n return {\n type: 'admin-user',\n user: { id: user.id, email: user.email, name: getDisplayName(user) },\n };\n};\n\n/**\n * The retention the daily delete job applies, from the license's value and the admin override.\n * Shared with the Plan card's resolver (../entitlements.ts) so the card shows this same figure.\n */\nexport const computeRetentionDays = (\n licenseRetentionDays: unknown,\n userRetentionDays: number | null | undefined\n): number => {\n // For enterprise plans, use 90 days by default, but allow users to override it\n if (licenseRetentionDays == null) {\n return userRetentionDays ?? DEFAULT_RETENTION_DAYS;\n }\n\n // The registry can ship the value as a numeric string\n const licenseDays = Number(licenseRetentionDays);\n\n // Allow users to override the license retention days, but not to increase it\n if (userRetentionDays && userRetentionDays <= licenseDays) {\n return userRetentionDays;\n }\n\n // User didn't provide a retention days value, use the license one\n return licenseDays;\n};\n\nconst getRetentionDays = (strapi: Core.Strapi) => {\n const featureConfig = strapi.ee.features.get('audit-logs');\n\n return computeRetentionDays(\n typeof featureConfig === 'object' ? featureConfig?.options?.retentionDays : undefined,\n strapi.config.get('admin.auditLogs.retentionDays')\n );\n};\n\n/**\n * @description\n * Manages the lifecycle of audit logs. Accessible via strapi.get('audit-logs-lifecycle')\n */\nconst createAuditLogsLifecycleService = (strapi: Core.Strapi) => {\n // Manage internal service state privately\n const state = {} as any;\n const auditLogsService = strapi.get('audit-logs');\n\n const eventMap = getEventMap(defaultEvents);\n\n /**\n * The system origins accepted from the execution context; anything else needs a\n * user. Keyed on the type, so extending SystemOrigin without gating it here fails\n * to compile.\n */\n const SYSTEM_ORIGIN_FLAGS: Record<Modules.AuditLogs.SystemOrigin, true> = {\n scheduler: true,\n };\n const SYSTEM_ORIGINS = Object.keys(SYSTEM_ORIGIN_FLAGS);\n\n const processEvent = async (name: string, ...args: any) => {\n const registration = eventMap[name];\n\n if (!registration) {\n return null;\n }\n\n const rawEvent = args[0];\n\n const requestState = strapi.requestContext.get()?.state;\n\n const isUsingAdminAuth = requestState?.route?.info?.type === 'admin';\n const auditSource = requestState?.auditSource;\n const isMcpAdminAction = auditSource === 'mcp';\n const options: RegisterEventOptions =\n registration.kind === 'standard' ? registration.options : {};\n const user = options.alwaysUnknownActor ? undefined : requestState?.user;\n\n const systemOrigin =\n auditSource && SYSTEM_ORIGINS.includes(auditSource)\n ? (auditSource as Modules.AuditLogs.SystemOrigin)\n : undefined;\n\n if (!systemOrigin && !isUsingAdminAuth && !isMcpAdminAction) {\n return null;\n }\n\n const allowsUnknownActor =\n options.allowUnknownActor === true || options.alwaysUnknownActor === true;\n\n if (!systemOrigin && !user && !allowsUnknownActor) {\n return null;\n }\n\n if (options.shouldRecord?.(...args) === false) {\n return null;\n }\n\n const origin: Modules.AuditLogs.AuditSource = systemOrigin ?? auditSource ?? 'admin-panel';\n const date = new Date().toISOString();\n // Scheduled actions have no user, so a null user is expected. The earlier audit\n // entry that set the schedule records who did it. Events allowing an unknown actor\n // have no user either.\n const userId = user ? user.id : null;\n\n if (registration.kind === 'legacy') {\n // TODO: What does this ignore in upload? Why would we want to ignore anything?\n const ignoredUids = ['plugin::upload.file', 'plugin::upload.folder'];\n if (ignoredUids.includes(rawEvent?.uid)) {\n return null;\n }\n\n return {\n action: name,\n date,\n payload: { ...rawEvent, origin },\n userId,\n };\n }\n\n const actor = getActor(systemOrigin, user);\n\n let shape: Modules.AuditLogs.EventShape | null = null;\n\n try {\n shape = await registration.transform(...args);\n } catch (error) {\n // If the transformer fails, we still keep the audit event: the row is saved\n // with the subscriber's fields only.\n strapi.log.error(`Failed to build the audit log payload for ${name}`, { error });\n }\n\n const {\n action: _action,\n date: _date,\n actor: _actor,\n origin: _origin,\n ...rest\n } = (shape ?? {}) as Record<string, unknown>;\n const payload = shape\n ? ({ action: name, date, actor, origin, ...rest } as Modules.AuditLogs.StoredPayload)\n : { action: name, date, actor, origin };\n\n return { action: name, date, payload, userId };\n };\n\n const handleEvent = async (name: string, ...args: any) => {\n try {\n const processedEvent = await processEvent(name, ...args);\n\n if (processedEvent) {\n await auditLogsService.saveEvent(processedEvent);\n }\n } catch (error) {\n // Logged, not propagated: most emitters fire and forget (the document service\n // emits entry.* from an unawaited onCommit callback), and a rejection with no\n // one awaiting it takes the process down. Audit logging is therefore fail-open:\n // the entry is lost and only this line records it.\n strapi.log.error(`Failed to save the audit log entry for ${name}`, { error });\n }\n };\n\n return {\n /**\n * Adds an event to the list of audited events. Plugins register their own from\n * their bootstrap; the transformer builds the audited shape\n * ({resource, details, outcome}) from the arguments passed to eventHub.emit().\n */\n registerEvent<TDetails = unknown>(\n name: string,\n transform: Modules.AuditLogs.EventTransformer<TDetails>,\n options: RegisterEventOptions = {}\n ) {\n if (eventMap[name]?.kind === 'legacy') {\n throw new Error(\n `Cannot register the audit log event \"${name}\": it is one of the built-in events, whose stored shape is frozen.`\n );\n }\n\n if (eventMap[name]) {\n strapi.log.warn(`The audit log event \"${name}\" was already registered and is replaced.`);\n }\n\n eventMap[name] = {\n kind: 'standard',\n transform: transform as Modules.AuditLogs.EventTransformer,\n options,\n };\n },\n\n async register() {\n // Handle license being enabled\n if (!state.eeEnableUnsubscribe) {\n // @ts-expect-error- update event hub to receive callback argument\n state.eeEnableUnsubscribe = strapi.eventHub.on('ee.enable', () => {\n // Recreate the service to use the new license info\n this.destroy();\n this.register();\n });\n }\n\n // Handle license being updated\n if (!state.eeUpdateUnsubscribe) {\n // @ts-expect-error- update event hub to receive callback argument\n state.eeUpdateUnsubscribe = strapi.eventHub.on('ee.update', () => {\n // Recreate the service to use the new license info\n this.destroy();\n this.register();\n });\n }\n\n // Handle license being disabled\n // @ts-expect-error- update event hub to receive callback argument\n state.eeDisableUnsubscribe = strapi.eventHub.on('ee.disable', () => {\n // Turn off service when the license gets disabled\n // Only ee.enable and ee.update listeners remain active to recreate the service\n this.destroy();\n });\n\n // Check current state of license\n if (!strapi.ee.features.isEnabled('audit-logs')) {\n return this;\n }\n\n // Start saving events\n state.eventHubUnsubscribe = strapi.eventHub.subscribe(handleEvent);\n\n // Manage audit logs auto deletion\n const retentionDays = getRetentionDays(strapi);\n\n strapi.cron.add({\n deleteExpiredAuditLogs: {\n async task() {\n const expirationDate = new Date(Date.now() - retentionDays * 24 * 60 * 60 * 1000);\n await auditLogsService.deleteExpiredEvents(expirationDate);\n },\n options: '0 0 * * *',\n },\n });\n\n return this;\n },\n\n unsubscribe() {\n if (state.eeDisableUnsubscribe) {\n state.eeDisableUnsubscribe();\n }\n\n if (state.eventHubUnsubscribe) {\n state.eventHubUnsubscribe();\n }\n\n strapi.cron.remove('deleteExpiredAuditLogs');\n\n return this;\n },\n\n destroy() {\n return this.unsubscribe();\n },\n };\n};\n\nexport { createAuditLogsLifecycleService };\n"],"names":["DEFAULT_RETENTION_DAYS","defaultEvents","getEventMap","events","reduce","acc","event","kind","getActor","systemOrigin","user","type","id","email","name","getDisplayName","computeRetentionDays","licenseRetentionDays","userRetentionDays","licenseDays","Number","getRetentionDays","strapi","featureConfig","ee","features","get","options","retentionDays","undefined","config","createAuditLogsLifecycleService","state","auditLogsService","eventMap","SYSTEM_ORIGIN_FLAGS","scheduler","SYSTEM_ORIGINS","Object","keys","processEvent","args","registration","rawEvent","requestState","requestContext","isUsingAdminAuth","route","info","auditSource","isMcpAdminAction","alwaysUnknownActor","includes","allowsUnknownActor","allowUnknownActor","shouldRecord","origin","date","Date","toISOString","userId","ignoredUids","uid","action","payload","actor","shape","transform","error","log","_action","_date","_actor","_origin","rest","handleEvent","processedEvent","saveEvent","registerEvent","Error","warn","register","eeEnableUnsubscribe","eventHub","on","destroy","eeUpdateUnsubscribe","eeDisableUnsubscribe","isEnabled","eventHubUnsubscribe","subscribe","cron","add","deleteExpiredAuditLogs","task","expirationDate","now","deleteExpiredEvents","unsubscribe","remove"],"mappings":"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"}
@@ -64,20 +64,26 @@ const getActor = (systemOrigin, user)=>{
64
64
  }
65
65
  };
66
66
  };
67
- const getRetentionDays = (strapi)=>{
68
- const featureConfig = strapi.ee.features.get('audit-logs');
69
- const licenseRetentionDays = typeof featureConfig === 'object' && featureConfig?.options?.retentionDays;
70
- const userRetentionDays = strapi.config.get('admin.auditLogs.retentionDays');
67
+ /**
68
+ * The retention the daily delete job applies, from the license's value and the admin override.
69
+ * Shared with the Plan card's resolver (../entitlements.ts) so the card shows this same figure.
70
+ */ const computeRetentionDays = (licenseRetentionDays, userRetentionDays)=>{
71
71
  // For enterprise plans, use 90 days by default, but allow users to override it
72
72
  if (licenseRetentionDays == null) {
73
73
  return userRetentionDays ?? DEFAULT_RETENTION_DAYS;
74
74
  }
75
+ // The registry can ship the value as a numeric string
76
+ const licenseDays = Number(licenseRetentionDays);
75
77
  // Allow users to override the license retention days, but not to increase it
76
- if (userRetentionDays && userRetentionDays <= licenseRetentionDays) {
78
+ if (userRetentionDays && userRetentionDays <= licenseDays) {
77
79
  return userRetentionDays;
78
80
  }
79
81
  // User didn't provide a retention days value, use the license one
80
- return licenseRetentionDays;
82
+ return licenseDays;
83
+ };
84
+ const getRetentionDays = (strapi)=>{
85
+ const featureConfig = strapi.ee.features.get('audit-logs');
86
+ return computeRetentionDays(typeof featureConfig === 'object' ? featureConfig?.options?.retentionDays : undefined, strapi.config.get('admin.auditLogs.retentionDays'));
81
87
  };
82
88
  /**
83
89
  * @description
@@ -105,15 +111,19 @@ const getRetentionDays = (strapi)=>{
105
111
  const isUsingAdminAuth = requestState?.route?.info?.type === 'admin';
106
112
  const auditSource = requestState?.auditSource;
107
113
  const isMcpAdminAction = auditSource === 'mcp';
108
- const user = requestState?.user;
114
+ const options = registration.kind === 'standard' ? registration.options : {};
115
+ const user = options.alwaysUnknownActor ? undefined : requestState?.user;
109
116
  const systemOrigin = auditSource && SYSTEM_ORIGINS.includes(auditSource) ? auditSource : undefined;
110
117
  if (!systemOrigin && !isUsingAdminAuth && !isMcpAdminAction) {
111
118
  return null;
112
119
  }
113
- const allowsUnknownActor = registration.kind === 'standard' && registration.options.allowUnknownActor === true;
120
+ const allowsUnknownActor = options.allowUnknownActor === true || options.alwaysUnknownActor === true;
114
121
  if (!systemOrigin && !user && !allowsUnknownActor) {
115
122
  return null;
116
123
  }
124
+ if (options.shouldRecord?.(...args) === false) {
125
+ return null;
126
+ }
117
127
  const origin = systemOrigin ?? auditSource ?? 'admin-panel';
118
128
  const date = new Date().toISOString();
119
129
  // Scheduled actions have no user, so a null user is expected. The earlier audit
@@ -265,5 +275,5 @@ const getRetentionDays = (strapi)=>{
265
275
  };
266
276
  };
267
277
 
268
- export { createAuditLogsLifecycleService };
278
+ export { DEFAULT_RETENTION_DAYS, computeRetentionDays, createAuditLogsLifecycleService };
269
279
  //# sourceMappingURL=lifecycles.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"lifecycles.mjs","sources":["../../../../../../../ee/server/src/audit-logs/services/lifecycles.ts"],"sourcesContent":["import type { Core, Modules } from '@strapi/types';\n\nimport { getDisplayName } from '../utils';\n\nconst DEFAULT_RETENTION_DAYS = 90;\n\n/**\n * Events audited before the payload standard; their stored shape is frozen for\n * compatibility. Do not add events here: new events come through registerEvent().\n * The event hub still emits user.create, user.update and user.delete; the audit log\n * records them as admin-user.* (server/src/audit-logs/admin-users.ts).\n * TODO: migrate the rest to the standard.\n */\nconst defaultEvents = [\n 'entry.create',\n 'entry.update',\n 'entry.delete',\n 'entry.publish',\n 'entry.unpublish',\n 'media.create',\n 'media.update',\n 'media.delete',\n 'media-folder.create',\n 'media-folder.update',\n 'media-folder.delete',\n 'admin.auth.success',\n 'admin.logout',\n 'content-type.create',\n 'content-type.update',\n 'content-type.delete',\n 'component.create',\n 'component.update',\n 'component.delete',\n 'role.create',\n 'role.update',\n 'role.delete',\n 'permission.create',\n 'permission.update',\n 'permission.delete',\n];\n\n/**\n * Legacy events store the first emitted argument as-is; registered events store the\n * standard shape built by their transformer.\n */\ntype EventRegistration =\n | { kind: 'legacy' }\n | {\n kind: 'standard';\n transform: Modules.AuditLogs.EventTransformer;\n options: RegisterEventOptions;\n };\n\nexport interface RegisterEventOptions {\n /**\n * Records the event when the request has no authenticated user, with an\n * `unknown` actor and no user column. For actions taken from public admin\n * forms (password reset, invitation). Off by default: an event with no user\n * is dropped.\n */\n allowUnknownActor?: boolean;\n}\n\nconst getEventMap = (events: string[]) => {\n return events.reduce(\n (acc, event) => {\n acc[event] = { kind: 'legacy' };\n return acc;\n },\n {} as Record<string, EventRegistration>\n );\n};\n\nconst getActor = (\n systemOrigin: Modules.AuditLogs.SystemOrigin | undefined,\n user: { id: string | number; email: string; firstname?: string; lastname?: string } | undefined\n): Modules.AuditLogs.Actor => {\n if (systemOrigin) {\n return { type: 'system' };\n }\n\n if (!user) {\n return { type: 'unknown' };\n }\n\n // We copy the user data into the row so the history stays unchanged if the user\n // changes later\n return {\n type: 'admin-user',\n user: { id: user.id, email: user.email, name: getDisplayName(user) },\n };\n};\n\nconst getRetentionDays = (strapi: Core.Strapi) => {\n const featureConfig = strapi.ee.features.get('audit-logs');\n const licenseRetentionDays =\n typeof featureConfig === 'object' && featureConfig?.options?.retentionDays;\n const userRetentionDays = strapi.config.get('admin.auditLogs.retentionDays');\n\n // For enterprise plans, use 90 days by default, but allow users to override it\n if (licenseRetentionDays == null) {\n return userRetentionDays ?? DEFAULT_RETENTION_DAYS;\n }\n\n // Allow users to override the license retention days, but not to increase it\n if (userRetentionDays && userRetentionDays <= licenseRetentionDays) {\n return userRetentionDays;\n }\n\n // User didn't provide a retention days value, use the license one\n return licenseRetentionDays;\n};\n\n/**\n * @description\n * Manages the lifecycle of audit logs. Accessible via strapi.get('audit-logs-lifecycle')\n */\nconst createAuditLogsLifecycleService = (strapi: Core.Strapi) => {\n // Manage internal service state privately\n const state = {} as any;\n const auditLogsService = strapi.get('audit-logs');\n\n const eventMap = getEventMap(defaultEvents);\n\n /**\n * The system origins accepted from the execution context; anything else needs a\n * user. Keyed on the type, so extending SystemOrigin without gating it here fails\n * to compile.\n */\n const SYSTEM_ORIGIN_FLAGS: Record<Modules.AuditLogs.SystemOrigin, true> = {\n scheduler: true,\n };\n const SYSTEM_ORIGINS = Object.keys(SYSTEM_ORIGIN_FLAGS);\n\n const processEvent = async (name: string, ...args: any) => {\n const registration = eventMap[name];\n\n if (!registration) {\n return null;\n }\n\n const rawEvent = args[0];\n\n const requestState = strapi.requestContext.get()?.state;\n\n const isUsingAdminAuth = requestState?.route?.info?.type === 'admin';\n const auditSource = requestState?.auditSource;\n const isMcpAdminAction = auditSource === 'mcp';\n const user = requestState?.user;\n\n const systemOrigin =\n auditSource && SYSTEM_ORIGINS.includes(auditSource)\n ? (auditSource as Modules.AuditLogs.SystemOrigin)\n : undefined;\n\n if (!systemOrigin && !isUsingAdminAuth && !isMcpAdminAction) {\n return null;\n }\n\n const allowsUnknownActor =\n registration.kind === 'standard' && registration.options.allowUnknownActor === true;\n\n if (!systemOrigin && !user && !allowsUnknownActor) {\n return null;\n }\n\n const origin: Modules.AuditLogs.AuditSource = systemOrigin ?? auditSource ?? 'admin-panel';\n const date = new Date().toISOString();\n // Scheduled actions have no user, so a null user is expected. The earlier audit\n // entry that set the schedule records who did it. Events allowing an unknown actor\n // have no user either.\n const userId = user ? user.id : null;\n\n if (registration.kind === 'legacy') {\n // TODO: What does this ignore in upload? Why would we want to ignore anything?\n const ignoredUids = ['plugin::upload.file', 'plugin::upload.folder'];\n if (ignoredUids.includes(rawEvent?.uid)) {\n return null;\n }\n\n return {\n action: name,\n date,\n payload: { ...rawEvent, origin },\n userId,\n };\n }\n\n const actor = getActor(systemOrigin, user);\n\n let shape: Modules.AuditLogs.EventShape | null = null;\n\n try {\n shape = await registration.transform(...args);\n } catch (error) {\n // If the transformer fails, we still keep the audit event: the row is saved\n // with the subscriber's fields only.\n strapi.log.error(`Failed to build the audit log payload for ${name}`, { error });\n }\n\n const {\n action: _action,\n date: _date,\n actor: _actor,\n origin: _origin,\n ...rest\n } = (shape ?? {}) as Record<string, unknown>;\n const payload = shape\n ? ({ action: name, date, actor, origin, ...rest } as Modules.AuditLogs.StoredPayload)\n : { action: name, date, actor, origin };\n\n return { action: name, date, payload, userId };\n };\n\n const handleEvent = async (name: string, ...args: any) => {\n try {\n const processedEvent = await processEvent(name, ...args);\n\n if (processedEvent) {\n await auditLogsService.saveEvent(processedEvent);\n }\n } catch (error) {\n // Logged, not propagated: most emitters fire and forget (the document service\n // emits entry.* from an unawaited onCommit callback), and a rejection with no\n // one awaiting it takes the process down. Audit logging is therefore fail-open:\n // the entry is lost and only this line records it.\n strapi.log.error(`Failed to save the audit log entry for ${name}`, { error });\n }\n };\n\n return {\n /**\n * Adds an event to the list of audited events. Plugins register their own from\n * their bootstrap; the transformer builds the audited shape\n * ({resource, details, outcome}) from the arguments passed to eventHub.emit().\n */\n registerEvent<TDetails = unknown>(\n name: string,\n transform: Modules.AuditLogs.EventTransformer<TDetails>,\n options: RegisterEventOptions = {}\n ) {\n if (eventMap[name]?.kind === 'legacy') {\n throw new Error(\n `Cannot register the audit log event \"${name}\": it is one of the built-in events, whose stored shape is frozen.`\n );\n }\n\n if (eventMap[name]) {\n strapi.log.warn(`The audit log event \"${name}\" was already registered and is replaced.`);\n }\n\n eventMap[name] = {\n kind: 'standard',\n transform: transform as Modules.AuditLogs.EventTransformer,\n options,\n };\n },\n\n async register() {\n // Handle license being enabled\n if (!state.eeEnableUnsubscribe) {\n // @ts-expect-error- update event hub to receive callback argument\n state.eeEnableUnsubscribe = strapi.eventHub.on('ee.enable', () => {\n // Recreate the service to use the new license info\n this.destroy();\n this.register();\n });\n }\n\n // Handle license being updated\n if (!state.eeUpdateUnsubscribe) {\n // @ts-expect-error- update event hub to receive callback argument\n state.eeUpdateUnsubscribe = strapi.eventHub.on('ee.update', () => {\n // Recreate the service to use the new license info\n this.destroy();\n this.register();\n });\n }\n\n // Handle license being disabled\n // @ts-expect-error- update event hub to receive callback argument\n state.eeDisableUnsubscribe = strapi.eventHub.on('ee.disable', () => {\n // Turn off service when the license gets disabled\n // Only ee.enable and ee.update listeners remain active to recreate the service\n this.destroy();\n });\n\n // Check current state of license\n if (!strapi.ee.features.isEnabled('audit-logs')) {\n return this;\n }\n\n // Start saving events\n state.eventHubUnsubscribe = strapi.eventHub.subscribe(handleEvent);\n\n // Manage audit logs auto deletion\n const retentionDays = getRetentionDays(strapi);\n\n strapi.cron.add({\n deleteExpiredAuditLogs: {\n async task() {\n const expirationDate = new Date(Date.now() - retentionDays * 24 * 60 * 60 * 1000);\n await auditLogsService.deleteExpiredEvents(expirationDate);\n },\n options: '0 0 * * *',\n },\n });\n\n return this;\n },\n\n unsubscribe() {\n if (state.eeDisableUnsubscribe) {\n state.eeDisableUnsubscribe();\n }\n\n if (state.eventHubUnsubscribe) {\n state.eventHubUnsubscribe();\n }\n\n strapi.cron.remove('deleteExpiredAuditLogs');\n\n return this;\n },\n\n destroy() {\n return this.unsubscribe();\n },\n };\n};\n\nexport { createAuditLogsLifecycleService };\n"],"names":["DEFAULT_RETENTION_DAYS","defaultEvents","getEventMap","events","reduce","acc","event","kind","getActor","systemOrigin","user","type","id","email","name","getDisplayName","getRetentionDays","strapi","featureConfig","ee","features","get","licenseRetentionDays","options","retentionDays","userRetentionDays","config","createAuditLogsLifecycleService","state","auditLogsService","eventMap","SYSTEM_ORIGIN_FLAGS","scheduler","SYSTEM_ORIGINS","Object","keys","processEvent","args","registration","rawEvent","requestState","requestContext","isUsingAdminAuth","route","info","auditSource","isMcpAdminAction","includes","undefined","allowsUnknownActor","allowUnknownActor","origin","date","Date","toISOString","userId","ignoredUids","uid","action","payload","actor","shape","transform","error","log","_action","_date","_actor","_origin","rest","handleEvent","processedEvent","saveEvent","registerEvent","Error","warn","register","eeEnableUnsubscribe","eventHub","on","destroy","eeUpdateUnsubscribe","eeDisableUnsubscribe","isEnabled","eventHubUnsubscribe","subscribe","cron","add","deleteExpiredAuditLogs","task","expirationDate","now","deleteExpiredEvents","unsubscribe","remove"],"mappings":"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"}
1
+ {"version":3,"file":"lifecycles.mjs","sources":["../../../../../../../ee/server/src/audit-logs/services/lifecycles.ts"],"sourcesContent":["import type { Core, Modules } from '@strapi/types';\n\nimport { getDisplayName } from '../utils';\n\nexport const DEFAULT_RETENTION_DAYS = 90;\n\n/**\n * Events audited before the payload standard; their stored shape is frozen for\n * compatibility. Do not add events here: new events come through registerEvent().\n * The event hub still emits user.create, user.update and user.delete; the audit log\n * records them as admin-user.* (server/src/audit-logs/admin-users.ts).\n * TODO: migrate the rest to the standard.\n */\nconst defaultEvents = [\n 'entry.create',\n 'entry.update',\n 'entry.delete',\n 'entry.publish',\n 'entry.unpublish',\n 'media.create',\n 'media.update',\n 'media.delete',\n 'media-folder.create',\n 'media-folder.update',\n 'media-folder.delete',\n 'admin.auth.success',\n 'admin.logout',\n 'content-type.create',\n 'content-type.update',\n 'content-type.delete',\n 'component.create',\n 'component.update',\n 'component.delete',\n 'role.create',\n 'role.update',\n 'role.delete',\n 'permission.create',\n 'permission.update',\n 'permission.delete',\n];\n\n/**\n * Legacy events store the first emitted argument as-is; registered events store the\n * standard shape built by their transformer.\n */\ntype EventRegistration =\n | { kind: 'legacy' }\n | {\n kind: 'standard';\n transform: Modules.AuditLogs.EventTransformer;\n options: RegisterEventOptions;\n };\n\nexport interface RegisterEventOptions {\n /**\n * Records the event when the request has no authenticated user, with an\n * `unknown` actor and no user column. For actions taken from public admin\n * forms (password reset, invitation). Off by default: an event with no user\n * is dropped.\n */\n allowUnknownActor?: boolean;\n /**\n * Records the event with an `unknown` actor and no user column even when the request\n * has an authenticated user. For events about a login that did not complete.\n */\n alwaysUnknownActor?: boolean;\n /**\n * Receives the arguments passed to eventHub.emit(); returning false keeps the\n * event out of the audit log. Listeners on the event hub still receive it.\n */\n shouldRecord?: (...args: any[]) => boolean;\n}\n\nconst getEventMap = (events: string[]) => {\n return events.reduce(\n (acc, event) => {\n acc[event] = { kind: 'legacy' };\n return acc;\n },\n {} as Record<string, EventRegistration>\n );\n};\n\nconst getActor = (\n systemOrigin: Modules.AuditLogs.SystemOrigin | undefined,\n user: { id: string | number; email: string; firstname?: string; lastname?: string } | undefined\n): Modules.AuditLogs.Actor => {\n if (systemOrigin) {\n return { type: 'system' };\n }\n\n if (!user) {\n return { type: 'unknown' };\n }\n\n // We copy the user data into the row so the history stays unchanged if the user\n // changes later\n return {\n type: 'admin-user',\n user: { id: user.id, email: user.email, name: getDisplayName(user) },\n };\n};\n\n/**\n * The retention the daily delete job applies, from the license's value and the admin override.\n * Shared with the Plan card's resolver (../entitlements.ts) so the card shows this same figure.\n */\nexport const computeRetentionDays = (\n licenseRetentionDays: unknown,\n userRetentionDays: number | null | undefined\n): number => {\n // For enterprise plans, use 90 days by default, but allow users to override it\n if (licenseRetentionDays == null) {\n return userRetentionDays ?? DEFAULT_RETENTION_DAYS;\n }\n\n // The registry can ship the value as a numeric string\n const licenseDays = Number(licenseRetentionDays);\n\n // Allow users to override the license retention days, but not to increase it\n if (userRetentionDays && userRetentionDays <= licenseDays) {\n return userRetentionDays;\n }\n\n // User didn't provide a retention days value, use the license one\n return licenseDays;\n};\n\nconst getRetentionDays = (strapi: Core.Strapi) => {\n const featureConfig = strapi.ee.features.get('audit-logs');\n\n return computeRetentionDays(\n typeof featureConfig === 'object' ? featureConfig?.options?.retentionDays : undefined,\n strapi.config.get('admin.auditLogs.retentionDays')\n );\n};\n\n/**\n * @description\n * Manages the lifecycle of audit logs. Accessible via strapi.get('audit-logs-lifecycle')\n */\nconst createAuditLogsLifecycleService = (strapi: Core.Strapi) => {\n // Manage internal service state privately\n const state = {} as any;\n const auditLogsService = strapi.get('audit-logs');\n\n const eventMap = getEventMap(defaultEvents);\n\n /**\n * The system origins accepted from the execution context; anything else needs a\n * user. Keyed on the type, so extending SystemOrigin without gating it here fails\n * to compile.\n */\n const SYSTEM_ORIGIN_FLAGS: Record<Modules.AuditLogs.SystemOrigin, true> = {\n scheduler: true,\n };\n const SYSTEM_ORIGINS = Object.keys(SYSTEM_ORIGIN_FLAGS);\n\n const processEvent = async (name: string, ...args: any) => {\n const registration = eventMap[name];\n\n if (!registration) {\n return null;\n }\n\n const rawEvent = args[0];\n\n const requestState = strapi.requestContext.get()?.state;\n\n const isUsingAdminAuth = requestState?.route?.info?.type === 'admin';\n const auditSource = requestState?.auditSource;\n const isMcpAdminAction = auditSource === 'mcp';\n const options: RegisterEventOptions =\n registration.kind === 'standard' ? registration.options : {};\n const user = options.alwaysUnknownActor ? undefined : requestState?.user;\n\n const systemOrigin =\n auditSource && SYSTEM_ORIGINS.includes(auditSource)\n ? (auditSource as Modules.AuditLogs.SystemOrigin)\n : undefined;\n\n if (!systemOrigin && !isUsingAdminAuth && !isMcpAdminAction) {\n return null;\n }\n\n const allowsUnknownActor =\n options.allowUnknownActor === true || options.alwaysUnknownActor === true;\n\n if (!systemOrigin && !user && !allowsUnknownActor) {\n return null;\n }\n\n if (options.shouldRecord?.(...args) === false) {\n return null;\n }\n\n const origin: Modules.AuditLogs.AuditSource = systemOrigin ?? auditSource ?? 'admin-panel';\n const date = new Date().toISOString();\n // Scheduled actions have no user, so a null user is expected. The earlier audit\n // entry that set the schedule records who did it. Events allowing an unknown actor\n // have no user either.\n const userId = user ? user.id : null;\n\n if (registration.kind === 'legacy') {\n // TODO: What does this ignore in upload? Why would we want to ignore anything?\n const ignoredUids = ['plugin::upload.file', 'plugin::upload.folder'];\n if (ignoredUids.includes(rawEvent?.uid)) {\n return null;\n }\n\n return {\n action: name,\n date,\n payload: { ...rawEvent, origin },\n userId,\n };\n }\n\n const actor = getActor(systemOrigin, user);\n\n let shape: Modules.AuditLogs.EventShape | null = null;\n\n try {\n shape = await registration.transform(...args);\n } catch (error) {\n // If the transformer fails, we still keep the audit event: the row is saved\n // with the subscriber's fields only.\n strapi.log.error(`Failed to build the audit log payload for ${name}`, { error });\n }\n\n const {\n action: _action,\n date: _date,\n actor: _actor,\n origin: _origin,\n ...rest\n } = (shape ?? {}) as Record<string, unknown>;\n const payload = shape\n ? ({ action: name, date, actor, origin, ...rest } as Modules.AuditLogs.StoredPayload)\n : { action: name, date, actor, origin };\n\n return { action: name, date, payload, userId };\n };\n\n const handleEvent = async (name: string, ...args: any) => {\n try {\n const processedEvent = await processEvent(name, ...args);\n\n if (processedEvent) {\n await auditLogsService.saveEvent(processedEvent);\n }\n } catch (error) {\n // Logged, not propagated: most emitters fire and forget (the document service\n // emits entry.* from an unawaited onCommit callback), and a rejection with no\n // one awaiting it takes the process down. Audit logging is therefore fail-open:\n // the entry is lost and only this line records it.\n strapi.log.error(`Failed to save the audit log entry for ${name}`, { error });\n }\n };\n\n return {\n /**\n * Adds an event to the list of audited events. Plugins register their own from\n * their bootstrap; the transformer builds the audited shape\n * ({resource, details, outcome}) from the arguments passed to eventHub.emit().\n */\n registerEvent<TDetails = unknown>(\n name: string,\n transform: Modules.AuditLogs.EventTransformer<TDetails>,\n options: RegisterEventOptions = {}\n ) {\n if (eventMap[name]?.kind === 'legacy') {\n throw new Error(\n `Cannot register the audit log event \"${name}\": it is one of the built-in events, whose stored shape is frozen.`\n );\n }\n\n if (eventMap[name]) {\n strapi.log.warn(`The audit log event \"${name}\" was already registered and is replaced.`);\n }\n\n eventMap[name] = {\n kind: 'standard',\n transform: transform as Modules.AuditLogs.EventTransformer,\n options,\n };\n },\n\n async register() {\n // Handle license being enabled\n if (!state.eeEnableUnsubscribe) {\n // @ts-expect-error- update event hub to receive callback argument\n state.eeEnableUnsubscribe = strapi.eventHub.on('ee.enable', () => {\n // Recreate the service to use the new license info\n this.destroy();\n this.register();\n });\n }\n\n // Handle license being updated\n if (!state.eeUpdateUnsubscribe) {\n // @ts-expect-error- update event hub to receive callback argument\n state.eeUpdateUnsubscribe = strapi.eventHub.on('ee.update', () => {\n // Recreate the service to use the new license info\n this.destroy();\n this.register();\n });\n }\n\n // Handle license being disabled\n // @ts-expect-error- update event hub to receive callback argument\n state.eeDisableUnsubscribe = strapi.eventHub.on('ee.disable', () => {\n // Turn off service when the license gets disabled\n // Only ee.enable and ee.update listeners remain active to recreate the service\n this.destroy();\n });\n\n // Check current state of license\n if (!strapi.ee.features.isEnabled('audit-logs')) {\n return this;\n }\n\n // Start saving events\n state.eventHubUnsubscribe = strapi.eventHub.subscribe(handleEvent);\n\n // Manage audit logs auto deletion\n const retentionDays = getRetentionDays(strapi);\n\n strapi.cron.add({\n deleteExpiredAuditLogs: {\n async task() {\n const expirationDate = new Date(Date.now() - retentionDays * 24 * 60 * 60 * 1000);\n await auditLogsService.deleteExpiredEvents(expirationDate);\n },\n options: '0 0 * * *',\n },\n });\n\n return this;\n },\n\n unsubscribe() {\n if (state.eeDisableUnsubscribe) {\n state.eeDisableUnsubscribe();\n }\n\n if (state.eventHubUnsubscribe) {\n state.eventHubUnsubscribe();\n }\n\n strapi.cron.remove('deleteExpiredAuditLogs');\n\n return this;\n },\n\n destroy() {\n return this.unsubscribe();\n },\n };\n};\n\nexport { createAuditLogsLifecycleService };\n"],"names":["DEFAULT_RETENTION_DAYS","defaultEvents","getEventMap","events","reduce","acc","event","kind","getActor","systemOrigin","user","type","id","email","name","getDisplayName","computeRetentionDays","licenseRetentionDays","userRetentionDays","licenseDays","Number","getRetentionDays","strapi","featureConfig","ee","features","get","options","retentionDays","undefined","config","createAuditLogsLifecycleService","state","auditLogsService","eventMap","SYSTEM_ORIGIN_FLAGS","scheduler","SYSTEM_ORIGINS","Object","keys","processEvent","args","registration","rawEvent","requestState","requestContext","isUsingAdminAuth","route","info","auditSource","isMcpAdminAction","alwaysUnknownActor","includes","allowsUnknownActor","allowUnknownActor","shouldRecord","origin","date","Date","toISOString","userId","ignoredUids","uid","action","payload","actor","shape","transform","error","log","_action","_date","_actor","_origin","rest","handleEvent","processedEvent","saveEvent","registerEvent","Error","warn","register","eeEnableUnsubscribe","eventHub","on","destroy","eeUpdateUnsubscribe","eeDisableUnsubscribe","isEnabled","eventHubUnsubscribe","subscribe","cron","add","deleteExpiredAuditLogs","task","expirationDate","now","deleteExpiredEvents","unsubscribe","remove"],"mappings":"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"}
@@ -3,6 +3,9 @@
3
3
  var utils = require('@strapi/utils');
4
4
  var index = require('../utils/index.js');
5
5
 
6
+ const findRetainedFeature = (retainedFeatures, featureName)=>retainedFeatures?.map((entry)=>typeof entry === 'string' ? {
7
+ name: entry
8
+ } : entry).find((entry)=>entry.name === featureName);
6
9
  var admin = {
7
10
  // NOTE: Overrides CE admin controller
8
11
  async getProjectType () {
@@ -38,6 +41,14 @@ var admin = {
38
41
  },
39
42
  async licenseLimitInformation () {
40
43
  const permittedSeats = strapi.ee.seats;
44
+ // Display-only fallback so an expired/unknown license can still show its plan, seats
45
+ // and subscription. Never used for enforcement (permittedSeats above is untouched).
46
+ const retained = strapi.ee.retainedLicense;
47
+ const isActiveLicense = strapi.ee.licenseStatus === 'active';
48
+ const activeEntitlements = strapi.ee.entitlements.list();
49
+ // A lapsed license resolves through the same resolvers against its retained snapshot, so the
50
+ // card shows the defaulted, clamped limits the plan enforced rather than raw options.
51
+ const retainedEntitlements = isActiveLicense ? [] : strapi.ee.entitlements.listRetained();
41
52
  let shouldNotify = false;
42
53
  let licenseLimitStatus = null;
43
54
  let enforcementUserCount;
@@ -56,17 +67,79 @@ var admin = {
56
67
  shouldNotify = true;
57
68
  licenseLimitStatus = 'AT_LIMIT';
58
69
  }
70
+ const eeInformation = await strapi.db.query('strapi::core-store').findOne({
71
+ where: {
72
+ key: 'ee_information'
73
+ }
74
+ }).then((row)=>row ? JSON.parse(row.value) : null).catch(()=>null);
75
+ // disable() wipes the live type on expiry but keeps it on the retained snapshot, so resolve
76
+ // it once here: an expired offline gold license must still report `offline` (and show its
77
+ // real expiry) rather than the online check-in line.
78
+ const licenseType = strapi.ee.type ?? retained?.type ?? null;
79
+ const licenseMode = licenseType === 'gold' && process.env.STRAPI_DISABLE_LICENSE_PING?.toLowerCase() === 'true' ? 'offline' : 'online';
80
+ // Registry re-check cron cadence ('0 0 */12 * * *', shifted to the startup time -> every 12h).
81
+ const REGISTRY_CHECK_INTERVAL_MS = 12 * 60 * 60 * 1000;
82
+ const lastRegistrySyncAt = eeInformation?.lastCheckAt ?? null;
83
+ let nextRegistrySyncAt = null;
84
+ if (licenseMode === 'online' && typeof lastRegistrySyncAt === 'number') {
85
+ // Step forward from the last check-in in 12h increments until we land in the
86
+ // future, so a stale last check-in never reports a "next check-in" in the past.
87
+ const now = Date.now();
88
+ let next = lastRegistrySyncAt + REGISTRY_CHECK_INTERVAL_MS;
89
+ while(next <= now){
90
+ next += REGISTRY_CHECK_INTERVAL_MS;
91
+ }
92
+ nextRegistrySyncAt = next;
93
+ }
94
+ // An offline instance never contacts the registry, so an error (and the cached license that
95
+ // came with it) stored by an earlier online run says nothing about its current state.
96
+ const registryState = licenseMode === 'online' ? eeInformation : null;
59
97
  const data = {
60
98
  enforcementUserCount,
61
99
  currentActiveUserCount,
62
- permittedSeats,
100
+ // Typed `number` in the published contract; null at runtime without a seat limit
101
+ permittedSeats: permittedSeats ?? null,
102
+ seats: strapi.ee.seats ?? retained?.seats ?? null,
103
+ subscriptionId: strapi.ee.subscriptionId ?? retained?.subscriptionId ?? null,
104
+ expireAt: strapi.ee.expireAt ?? retained?.expireAt ?? null,
105
+ licenseStatus: strapi.ee.licenseStatus,
106
+ planPriceId: strapi.ee.planPriceId ?? retained?.planPriceId ?? null,
107
+ renewalDate: strapi.ee.renewalDate,
108
+ planEntitlements: strapi.ee.planFeatureCatalog.map((feature)=>{
109
+ if (isActiveLicense) {
110
+ // Every resolver runs for an active license and falls back to its default for a
111
+ // missing feature, so only an included feature keeps its limits.
112
+ const available = strapi.ee.features.isEnabled(feature);
113
+ return {
114
+ feature,
115
+ available,
116
+ limits: available ? activeEntitlements.find((entry)=>entry.feature === feature)?.limits ?? [] : []
117
+ };
118
+ }
119
+ const retainedFeature = findRetainedFeature(retained?.features, feature);
120
+ return {
121
+ feature,
122
+ available: Boolean(retainedFeature),
123
+ limits: retainedFeature ? retainedEntitlements.find((entry)=>entry.feature === feature)?.limits ?? [] : []
124
+ };
125
+ }),
126
+ licenseMode,
127
+ lastRegistrySyncAt,
128
+ nextRegistrySyncAt,
129
+ usingCachedLicense: Boolean(registryState?.error && registryState?.license),
130
+ registrySyncError: registryState?.error ?? null,
131
+ registrySyncErrorKind: registryState?.errorKind ?? null,
63
132
  shouldNotify,
64
133
  shouldStopCreate: permittedSeats == null ? false : currentActiveUserCount >= permittedSeats,
65
134
  licenseLimitStatus,
66
135
  isHostedOnStrapiCloud: utils.env('STRAPI_HOSTING', null) === 'strapi.cloud',
67
- type: strapi.ee.type,
136
+ // Typed `string` in the published contract; null at runtime without a license
137
+ type: licenseType,
68
138
  isTrial: strapi.ee.isTrial,
69
- features: strapi.ee.features.list() ?? []
139
+ // `features.list()` is loosely typed at the source (`{ name: string; [k]: any }[]`);
140
+ // narrow it to the contract's named-feature union so consumers (e.g. useLicenseLimits) keep their types.
141
+ features: strapi.ee.features.list() ?? [],
142
+ entitlements: strapi.ee.entitlements.list()
70
143
  };
71
144
  return {
72
145
  data
@@ -1 +1 @@
1
- {"version":3,"file":"admin.js","sources":["../../../../../../ee/server/src/controllers/admin.ts"],"sourcesContent":["import { env } from '@strapi/utils';\n\nimport { getService } from '../utils';\n\nimport type { GetProjectType } from '../../../../shared/contracts/admin';\n\nexport default {\n // NOTE: Overrides CE admin controller\n async getProjectType(): Promise<GetProjectType.Response> {\n const flags = strapi.config.get('admin.flags', {});\n\n try {\n return {\n data: {\n // The license fields are nullable internally; the contract is not.\n isEE: Boolean(strapi.EE),\n isTrial: strapi.ee.isTrial,\n features: strapi.ee.features.list(),\n flags,\n type: strapi.ee.type ?? undefined,\n planPriceId: strapi.ee.planPriceId ?? undefined,\n ai: {\n enabled: strapi.ai.admin.isStrapiManagedAiEnabled(),\n },\n },\n };\n } catch {\n return { data: { isEE: false, isTrial: false, features: [], flags, ai: { enabled: false } } };\n }\n },\n\n async licenseLimitInformation() {\n const permittedSeats = strapi.ee.seats;\n\n let shouldNotify = false;\n let licenseLimitStatus = null;\n let enforcementUserCount;\n\n const currentActiveUserCount = await getService('user').getCurrentActiveUserCount();\n\n const eeDisabledUsers = await getService('seat-enforcement').getDisabledUserList();\n\n if (eeDisabledUsers) {\n enforcementUserCount = currentActiveUserCount + eeDisabledUsers.length;\n } else {\n enforcementUserCount = currentActiveUserCount;\n }\n\n if (permittedSeats != null && enforcementUserCount > permittedSeats) {\n shouldNotify = true;\n licenseLimitStatus = 'OVER_LIMIT';\n }\n\n if (permittedSeats != null && enforcementUserCount === permittedSeats) {\n shouldNotify = true;\n licenseLimitStatus = 'AT_LIMIT';\n }\n\n const data = {\n enforcementUserCount,\n currentActiveUserCount,\n permittedSeats,\n shouldNotify,\n shouldStopCreate: permittedSeats == null ? false : currentActiveUserCount >= permittedSeats,\n licenseLimitStatus,\n isHostedOnStrapiCloud: env('STRAPI_HOSTING', null) === 'strapi.cloud',\n type: strapi.ee.type,\n isTrial: strapi.ee.isTrial,\n features: strapi.ee.features.list() ?? [],\n };\n\n return { data };\n },\n};\n"],"names":["getProjectType","flags","strapi","config","get","data","isEE","Boolean","EE","isTrial","ee","features","list","type","undefined","planPriceId","ai","enabled","admin","isStrapiManagedAiEnabled","licenseLimitInformation","permittedSeats","seats","shouldNotify","licenseLimitStatus","enforcementUserCount","currentActiveUserCount","getService","getCurrentActiveUserCount","eeDisabledUsers","getDisabledUserList","length","shouldStopCreate","isHostedOnStrapiCloud","env"],"mappings":";;;;;AAMA,YAAe;;IAEb,MAAMA,cAAAA,CAAAA,GAAAA;AACJ,QAAA,MAAMC,QAAQC,MAAAA,CAAOC,MAAM,CAACC,GAAG,CAAC,eAAe,EAAC,CAAA;QAEhD,IAAI;YACF,OAAO;gBACLC,IAAAA,EAAM;;oBAEJC,IAAAA,EAAMC,OAAAA,CAAQL,OAAOM,EAAE,CAAA;oBACvBC,OAAAA,EAASP,MAAAA,CAAOQ,EAAE,CAACD,OAAO;AAC1BE,oBAAAA,QAAAA,EAAUT,MAAAA,CAAOQ,EAAE,CAACC,QAAQ,CAACC,IAAI,EAAA;AACjCX,oBAAAA,KAAAA;AACAY,oBAAAA,IAAAA,EAAMX,MAAAA,CAAOQ,EAAE,CAACG,IAAI,IAAIC,SAAAA;AACxBC,oBAAAA,WAAAA,EAAab,MAAAA,CAAOQ,EAAE,CAACK,WAAW,IAAID,SAAAA;oBACtCE,EAAAA,EAAI;AACFC,wBAAAA,OAAAA,EAASf,MAAAA,CAAOc,EAAE,CAACE,KAAK,CAACC,wBAAwB;AACnD;AACF;AACF,aAAA;AACF,QAAA,CAAA,CAAE,OAAM;YACN,OAAO;gBAAEd,IAAAA,EAAM;oBAAEC,IAAAA,EAAM,KAAA;oBAAOG,OAAAA,EAAS,KAAA;AAAOE,oBAAAA,QAAAA,EAAU,EAAE;AAAEV,oBAAAA,KAAAA;oBAAOe,EAAAA,EAAI;wBAAEC,OAAAA,EAAS;AAAM;AAAE;AAAE,aAAA;AAC9F,QAAA;AACF,IAAA,CAAA;IAEA,MAAMG,uBAAAA,CAAAA,GAAAA;AACJ,QAAA,MAAMC,cAAAA,GAAiBnB,MAAAA,CAAOQ,EAAE,CAACY,KAAK;AAEtC,QAAA,IAAIC,YAAAA,GAAe,KAAA;AACnB,QAAA,IAAIC,kBAAAA,GAAqB,IAAA;QACzB,IAAIC,oBAAAA;AAEJ,QAAA,MAAMC,sBAAAA,GAAyB,MAAMC,gBAAAA,CAAW,MAAA,CAAA,CAAQC,yBAAyB,EAAA;AAEjF,QAAA,MAAMC,eAAAA,GAAkB,MAAMF,gBAAAA,CAAW,kBAAA,CAAA,CAAoBG,mBAAmB,EAAA;AAEhF,QAAA,IAAID,eAAAA,EAAiB;YACnBJ,oBAAAA,GAAuBC,sBAAAA,GAAyBG,gBAAgBE,MAAM;QACxE,CAAA,MAAO;YACLN,oBAAAA,GAAuBC,sBAAAA;AACzB,QAAA;QAEA,IAAIL,cAAAA,IAAkB,IAAA,IAAQI,oBAAAA,GAAuBJ,cAAAA,EAAgB;YACnEE,YAAAA,GAAe,IAAA;YACfC,kBAAAA,GAAqB,YAAA;AACvB,QAAA;QAEA,IAAIH,cAAAA,IAAkB,IAAA,IAAQI,oBAAAA,KAAyBJ,cAAAA,EAAgB;YACrEE,YAAAA,GAAe,IAAA;YACfC,kBAAAA,GAAqB,UAAA;AACvB,QAAA;AAEA,QAAA,MAAMnB,IAAAA,GAAO;AACXoB,YAAAA,oBAAAA;AACAC,YAAAA,sBAAAA;AACAL,YAAAA,cAAAA;AACAE,YAAAA,YAAAA;YACAS,gBAAAA,EAAkBX,cAAAA,IAAkB,IAAA,GAAO,KAAA,GAAQK,sBAAAA,IAA0BL,cAAAA;AAC7EG,YAAAA,kBAAAA;YACAS,qBAAAA,EAAuBC,SAAAA,CAAI,kBAAkB,IAAA,CAAA,KAAU,cAAA;YACvDrB,IAAAA,EAAMX,MAAAA,CAAOQ,EAAE,CAACG,IAAI;YACpBJ,OAAAA,EAASP,MAAAA,CAAOQ,EAAE,CAACD,OAAO;AAC1BE,YAAAA,QAAAA,EAAUT,OAAOQ,EAAE,CAACC,QAAQ,CAACC,IAAI,MAAM;AACzC,SAAA;QAEA,OAAO;AAAEP,YAAAA;AAAK,SAAA;AAChB,IAAA;AACF,CAAA;;;;"}
1
+ {"version":3,"file":"admin.js","sources":["../../../../../../ee/server/src/controllers/admin.ts"],"sourcesContent":["import { env } from '@strapi/utils';\n\nimport type {\n GetLicenseLimitInformation,\n GetProjectType,\n} from '../../../../shared/contracts/admin';\nimport { getService } from '../utils';\n\ntype RetainedFeature = { name: string; [key: string]: any };\n\nconst findRetainedFeature = (\n retainedFeatures: Array<RetainedFeature | string> | undefined,\n featureName: string\n): RetainedFeature | undefined =>\n retainedFeatures\n ?.map((entry) => (typeof entry === 'string' ? { name: entry } : entry))\n .find((entry) => entry.name === featureName);\n\nexport default {\n // NOTE: Overrides CE admin controller\n async getProjectType(): Promise<GetProjectType.Response> {\n const flags = strapi.config.get('admin.flags', {});\n\n try {\n return {\n data: {\n // The license fields are nullable internally; the contract is not.\n isEE: Boolean(strapi.EE),\n isTrial: strapi.ee.isTrial,\n features: strapi.ee.features.list(),\n flags,\n type: strapi.ee.type ?? undefined,\n planPriceId: strapi.ee.planPriceId ?? undefined,\n ai: {\n enabled: strapi.ai.admin.isStrapiManagedAiEnabled(),\n },\n },\n };\n } catch {\n return { data: { isEE: false, isTrial: false, features: [], flags, ai: { enabled: false } } };\n }\n },\n\n async licenseLimitInformation() {\n const permittedSeats = strapi.ee.seats;\n // Display-only fallback so an expired/unknown license can still show its plan, seats\n // and subscription. Never used for enforcement (permittedSeats above is untouched).\n const retained = strapi.ee.retainedLicense;\n const isActiveLicense = strapi.ee.licenseStatus === 'active';\n const activeEntitlements = strapi.ee.entitlements.list();\n // A lapsed license resolves through the same resolvers against its retained snapshot, so the\n // card shows the defaulted, clamped limits the plan enforced rather than raw options.\n const retainedEntitlements = isActiveLicense ? [] : strapi.ee.entitlements.listRetained();\n\n let shouldNotify = false;\n let licenseLimitStatus = null;\n let enforcementUserCount;\n\n const currentActiveUserCount = await getService('user').getCurrentActiveUserCount();\n\n const eeDisabledUsers = await getService('seat-enforcement').getDisabledUserList();\n\n if (eeDisabledUsers) {\n enforcementUserCount = currentActiveUserCount + eeDisabledUsers.length;\n } else {\n enforcementUserCount = currentActiveUserCount;\n }\n\n if (permittedSeats != null && enforcementUserCount > permittedSeats) {\n shouldNotify = true;\n licenseLimitStatus = 'OVER_LIMIT';\n }\n\n if (permittedSeats != null && enforcementUserCount === permittedSeats) {\n shouldNotify = true;\n licenseLimitStatus = 'AT_LIMIT';\n }\n\n const eeInformation = await strapi.db\n .query('strapi::core-store')\n .findOne({ where: { key: 'ee_information' } })\n .then((row: { value: string } | null) =>\n row\n ? (JSON.parse(row.value) as {\n license?: string | null;\n error?: string;\n errorKind?: 'unreachable' | 'rejected';\n lastCheckAt?: number;\n })\n : null\n )\n .catch(() => null);\n\n // disable() wipes the live type on expiry but keeps it on the retained snapshot, so resolve\n // it once here: an expired offline gold license must still report `offline` (and show its\n // real expiry) rather than the online check-in line.\n const licenseType = strapi.ee.type ?? retained?.type ?? null;\n const licenseMode: 'online' | 'offline' =\n licenseType === 'gold' && process.env.STRAPI_DISABLE_LICENSE_PING?.toLowerCase() === 'true'\n ? 'offline'\n : 'online';\n\n // Registry re-check cron cadence ('0 0 */12 * * *', shifted to the startup time -> every 12h).\n const REGISTRY_CHECK_INTERVAL_MS = 12 * 60 * 60 * 1000;\n const lastRegistrySyncAt: number | null = eeInformation?.lastCheckAt ?? null;\n let nextRegistrySyncAt: number | null = null;\n if (licenseMode === 'online' && typeof lastRegistrySyncAt === 'number') {\n // Step forward from the last check-in in 12h increments until we land in the\n // future, so a stale last check-in never reports a \"next check-in\" in the past.\n const now = Date.now();\n let next = lastRegistrySyncAt + REGISTRY_CHECK_INTERVAL_MS;\n while (next <= now) {\n next += REGISTRY_CHECK_INTERVAL_MS;\n }\n nextRegistrySyncAt = next;\n }\n\n // An offline instance never contacts the registry, so an error (and the cached license that\n // came with it) stored by an earlier online run says nothing about its current state.\n const registryState = licenseMode === 'online' ? eeInformation : null;\n\n const data: GetLicenseLimitInformation.Response['data'] = {\n enforcementUserCount,\n currentActiveUserCount,\n // Typed `number` in the published contract; null at runtime without a seat limit\n permittedSeats: (permittedSeats ?? null) as number,\n seats: strapi.ee.seats ?? retained?.seats ?? null,\n subscriptionId: strapi.ee.subscriptionId ?? retained?.subscriptionId ?? null,\n expireAt: strapi.ee.expireAt ?? retained?.expireAt ?? null,\n licenseStatus: strapi.ee.licenseStatus,\n planPriceId: strapi.ee.planPriceId ?? retained?.planPriceId ?? null,\n renewalDate: strapi.ee.renewalDate,\n planEntitlements: strapi.ee.planFeatureCatalog.map((feature) => {\n if (isActiveLicense) {\n // Every resolver runs for an active license and falls back to its default for a\n // missing feature, so only an included feature keeps its limits.\n const available = strapi.ee.features.isEnabled(feature);\n return {\n feature,\n available,\n limits: available\n ? (activeEntitlements.find((entry) => entry.feature === feature)?.limits ?? [])\n : [],\n };\n }\n\n const retainedFeature = findRetainedFeature(retained?.features, feature);\n\n return {\n feature,\n available: Boolean(retainedFeature),\n limits: retainedFeature\n ? (retainedEntitlements.find((entry) => entry.feature === feature)?.limits ?? [])\n : [],\n };\n }),\n licenseMode,\n lastRegistrySyncAt,\n nextRegistrySyncAt,\n usingCachedLicense: Boolean(registryState?.error && registryState?.license),\n registrySyncError: registryState?.error ?? null,\n registrySyncErrorKind: registryState?.errorKind ?? null,\n shouldNotify,\n shouldStopCreate: permittedSeats == null ? false : currentActiveUserCount >= permittedSeats,\n licenseLimitStatus,\n isHostedOnStrapiCloud: env('STRAPI_HOSTING', null) === 'strapi.cloud',\n // Typed `string` in the published contract; null at runtime without a license\n type: licenseType as string,\n isTrial: strapi.ee.isTrial,\n // `features.list()` is loosely typed at the source (`{ name: string; [k]: any }[]`);\n // narrow it to the contract's named-feature union so consumers (e.g. useLicenseLimits) keep their types.\n features: (strapi.ee.features.list() ??\n []) as GetLicenseLimitInformation.Response['data']['features'],\n entitlements: strapi.ee.entitlements.list(),\n };\n\n return { data } satisfies GetLicenseLimitInformation.Response;\n },\n};\n"],"names":["findRetainedFeature","retainedFeatures","featureName","map","entry","name","find","getProjectType","flags","strapi","config","get","data","isEE","Boolean","EE","isTrial","ee","features","list","type","undefined","planPriceId","ai","enabled","admin","isStrapiManagedAiEnabled","licenseLimitInformation","permittedSeats","seats","retained","retainedLicense","isActiveLicense","licenseStatus","activeEntitlements","entitlements","retainedEntitlements","listRetained","shouldNotify","licenseLimitStatus","enforcementUserCount","currentActiveUserCount","getService","getCurrentActiveUserCount","eeDisabledUsers","getDisabledUserList","length","eeInformation","db","query","findOne","where","key","then","row","JSON","parse","value","catch","licenseType","licenseMode","process","env","STRAPI_DISABLE_LICENSE_PING","toLowerCase","REGISTRY_CHECK_INTERVAL_MS","lastRegistrySyncAt","lastCheckAt","nextRegistrySyncAt","now","Date","next","registryState","subscriptionId","expireAt","renewalDate","planEntitlements","planFeatureCatalog","feature","available","isEnabled","limits","retainedFeature","usingCachedLicense","error","license","registrySyncError","registrySyncErrorKind","errorKind","shouldStopCreate","isHostedOnStrapiCloud"],"mappings":";;;;;AAUA,MAAMA,mBAAAA,GAAsB,CAC1BC,gBAAAA,EACAC,WAAAA,GAEAD,gBAAAA,EACIE,IAAI,CAACC,KAAAA,GAAW,OAAOA,KAAAA,KAAU,QAAA,GAAW;YAAEC,IAAAA,EAAMD;AAAM,SAAA,GAAIA,OAC/DE,IAAAA,CAAK,CAACF,KAAAA,GAAUA,KAAAA,CAAMC,IAAI,KAAKH,WAAAA,CAAAA;AAEpC,YAAe;;IAEb,MAAMK,cAAAA,CAAAA,GAAAA;AACJ,QAAA,MAAMC,QAAQC,MAAAA,CAAOC,MAAM,CAACC,GAAG,CAAC,eAAe,EAAC,CAAA;QAEhD,IAAI;YACF,OAAO;gBACLC,IAAAA,EAAM;;oBAEJC,IAAAA,EAAMC,OAAAA,CAAQL,OAAOM,EAAE,CAAA;oBACvBC,OAAAA,EAASP,MAAAA,CAAOQ,EAAE,CAACD,OAAO;AAC1BE,oBAAAA,QAAAA,EAAUT,MAAAA,CAAOQ,EAAE,CAACC,QAAQ,CAACC,IAAI,EAAA;AACjCX,oBAAAA,KAAAA;AACAY,oBAAAA,IAAAA,EAAMX,MAAAA,CAAOQ,EAAE,CAACG,IAAI,IAAIC,SAAAA;AACxBC,oBAAAA,WAAAA,EAAab,MAAAA,CAAOQ,EAAE,CAACK,WAAW,IAAID,SAAAA;oBACtCE,EAAAA,EAAI;AACFC,wBAAAA,OAAAA,EAASf,MAAAA,CAAOc,EAAE,CAACE,KAAK,CAACC,wBAAwB;AACnD;AACF;AACF,aAAA;AACF,QAAA,CAAA,CAAE,OAAM;YACN,OAAO;gBAAEd,IAAAA,EAAM;oBAAEC,IAAAA,EAAM,KAAA;oBAAOG,OAAAA,EAAS,KAAA;AAAOE,oBAAAA,QAAAA,EAAU,EAAE;AAAEV,oBAAAA,KAAAA;oBAAOe,EAAAA,EAAI;wBAAEC,OAAAA,EAAS;AAAM;AAAE;AAAE,aAAA;AAC9F,QAAA;AACF,IAAA,CAAA;IAEA,MAAMG,uBAAAA,CAAAA,GAAAA;AACJ,QAAA,MAAMC,cAAAA,GAAiBnB,MAAAA,CAAOQ,EAAE,CAACY,KAAK;;;AAGtC,QAAA,MAAMC,QAAAA,GAAWrB,MAAAA,CAAOQ,EAAE,CAACc,eAAe;AAC1C,QAAA,MAAMC,eAAAA,GAAkBvB,MAAAA,CAAOQ,EAAE,CAACgB,aAAa,KAAK,QAAA;AACpD,QAAA,MAAMC,qBAAqBzB,MAAAA,CAAOQ,EAAE,CAACkB,YAAY,CAAChB,IAAI,EAAA;;;QAGtD,MAAMiB,oBAAAA,GAAuBJ,kBAAkB,EAAE,GAAGvB,OAAOQ,EAAE,CAACkB,YAAY,CAACE,YAAY,EAAA;AAEvF,QAAA,IAAIC,YAAAA,GAAe,KAAA;AACnB,QAAA,IAAIC,kBAAAA,GAAqB,IAAA;QACzB,IAAIC,oBAAAA;AAEJ,QAAA,MAAMC,sBAAAA,GAAyB,MAAMC,gBAAAA,CAAW,MAAA,CAAA,CAAQC,yBAAyB,EAAA;AAEjF,QAAA,MAAMC,eAAAA,GAAkB,MAAMF,gBAAAA,CAAW,kBAAA,CAAA,CAAoBG,mBAAmB,EAAA;AAEhF,QAAA,IAAID,eAAAA,EAAiB;YACnBJ,oBAAAA,GAAuBC,sBAAAA,GAAyBG,gBAAgBE,MAAM;QACxE,CAAA,MAAO;YACLN,oBAAAA,GAAuBC,sBAAAA;AACzB,QAAA;QAEA,IAAIb,cAAAA,IAAkB,IAAA,IAAQY,oBAAAA,GAAuBZ,cAAAA,EAAgB;YACnEU,YAAAA,GAAe,IAAA;YACfC,kBAAAA,GAAqB,YAAA;AACvB,QAAA;QAEA,IAAIX,cAAAA,IAAkB,IAAA,IAAQY,oBAAAA,KAAyBZ,cAAAA,EAAgB;YACrEU,YAAAA,GAAe,IAAA;YACfC,kBAAAA,GAAqB,UAAA;AACvB,QAAA;QAEA,MAAMQ,aAAAA,GAAgB,MAAMtC,MAAAA,CAAOuC,EAAE,CAClCC,KAAK,CAAC,oBAAA,CAAA,CACNC,OAAO,CAAC;YAAEC,KAAAA,EAAO;gBAAEC,GAAAA,EAAK;AAAiB;AAAE,SAAA,CAAA,CAC3CC,IAAI,CAAC,CAACC,GAAAA,GACLA,MACKC,IAAAA,CAAKC,KAAK,CAACF,GAAAA,CAAIG,KAAK,CAAA,GAMrB,IAAA,CAAA,CAELC,KAAK,CAAC,IAAM,IAAA,CAAA;;;;AAKf,QAAA,MAAMC,cAAclD,MAAAA,CAAOQ,EAAE,CAACG,IAAI,IAAIU,UAAUV,IAAAA,IAAQ,IAAA;QACxD,MAAMwC,WAAAA,GACJD,WAAAA,KAAgB,MAAA,IAAUE,OAAAA,CAAQC,GAAG,CAACC,2BAA2B,EAAEC,WAAAA,EAAAA,KAAkB,MAAA,GACjF,SAAA,GACA,QAAA;;QAGN,MAAMC,0BAAAA,GAA6B,EAAA,GAAK,EAAA,GAAK,EAAA,GAAK,IAAA;QAClD,MAAMC,kBAAAA,GAAoCnB,eAAeoB,WAAAA,IAAe,IAAA;AACxE,QAAA,IAAIC,kBAAAA,GAAoC,IAAA;AACxC,QAAA,IAAIR,WAAAA,KAAgB,QAAA,IAAY,OAAOM,kBAAAA,KAAuB,QAAA,EAAU;;;YAGtE,MAAMG,GAAAA,GAAMC,KAAKD,GAAG,EAAA;AACpB,YAAA,IAAIE,OAAOL,kBAAAA,GAAqBD,0BAAAA;AAChC,YAAA,MAAOM,QAAQF,GAAAA,CAAK;gBAClBE,IAAAA,IAAQN,0BAAAA;AACV,YAAA;YACAG,kBAAAA,GAAqBG,IAAAA;AACvB,QAAA;;;QAIA,MAAMC,aAAAA,GAAgBZ,WAAAA,KAAgB,QAAA,GAAWb,aAAAA,GAAgB,IAAA;AAEjE,QAAA,MAAMnC,IAAAA,GAAoD;AACxD4B,YAAAA,oBAAAA;AACAC,YAAAA,sBAAAA;;AAEAb,YAAAA,cAAAA,EAAiBA,cAAAA,IAAkB,IAAA;AACnCC,YAAAA,KAAAA,EAAOpB,OAAOQ,EAAE,CAACY,KAAK,IAAIC,UAAUD,KAAAA,IAAS,IAAA;AAC7C4C,YAAAA,cAAAA,EAAgBhE,OAAOQ,EAAE,CAACwD,cAAc,IAAI3C,UAAU2C,cAAAA,IAAkB,IAAA;AACxEC,YAAAA,QAAAA,EAAUjE,OAAOQ,EAAE,CAACyD,QAAQ,IAAI5C,UAAU4C,QAAAA,IAAY,IAAA;YACtDzC,aAAAA,EAAexB,MAAAA,CAAOQ,EAAE,CAACgB,aAAa;AACtCX,YAAAA,WAAAA,EAAab,OAAOQ,EAAE,CAACK,WAAW,IAAIQ,UAAUR,WAAAA,IAAe,IAAA;YAC/DqD,WAAAA,EAAalE,MAAAA,CAAOQ,EAAE,CAAC0D,WAAW;AAClCC,YAAAA,gBAAAA,EAAkBnE,OAAOQ,EAAE,CAAC4D,kBAAkB,CAAC1E,GAAG,CAAC,CAAC2E,OAAAA,GAAAA;AAClD,gBAAA,IAAI9C,eAAAA,EAAiB;;;AAGnB,oBAAA,MAAM+C,YAAYtE,MAAAA,CAAOQ,EAAE,CAACC,QAAQ,CAAC8D,SAAS,CAACF,OAAAA,CAAAA;oBAC/C,OAAO;AACLA,wBAAAA,OAAAA;AACAC,wBAAAA,SAAAA;AACAE,wBAAAA,MAAAA,EAAQF,SAAAA,GACH7C,kBAAAA,CAAmB5B,IAAI,CAAC,CAACF,KAAAA,GAAUA,KAAAA,CAAM0E,OAAO,KAAKA,OAAAA,CAAAA,EAAUG,MAAAA,IAAU,EAAE,GAC5E;AACN,qBAAA;AACF,gBAAA;gBAEA,MAAMC,eAAAA,GAAkBlF,mBAAAA,CAAoB8B,QAAAA,EAAUZ,QAAAA,EAAU4D,OAAAA,CAAAA;gBAEhE,OAAO;AACLA,oBAAAA,OAAAA;AACAC,oBAAAA,SAAAA,EAAWjE,OAAAA,CAAQoE,eAAAA,CAAAA;AACnBD,oBAAAA,MAAAA,EAAQC,eAAAA,GACH9C,oBAAAA,CAAqB9B,IAAI,CAAC,CAACF,KAAAA,GAAUA,KAAAA,CAAM0E,OAAO,KAAKA,OAAAA,CAAAA,EAAUG,MAAAA,IAAU,EAAE,GAC9E;AACN,iBAAA;AACF,YAAA,CAAA,CAAA;AACArB,YAAAA,WAAAA;AACAM,YAAAA,kBAAAA;AACAE,YAAAA,kBAAAA;YACAe,kBAAAA,EAAoBrE,OAAAA,CAAQ0D,aAAAA,EAAeY,KAAAA,IAASZ,aAAAA,EAAea,OAAAA,CAAAA;AACnEC,YAAAA,iBAAAA,EAAmBd,eAAeY,KAAAA,IAAS,IAAA;AAC3CG,YAAAA,qBAAAA,EAAuBf,eAAegB,SAAAA,IAAa,IAAA;AACnDlD,YAAAA,YAAAA;YACAmD,gBAAAA,EAAkB7D,cAAAA,IAAkB,IAAA,GAAO,KAAA,GAAQa,sBAAAA,IAA0Bb,cAAAA;AAC7EW,YAAAA,kBAAAA;YACAmD,qBAAAA,EAAuB5B,SAAAA,CAAI,kBAAkB,IAAA,CAAA,KAAU,cAAA;;YAEvD1C,IAAAA,EAAMuC,WAAAA;YACN3C,OAAAA,EAASP,MAAAA,CAAOQ,EAAE,CAACD,OAAO;;;AAG1BE,YAAAA,QAAAA,EAAWT,OAAOQ,EAAE,CAACC,QAAQ,CAACC,IAAI,MAChC,EAAE;AACJgB,YAAAA,YAAAA,EAAc1B,MAAAA,CAAOQ,EAAE,CAACkB,YAAY,CAAChB,IAAI;AAC3C,SAAA;QAEA,OAAO;AAAEP,YAAAA;AAAK,SAAA;AAChB,IAAA;AACF,CAAA;;;;"}