@strapi/admin 5.54.0 → 5.55.1

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 (92) hide show
  1. package/dist/admin/admin/src/components/LanguageProvider.js +35 -1
  2. package/dist/admin/admin/src/components/LanguageProvider.js.map +1 -1
  3. package/dist/admin/admin/src/components/LanguageProvider.mjs +17 -2
  4. package/dist/admin/admin/src/components/LanguageProvider.mjs.map +1 -1
  5. package/dist/admin/admin/src/components/SubNav.js +113 -35
  6. package/dist/admin/admin/src/components/SubNav.js.map +1 -1
  7. package/dist/admin/admin/src/components/SubNav.mjs +115 -37
  8. package/dist/admin/admin/src/components/SubNav.mjs.map +1 -1
  9. package/dist/admin/admin/src/components/SubNavFolder.js +188 -0
  10. package/dist/admin/admin/src/components/SubNavFolder.js.map +1 -0
  11. package/dist/admin/admin/src/components/SubNavFolder.mjs +186 -0
  12. package/dist/admin/admin/src/components/SubNavFolder.mjs.map +1 -0
  13. package/dist/admin/admin/src/features/Tracking.js.map +1 -1
  14. package/dist/admin/admin/src/features/Tracking.mjs.map +1 -1
  15. package/dist/admin/admin/src/render.js +1 -1
  16. package/dist/admin/admin/src/render.js.map +1 -1
  17. package/dist/admin/admin/src/render.mjs +1 -1
  18. package/dist/admin/admin/src/render.mjs.map +1 -1
  19. package/dist/admin/admin/src/translations/en.json.js +4 -0
  20. package/dist/admin/admin/src/translations/en.json.js.map +1 -1
  21. package/dist/admin/admin/src/translations/en.json.mjs +4 -0
  22. package/dist/admin/admin/src/translations/en.json.mjs.map +1 -1
  23. package/dist/admin/ee/admin/src/hooks/useAIAvailability.js +1 -6
  24. package/dist/admin/ee/admin/src/hooks/useAIAvailability.js.map +1 -1
  25. package/dist/admin/ee/admin/src/hooks/useAIAvailability.mjs +1 -6
  26. package/dist/admin/ee/admin/src/hooks/useAIAvailability.mjs.map +1 -1
  27. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/ApplicationInfoPage/components/AIUsage.js +7 -1
  28. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/ApplicationInfoPage/components/AIUsage.js.map +1 -1
  29. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/ApplicationInfoPage/components/AIUsage.mjs +7 -1
  30. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/ApplicationInfoPage/components/AIUsage.mjs.map +1 -1
  31. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/utils/getActionTypesDefaultMessages.js +5 -1
  32. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/utils/getActionTypesDefaultMessages.js.map +1 -1
  33. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/utils/getActionTypesDefaultMessages.mjs +5 -1
  34. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/utils/getActionTypesDefaultMessages.mjs.map +1 -1
  35. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/SingleSignOnPage.js +0 -4
  36. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/SingleSignOnPage.js.map +1 -1
  37. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/SingleSignOnPage.mjs +0 -4
  38. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/SingleSignOnPage.mjs.map +1 -1
  39. package/dist/admin/src/components/SubNav.d.ts +27 -8
  40. package/dist/admin/src/components/SubNavFolder.d.ts +15 -0
  41. package/dist/admin/src/features/Tracking.d.ts +2 -1
  42. package/dist/admin/src/services/admin.d.ts +1 -0
  43. package/dist/ee/admin/src/pages/SettingsPage/pages/AuditLogs/utils/getActionTypesDefaultMessages.d.ts +4 -0
  44. package/dist/ee/server/src/controllers/admin.d.ts.map +1 -1
  45. package/dist/ee/server/src/index.d.ts.map +1 -1
  46. package/dist/server/ee/server/src/controllers/admin.js +1 -5
  47. package/dist/server/ee/server/src/controllers/admin.js.map +1 -1
  48. package/dist/server/ee/server/src/controllers/admin.mjs +1 -5
  49. package/dist/server/ee/server/src/controllers/admin.mjs.map +1 -1
  50. package/dist/server/ee/server/src/index.js +2 -0
  51. package/dist/server/ee/server/src/index.js.map +1 -1
  52. package/dist/server/ee/server/src/index.mjs +2 -0
  53. package/dist/server/ee/server/src/index.mjs.map +1 -1
  54. package/dist/server/server/src/ai/controllers/ai.js +3 -3
  55. package/dist/server/server/src/ai/controllers/ai.js.map +1 -1
  56. package/dist/server/server/src/ai/controllers/ai.mjs +3 -3
  57. package/dist/server/server/src/ai/controllers/ai.mjs.map +1 -1
  58. package/dist/server/server/src/ai/services/ai.js +37 -12
  59. package/dist/server/server/src/ai/services/ai.js.map +1 -1
  60. package/dist/server/server/src/ai/services/ai.mjs +37 -12
  61. package/dist/server/server/src/ai/services/ai.mjs.map +1 -1
  62. package/dist/server/server/src/audit-logs/tokens.js +106 -0
  63. package/dist/server/server/src/audit-logs/tokens.js.map +1 -0
  64. package/dist/server/server/src/audit-logs/tokens.mjs +99 -0
  65. package/dist/server/server/src/audit-logs/tokens.mjs.map +1 -0
  66. package/dist/server/server/src/controllers/admin.js +10 -1
  67. package/dist/server/server/src/controllers/admin.js.map +1 -1
  68. package/dist/server/server/src/controllers/admin.mjs +10 -1
  69. package/dist/server/server/src/controllers/admin.mjs.map +1 -1
  70. package/dist/server/server/src/services/api-token.js +106 -4
  71. package/dist/server/server/src/services/api-token.js.map +1 -1
  72. package/dist/server/server/src/services/api-token.mjs +107 -5
  73. package/dist/server/server/src/services/api-token.mjs.map +1 -1
  74. package/dist/server/server/src/services/transfer/token.js +56 -4
  75. package/dist/server/server/src/services/transfer/token.js.map +1 -1
  76. package/dist/server/server/src/services/transfer/token.mjs +57 -5
  77. package/dist/server/server/src/services/transfer/token.mjs.map +1 -1
  78. package/dist/server/src/ai/services/ai.d.ts +3 -1
  79. package/dist/server/src/ai/services/ai.d.ts.map +1 -1
  80. package/dist/server/src/audit-logs/tokens.d.ts +86 -0
  81. package/dist/server/src/audit-logs/tokens.d.ts.map +1 -0
  82. package/dist/server/src/controllers/admin.d.ts +1 -0
  83. package/dist/server/src/controllers/admin.d.ts.map +1 -1
  84. package/dist/server/src/controllers/index.d.ts +1 -0
  85. package/dist/server/src/controllers/index.d.ts.map +1 -1
  86. package/dist/server/src/index.d.ts +1 -0
  87. package/dist/server/src/index.d.ts.map +1 -1
  88. package/dist/server/src/services/api-token.d.ts.map +1 -1
  89. package/dist/server/src/services/transfer/token.d.ts.map +1 -1
  90. package/dist/shared/contracts/admin.d.ts +1 -0
  91. package/dist/shared/contracts/admin.d.ts.map +1 -1
  92. package/package.json +7 -7
@@ -40,5 +40,9 @@ export declare const actionTypes: {
40
40
  'locale.update': string;
41
41
  'locale.delete': string;
42
42
  'locale.default.update': string;
43
+ 'token.create': string;
44
+ 'token.update': string;
45
+ 'token.delete': string;
46
+ 'token.regenerate': string;
43
47
  };
44
48
  export declare const getDefaultMessage: (value: keyof typeof actionTypes) => string;
@@ -1 +1 @@
1
- {"version":3,"file":"admin.d.ts","sourceRoot":"","sources":["../../../../../ee/server/src/controllers/admin.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAKA,wBAoEE"}
1
+ {"version":3,"file":"admin.d.ts","sourceRoot":"","sources":["../../../../../ee/server/src/controllers/admin.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAKA,wBAkEE"}
@@ -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;AAe1C,QAAA,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBA4Be;QAAE,MAAM,EAAE,IAAI,CAAC,MAAM,CAAA;KAAE;wBAsBxB;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;AAgB1C,QAAA,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBA4Be;QAAE,MAAM,EAAE,IAAI,CAAC,MAAM,CAAA;KAAE;wBAwBxB;QAAE,MAAM,EAAE,IAAI,CAAC,MAAM,CAAA;KAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAOpD,CAAC;AAEF,eAAe,UAAU,CAAC"}
@@ -8,10 +8,6 @@ var admin = {
8
8
  // NOTE: Overrides CE admin controller
9
9
  async getProjectType () {
10
10
  const flags = strapi.config.get('admin.flags', {});
11
- const isAILicense = strapi.ee.features.isEnabled('cms-ai');
12
- const isAIConfigured = strapi.config.get('admin.ai', {
13
- enabled: isAILicense
14
- });
15
11
  try {
16
12
  return {
17
13
  data: {
@@ -22,7 +18,7 @@ var admin = {
22
18
  type: strapi.ee.type,
23
19
  planPriceId: strapi.ee.planPriceId,
24
20
  ai: {
25
- enabled: isAILicense && isAIConfigured.enabled
21
+ enabled: strapi.ai.admin.isStrapiManagedAiEnabled()
26
22
  }
27
23
  }
28
24
  };
@@ -1 +1 @@
1
- {"version":3,"file":"admin.js","sources":["../../../../../../ee/server/src/controllers/admin.ts"],"sourcesContent":["import { isNil } from 'lodash/fp';\nimport { env } from '@strapi/utils';\n\nimport { getService } from '../utils';\n\nexport default {\n // NOTE: Overrides CE admin controller\n async getProjectType() {\n const flags = strapi.config.get('admin.flags', {});\n const isAILicense = strapi.ee.features.isEnabled('cms-ai');\n const isAIConfigured = strapi.config.get('admin.ai', { enabled: isAILicense });\n\n try {\n return {\n data: {\n isEE: strapi.EE,\n isTrial: strapi.ee.isTrial,\n features: strapi.ee.features.list(),\n flags,\n type: strapi.ee.type,\n planPriceId: strapi.ee.planPriceId,\n ai: {\n enabled: isAILicense && isAIConfigured.enabled,\n },\n },\n };\n } catch {\n return { data: { isEE: 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 (!isNil(permittedSeats) && enforcementUserCount > permittedSeats) {\n shouldNotify = true;\n licenseLimitStatus = 'OVER_LIMIT';\n }\n\n if (!isNil(permittedSeats) && enforcementUserCount === permittedSeats) {\n shouldNotify = true;\n licenseLimitStatus = 'AT_LIMIT';\n }\n\n const data = {\n enforcementUserCount,\n currentActiveUserCount,\n permittedSeats,\n shouldNotify,\n shouldStopCreate: isNil(permittedSeats) ? 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","isAILicense","ee","features","isEnabled","isAIConfigured","enabled","data","isEE","EE","isTrial","list","type","planPriceId","ai","licenseLimitInformation","permittedSeats","seats","shouldNotify","licenseLimitStatus","enforcementUserCount","currentActiveUserCount","getService","getCurrentActiveUserCount","eeDisabledUsers","getDisabledUserList","length","isNil","shouldStopCreate","isHostedOnStrapiCloud","env"],"mappings":"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"}
1
+ {"version":3,"file":"admin.js","sources":["../../../../../../ee/server/src/controllers/admin.ts"],"sourcesContent":["import { isNil } from 'lodash/fp';\nimport { env } from '@strapi/utils';\n\nimport { getService } from '../utils';\n\nexport default {\n // NOTE: Overrides CE admin controller\n async getProjectType() {\n const flags = strapi.config.get('admin.flags', {});\n\n try {\n return {\n data: {\n isEE: strapi.EE,\n isTrial: strapi.ee.isTrial,\n features: strapi.ee.features.list(),\n flags,\n type: strapi.ee.type,\n planPriceId: strapi.ee.planPriceId,\n ai: {\n enabled: strapi.ai.admin.isStrapiManagedAiEnabled(),\n },\n },\n };\n } catch {\n return { data: { isEE: 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 (!isNil(permittedSeats) && enforcementUserCount > permittedSeats) {\n shouldNotify = true;\n licenseLimitStatus = 'OVER_LIMIT';\n }\n\n if (!isNil(permittedSeats) && enforcementUserCount === permittedSeats) {\n shouldNotify = true;\n licenseLimitStatus = 'AT_LIMIT';\n }\n\n const data = {\n enforcementUserCount,\n currentActiveUserCount,\n permittedSeats,\n shouldNotify,\n shouldStopCreate: isNil(permittedSeats) ? 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","EE","isTrial","ee","features","list","type","planPriceId","ai","enabled","admin","isStrapiManagedAiEnabled","licenseLimitInformation","permittedSeats","seats","shouldNotify","licenseLimitStatus","enforcementUserCount","currentActiveUserCount","getService","getCurrentActiveUserCount","eeDisabledUsers","getDisabledUserList","length","isNil","shouldStopCreate","isHostedOnStrapiCloud","env"],"mappings":";;;;;;AAKA,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;AACJC,oBAAAA,IAAAA,EAAMJ,OAAOK,EAAE;oBACfC,OAAAA,EAASN,MAAAA,CAAOO,EAAE,CAACD,OAAO;AAC1BE,oBAAAA,QAAAA,EAAUR,MAAAA,CAAOO,EAAE,CAACC,QAAQ,CAACC,IAAI,EAAA;AACjCV,oBAAAA,KAAAA;oBACAW,IAAAA,EAAMV,MAAAA,CAAOO,EAAE,CAACG,IAAI;oBACpBC,WAAAA,EAAaX,MAAAA,CAAOO,EAAE,CAACI,WAAW;oBAClCC,EAAAA,EAAI;AACFC,wBAAAA,OAAAA,EAASb,MAAAA,CAAOY,EAAE,CAACE,KAAK,CAACC,wBAAwB;AACnD;AACF;AACF,aAAA;AACF,QAAA,CAAA,CAAE,OAAM;YACN,OAAO;gBAAEZ,IAAAA,EAAM;oBAAEC,IAAAA,EAAM,KAAA;AAAOI,oBAAAA,QAAAA,EAAU,EAAE;AAAET,oBAAAA,KAAAA;oBAAOa,EAAAA,EAAI;wBAAEC,OAAAA,EAAS;AAAM;AAAE;AAAE,aAAA;AAC9E,QAAA;AACF,IAAA,CAAA;IAEA,MAAMG,uBAAAA,CAAAA,GAAAA;AACJ,QAAA,MAAMC,cAAAA,GAAiBjB,MAAAA,CAAOO,EAAE,CAACW,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;AAEA,QAAA,IAAI,CAACM,QAAAA,CAAMX,cAAAA,CAAAA,IAAmBI,oBAAAA,GAAuBJ,cAAAA,EAAgB;YACnEE,YAAAA,GAAe,IAAA;YACfC,kBAAAA,GAAqB,YAAA;AACvB,QAAA;AAEA,QAAA,IAAI,CAACQ,QAAAA,CAAMX,cAAAA,CAAAA,IAAmBI,oBAAAA,KAAyBJ,cAAAA,EAAgB;YACrEE,YAAAA,GAAe,IAAA;YACfC,kBAAAA,GAAqB,UAAA;AACvB,QAAA;AAEA,QAAA,MAAMjB,IAAAA,GAAO;AACXkB,YAAAA,oBAAAA;AACAC,YAAAA,sBAAAA;AACAL,YAAAA,cAAAA;AACAE,YAAAA,YAAAA;YACAU,gBAAAA,EAAkBD,QAAAA,CAAMX,cAAAA,CAAAA,GAAkB,KAAA,GAAQK,sBAAAA,IAA0BL,cAAAA;AAC5EG,YAAAA,kBAAAA;YACAU,qBAAAA,EAAuBC,SAAAA,CAAI,kBAAkB,IAAA,CAAA,KAAU,cAAA;YACvDrB,IAAAA,EAAMV,MAAAA,CAAOO,EAAE,CAACG,IAAI;YACpBJ,OAAAA,EAASN,MAAAA,CAAOO,EAAE,CAACD,OAAO;AAC1BE,YAAAA,QAAAA,EAAUR,OAAOO,EAAE,CAACC,QAAQ,CAACC,IAAI,MAAM;AACzC,SAAA;QAEA,OAAO;AAAEN,YAAAA;AAAK,SAAA;AAChB,IAAA;AACF,CAAA;;;;"}
@@ -6,10 +6,6 @@ var admin = {
6
6
  // NOTE: Overrides CE admin controller
7
7
  async getProjectType () {
8
8
  const flags = strapi.config.get('admin.flags', {});
9
- const isAILicense = strapi.ee.features.isEnabled('cms-ai');
10
- const isAIConfigured = strapi.config.get('admin.ai', {
11
- enabled: isAILicense
12
- });
13
9
  try {
14
10
  return {
15
11
  data: {
@@ -20,7 +16,7 @@ var admin = {
20
16
  type: strapi.ee.type,
21
17
  planPriceId: strapi.ee.planPriceId,
22
18
  ai: {
23
- enabled: isAILicense && isAIConfigured.enabled
19
+ enabled: strapi.ai.admin.isStrapiManagedAiEnabled()
24
20
  }
25
21
  }
26
22
  };
@@ -1 +1 @@
1
- {"version":3,"file":"admin.mjs","sources":["../../../../../../ee/server/src/controllers/admin.ts"],"sourcesContent":["import { isNil } from 'lodash/fp';\nimport { env } from '@strapi/utils';\n\nimport { getService } from '../utils';\n\nexport default {\n // NOTE: Overrides CE admin controller\n async getProjectType() {\n const flags = strapi.config.get('admin.flags', {});\n const isAILicense = strapi.ee.features.isEnabled('cms-ai');\n const isAIConfigured = strapi.config.get('admin.ai', { enabled: isAILicense });\n\n try {\n return {\n data: {\n isEE: strapi.EE,\n isTrial: strapi.ee.isTrial,\n features: strapi.ee.features.list(),\n flags,\n type: strapi.ee.type,\n planPriceId: strapi.ee.planPriceId,\n ai: {\n enabled: isAILicense && isAIConfigured.enabled,\n },\n },\n };\n } catch {\n return { data: { isEE: 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 (!isNil(permittedSeats) && enforcementUserCount > permittedSeats) {\n shouldNotify = true;\n licenseLimitStatus = 'OVER_LIMIT';\n }\n\n if (!isNil(permittedSeats) && enforcementUserCount === permittedSeats) {\n shouldNotify = true;\n licenseLimitStatus = 'AT_LIMIT';\n }\n\n const data = {\n enforcementUserCount,\n currentActiveUserCount,\n permittedSeats,\n shouldNotify,\n shouldStopCreate: isNil(permittedSeats) ? 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","isAILicense","ee","features","isEnabled","isAIConfigured","enabled","data","isEE","EE","isTrial","list","type","planPriceId","ai","licenseLimitInformation","permittedSeats","seats","shouldNotify","licenseLimitStatus","enforcementUserCount","currentActiveUserCount","getService","getCurrentActiveUserCount","eeDisabledUsers","getDisabledUserList","length","isNil","shouldStopCreate","isHostedOnStrapiCloud","env"],"mappings":"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"}
1
+ {"version":3,"file":"admin.mjs","sources":["../../../../../../ee/server/src/controllers/admin.ts"],"sourcesContent":["import { isNil } from 'lodash/fp';\nimport { env } from '@strapi/utils';\n\nimport { getService } from '../utils';\n\nexport default {\n // NOTE: Overrides CE admin controller\n async getProjectType() {\n const flags = strapi.config.get('admin.flags', {});\n\n try {\n return {\n data: {\n isEE: strapi.EE,\n isTrial: strapi.ee.isTrial,\n features: strapi.ee.features.list(),\n flags,\n type: strapi.ee.type,\n planPriceId: strapi.ee.planPriceId,\n ai: {\n enabled: strapi.ai.admin.isStrapiManagedAiEnabled(),\n },\n },\n };\n } catch {\n return { data: { isEE: 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 (!isNil(permittedSeats) && enforcementUserCount > permittedSeats) {\n shouldNotify = true;\n licenseLimitStatus = 'OVER_LIMIT';\n }\n\n if (!isNil(permittedSeats) && enforcementUserCount === permittedSeats) {\n shouldNotify = true;\n licenseLimitStatus = 'AT_LIMIT';\n }\n\n const data = {\n enforcementUserCount,\n currentActiveUserCount,\n permittedSeats,\n shouldNotify,\n shouldStopCreate: isNil(permittedSeats) ? 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","EE","isTrial","ee","features","list","type","planPriceId","ai","enabled","admin","isStrapiManagedAiEnabled","licenseLimitInformation","permittedSeats","seats","shouldNotify","licenseLimitStatus","enforcementUserCount","currentActiveUserCount","getService","getCurrentActiveUserCount","eeDisabledUsers","getDisabledUserList","length","isNil","shouldStopCreate","isHostedOnStrapiCloud","env"],"mappings":";;;;AAKA,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;AACJC,oBAAAA,IAAAA,EAAMJ,OAAOK,EAAE;oBACfC,OAAAA,EAASN,MAAAA,CAAOO,EAAE,CAACD,OAAO;AAC1BE,oBAAAA,QAAAA,EAAUR,MAAAA,CAAOO,EAAE,CAACC,QAAQ,CAACC,IAAI,EAAA;AACjCV,oBAAAA,KAAAA;oBACAW,IAAAA,EAAMV,MAAAA,CAAOO,EAAE,CAACG,IAAI;oBACpBC,WAAAA,EAAaX,MAAAA,CAAOO,EAAE,CAACI,WAAW;oBAClCC,EAAAA,EAAI;AACFC,wBAAAA,OAAAA,EAASb,MAAAA,CAAOY,EAAE,CAACE,KAAK,CAACC,wBAAwB;AACnD;AACF;AACF,aAAA;AACF,QAAA,CAAA,CAAE,OAAM;YACN,OAAO;gBAAEZ,IAAAA,EAAM;oBAAEC,IAAAA,EAAM,KAAA;AAAOI,oBAAAA,QAAAA,EAAU,EAAE;AAAET,oBAAAA,KAAAA;oBAAOa,EAAAA,EAAI;wBAAEC,OAAAA,EAAS;AAAM;AAAE;AAAE,aAAA;AAC9E,QAAA;AACF,IAAA,CAAA;IAEA,MAAMG,uBAAAA,CAAAA,GAAAA;AACJ,QAAA,MAAMC,cAAAA,GAAiBjB,MAAAA,CAAOO,EAAE,CAACW,KAAK;AAEtC,QAAA,IAAIC,YAAAA,GAAe,KAAA;AACnB,QAAA,IAAIC,kBAAAA,GAAqB,IAAA;QACzB,IAAIC,oBAAAA;AAEJ,QAAA,MAAMC,sBAAAA,GAAyB,MAAMC,UAAAA,CAAW,MAAA,CAAA,CAAQC,yBAAyB,EAAA;AAEjF,QAAA,MAAMC,eAAAA,GAAkB,MAAMF,UAAAA,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;AAEA,QAAA,IAAI,CAACM,KAAAA,CAAMX,cAAAA,CAAAA,IAAmBI,oBAAAA,GAAuBJ,cAAAA,EAAgB;YACnEE,YAAAA,GAAe,IAAA;YACfC,kBAAAA,GAAqB,YAAA;AACvB,QAAA;AAEA,QAAA,IAAI,CAACQ,KAAAA,CAAMX,cAAAA,CAAAA,IAAmBI,oBAAAA,KAAyBJ,cAAAA,EAAgB;YACrEE,YAAAA,GAAe,IAAA;YACfC,kBAAAA,GAAqB,UAAA;AACvB,QAAA;AAEA,QAAA,MAAMjB,IAAAA,GAAO;AACXkB,YAAAA,oBAAAA;AACAC,YAAAA,sBAAAA;AACAL,YAAAA,cAAAA;AACAE,YAAAA,YAAAA;YACAU,gBAAAA,EAAkBD,KAAAA,CAAMX,cAAAA,CAAAA,GAAkB,KAAA,GAAQK,sBAAAA,IAA0BL,cAAAA;AAC5EG,YAAAA,kBAAAA;YACAU,qBAAAA,EAAuBC,GAAAA,CAAI,kBAAkB,IAAA,CAAA,KAAU,cAAA;YACvDrB,IAAAA,EAAMV,MAAAA,CAAOO,EAAE,CAACG,IAAI;YACpBJ,OAAAA,EAASN,MAAAA,CAAOO,EAAE,CAACD,OAAO;AAC1BE,YAAAA,QAAAA,EAAUR,OAAOO,EAAE,CAACC,QAAQ,CAACC,IAAI,MAAM;AACzC,SAAA;QAEA,OAAO;AAAEN,YAAAA;AAAK,SAAA;AAChB,IAAA;AACF,CAAA;;;;"}
@@ -13,6 +13,7 @@ var auditLogs$2 = require('./audit-logs/services/audit-logs.js');
13
13
  var lifecycles = require('./audit-logs/services/lifecycles.js');
14
14
  var auditLog = require('./audit-logs/content-types/audit-log.js');
15
15
  var auditLogExport = require('../../../shared/utils/audit-log-export.js');
16
+ var tokens = require('../../../server/src/audit-logs/tokens.js');
16
17
 
17
18
  const getAdminEE = ()=>{
18
19
  const eeAdmin = {
@@ -63,6 +64,7 @@ const getAdminEE = ()=>{
63
64
  filters: event?.filters ?? null
64
65
  }
65
66
  }));
67
+ tokens.registerTokenAuditEvents(auditLogsLifecycle);
66
68
  await auditLogsLifecycle.register();
67
69
  }
68
70
  },
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../../../../ee/server/src/index.ts"],"sourcesContent":["import type { Core } from '@strapi/types';\nimport register from './register';\nimport bootstrap from './bootstrap';\nimport destroy from './destroy';\nimport adminContentTypes from './content-types';\nimport services from './services';\nimport controllers from './controllers';\nimport routes from './routes';\nimport auditLogsRoutes from './audit-logs/routes/audit-logs';\nimport auditLogsController from './audit-logs/controllers/audit-logs';\nimport { createAuditLogsService } from './audit-logs/services/audit-logs';\nimport { createAuditLogsLifecycleService } from './audit-logs/services/lifecycles';\nimport { auditLog } from './audit-logs/content-types/audit-log';\nimport { AUDIT_LOG_EXPORT_EVENT } from '../../../shared/utils/audit-log-export';\n\nconst getAdminEE = () => {\n const eeAdmin = {\n register,\n bootstrap,\n destroy,\n contentTypes: {\n // Always register the audit-log content type to prevent data loss\n 'audit-log': auditLog,\n ...adminContentTypes,\n },\n services,\n controllers,\n routes,\n };\n\n const isAuditLogsEnabled =\n strapi.config.get('admin.auditLogs.enabled', true) &&\n strapi.ee.features.isEnabled('audit-logs');\n return {\n ...eeAdmin,\n controllers: {\n ...eeAdmin.controllers,\n ...(isAuditLogsEnabled ? { 'audit-logs': auditLogsController } : {}),\n },\n routes: {\n ...eeAdmin.routes,\n ...(isAuditLogsEnabled ? { 'audit-logs': auditLogsRoutes } : {}),\n },\n async register({ strapi }: { strapi: Core.Strapi }) {\n // Run the default registration\n await eeAdmin.register({ strapi });\n\n if (isAuditLogsEnabled) {\n // Register an internal audit logs service\n strapi.add('audit-logs', createAuditLogsService(strapi));\n // Register an internal audit logs lifecycle service\n const auditLogsLifecycle = createAuditLogsLifecycleService(strapi);\n strapi.add('audit-logs-lifecycle', auditLogsLifecycle);\n\n auditLogsLifecycle.registerEvent(\n AUDIT_LOG_EXPORT_EVENT,\n (event: { filters?: unknown }) => ({\n resource: { type: 'audit-log' },\n details: { format: 'csv', filters: event?.filters ?? null },\n })\n );\n\n await auditLogsLifecycle.register();\n }\n },\n async destroy({ strapi }: { strapi: Core.Strapi }) {\n if (isAuditLogsEnabled) {\n strapi.get('audit-logs-lifecycle').destroy();\n }\n await eeAdmin.destroy();\n },\n };\n};\n\nexport default getAdminEE;\n"],"names":["getAdminEE","eeAdmin","register","bootstrap","destroy","contentTypes","auditLog","adminContentTypes","services","controllers","routes","isAuditLogsEnabled","strapi","config","get","ee","features","isEnabled","auditLogsController","auditLogsRoutes","add","createAuditLogsService","auditLogsLifecycle","createAuditLogsLifecycleService","registerEvent","AUDIT_LOG_EXPORT_EVENT","event","resource","type","details","format","filters"],"mappings":";;;;;;;;;;;;;;;;AAeA,MAAMA,UAAAA,GAAa,IAAA;AACjB,IAAA,MAAMC,OAAAA,GAAU;AACdC,QAAAA,QAAAA;AACAC,QAAAA,SAAAA;AACAC,QAAAA,OAAAA;QACAC,YAAAA,EAAc;;YAEZ,WAAA,EAAaC,iBAAAA;AACb,YAAA,GAAGC;AACL,SAAA;AACAC,kBAAAA,OAAAA;AACAC,qBAAAA,OAAAA;AACAC,gBAAAA;AACF,KAAA;AAEA,IAAA,MAAMC,kBAAAA,GACJC,MAAAA,CAAOC,MAAM,CAACC,GAAG,CAAC,yBAAA,EAA2B,IAAA,CAAA,IAC7CF,MAAAA,CAAOG,EAAE,CAACC,QAAQ,CAACC,SAAS,CAAC,YAAA,CAAA;IAC/B,OAAO;AACL,QAAA,GAAGhB,OAAO;QACVQ,WAAAA,EAAa;AACX,YAAA,GAAGR,QAAQQ,WAAW;AACtB,YAAA,GAAIE,kBAAAA,GAAqB;gBAAE,YAAA,EAAcO;AAAoB,aAAA,GAAI;AACnE,SAAA;QACAR,MAAAA,EAAQ;AACN,YAAA,GAAGT,QAAQS,MAAM;AACjB,YAAA,GAAIC,kBAAAA,GAAqB;gBAAE,YAAA,EAAcQ;AAAgB,aAAA,GAAI;AAC/D,SAAA;AACA,QAAA,MAAMjB,QAAAA,CAAAA,CAAS,EAAEU,MAAAA,EAAAA,OAAM,EAA2B,EAAA;;YAEhD,MAAMX,OAAAA,CAAQC,QAAQ,CAAC;gBAAEU,MAAAA,EAAAA;AAAO,aAAA,CAAA;AAEhC,YAAA,IAAID,kBAAAA,EAAoB;;gBAEtBC,OAAAA,CAAOQ,GAAG,CAAC,YAAA,EAAcC,kCAAAA,CAAuBT,OAAAA,CAAAA,CAAAA;;AAEhD,gBAAA,MAAMU,qBAAqBC,0CAAAA,CAAgCX,OAAAA,CAAAA;gBAC3DA,OAAAA,CAAOQ,GAAG,CAAC,sBAAA,EAAwBE,kBAAAA,CAAAA;AAEnCA,gBAAAA,kBAAAA,CAAmBE,aAAa,CAC9BC,qCAAAA,EACA,CAACC,SAAkC;wBACjCC,QAAAA,EAAU;4BAAEC,IAAAA,EAAM;AAAY,yBAAA;wBAC9BC,OAAAA,EAAS;4BAAEC,MAAAA,EAAQ,KAAA;AAAOC,4BAAAA,OAAAA,EAASL,OAAOK,OAAAA,IAAW;AAAK;qBAC5D,CAAA,CAAA;AAGF,gBAAA,MAAMT,mBAAmBpB,QAAQ,EAAA;AACnC,YAAA;AACF,QAAA,CAAA;AACA,QAAA,MAAME,OAAAA,CAAAA,CAAQ,EAAEQ,MAAAA,EAAAA,OAAM,EAA2B,EAAA;AAC/C,YAAA,IAAID,kBAAAA,EAAoB;gBACtBC,OAAAA,CAAOE,GAAG,CAAC,sBAAA,CAAA,CAAwBV,OAAO,EAAA;AAC5C,YAAA;AACA,YAAA,MAAMH,QAAQG,OAAO,EAAA;AACvB,QAAA;AACF,KAAA;AACF;;;;"}
1
+ {"version":3,"file":"index.js","sources":["../../../../../ee/server/src/index.ts"],"sourcesContent":["import type { Core } from '@strapi/types';\nimport register from './register';\nimport bootstrap from './bootstrap';\nimport destroy from './destroy';\nimport adminContentTypes from './content-types';\nimport services from './services';\nimport controllers from './controllers';\nimport routes from './routes';\nimport auditLogsRoutes from './audit-logs/routes/audit-logs';\nimport auditLogsController from './audit-logs/controllers/audit-logs';\nimport { createAuditLogsService } from './audit-logs/services/audit-logs';\nimport { createAuditLogsLifecycleService } from './audit-logs/services/lifecycles';\nimport { auditLog } from './audit-logs/content-types/audit-log';\nimport { AUDIT_LOG_EXPORT_EVENT } from '../../../shared/utils/audit-log-export';\nimport { registerTokenAuditEvents } from '../../../server/src/audit-logs/tokens';\n\nconst getAdminEE = () => {\n const eeAdmin = {\n register,\n bootstrap,\n destroy,\n contentTypes: {\n // Always register the audit-log content type to prevent data loss\n 'audit-log': auditLog,\n ...adminContentTypes,\n },\n services,\n controllers,\n routes,\n };\n\n const isAuditLogsEnabled =\n strapi.config.get('admin.auditLogs.enabled', true) &&\n strapi.ee.features.isEnabled('audit-logs');\n return {\n ...eeAdmin,\n controllers: {\n ...eeAdmin.controllers,\n ...(isAuditLogsEnabled ? { 'audit-logs': auditLogsController } : {}),\n },\n routes: {\n ...eeAdmin.routes,\n ...(isAuditLogsEnabled ? { 'audit-logs': auditLogsRoutes } : {}),\n },\n async register({ strapi }: { strapi: Core.Strapi }) {\n // Run the default registration\n await eeAdmin.register({ strapi });\n\n if (isAuditLogsEnabled) {\n // Register an internal audit logs service\n strapi.add('audit-logs', createAuditLogsService(strapi));\n // Register an internal audit logs lifecycle service\n const auditLogsLifecycle = createAuditLogsLifecycleService(strapi);\n strapi.add('audit-logs-lifecycle', auditLogsLifecycle);\n\n auditLogsLifecycle.registerEvent(\n AUDIT_LOG_EXPORT_EVENT,\n (event: { filters?: unknown }) => ({\n resource: { type: 'audit-log' },\n details: { format: 'csv', filters: event?.filters ?? null },\n })\n );\n\n registerTokenAuditEvents(auditLogsLifecycle);\n\n await auditLogsLifecycle.register();\n }\n },\n async destroy({ strapi }: { strapi: Core.Strapi }) {\n if (isAuditLogsEnabled) {\n strapi.get('audit-logs-lifecycle').destroy();\n }\n await eeAdmin.destroy();\n },\n };\n};\n\nexport default getAdminEE;\n"],"names":["getAdminEE","eeAdmin","register","bootstrap","destroy","contentTypes","auditLog","adminContentTypes","services","controllers","routes","isAuditLogsEnabled","strapi","config","get","ee","features","isEnabled","auditLogsController","auditLogsRoutes","add","createAuditLogsService","auditLogsLifecycle","createAuditLogsLifecycleService","registerEvent","AUDIT_LOG_EXPORT_EVENT","event","resource","type","details","format","filters","registerTokenAuditEvents"],"mappings":";;;;;;;;;;;;;;;;;AAgBA,MAAMA,UAAAA,GAAa,IAAA;AACjB,IAAA,MAAMC,OAAAA,GAAU;AACdC,QAAAA,QAAAA;AACAC,QAAAA,SAAAA;AACAC,QAAAA,OAAAA;QACAC,YAAAA,EAAc;;YAEZ,WAAA,EAAaC,iBAAAA;AACb,YAAA,GAAGC;AACL,SAAA;AACAC,kBAAAA,OAAAA;AACAC,qBAAAA,OAAAA;AACAC,gBAAAA;AACF,KAAA;AAEA,IAAA,MAAMC,kBAAAA,GACJC,MAAAA,CAAOC,MAAM,CAACC,GAAG,CAAC,yBAAA,EAA2B,IAAA,CAAA,IAC7CF,MAAAA,CAAOG,EAAE,CAACC,QAAQ,CAACC,SAAS,CAAC,YAAA,CAAA;IAC/B,OAAO;AACL,QAAA,GAAGhB,OAAO;QACVQ,WAAAA,EAAa;AACX,YAAA,GAAGR,QAAQQ,WAAW;AACtB,YAAA,GAAIE,kBAAAA,GAAqB;gBAAE,YAAA,EAAcO;AAAoB,aAAA,GAAI;AACnE,SAAA;QACAR,MAAAA,EAAQ;AACN,YAAA,GAAGT,QAAQS,MAAM;AACjB,YAAA,GAAIC,kBAAAA,GAAqB;gBAAE,YAAA,EAAcQ;AAAgB,aAAA,GAAI;AAC/D,SAAA;AACA,QAAA,MAAMjB,QAAAA,CAAAA,CAAS,EAAEU,MAAAA,EAAAA,OAAM,EAA2B,EAAA;;YAEhD,MAAMX,OAAAA,CAAQC,QAAQ,CAAC;gBAAEU,MAAAA,EAAAA;AAAO,aAAA,CAAA;AAEhC,YAAA,IAAID,kBAAAA,EAAoB;;gBAEtBC,OAAAA,CAAOQ,GAAG,CAAC,YAAA,EAAcC,kCAAAA,CAAuBT,OAAAA,CAAAA,CAAAA;;AAEhD,gBAAA,MAAMU,qBAAqBC,0CAAAA,CAAgCX,OAAAA,CAAAA;gBAC3DA,OAAAA,CAAOQ,GAAG,CAAC,sBAAA,EAAwBE,kBAAAA,CAAAA;AAEnCA,gBAAAA,kBAAAA,CAAmBE,aAAa,CAC9BC,qCAAAA,EACA,CAACC,SAAkC;wBACjCC,QAAAA,EAAU;4BAAEC,IAAAA,EAAM;AAAY,yBAAA;wBAC9BC,OAAAA,EAAS;4BAAEC,MAAAA,EAAQ,KAAA;AAAOC,4BAAAA,OAAAA,EAASL,OAAOK,OAAAA,IAAW;AAAK;qBAC5D,CAAA,CAAA;gBAGFC,+BAAAA,CAAyBV,kBAAAA,CAAAA;AAEzB,gBAAA,MAAMA,mBAAmBpB,QAAQ,EAAA;AACnC,YAAA;AACF,QAAA,CAAA;AACA,QAAA,MAAME,OAAAA,CAAAA,CAAQ,EAAEQ,MAAAA,EAAAA,OAAM,EAA2B,EAAA;AAC/C,YAAA,IAAID,kBAAAA,EAAoB;gBACtBC,OAAAA,CAAOE,GAAG,CAAC,sBAAA,CAAA,CAAwBV,OAAO,EAAA;AAC5C,YAAA;AACA,YAAA,MAAMH,QAAQG,OAAO,EAAA;AACvB,QAAA;AACF,KAAA;AACF;;;;"}
@@ -11,6 +11,7 @@ import { createAuditLogsService } from './audit-logs/services/audit-logs.mjs';
11
11
  import { createAuditLogsLifecycleService } from './audit-logs/services/lifecycles.mjs';
12
12
  import { auditLog } from './audit-logs/content-types/audit-log.mjs';
13
13
  import { AUDIT_LOG_EXPORT_EVENT } from '../../../shared/utils/audit-log-export.mjs';
14
+ import { registerTokenAuditEvents } from '../../../server/src/audit-logs/tokens.mjs';
14
15
 
15
16
  const getAdminEE = ()=>{
16
17
  const eeAdmin = {
@@ -61,6 +62,7 @@ const getAdminEE = ()=>{
61
62
  filters: event?.filters ?? null
62
63
  }
63
64
  }));
65
+ registerTokenAuditEvents(auditLogsLifecycle);
64
66
  await auditLogsLifecycle.register();
65
67
  }
66
68
  },
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sources":["../../../../../ee/server/src/index.ts"],"sourcesContent":["import type { Core } from '@strapi/types';\nimport register from './register';\nimport bootstrap from './bootstrap';\nimport destroy from './destroy';\nimport adminContentTypes from './content-types';\nimport services from './services';\nimport controllers from './controllers';\nimport routes from './routes';\nimport auditLogsRoutes from './audit-logs/routes/audit-logs';\nimport auditLogsController from './audit-logs/controllers/audit-logs';\nimport { createAuditLogsService } from './audit-logs/services/audit-logs';\nimport { createAuditLogsLifecycleService } from './audit-logs/services/lifecycles';\nimport { auditLog } from './audit-logs/content-types/audit-log';\nimport { AUDIT_LOG_EXPORT_EVENT } from '../../../shared/utils/audit-log-export';\n\nconst getAdminEE = () => {\n const eeAdmin = {\n register,\n bootstrap,\n destroy,\n contentTypes: {\n // Always register the audit-log content type to prevent data loss\n 'audit-log': auditLog,\n ...adminContentTypes,\n },\n services,\n controllers,\n routes,\n };\n\n const isAuditLogsEnabled =\n strapi.config.get('admin.auditLogs.enabled', true) &&\n strapi.ee.features.isEnabled('audit-logs');\n return {\n ...eeAdmin,\n controllers: {\n ...eeAdmin.controllers,\n ...(isAuditLogsEnabled ? { 'audit-logs': auditLogsController } : {}),\n },\n routes: {\n ...eeAdmin.routes,\n ...(isAuditLogsEnabled ? { 'audit-logs': auditLogsRoutes } : {}),\n },\n async register({ strapi }: { strapi: Core.Strapi }) {\n // Run the default registration\n await eeAdmin.register({ strapi });\n\n if (isAuditLogsEnabled) {\n // Register an internal audit logs service\n strapi.add('audit-logs', createAuditLogsService(strapi));\n // Register an internal audit logs lifecycle service\n const auditLogsLifecycle = createAuditLogsLifecycleService(strapi);\n strapi.add('audit-logs-lifecycle', auditLogsLifecycle);\n\n auditLogsLifecycle.registerEvent(\n AUDIT_LOG_EXPORT_EVENT,\n (event: { filters?: unknown }) => ({\n resource: { type: 'audit-log' },\n details: { format: 'csv', filters: event?.filters ?? null },\n })\n );\n\n await auditLogsLifecycle.register();\n }\n },\n async destroy({ strapi }: { strapi: Core.Strapi }) {\n if (isAuditLogsEnabled) {\n strapi.get('audit-logs-lifecycle').destroy();\n }\n await eeAdmin.destroy();\n },\n };\n};\n\nexport default getAdminEE;\n"],"names":["getAdminEE","eeAdmin","register","bootstrap","destroy","contentTypes","auditLog","adminContentTypes","services","controllers","routes","isAuditLogsEnabled","strapi","config","get","ee","features","isEnabled","auditLogsController","auditLogsRoutes","add","createAuditLogsService","auditLogsLifecycle","createAuditLogsLifecycleService","registerEvent","AUDIT_LOG_EXPORT_EVENT","event","resource","type","details","format","filters"],"mappings":";;;;;;;;;;;;;;AAeA,MAAMA,UAAAA,GAAa,IAAA;AACjB,IAAA,MAAMC,OAAAA,GAAU;AACdC,QAAAA,QAAAA;AACAC,QAAAA,SAAAA;AACAC,QAAAA,OAAAA;QACAC,YAAAA,EAAc;;YAEZ,WAAA,EAAaC,QAAAA;AACb,YAAA,GAAGC;AACL,SAAA;AACAC,QAAAA,QAAAA;AACAC,QAAAA,WAAAA;AACAC,QAAAA;AACF,KAAA;AAEA,IAAA,MAAMC,kBAAAA,GACJC,MAAAA,CAAOC,MAAM,CAACC,GAAG,CAAC,yBAAA,EAA2B,IAAA,CAAA,IAC7CF,MAAAA,CAAOG,EAAE,CAACC,QAAQ,CAACC,SAAS,CAAC,YAAA,CAAA;IAC/B,OAAO;AACL,QAAA,GAAGhB,OAAO;QACVQ,WAAAA,EAAa;AACX,YAAA,GAAGR,QAAQQ,WAAW;AACtB,YAAA,GAAIE,kBAAAA,GAAqB;gBAAE,YAAA,EAAcO;AAAoB,aAAA,GAAI;AACnE,SAAA;QACAR,MAAAA,EAAQ;AACN,YAAA,GAAGT,QAAQS,MAAM;AACjB,YAAA,GAAIC,kBAAAA,GAAqB;gBAAE,YAAA,EAAcQ;AAAgB,aAAA,GAAI;AAC/D,SAAA;AACA,QAAA,MAAMjB,QAAAA,CAAAA,CAAS,EAAEU,MAAAA,EAAAA,OAAM,EAA2B,EAAA;;YAEhD,MAAMX,OAAAA,CAAQC,QAAQ,CAAC;gBAAEU,MAAAA,EAAAA;AAAO,aAAA,CAAA;AAEhC,YAAA,IAAID,kBAAAA,EAAoB;;gBAEtBC,OAAAA,CAAOQ,GAAG,CAAC,YAAA,EAAcC,sBAAAA,CAAuBT,OAAAA,CAAAA,CAAAA;;AAEhD,gBAAA,MAAMU,qBAAqBC,+BAAAA,CAAgCX,OAAAA,CAAAA;gBAC3DA,OAAAA,CAAOQ,GAAG,CAAC,sBAAA,EAAwBE,kBAAAA,CAAAA;AAEnCA,gBAAAA,kBAAAA,CAAmBE,aAAa,CAC9BC,sBAAAA,EACA,CAACC,SAAkC;wBACjCC,QAAAA,EAAU;4BAAEC,IAAAA,EAAM;AAAY,yBAAA;wBAC9BC,OAAAA,EAAS;4BAAEC,MAAAA,EAAQ,KAAA;AAAOC,4BAAAA,OAAAA,EAASL,OAAOK,OAAAA,IAAW;AAAK;qBAC5D,CAAA,CAAA;AAGF,gBAAA,MAAMT,mBAAmBpB,QAAQ,EAAA;AACnC,YAAA;AACF,QAAA,CAAA;AACA,QAAA,MAAME,OAAAA,CAAAA,CAAQ,EAAEQ,MAAAA,EAAAA,OAAM,EAA2B,EAAA;AAC/C,YAAA,IAAID,kBAAAA,EAAoB;gBACtBC,OAAAA,CAAOE,GAAG,CAAC,sBAAA,CAAA,CAAwBV,OAAO,EAAA;AAC5C,YAAA;AACA,YAAA,MAAMH,QAAQG,OAAO,EAAA;AACvB,QAAA;AACF,KAAA;AACF;;;;"}
1
+ {"version":3,"file":"index.mjs","sources":["../../../../../ee/server/src/index.ts"],"sourcesContent":["import type { Core } from '@strapi/types';\nimport register from './register';\nimport bootstrap from './bootstrap';\nimport destroy from './destroy';\nimport adminContentTypes from './content-types';\nimport services from './services';\nimport controllers from './controllers';\nimport routes from './routes';\nimport auditLogsRoutes from './audit-logs/routes/audit-logs';\nimport auditLogsController from './audit-logs/controllers/audit-logs';\nimport { createAuditLogsService } from './audit-logs/services/audit-logs';\nimport { createAuditLogsLifecycleService } from './audit-logs/services/lifecycles';\nimport { auditLog } from './audit-logs/content-types/audit-log';\nimport { AUDIT_LOG_EXPORT_EVENT } from '../../../shared/utils/audit-log-export';\nimport { registerTokenAuditEvents } from '../../../server/src/audit-logs/tokens';\n\nconst getAdminEE = () => {\n const eeAdmin = {\n register,\n bootstrap,\n destroy,\n contentTypes: {\n // Always register the audit-log content type to prevent data loss\n 'audit-log': auditLog,\n ...adminContentTypes,\n },\n services,\n controllers,\n routes,\n };\n\n const isAuditLogsEnabled =\n strapi.config.get('admin.auditLogs.enabled', true) &&\n strapi.ee.features.isEnabled('audit-logs');\n return {\n ...eeAdmin,\n controllers: {\n ...eeAdmin.controllers,\n ...(isAuditLogsEnabled ? { 'audit-logs': auditLogsController } : {}),\n },\n routes: {\n ...eeAdmin.routes,\n ...(isAuditLogsEnabled ? { 'audit-logs': auditLogsRoutes } : {}),\n },\n async register({ strapi }: { strapi: Core.Strapi }) {\n // Run the default registration\n await eeAdmin.register({ strapi });\n\n if (isAuditLogsEnabled) {\n // Register an internal audit logs service\n strapi.add('audit-logs', createAuditLogsService(strapi));\n // Register an internal audit logs lifecycle service\n const auditLogsLifecycle = createAuditLogsLifecycleService(strapi);\n strapi.add('audit-logs-lifecycle', auditLogsLifecycle);\n\n auditLogsLifecycle.registerEvent(\n AUDIT_LOG_EXPORT_EVENT,\n (event: { filters?: unknown }) => ({\n resource: { type: 'audit-log' },\n details: { format: 'csv', filters: event?.filters ?? null },\n })\n );\n\n registerTokenAuditEvents(auditLogsLifecycle);\n\n await auditLogsLifecycle.register();\n }\n },\n async destroy({ strapi }: { strapi: Core.Strapi }) {\n if (isAuditLogsEnabled) {\n strapi.get('audit-logs-lifecycle').destroy();\n }\n await eeAdmin.destroy();\n },\n };\n};\n\nexport default getAdminEE;\n"],"names":["getAdminEE","eeAdmin","register","bootstrap","destroy","contentTypes","auditLog","adminContentTypes","services","controllers","routes","isAuditLogsEnabled","strapi","config","get","ee","features","isEnabled","auditLogsController","auditLogsRoutes","add","createAuditLogsService","auditLogsLifecycle","createAuditLogsLifecycleService","registerEvent","AUDIT_LOG_EXPORT_EVENT","event","resource","type","details","format","filters","registerTokenAuditEvents"],"mappings":";;;;;;;;;;;;;;;AAgBA,MAAMA,UAAAA,GAAa,IAAA;AACjB,IAAA,MAAMC,OAAAA,GAAU;AACdC,QAAAA,QAAAA;AACAC,QAAAA,SAAAA;AACAC,QAAAA,OAAAA;QACAC,YAAAA,EAAc;;YAEZ,WAAA,EAAaC,QAAAA;AACb,YAAA,GAAGC;AACL,SAAA;AACAC,QAAAA,QAAAA;AACAC,QAAAA,WAAAA;AACAC,QAAAA;AACF,KAAA;AAEA,IAAA,MAAMC,kBAAAA,GACJC,MAAAA,CAAOC,MAAM,CAACC,GAAG,CAAC,yBAAA,EAA2B,IAAA,CAAA,IAC7CF,MAAAA,CAAOG,EAAE,CAACC,QAAQ,CAACC,SAAS,CAAC,YAAA,CAAA;IAC/B,OAAO;AACL,QAAA,GAAGhB,OAAO;QACVQ,WAAAA,EAAa;AACX,YAAA,GAAGR,QAAQQ,WAAW;AACtB,YAAA,GAAIE,kBAAAA,GAAqB;gBAAE,YAAA,EAAcO;AAAoB,aAAA,GAAI;AACnE,SAAA;QACAR,MAAAA,EAAQ;AACN,YAAA,GAAGT,QAAQS,MAAM;AACjB,YAAA,GAAIC,kBAAAA,GAAqB;gBAAE,YAAA,EAAcQ;AAAgB,aAAA,GAAI;AAC/D,SAAA;AACA,QAAA,MAAMjB,QAAAA,CAAAA,CAAS,EAAEU,MAAAA,EAAAA,OAAM,EAA2B,EAAA;;YAEhD,MAAMX,OAAAA,CAAQC,QAAQ,CAAC;gBAAEU,MAAAA,EAAAA;AAAO,aAAA,CAAA;AAEhC,YAAA,IAAID,kBAAAA,EAAoB;;gBAEtBC,OAAAA,CAAOQ,GAAG,CAAC,YAAA,EAAcC,sBAAAA,CAAuBT,OAAAA,CAAAA,CAAAA;;AAEhD,gBAAA,MAAMU,qBAAqBC,+BAAAA,CAAgCX,OAAAA,CAAAA;gBAC3DA,OAAAA,CAAOQ,GAAG,CAAC,sBAAA,EAAwBE,kBAAAA,CAAAA;AAEnCA,gBAAAA,kBAAAA,CAAmBE,aAAa,CAC9BC,sBAAAA,EACA,CAACC,SAAkC;wBACjCC,QAAAA,EAAU;4BAAEC,IAAAA,EAAM;AAAY,yBAAA;wBAC9BC,OAAAA,EAAS;4BAAEC,MAAAA,EAAQ,KAAA;AAAOC,4BAAAA,OAAAA,EAASL,OAAOK,OAAAA,IAAW;AAAK;qBAC5D,CAAA,CAAA;gBAGFC,wBAAAA,CAAyBV,kBAAAA,CAAAA;AAEzB,gBAAA,MAAMA,mBAAmBpB,QAAQ,EAAA;AACnC,YAAA;AACF,QAAA,CAAA;AACA,QAAA,MAAME,OAAAA,CAAAA,CAAQ,EAAEQ,MAAAA,EAAAA,OAAM,EAA2B,EAAA;AAC/C,YAAA,IAAID,kBAAAA,EAAoB;gBACtBC,OAAAA,CAAOE,GAAG,CAAC,sBAAA,CAAA,CAAwBV,OAAO,EAAA;AAC5C,YAAA;AACA,YAAA,MAAMH,QAAQG,OAAO,EAAA;AACvB,QAAA;AACF,KAAA;AACF;;;;"}
@@ -2,7 +2,7 @@
2
2
 
3
3
  var ai = {
4
4
  async getAiToken (ctx) {
5
- if (strapi.ai.admin.isEnabled() === false) {
5
+ if (strapi.ai.admin.isStrapiManagedAiEnabled() === false) {
6
6
  return ctx.notFound();
7
7
  }
8
8
  try {
@@ -22,7 +22,7 @@ var ai = {
22
22
  }
23
23
  },
24
24
  async getAiUsage (ctx) {
25
- if (strapi.ai.admin.isEnabled() === false) {
25
+ if (strapi.ai.admin.isStrapiManagedAiEnabled() === false) {
26
26
  return ctx.notFound();
27
27
  }
28
28
  try {
@@ -33,7 +33,7 @@ var ai = {
33
33
  }
34
34
  },
35
35
  async getAiFeatureConfig (ctx) {
36
- if (strapi.ai.admin.isEnabled() === false) {
36
+ if (strapi.ai.admin.isAvailable() === false) {
37
37
  return ctx.notFound();
38
38
  }
39
39
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"ai.js","sources":["../../../../../../server/src/ai/controllers/ai.ts"],"sourcesContent":["import type { Context } from 'koa';\nimport { GetAiFeatureConfig, GetAiToken } from '../../../../shared/contracts/ai';\n\nexport default {\n async getAiToken(ctx: Context) {\n if (strapi.ai.admin.isEnabled() === false) {\n return ctx.notFound();\n }\n\n try {\n // `admin::isAuthenticatedAdmin` only checks `ctx.state.isAuthenticated`, not `ctx.state.user`.\n // With the current admin JWT strategy, a successful auth run always sets both; this handler\n // still requires `user` because `getAiToken()` needs an admin identity. Keeps us safe if the\n // strategy/policy contract ever diverges or this action is invoked outside the normal pipeline.\n if (!ctx.state.user) {\n return ctx.unauthorized('Authentication required');\n }\n\n const aiToken = await strapi.ai.admin.getAiToken();\n\n ctx.body = {\n data: aiToken,\n } satisfies GetAiToken.Response;\n } catch {\n return ctx.internalServerError('AI token request failed. Check server logs for details.');\n }\n },\n\n async getAiUsage(ctx: Context) {\n if (strapi.ai.admin.isEnabled() === false) {\n return ctx.notFound();\n }\n\n try {\n const usage = await strapi.ai.admin.getAiUsage();\n ctx.body = usage;\n } catch {\n return ctx.internalServerError(\n 'AI usage data request failed. Check server logs for details.'\n );\n }\n },\n\n async getAiFeatureConfig(ctx: Context) {\n if (strapi.ai.admin.isEnabled() === false) {\n return ctx.notFound();\n }\n\n try {\n const aiFeatureConfig = await strapi.ai.admin.getAiFeatureConfig();\n\n ctx.body = {\n data: aiFeatureConfig,\n } satisfies GetAiFeatureConfig.Response;\n } catch (error) {\n strapi.log.error('AI feature config request failed', error);\n return ctx.internalServerError(\n 'AI feature config request failed. Check server logs for details.'\n );\n }\n },\n};\n"],"names":["getAiToken","ctx","strapi","ai","admin","isEnabled","notFound","state","user","unauthorized","aiToken","body","data","internalServerError","getAiUsage","usage","getAiFeatureConfig","aiFeatureConfig","error","log"],"mappings":";;AAGA,SAAe;AACb,IAAA,MAAMA,YAAWC,GAAY,EAAA;AAC3B,QAAA,IAAIC,OAAOC,EAAE,CAACC,KAAK,CAACC,SAAS,OAAO,KAAA,EAAO;AACzC,YAAA,OAAOJ,IAAIK,QAAQ,EAAA;AACrB,QAAA;QAEA,IAAI;;;;;AAKF,YAAA,IAAI,CAACL,GAAAA,CAAIM,KAAK,CAACC,IAAI,EAAE;gBACnB,OAAOP,GAAAA,CAAIQ,YAAY,CAAC,yBAAA,CAAA;AAC1B,YAAA;AAEA,YAAA,MAAMC,UAAU,MAAMR,MAAAA,CAAOC,EAAE,CAACC,KAAK,CAACJ,UAAU,EAAA;AAEhDC,YAAAA,GAAAA,CAAIU,IAAI,GAAG;gBACTC,IAAAA,EAAMF;AACR,aAAA;AACF,QAAA,CAAA,CAAE,OAAM;YACN,OAAOT,GAAAA,CAAIY,mBAAmB,CAAC,yDAAA,CAAA;AACjC,QAAA;AACF,IAAA,CAAA;AAEA,IAAA,MAAMC,YAAWb,GAAY,EAAA;AAC3B,QAAA,IAAIC,OAAOC,EAAE,CAACC,KAAK,CAACC,SAAS,OAAO,KAAA,EAAO;AACzC,YAAA,OAAOJ,IAAIK,QAAQ,EAAA;AACrB,QAAA;QAEA,IAAI;AACF,YAAA,MAAMS,QAAQ,MAAMb,MAAAA,CAAOC,EAAE,CAACC,KAAK,CAACU,UAAU,EAAA;AAC9Cb,YAAAA,GAAAA,CAAIU,IAAI,GAAGI,KAAAA;AACb,QAAA,CAAA,CAAE,OAAM;YACN,OAAOd,GAAAA,CAAIY,mBAAmB,CAC5B,8DAAA,CAAA;AAEJ,QAAA;AACF,IAAA,CAAA;AAEA,IAAA,MAAMG,oBAAmBf,GAAY,EAAA;AACnC,QAAA,IAAIC,OAAOC,EAAE,CAACC,KAAK,CAACC,SAAS,OAAO,KAAA,EAAO;AACzC,YAAA,OAAOJ,IAAIK,QAAQ,EAAA;AACrB,QAAA;QAEA,IAAI;AACF,YAAA,MAAMW,kBAAkB,MAAMf,MAAAA,CAAOC,EAAE,CAACC,KAAK,CAACY,kBAAkB,EAAA;AAEhEf,YAAAA,GAAAA,CAAIU,IAAI,GAAG;gBACTC,IAAAA,EAAMK;AACR,aAAA;AACF,QAAA,CAAA,CAAE,OAAOC,KAAAA,EAAO;AACdhB,YAAAA,MAAAA,CAAOiB,GAAG,CAACD,KAAK,CAAC,kCAAA,EAAoCA,KAAAA,CAAAA;YACrD,OAAOjB,GAAAA,CAAIY,mBAAmB,CAC5B,kEAAA,CAAA;AAEJ,QAAA;AACF,IAAA;AACF,CAAA;;;;"}
1
+ {"version":3,"file":"ai.js","sources":["../../../../../../server/src/ai/controllers/ai.ts"],"sourcesContent":["import type { Context } from 'koa';\nimport { GetAiFeatureConfig, GetAiToken } from '../../../../shared/contracts/ai';\n\nexport default {\n async getAiToken(ctx: Context) {\n if (strapi.ai.admin.isStrapiManagedAiEnabled() === false) {\n return ctx.notFound();\n }\n\n try {\n // `admin::isAuthenticatedAdmin` only checks `ctx.state.isAuthenticated`, not `ctx.state.user`.\n // With the current admin JWT strategy, a successful auth run always sets both; this handler\n // still requires `user` because `getAiToken()` needs an admin identity. Keeps us safe if the\n // strategy/policy contract ever diverges or this action is invoked outside the normal pipeline.\n if (!ctx.state.user) {\n return ctx.unauthorized('Authentication required');\n }\n\n const aiToken = await strapi.ai.admin.getAiToken();\n\n ctx.body = {\n data: aiToken,\n } satisfies GetAiToken.Response;\n } catch {\n return ctx.internalServerError('AI token request failed. Check server logs for details.');\n }\n },\n\n async getAiUsage(ctx: Context) {\n if (strapi.ai.admin.isStrapiManagedAiEnabled() === false) {\n return ctx.notFound();\n }\n\n try {\n const usage = await strapi.ai.admin.getAiUsage();\n ctx.body = usage;\n } catch {\n return ctx.internalServerError(\n 'AI usage data request failed. Check server logs for details.'\n );\n }\n },\n\n async getAiFeatureConfig(ctx: Context) {\n if (strapi.ai.admin.isAvailable() === false) {\n return ctx.notFound();\n }\n\n try {\n const aiFeatureConfig = await strapi.ai.admin.getAiFeatureConfig();\n\n ctx.body = {\n data: aiFeatureConfig,\n } satisfies GetAiFeatureConfig.Response;\n } catch (error) {\n strapi.log.error('AI feature config request failed', error);\n return ctx.internalServerError(\n 'AI feature config request failed. Check server logs for details.'\n );\n }\n },\n};\n"],"names":["getAiToken","ctx","strapi","ai","admin","isStrapiManagedAiEnabled","notFound","state","user","unauthorized","aiToken","body","data","internalServerError","getAiUsage","usage","getAiFeatureConfig","isAvailable","aiFeatureConfig","error","log"],"mappings":";;AAGA,SAAe;AACb,IAAA,MAAMA,YAAWC,GAAY,EAAA;AAC3B,QAAA,IAAIC,OAAOC,EAAE,CAACC,KAAK,CAACC,wBAAwB,OAAO,KAAA,EAAO;AACxD,YAAA,OAAOJ,IAAIK,QAAQ,EAAA;AACrB,QAAA;QAEA,IAAI;;;;;AAKF,YAAA,IAAI,CAACL,GAAAA,CAAIM,KAAK,CAACC,IAAI,EAAE;gBACnB,OAAOP,GAAAA,CAAIQ,YAAY,CAAC,yBAAA,CAAA;AAC1B,YAAA;AAEA,YAAA,MAAMC,UAAU,MAAMR,MAAAA,CAAOC,EAAE,CAACC,KAAK,CAACJ,UAAU,EAAA;AAEhDC,YAAAA,GAAAA,CAAIU,IAAI,GAAG;gBACTC,IAAAA,EAAMF;AACR,aAAA;AACF,QAAA,CAAA,CAAE,OAAM;YACN,OAAOT,GAAAA,CAAIY,mBAAmB,CAAC,yDAAA,CAAA;AACjC,QAAA;AACF,IAAA,CAAA;AAEA,IAAA,MAAMC,YAAWb,GAAY,EAAA;AAC3B,QAAA,IAAIC,OAAOC,EAAE,CAACC,KAAK,CAACC,wBAAwB,OAAO,KAAA,EAAO;AACxD,YAAA,OAAOJ,IAAIK,QAAQ,EAAA;AACrB,QAAA;QAEA,IAAI;AACF,YAAA,MAAMS,QAAQ,MAAMb,MAAAA,CAAOC,EAAE,CAACC,KAAK,CAACU,UAAU,EAAA;AAC9Cb,YAAAA,GAAAA,CAAIU,IAAI,GAAGI,KAAAA;AACb,QAAA,CAAA,CAAE,OAAM;YACN,OAAOd,GAAAA,CAAIY,mBAAmB,CAC5B,8DAAA,CAAA;AAEJ,QAAA;AACF,IAAA,CAAA;AAEA,IAAA,MAAMG,oBAAmBf,GAAY,EAAA;AACnC,QAAA,IAAIC,OAAOC,EAAE,CAACC,KAAK,CAACa,WAAW,OAAO,KAAA,EAAO;AAC3C,YAAA,OAAOhB,IAAIK,QAAQ,EAAA;AACrB,QAAA;QAEA,IAAI;AACF,YAAA,MAAMY,kBAAkB,MAAMhB,MAAAA,CAAOC,EAAE,CAACC,KAAK,CAACY,kBAAkB,EAAA;AAEhEf,YAAAA,GAAAA,CAAIU,IAAI,GAAG;gBACTC,IAAAA,EAAMM;AACR,aAAA;AACF,QAAA,CAAA,CAAE,OAAOC,KAAAA,EAAO;AACdjB,YAAAA,MAAAA,CAAOkB,GAAG,CAACD,KAAK,CAAC,kCAAA,EAAoCA,KAAAA,CAAAA;YACrD,OAAOlB,GAAAA,CAAIY,mBAAmB,CAC5B,kEAAA,CAAA;AAEJ,QAAA;AACF,IAAA;AACF,CAAA;;;;"}
@@ -1,6 +1,6 @@
1
1
  var ai = {
2
2
  async getAiToken (ctx) {
3
- if (strapi.ai.admin.isEnabled() === false) {
3
+ if (strapi.ai.admin.isStrapiManagedAiEnabled() === false) {
4
4
  return ctx.notFound();
5
5
  }
6
6
  try {
@@ -20,7 +20,7 @@ var ai = {
20
20
  }
21
21
  },
22
22
  async getAiUsage (ctx) {
23
- if (strapi.ai.admin.isEnabled() === false) {
23
+ if (strapi.ai.admin.isStrapiManagedAiEnabled() === false) {
24
24
  return ctx.notFound();
25
25
  }
26
26
  try {
@@ -31,7 +31,7 @@ var ai = {
31
31
  }
32
32
  },
33
33
  async getAiFeatureConfig (ctx) {
34
- if (strapi.ai.admin.isEnabled() === false) {
34
+ if (strapi.ai.admin.isAvailable() === false) {
35
35
  return ctx.notFound();
36
36
  }
37
37
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"ai.mjs","sources":["../../../../../../server/src/ai/controllers/ai.ts"],"sourcesContent":["import type { Context } from 'koa';\nimport { GetAiFeatureConfig, GetAiToken } from '../../../../shared/contracts/ai';\n\nexport default {\n async getAiToken(ctx: Context) {\n if (strapi.ai.admin.isEnabled() === false) {\n return ctx.notFound();\n }\n\n try {\n // `admin::isAuthenticatedAdmin` only checks `ctx.state.isAuthenticated`, not `ctx.state.user`.\n // With the current admin JWT strategy, a successful auth run always sets both; this handler\n // still requires `user` because `getAiToken()` needs an admin identity. Keeps us safe if the\n // strategy/policy contract ever diverges or this action is invoked outside the normal pipeline.\n if (!ctx.state.user) {\n return ctx.unauthorized('Authentication required');\n }\n\n const aiToken = await strapi.ai.admin.getAiToken();\n\n ctx.body = {\n data: aiToken,\n } satisfies GetAiToken.Response;\n } catch {\n return ctx.internalServerError('AI token request failed. Check server logs for details.');\n }\n },\n\n async getAiUsage(ctx: Context) {\n if (strapi.ai.admin.isEnabled() === false) {\n return ctx.notFound();\n }\n\n try {\n const usage = await strapi.ai.admin.getAiUsage();\n ctx.body = usage;\n } catch {\n return ctx.internalServerError(\n 'AI usage data request failed. Check server logs for details.'\n );\n }\n },\n\n async getAiFeatureConfig(ctx: Context) {\n if (strapi.ai.admin.isEnabled() === false) {\n return ctx.notFound();\n }\n\n try {\n const aiFeatureConfig = await strapi.ai.admin.getAiFeatureConfig();\n\n ctx.body = {\n data: aiFeatureConfig,\n } satisfies GetAiFeatureConfig.Response;\n } catch (error) {\n strapi.log.error('AI feature config request failed', error);\n return ctx.internalServerError(\n 'AI feature config request failed. Check server logs for details.'\n );\n }\n },\n};\n"],"names":["getAiToken","ctx","strapi","ai","admin","isEnabled","notFound","state","user","unauthorized","aiToken","body","data","internalServerError","getAiUsage","usage","getAiFeatureConfig","aiFeatureConfig","error","log"],"mappings":"AAGA,SAAe;AACb,IAAA,MAAMA,YAAWC,GAAY,EAAA;AAC3B,QAAA,IAAIC,OAAOC,EAAE,CAACC,KAAK,CAACC,SAAS,OAAO,KAAA,EAAO;AACzC,YAAA,OAAOJ,IAAIK,QAAQ,EAAA;AACrB,QAAA;QAEA,IAAI;;;;;AAKF,YAAA,IAAI,CAACL,GAAAA,CAAIM,KAAK,CAACC,IAAI,EAAE;gBACnB,OAAOP,GAAAA,CAAIQ,YAAY,CAAC,yBAAA,CAAA;AAC1B,YAAA;AAEA,YAAA,MAAMC,UAAU,MAAMR,MAAAA,CAAOC,EAAE,CAACC,KAAK,CAACJ,UAAU,EAAA;AAEhDC,YAAAA,GAAAA,CAAIU,IAAI,GAAG;gBACTC,IAAAA,EAAMF;AACR,aAAA;AACF,QAAA,CAAA,CAAE,OAAM;YACN,OAAOT,GAAAA,CAAIY,mBAAmB,CAAC,yDAAA,CAAA;AACjC,QAAA;AACF,IAAA,CAAA;AAEA,IAAA,MAAMC,YAAWb,GAAY,EAAA;AAC3B,QAAA,IAAIC,OAAOC,EAAE,CAACC,KAAK,CAACC,SAAS,OAAO,KAAA,EAAO;AACzC,YAAA,OAAOJ,IAAIK,QAAQ,EAAA;AACrB,QAAA;QAEA,IAAI;AACF,YAAA,MAAMS,QAAQ,MAAMb,MAAAA,CAAOC,EAAE,CAACC,KAAK,CAACU,UAAU,EAAA;AAC9Cb,YAAAA,GAAAA,CAAIU,IAAI,GAAGI,KAAAA;AACb,QAAA,CAAA,CAAE,OAAM;YACN,OAAOd,GAAAA,CAAIY,mBAAmB,CAC5B,8DAAA,CAAA;AAEJ,QAAA;AACF,IAAA,CAAA;AAEA,IAAA,MAAMG,oBAAmBf,GAAY,EAAA;AACnC,QAAA,IAAIC,OAAOC,EAAE,CAACC,KAAK,CAACC,SAAS,OAAO,KAAA,EAAO;AACzC,YAAA,OAAOJ,IAAIK,QAAQ,EAAA;AACrB,QAAA;QAEA,IAAI;AACF,YAAA,MAAMW,kBAAkB,MAAMf,MAAAA,CAAOC,EAAE,CAACC,KAAK,CAACY,kBAAkB,EAAA;AAEhEf,YAAAA,GAAAA,CAAIU,IAAI,GAAG;gBACTC,IAAAA,EAAMK;AACR,aAAA;AACF,QAAA,CAAA,CAAE,OAAOC,KAAAA,EAAO;AACdhB,YAAAA,MAAAA,CAAOiB,GAAG,CAACD,KAAK,CAAC,kCAAA,EAAoCA,KAAAA,CAAAA;YACrD,OAAOjB,GAAAA,CAAIY,mBAAmB,CAC5B,kEAAA,CAAA;AAEJ,QAAA;AACF,IAAA;AACF,CAAA;;;;"}
1
+ {"version":3,"file":"ai.mjs","sources":["../../../../../../server/src/ai/controllers/ai.ts"],"sourcesContent":["import type { Context } from 'koa';\nimport { GetAiFeatureConfig, GetAiToken } from '../../../../shared/contracts/ai';\n\nexport default {\n async getAiToken(ctx: Context) {\n if (strapi.ai.admin.isStrapiManagedAiEnabled() === false) {\n return ctx.notFound();\n }\n\n try {\n // `admin::isAuthenticatedAdmin` only checks `ctx.state.isAuthenticated`, not `ctx.state.user`.\n // With the current admin JWT strategy, a successful auth run always sets both; this handler\n // still requires `user` because `getAiToken()` needs an admin identity. Keeps us safe if the\n // strategy/policy contract ever diverges or this action is invoked outside the normal pipeline.\n if (!ctx.state.user) {\n return ctx.unauthorized('Authentication required');\n }\n\n const aiToken = await strapi.ai.admin.getAiToken();\n\n ctx.body = {\n data: aiToken,\n } satisfies GetAiToken.Response;\n } catch {\n return ctx.internalServerError('AI token request failed. Check server logs for details.');\n }\n },\n\n async getAiUsage(ctx: Context) {\n if (strapi.ai.admin.isStrapiManagedAiEnabled() === false) {\n return ctx.notFound();\n }\n\n try {\n const usage = await strapi.ai.admin.getAiUsage();\n ctx.body = usage;\n } catch {\n return ctx.internalServerError(\n 'AI usage data request failed. Check server logs for details.'\n );\n }\n },\n\n async getAiFeatureConfig(ctx: Context) {\n if (strapi.ai.admin.isAvailable() === false) {\n return ctx.notFound();\n }\n\n try {\n const aiFeatureConfig = await strapi.ai.admin.getAiFeatureConfig();\n\n ctx.body = {\n data: aiFeatureConfig,\n } satisfies GetAiFeatureConfig.Response;\n } catch (error) {\n strapi.log.error('AI feature config request failed', error);\n return ctx.internalServerError(\n 'AI feature config request failed. Check server logs for details.'\n );\n }\n },\n};\n"],"names":["getAiToken","ctx","strapi","ai","admin","isStrapiManagedAiEnabled","notFound","state","user","unauthorized","aiToken","body","data","internalServerError","getAiUsage","usage","getAiFeatureConfig","isAvailable","aiFeatureConfig","error","log"],"mappings":"AAGA,SAAe;AACb,IAAA,MAAMA,YAAWC,GAAY,EAAA;AAC3B,QAAA,IAAIC,OAAOC,EAAE,CAACC,KAAK,CAACC,wBAAwB,OAAO,KAAA,EAAO;AACxD,YAAA,OAAOJ,IAAIK,QAAQ,EAAA;AACrB,QAAA;QAEA,IAAI;;;;;AAKF,YAAA,IAAI,CAACL,GAAAA,CAAIM,KAAK,CAACC,IAAI,EAAE;gBACnB,OAAOP,GAAAA,CAAIQ,YAAY,CAAC,yBAAA,CAAA;AAC1B,YAAA;AAEA,YAAA,MAAMC,UAAU,MAAMR,MAAAA,CAAOC,EAAE,CAACC,KAAK,CAACJ,UAAU,EAAA;AAEhDC,YAAAA,GAAAA,CAAIU,IAAI,GAAG;gBACTC,IAAAA,EAAMF;AACR,aAAA;AACF,QAAA,CAAA,CAAE,OAAM;YACN,OAAOT,GAAAA,CAAIY,mBAAmB,CAAC,yDAAA,CAAA;AACjC,QAAA;AACF,IAAA,CAAA;AAEA,IAAA,MAAMC,YAAWb,GAAY,EAAA;AAC3B,QAAA,IAAIC,OAAOC,EAAE,CAACC,KAAK,CAACC,wBAAwB,OAAO,KAAA,EAAO;AACxD,YAAA,OAAOJ,IAAIK,QAAQ,EAAA;AACrB,QAAA;QAEA,IAAI;AACF,YAAA,MAAMS,QAAQ,MAAMb,MAAAA,CAAOC,EAAE,CAACC,KAAK,CAACU,UAAU,EAAA;AAC9Cb,YAAAA,GAAAA,CAAIU,IAAI,GAAGI,KAAAA;AACb,QAAA,CAAA,CAAE,OAAM;YACN,OAAOd,GAAAA,CAAIY,mBAAmB,CAC5B,8DAAA,CAAA;AAEJ,QAAA;AACF,IAAA,CAAA;AAEA,IAAA,MAAMG,oBAAmBf,GAAY,EAAA;AACnC,QAAA,IAAIC,OAAOC,EAAE,CAACC,KAAK,CAACa,WAAW,OAAO,KAAA,EAAO;AAC3C,YAAA,OAAOhB,IAAIK,QAAQ,EAAA;AACrB,QAAA;QAEA,IAAI;AACF,YAAA,MAAMY,kBAAkB,MAAMhB,MAAAA,CAAOC,EAAE,CAACC,KAAK,CAACY,kBAAkB,EAAA;AAEhEf,YAAAA,GAAAA,CAAIU,IAAI,GAAG;gBACTC,IAAAA,EAAMM;AACR,aAAA;AACF,QAAA,CAAA,CAAE,OAAOC,KAAAA,EAAO;AACdjB,YAAAA,MAAAA,CAAOkB,GAAG,CAACD,KAAK,CAAC,kCAAA,EAAoCA,KAAAA,CAAAA;YACrD,OAAOlB,GAAAA,CAAIY,mBAAmB,CAC5B,kEAAA,CAAA;AAEJ,QAAA;AACF,IAAA;AACF,CAAA;;;;"}
@@ -10,35 +10,57 @@ var crypto__default = /*#__PURE__*/_interopDefault(crypto);
10
10
  var fs__default = /*#__PURE__*/_interopDefault(fs);
11
11
  var path__default = /*#__PURE__*/_interopDefault(path);
12
12
 
13
+ const STRAPI_MANAGED_AI_LICENSE_FEATURE = 'cms-ai';
14
+ const CUSTOM_AI_PROVIDER_LICENSE_FEATURE = 'cms-byok-ai';
13
15
  const createAiAdminService = ({ strapi })=>{
14
16
  /**
15
17
  * In-memory cache for AI tokens
16
18
  * Key format: `${projectId}:${userId}`
17
19
  */ const aiTokenCache = new Map();
18
- const isEnabled = ()=>{
19
- const configEnabled = strapi.config.get('admin.ai.enabled', true) === true;
20
- const licenseEnabled = strapi.ee?.features?.isEnabled('cms-ai') === true;
21
- return configEnabled && licenseEnabled;
20
+ let isCustomProviderRejected = false;
21
+ const isConfigEnabled = ()=>strapi.config.get('admin.ai.enabled', true) === true;
22
+ const isAvailable = ()=>isConfigEnabled() && strapi.ee?.isEE === true && !isCustomProviderRejected;
23
+ const isStrapiManagedAiEnabled = ()=>isConfigEnabled() && !isCustomProviderRejected && strapi.ee?.features?.isEnabled(STRAPI_MANAGED_AI_LICENSE_FEATURE) === true;
24
+ const authorizeCustomProvider = ()=>{
25
+ if (!isConfigEnabled()) {
26
+ strapi.log.info('A custom AI provider was ignored: AI is disabled by the "admin.ai.enabled" config.');
27
+ return false;
28
+ }
29
+ if (strapi.ee?.features?.isEnabled(CUSTOM_AI_PROVIDER_LICENSE_FEATURE) === true) {
30
+ return true;
31
+ }
32
+ isCustomProviderRejected = true;
33
+ strapi.log.warn(`A custom AI provider was rejected: the Strapi license does not include the "${CUSTOM_AI_PROVIDER_LICENSE_FEATURE}" feature. All AI features are disabled.`);
34
+ return false;
35
+ };
36
+ const isPluginAiFeatureConfigured = async (plugin, service)=>{
37
+ const aiService = strapi.plugin(plugin)?.service(service);
38
+ if (typeof aiService?.isEnabled !== 'function') {
39
+ return false;
40
+ }
41
+ return await aiService.isEnabled() === true;
22
42
  };
23
43
  const getAiFeatureConfig = async ()=>{
24
- if (!isEnabled()) {
44
+ if (!isAvailable()) {
25
45
  return {
26
46
  isAiI18nConfigured: false,
27
47
  isAiMediaLibraryConfigured: false
28
48
  };
29
49
  }
30
- const i18nSettings = await strapi.plugin('i18n').service('settings').getSettings();
31
- const uploadSettings = await strapi.plugin('upload').service('upload').getSettings();
50
+ const [isAiI18nConfigured, isAiMediaLibraryConfigured] = await Promise.all([
51
+ isPluginAiFeatureConfigured('i18n', 'ai-localizations'),
52
+ isPluginAiFeatureConfigured('upload', 'aiMetadata')
53
+ ]);
32
54
  return {
33
- isAiI18nConfigured: Boolean(i18nSettings?.aiLocalizations),
34
- isAiMediaLibraryConfigured: Boolean(uploadSettings?.aiMetadata)
55
+ isAiI18nConfigured,
56
+ isAiMediaLibraryConfigured
35
57
  };
36
58
  };
37
59
  /**
38
60
  * Resolves the shared context required by both getAiToken and getAiUsage:
39
61
  * EE license, project ID, and AI server URL.
40
62
  */ const resolveAiContext = (errorPrefix)=>{
41
- if (!isEnabled()) {
63
+ if (!isStrapiManagedAiEnabled()) {
42
64
  strapi.log.error(`${errorPrefix} AI is not enabled`);
43
65
  throw new Error(`${errorPrefix.replace(/:$/, '')}. Check server logs for details.`);
44
66
  }
@@ -226,8 +248,11 @@ const createAiAdminService = ({ strapi })=>{
226
248
  }
227
249
  };
228
250
  return {
229
- isEnabled,
230
- getAiFeatureConfig,
251
+ /* Requires `ai.enabled=true` + license + no failed AI provider registration */ isAvailable,
252
+ /* `true` only when the license has the `cms-ai` entitlement to globally enable AI features.
253
+ TODO: once all AI features are migrated to the providers architecture, consider removing this flag */ isStrapiManagedAiEnabled,
254
+ authorizeCustomProvider,
255
+ /* Returns the status of each AI feature, flagging which are enabled. */ getAiFeatureConfig,
231
256
  getAiToken,
232
257
  getAiUsage
233
258
  };
@@ -1 +1 @@
1
- {"version":3,"file":"ai.js","sources":["../../../../../../server/src/ai/services/ai.ts"],"sourcesContent":["import type { Core } from '@strapi/types';\nimport crypto from 'crypto';\nimport fs from 'fs';\nimport path from 'path';\nimport { AdminUser } from '../../../../shared/contracts/shared';\n\nconst createAiAdminService = ({ strapi }: { strapi: Core.Strapi }) => {\n /**\n * In-memory cache for AI tokens\n * Key format: `${projectId}:${userId}`\n */\n const aiTokenCache = new Map<\n string,\n {\n token: string;\n expiresAt?: string;\n expiresAtMs?: number;\n }\n >();\n\n const isEnabled = (): boolean => {\n const configEnabled = strapi.config.get('admin.ai.enabled', true) === true;\n const licenseEnabled = strapi.ee?.features?.isEnabled('cms-ai') === true;\n return configEnabled && licenseEnabled;\n };\n\n const getAiFeatureConfig = async () => {\n if (!isEnabled()) {\n return {\n isAiI18nConfigured: false,\n isAiMediaLibraryConfigured: false,\n };\n }\n\n const i18nSettings = await strapi.plugin('i18n').service('settings').getSettings();\n const uploadSettings = await strapi.plugin('upload').service('upload').getSettings();\n\n return {\n isAiI18nConfigured: Boolean(i18nSettings?.aiLocalizations),\n isAiMediaLibraryConfigured: Boolean(uploadSettings?.aiMetadata),\n };\n };\n\n /**\n * Resolves the shared context required by both getAiToken and getAiUsage:\n * EE license, project ID, and AI server URL.\n */\n const resolveAiContext = (errorPrefix: string) => {\n if (!isEnabled()) {\n strapi.log.error(`${errorPrefix} AI is not enabled`);\n throw new Error(`${errorPrefix.replace(/:$/, '')}. Check server logs for details.`);\n }\n\n if (!strapi.ee?.isEE) {\n strapi.log.error(`${errorPrefix} Enterprise Edition features are not enabled`);\n throw new Error(`${errorPrefix.replace(/:$/, '')}. Check server logs for details.`);\n }\n\n let eeLicense = process.env.STRAPI_LICENSE;\n\n if (!eeLicense) {\n try {\n const licensePath = path.join(strapi.dirs.app.root, 'license.txt');\n eeLicense = fs.readFileSync(licensePath).toString();\n } catch {\n // License file doesn't exist or can't be read\n }\n }\n\n if (!eeLicense) {\n strapi.log.error(\n `${errorPrefix} No EE license found. Please ensure STRAPI_LICENSE environment variable is set or license.txt file exists.`\n );\n throw new Error(`${errorPrefix.replace(/:$/, '')}. Check server logs for details.`);\n }\n\n const projectId = strapi.config.get('uuid');\n if (!projectId) {\n strapi.log.error(`${errorPrefix} Project ID not configured`);\n throw new Error(`${errorPrefix.replace(/:$/, '')}. Check server logs for details.`);\n }\n\n const aiServerUrl = process.env.STRAPI_AI_URL || 'https://strapi-ai.apps.strapi.io';\n\n return { eeLicense, projectId, aiServerUrl };\n };\n\n const getAiToken = async () => {\n const ERROR_PREFIX = 'AI token request failed:';\n\n const { eeLicense, projectId, aiServerUrl } = resolveAiContext(ERROR_PREFIX);\n\n // Get the current user\n const user = strapi.requestContext.get()?.state?.user as AdminUser | undefined;\n if (!user) {\n strapi.log.error(`${ERROR_PREFIX} No authenticated user in request context`);\n throw new Error('AI token request failed. Check server logs for details.');\n }\n\n // Create a secure user identifier using only user ID\n const userIdentifier = user.id.toString();\n\n // Check cache for existing valid token\n const cacheKey = `${projectId}:${userIdentifier}`;\n const cachedToken = aiTokenCache.get(cacheKey);\n\n if (cachedToken) {\n const now = Date.now();\n // Check if token is still valid (with buffer so it has time to be used)\n const bufferMs = 2 * 60 * 1000; // 2 minutes\n\n if (cachedToken.expiresAtMs && cachedToken.expiresAtMs - bufferMs > now) {\n strapi.log.info('Using cached AI token');\n\n return {\n token: cachedToken.token,\n expiresAt: cachedToken.expiresAt,\n };\n }\n\n // Token expired or will expire soon, remove from cache\n aiTokenCache.delete(cacheKey);\n }\n\n strapi.log.http('Contacting AI Server for token generation');\n\n try {\n const response = await fetch(`${aiServerUrl}/auth/getAiJWT`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'X-Request-Id': crypto.randomUUID(),\n },\n body: JSON.stringify({\n eeLicense,\n userIdentifier,\n projectId,\n }),\n });\n\n if (!response.ok) {\n let errorData;\n let errorText;\n try {\n errorText = await response.text();\n errorData = JSON.parse(errorText);\n } catch {\n errorData = { error: errorText || 'Failed to parse error response' };\n }\n\n strapi.log.error(`${ERROR_PREFIX} ${errorData?.error || 'Unknown error'}`, {\n status: response.status,\n statusText: response.statusText,\n error: errorData,\n errorText,\n projectId,\n });\n\n throw new Error('AI token request failed. Check server logs for details.');\n }\n\n let data;\n try {\n data = (await response.json()) as {\n jwt: string;\n expiresAt?: string;\n };\n } catch (parseError) {\n strapi.log.error(`${ERROR_PREFIX} Failed to parse AI server response`, parseError);\n throw new Error('AI token request failed. Check server logs for details.');\n }\n\n if (!data.jwt) {\n strapi.log.error(`${ERROR_PREFIX} Invalid response: missing JWT token`);\n throw new Error('AI token request failed. Check server logs for details.');\n }\n\n strapi.log.info('AI token generated successfully', {\n userId: user.id,\n expiresAt: data.expiresAt,\n });\n\n // Cache the token if it has an expiration time\n if (data.expiresAt) {\n const expiresAtMs = new Date(data.expiresAt).getTime();\n aiTokenCache.set(cacheKey, {\n token: data.jwt,\n expiresAt: data.expiresAt,\n expiresAtMs,\n });\n }\n\n // Note: Token expires in 1 hour, client should handle refresh\n return {\n token: data.jwt,\n expiresAt: data.expiresAt,\n };\n } catch (fetchError) {\n if (fetchError instanceof Error && fetchError.name === 'AbortError') {\n strapi.log.error(`${ERROR_PREFIX} Request to AI server timed out`);\n throw new Error('AI token request failed. Check server logs for details.');\n }\n\n throw fetchError;\n }\n };\n\n const getAiUsage = async () => {\n const ERROR_PREFIX = 'AI usage data request failed:';\n\n const { eeLicense, projectId, aiServerUrl } = resolveAiContext(ERROR_PREFIX);\n\n strapi.log.http('Contacting AI Server for usage data');\n\n try {\n const response = await fetch(`${aiServerUrl}/cms/ai-data`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'X-Request-Id': crypto.randomUUID(),\n },\n body: JSON.stringify({\n eeKey: eeLicense,\n projectId,\n }),\n });\n\n if (!response.ok) {\n let errorData;\n let errorText;\n try {\n errorText = await response.text();\n errorData = JSON.parse(errorText);\n } catch {\n errorData = { error: errorText || 'Failed to parse error response' };\n }\n\n strapi.log.error(`${ERROR_PREFIX} ${errorData?.error || 'Unknown error'}`, {\n status: response.status,\n statusText: response.statusText,\n error: errorData,\n errorText,\n projectId,\n });\n\n throw new Error('AI usage data request failed. Check server logs for details.');\n }\n\n let data;\n try {\n data = (await response.json()) as {\n data: { cmsAiCreditsUsed: number };\n subscription: {\n subscriptionId: string;\n planPriceId: string;\n subscriptionStatus: string;\n isActiveSubscription: boolean;\n cmsAiEnabled: boolean;\n cmsAiCreditsBase: number;\n cmsAiCreditsMaxUsage: number;\n currentTermStart: string;\n currentTermEnd: string;\n };\n };\n } catch (parseError) {\n strapi.log.error(`${ERROR_PREFIX} Failed to parse AI server response`, parseError);\n throw new Error('AI usage data request failed. Check server logs for details.');\n }\n\n return {\n ...data.data,\n subscription: data.subscription,\n };\n } catch (fetchError) {\n if (fetchError instanceof Error && fetchError.name === 'AbortError') {\n strapi.log.error(`${ERROR_PREFIX} Request to AI server timed out`);\n throw new Error('AI usage data request failed. Check server logs for details.');\n }\n\n throw fetchError;\n }\n };\n\n return {\n isEnabled,\n getAiFeatureConfig,\n getAiToken,\n getAiUsage,\n };\n};\n\nexport { createAiAdminService };\n"],"names":["createAiAdminService","strapi","aiTokenCache","Map","isEnabled","configEnabled","config","get","licenseEnabled","ee","features","getAiFeatureConfig","isAiI18nConfigured","isAiMediaLibraryConfigured","i18nSettings","plugin","service","getSettings","uploadSettings","Boolean","aiLocalizations","aiMetadata","resolveAiContext","errorPrefix","log","error","Error","replace","isEE","eeLicense","process","env","STRAPI_LICENSE","licensePath","path","join","dirs","app","root","fs","readFileSync","toString","projectId","aiServerUrl","STRAPI_AI_URL","getAiToken","ERROR_PREFIX","user","requestContext","state","userIdentifier","id","cacheKey","cachedToken","now","Date","bufferMs","expiresAtMs","info","token","expiresAt","delete","http","response","fetch","method","headers","crypto","randomUUID","body","JSON","stringify","ok","errorData","errorText","text","parse","status","statusText","data","json","parseError","jwt","userId","getTime","set","fetchError","name","getAiUsage","eeKey","subscription"],"mappings":";;;;;;;;;;;;AAMA,MAAMA,oBAAAA,GAAuB,CAAC,EAAEC,MAAM,EAA2B,GAAA;AAC/D;;;MAIA,MAAMC,eAAe,IAAIC,GAAAA,EAAAA;AASzB,IAAA,MAAMC,SAAAA,GAAY,IAAA;AAChB,QAAA,MAAMC,gBAAgBJ,MAAAA,CAAOK,MAAM,CAACC,GAAG,CAAC,oBAAoB,IAAA,CAAA,KAAU,IAAA;AACtE,QAAA,MAAMC,iBAAiBP,MAAAA,CAAOQ,EAAE,EAAEC,QAAAA,EAAUN,UAAU,QAAA,CAAA,KAAc,IAAA;AACpE,QAAA,OAAOC,aAAAA,IAAiBG,cAAAA;AAC1B,IAAA,CAAA;AAEA,IAAA,MAAMG,kBAAAA,GAAqB,UAAA;AACzB,QAAA,IAAI,CAACP,SAAAA,EAAAA,EAAa;YAChB,OAAO;gBACLQ,kBAAAA,EAAoB,KAAA;gBACpBC,0BAAAA,EAA4B;AAC9B,aAAA;AACF,QAAA;QAEA,MAAMC,YAAAA,GAAe,MAAMb,MAAAA,CAAOc,MAAM,CAAC,MAAA,CAAA,CAAQC,OAAO,CAAC,UAAA,CAAA,CAAYC,WAAW,EAAA;QAChF,MAAMC,cAAAA,GAAiB,MAAMjB,MAAAA,CAAOc,MAAM,CAAC,QAAA,CAAA,CAAUC,OAAO,CAAC,QAAA,CAAA,CAAUC,WAAW,EAAA;QAElF,OAAO;AACLL,YAAAA,kBAAAA,EAAoBO,QAAQL,YAAAA,EAAcM,eAAAA,CAAAA;AAC1CP,YAAAA,0BAAAA,EAA4BM,QAAQD,cAAAA,EAAgBG,UAAAA;AACtD,SAAA;AACF,IAAA,CAAA;AAEA;;;MAIA,MAAMC,mBAAmB,CAACC,WAAAA,GAAAA;AACxB,QAAA,IAAI,CAACnB,SAAAA,EAAAA,EAAa;AAChBH,YAAAA,MAAAA,CAAOuB,GAAG,CAACC,KAAK,CAAC,CAAA,EAAGF,WAAAA,CAAY,kBAAkB,CAAC,CAAA;YACnD,MAAM,IAAIG,MAAM,CAAA,EAAGH,WAAAA,CAAYI,OAAO,CAAC,IAAA,EAAM,EAAA,CAAA,CAAI,gCAAgC,CAAC,CAAA;AACpF,QAAA;AAEA,QAAA,IAAI,CAAC1B,MAAAA,CAAOQ,EAAE,EAAEmB,IAAAA,EAAM;AACpB3B,YAAAA,MAAAA,CAAOuB,GAAG,CAACC,KAAK,CAAC,CAAA,EAAGF,WAAAA,CAAY,4CAA4C,CAAC,CAAA;YAC7E,MAAM,IAAIG,MAAM,CAAA,EAAGH,WAAAA,CAAYI,OAAO,CAAC,IAAA,EAAM,EAAA,CAAA,CAAI,gCAAgC,CAAC,CAAA;AACpF,QAAA;AAEA,QAAA,IAAIE,SAAAA,GAAYC,OAAAA,CAAQC,GAAG,CAACC,cAAc;AAE1C,QAAA,IAAI,CAACH,SAAAA,EAAW;YACd,IAAI;gBACF,MAAMI,WAAAA,GAAcC,qBAAAA,CAAKC,IAAI,CAAClC,MAAAA,CAAOmC,IAAI,CAACC,GAAG,CAACC,IAAI,EAAE,aAAA,CAAA;AACpDT,gBAAAA,SAAAA,GAAYU,mBAAAA,CAAGC,YAAY,CAACP,WAAAA,CAAAA,CAAaQ,QAAQ,EAAA;AACnD,YAAA,CAAA,CAAE,OAAM;;AAER,YAAA;AACF,QAAA;AAEA,QAAA,IAAI,CAACZ,SAAAA,EAAW;AACd5B,YAAAA,MAAAA,CAAOuB,GAAG,CAACC,KAAK,CACd,CAAA,EAAGF,WAAAA,CAAY,0GAA0G,CAAC,CAAA;YAE5H,MAAM,IAAIG,MAAM,CAAA,EAAGH,WAAAA,CAAYI,OAAO,CAAC,IAAA,EAAM,EAAA,CAAA,CAAI,gCAAgC,CAAC,CAAA;AACpF,QAAA;AAEA,QAAA,MAAMe,SAAAA,GAAYzC,MAAAA,CAAOK,MAAM,CAACC,GAAG,CAAC,MAAA,CAAA;AACpC,QAAA,IAAI,CAACmC,SAAAA,EAAW;AACdzC,YAAAA,MAAAA,CAAOuB,GAAG,CAACC,KAAK,CAAC,CAAA,EAAGF,WAAAA,CAAY,0BAA0B,CAAC,CAAA;YAC3D,MAAM,IAAIG,MAAM,CAAA,EAAGH,WAAAA,CAAYI,OAAO,CAAC,IAAA,EAAM,EAAA,CAAA,CAAI,gCAAgC,CAAC,CAAA;AACpF,QAAA;AAEA,QAAA,MAAMgB,WAAAA,GAAcb,OAAAA,CAAQC,GAAG,CAACa,aAAa,IAAI,kCAAA;QAEjD,OAAO;AAAEf,YAAAA,SAAAA;AAAWa,YAAAA,SAAAA;AAAWC,YAAAA;AAAY,SAAA;AAC7C,IAAA,CAAA;AAEA,IAAA,MAAME,UAAAA,GAAa,UAAA;AACjB,QAAA,MAAMC,YAAAA,GAAe,0BAAA;QAErB,MAAM,EAAEjB,SAAS,EAAEa,SAAS,EAAEC,WAAW,EAAE,GAAGrB,gBAAAA,CAAiBwB,YAAAA,CAAAA;;AAG/D,QAAA,MAAMC,OAAO9C,MAAAA,CAAO+C,cAAc,CAACzC,GAAG,IAAI0C,KAAAA,EAAOF,IAAAA;AACjD,QAAA,IAAI,CAACA,IAAAA,EAAM;AACT9C,YAAAA,MAAAA,CAAOuB,GAAG,CAACC,KAAK,CAAC,CAAA,EAAGqB,YAAAA,CAAa,yCAAyC,CAAC,CAAA;AAC3E,YAAA,MAAM,IAAIpB,KAAAA,CAAM,yDAAA,CAAA;AAClB,QAAA;;AAGA,QAAA,MAAMwB,cAAAA,GAAiBH,IAAAA,CAAKI,EAAE,CAACV,QAAQ,EAAA;;AAGvC,QAAA,MAAMW,QAAAA,GAAW,CAAA,EAAGV,SAAAA,CAAU,CAAC,EAAEQ,cAAAA,CAAAA,CAAgB;QACjD,MAAMG,WAAAA,GAAcnD,YAAAA,CAAaK,GAAG,CAAC6C,QAAAA,CAAAA;AAErC,QAAA,IAAIC,WAAAA,EAAa;YACf,MAAMC,GAAAA,GAAMC,KAAKD,GAAG,EAAA;;AAEpB,YAAA,MAAME,QAAAA,GAAW,CAAA,GAAI,EAAA,GAAK,IAAA,CAAA;AAE1B,YAAA,IAAIH,YAAYI,WAAW,IAAIJ,YAAYI,WAAW,GAAGD,WAAWF,GAAAA,EAAK;gBACvErD,MAAAA,CAAOuB,GAAG,CAACkC,IAAI,CAAC,uBAAA,CAAA;gBAEhB,OAAO;AACLC,oBAAAA,KAAAA,EAAON,YAAYM,KAAK;AACxBC,oBAAAA,SAAAA,EAAWP,YAAYO;AACzB,iBAAA;AACF,YAAA;;AAGA1D,YAAAA,YAAAA,CAAa2D,MAAM,CAACT,QAAAA,CAAAA;AACtB,QAAA;QAEAnD,MAAAA,CAAOuB,GAAG,CAACsC,IAAI,CAAC,2CAAA,CAAA;QAEhB,IAAI;AACF,YAAA,MAAMC,WAAW,MAAMC,KAAAA,CAAM,GAAGrB,WAAAA,CAAY,cAAc,CAAC,EAAE;gBAC3DsB,MAAAA,EAAQ,MAAA;gBACRC,OAAAA,EAAS;oBACP,cAAA,EAAgB,kBAAA;AAChB,oBAAA,cAAA,EAAgBC,wBAAOC,UAAU;AACnC,iBAAA;gBACAC,IAAAA,EAAMC,IAAAA,CAAKC,SAAS,CAAC;AACnB1C,oBAAAA,SAAAA;AACAqB,oBAAAA,cAAAA;AACAR,oBAAAA;AACF,iBAAA;AACF,aAAA,CAAA;YAEA,IAAI,CAACqB,QAAAA,CAASS,EAAE,EAAE;gBAChB,IAAIC,SAAAA;gBACJ,IAAIC,SAAAA;gBACJ,IAAI;oBACFA,SAAAA,GAAY,MAAMX,SAASY,IAAI,EAAA;oBAC/BF,SAAAA,GAAYH,IAAAA,CAAKM,KAAK,CAACF,SAAAA,CAAAA;AACzB,gBAAA,CAAA,CAAE,OAAM;oBACND,SAAAA,GAAY;AAAEhD,wBAAAA,KAAAA,EAAOiD,SAAAA,IAAa;AAAiC,qBAAA;AACrE,gBAAA;gBAEAzE,MAAAA,CAAOuB,GAAG,CAACC,KAAK,CAAC,CAAA,EAAGqB,YAAAA,CAAa,CAAC,EAAE2B,SAAAA,EAAWhD,KAAAA,IAAS,eAAA,CAAA,CAAiB,EAAE;AACzEoD,oBAAAA,MAAAA,EAAQd,SAASc,MAAM;AACvBC,oBAAAA,UAAAA,EAAYf,SAASe,UAAU;oBAC/BrD,KAAAA,EAAOgD,SAAAA;AACPC,oBAAAA,SAAAA;AACAhC,oBAAAA;AACF,iBAAA,CAAA;AAEA,gBAAA,MAAM,IAAIhB,KAAAA,CAAM,yDAAA,CAAA;AAClB,YAAA;YAEA,IAAIqD,IAAAA;YACJ,IAAI;gBACFA,IAAAA,GAAQ,MAAMhB,SAASiB,IAAI,EAAA;AAI7B,YAAA,CAAA,CAAE,OAAOC,UAAAA,EAAY;gBACnBhF,MAAAA,CAAOuB,GAAG,CAACC,KAAK,CAAC,GAAGqB,YAAAA,CAAa,mCAAmC,CAAC,EAAEmC,UAAAA,CAAAA;AACvE,gBAAA,MAAM,IAAIvD,KAAAA,CAAM,yDAAA,CAAA;AAClB,YAAA;YAEA,IAAI,CAACqD,IAAAA,CAAKG,GAAG,EAAE;AACbjF,gBAAAA,MAAAA,CAAOuB,GAAG,CAACC,KAAK,CAAC,CAAA,EAAGqB,YAAAA,CAAa,oCAAoC,CAAC,CAAA;AACtE,gBAAA,MAAM,IAAIpB,KAAAA,CAAM,yDAAA,CAAA;AAClB,YAAA;AAEAzB,YAAAA,MAAAA,CAAOuB,GAAG,CAACkC,IAAI,CAAC,iCAAA,EAAmC;AACjDyB,gBAAAA,MAAAA,EAAQpC,KAAKI,EAAE;AACfS,gBAAAA,SAAAA,EAAWmB,KAAKnB;AAClB,aAAA,CAAA;;YAGA,IAAImB,IAAAA,CAAKnB,SAAS,EAAE;AAClB,gBAAA,MAAMH,cAAc,IAAIF,IAAAA,CAAKwB,IAAAA,CAAKnB,SAAS,EAAEwB,OAAO,EAAA;gBACpDlF,YAAAA,CAAamF,GAAG,CAACjC,QAAAA,EAAU;AACzBO,oBAAAA,KAAAA,EAAOoB,KAAKG,GAAG;AACftB,oBAAAA,SAAAA,EAAWmB,KAAKnB,SAAS;AACzBH,oBAAAA;AACF,iBAAA,CAAA;AACF,YAAA;;YAGA,OAAO;AACLE,gBAAAA,KAAAA,EAAOoB,KAAKG,GAAG;AACftB,gBAAAA,SAAAA,EAAWmB,KAAKnB;AAClB,aAAA;AACF,QAAA,CAAA,CAAE,OAAO0B,UAAAA,EAAY;AACnB,YAAA,IAAIA,UAAAA,YAAsB5D,KAAAA,IAAS4D,UAAAA,CAAWC,IAAI,KAAK,YAAA,EAAc;AACnEtF,gBAAAA,MAAAA,CAAOuB,GAAG,CAACC,KAAK,CAAC,CAAA,EAAGqB,YAAAA,CAAa,+BAA+B,CAAC,CAAA;AACjE,gBAAA,MAAM,IAAIpB,KAAAA,CAAM,yDAAA,CAAA;AAClB,YAAA;YAEA,MAAM4D,UAAAA;AACR,QAAA;AACF,IAAA,CAAA;AAEA,IAAA,MAAME,UAAAA,GAAa,UAAA;AACjB,QAAA,MAAM1C,YAAAA,GAAe,+BAAA;QAErB,MAAM,EAAEjB,SAAS,EAAEa,SAAS,EAAEC,WAAW,EAAE,GAAGrB,gBAAAA,CAAiBwB,YAAAA,CAAAA;QAE/D7C,MAAAA,CAAOuB,GAAG,CAACsC,IAAI,CAAC,qCAAA,CAAA;QAEhB,IAAI;AACF,YAAA,MAAMC,WAAW,MAAMC,KAAAA,CAAM,GAAGrB,WAAAA,CAAY,YAAY,CAAC,EAAE;gBACzDsB,MAAAA,EAAQ,MAAA;gBACRC,OAAAA,EAAS;oBACP,cAAA,EAAgB,kBAAA;AAChB,oBAAA,cAAA,EAAgBC,wBAAOC,UAAU;AACnC,iBAAA;gBACAC,IAAAA,EAAMC,IAAAA,CAAKC,SAAS,CAAC;oBACnBkB,KAAAA,EAAO5D,SAAAA;AACPa,oBAAAA;AACF,iBAAA;AACF,aAAA,CAAA;YAEA,IAAI,CAACqB,QAAAA,CAASS,EAAE,EAAE;gBAChB,IAAIC,SAAAA;gBACJ,IAAIC,SAAAA;gBACJ,IAAI;oBACFA,SAAAA,GAAY,MAAMX,SAASY,IAAI,EAAA;oBAC/BF,SAAAA,GAAYH,IAAAA,CAAKM,KAAK,CAACF,SAAAA,CAAAA;AACzB,gBAAA,CAAA,CAAE,OAAM;oBACND,SAAAA,GAAY;AAAEhD,wBAAAA,KAAAA,EAAOiD,SAAAA,IAAa;AAAiC,qBAAA;AACrE,gBAAA;gBAEAzE,MAAAA,CAAOuB,GAAG,CAACC,KAAK,CAAC,CAAA,EAAGqB,YAAAA,CAAa,CAAC,EAAE2B,SAAAA,EAAWhD,KAAAA,IAAS,eAAA,CAAA,CAAiB,EAAE;AACzEoD,oBAAAA,MAAAA,EAAQd,SAASc,MAAM;AACvBC,oBAAAA,UAAAA,EAAYf,SAASe,UAAU;oBAC/BrD,KAAAA,EAAOgD,SAAAA;AACPC,oBAAAA,SAAAA;AACAhC,oBAAAA;AACF,iBAAA,CAAA;AAEA,gBAAA,MAAM,IAAIhB,KAAAA,CAAM,8DAAA,CAAA;AAClB,YAAA;YAEA,IAAIqD,IAAAA;YACJ,IAAI;gBACFA,IAAAA,GAAQ,MAAMhB,SAASiB,IAAI,EAAA;AAc7B,YAAA,CAAA,CAAE,OAAOC,UAAAA,EAAY;gBACnBhF,MAAAA,CAAOuB,GAAG,CAACC,KAAK,CAAC,GAAGqB,YAAAA,CAAa,mCAAmC,CAAC,EAAEmC,UAAAA,CAAAA;AACvE,gBAAA,MAAM,IAAIvD,KAAAA,CAAM,8DAAA,CAAA;AAClB,YAAA;YAEA,OAAO;AACL,gBAAA,GAAGqD,KAAKA,IAAI;AACZW,gBAAAA,YAAAA,EAAcX,KAAKW;AACrB,aAAA;AACF,QAAA,CAAA,CAAE,OAAOJ,UAAAA,EAAY;AACnB,YAAA,IAAIA,UAAAA,YAAsB5D,KAAAA,IAAS4D,UAAAA,CAAWC,IAAI,KAAK,YAAA,EAAc;AACnEtF,gBAAAA,MAAAA,CAAOuB,GAAG,CAACC,KAAK,CAAC,CAAA,EAAGqB,YAAAA,CAAa,+BAA+B,CAAC,CAAA;AACjE,gBAAA,MAAM,IAAIpB,KAAAA,CAAM,8DAAA,CAAA;AAClB,YAAA;YAEA,MAAM4D,UAAAA;AACR,QAAA;AACF,IAAA,CAAA;IAEA,OAAO;AACLlF,QAAAA,SAAAA;AACAO,QAAAA,kBAAAA;AACAkC,QAAAA,UAAAA;AACA2C,QAAAA;AACF,KAAA;AACF;;;;"}
1
+ {"version":3,"file":"ai.js","sources":["../../../../../../server/src/ai/services/ai.ts"],"sourcesContent":["import type { Core } from '@strapi/types';\nimport crypto from 'crypto';\nimport fs from 'fs';\nimport path from 'path';\nimport { AdminUser } from '../../../../shared/contracts/shared';\n\nconst STRAPI_MANAGED_AI_LICENSE_FEATURE = 'cms-ai';\nconst CUSTOM_AI_PROVIDER_LICENSE_FEATURE = 'cms-byok-ai';\n\nconst createAiAdminService = ({ strapi }: { strapi: Core.Strapi }) => {\n /**\n * In-memory cache for AI tokens\n * Key format: `${projectId}:${userId}`\n */\n const aiTokenCache = new Map<\n string,\n {\n token: string;\n expiresAt?: string;\n expiresAtMs?: number;\n }\n >();\n\n let isCustomProviderRejected = false;\n\n const isConfigEnabled = (): boolean => strapi.config.get('admin.ai.enabled', true) === true;\n\n const isAvailable = (): boolean =>\n isConfigEnabled() && strapi.ee?.isEE === true && !isCustomProviderRejected;\n\n const isStrapiManagedAiEnabled = (): boolean =>\n isConfigEnabled() &&\n !isCustomProviderRejected &&\n strapi.ee?.features?.isEnabled(STRAPI_MANAGED_AI_LICENSE_FEATURE) === true;\n\n const authorizeCustomProvider = (): boolean => {\n if (!isConfigEnabled()) {\n strapi.log.info(\n 'A custom AI provider was ignored: AI is disabled by the \"admin.ai.enabled\" config.'\n );\n return false;\n }\n\n if (strapi.ee?.features?.isEnabled(CUSTOM_AI_PROVIDER_LICENSE_FEATURE) === true) {\n return true;\n }\n\n isCustomProviderRejected = true;\n strapi.log.warn(\n `A custom AI provider was rejected: the Strapi license does not include the \"${CUSTOM_AI_PROVIDER_LICENSE_FEATURE}\" feature. All AI features are disabled.`\n );\n return false;\n };\n\n const isPluginAiFeatureConfigured = async (plugin: string, service: string): Promise<boolean> => {\n const aiService = strapi.plugin(plugin)?.service(service) as\n | { isEnabled?: () => Promise<boolean> | boolean }\n | undefined;\n\n if (typeof aiService?.isEnabled !== 'function') {\n return false;\n }\n\n return (await aiService.isEnabled()) === true;\n };\n\n const getAiFeatureConfig = async () => {\n if (!isAvailable()) {\n return {\n isAiI18nConfigured: false,\n isAiMediaLibraryConfigured: false,\n };\n }\n\n const [isAiI18nConfigured, isAiMediaLibraryConfigured] = await Promise.all([\n isPluginAiFeatureConfigured('i18n', 'ai-localizations'),\n isPluginAiFeatureConfigured('upload', 'aiMetadata'),\n ]);\n\n return { isAiI18nConfigured, isAiMediaLibraryConfigured };\n };\n\n /**\n * Resolves the shared context required by both getAiToken and getAiUsage:\n * EE license, project ID, and AI server URL.\n */\n const resolveAiContext = (errorPrefix: string) => {\n if (!isStrapiManagedAiEnabled()) {\n strapi.log.error(`${errorPrefix} AI is not enabled`);\n throw new Error(`${errorPrefix.replace(/:$/, '')}. Check server logs for details.`);\n }\n\n if (!strapi.ee?.isEE) {\n strapi.log.error(`${errorPrefix} Enterprise Edition features are not enabled`);\n throw new Error(`${errorPrefix.replace(/:$/, '')}. Check server logs for details.`);\n }\n\n let eeLicense = process.env.STRAPI_LICENSE;\n\n if (!eeLicense) {\n try {\n const licensePath = path.join(strapi.dirs.app.root, 'license.txt');\n eeLicense = fs.readFileSync(licensePath).toString();\n } catch {\n // License file doesn't exist or can't be read\n }\n }\n\n if (!eeLicense) {\n strapi.log.error(\n `${errorPrefix} No EE license found. Please ensure STRAPI_LICENSE environment variable is set or license.txt file exists.`\n );\n throw new Error(`${errorPrefix.replace(/:$/, '')}. Check server logs for details.`);\n }\n\n const projectId = strapi.config.get('uuid');\n if (!projectId) {\n strapi.log.error(`${errorPrefix} Project ID not configured`);\n throw new Error(`${errorPrefix.replace(/:$/, '')}. Check server logs for details.`);\n }\n\n const aiServerUrl = process.env.STRAPI_AI_URL || 'https://strapi-ai.apps.strapi.io';\n\n return { eeLicense, projectId, aiServerUrl };\n };\n\n const getAiToken = async () => {\n const ERROR_PREFIX = 'AI token request failed:';\n\n const { eeLicense, projectId, aiServerUrl } = resolveAiContext(ERROR_PREFIX);\n\n // Get the current user\n const user = strapi.requestContext.get()?.state?.user as AdminUser | undefined;\n if (!user) {\n strapi.log.error(`${ERROR_PREFIX} No authenticated user in request context`);\n throw new Error('AI token request failed. Check server logs for details.');\n }\n\n // Create a secure user identifier using only user ID\n const userIdentifier = user.id.toString();\n\n // Check cache for existing valid token\n const cacheKey = `${projectId}:${userIdentifier}`;\n const cachedToken = aiTokenCache.get(cacheKey);\n\n if (cachedToken) {\n const now = Date.now();\n // Check if token is still valid (with buffer so it has time to be used)\n const bufferMs = 2 * 60 * 1000; // 2 minutes\n\n if (cachedToken.expiresAtMs && cachedToken.expiresAtMs - bufferMs > now) {\n strapi.log.info('Using cached AI token');\n\n return {\n token: cachedToken.token,\n expiresAt: cachedToken.expiresAt,\n };\n }\n\n // Token expired or will expire soon, remove from cache\n aiTokenCache.delete(cacheKey);\n }\n\n strapi.log.http('Contacting AI Server for token generation');\n\n try {\n const response = await fetch(`${aiServerUrl}/auth/getAiJWT`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'X-Request-Id': crypto.randomUUID(),\n },\n body: JSON.stringify({\n eeLicense,\n userIdentifier,\n projectId,\n }),\n });\n\n if (!response.ok) {\n let errorData;\n let errorText;\n try {\n errorText = await response.text();\n errorData = JSON.parse(errorText);\n } catch {\n errorData = { error: errorText || 'Failed to parse error response' };\n }\n\n strapi.log.error(`${ERROR_PREFIX} ${errorData?.error || 'Unknown error'}`, {\n status: response.status,\n statusText: response.statusText,\n error: errorData,\n errorText,\n projectId,\n });\n\n throw new Error('AI token request failed. Check server logs for details.');\n }\n\n let data;\n try {\n data = (await response.json()) as {\n jwt: string;\n expiresAt?: string;\n };\n } catch (parseError) {\n strapi.log.error(`${ERROR_PREFIX} Failed to parse AI server response`, parseError);\n throw new Error('AI token request failed. Check server logs for details.');\n }\n\n if (!data.jwt) {\n strapi.log.error(`${ERROR_PREFIX} Invalid response: missing JWT token`);\n throw new Error('AI token request failed. Check server logs for details.');\n }\n\n strapi.log.info('AI token generated successfully', {\n userId: user.id,\n expiresAt: data.expiresAt,\n });\n\n // Cache the token if it has an expiration time\n if (data.expiresAt) {\n const expiresAtMs = new Date(data.expiresAt).getTime();\n aiTokenCache.set(cacheKey, {\n token: data.jwt,\n expiresAt: data.expiresAt,\n expiresAtMs,\n });\n }\n\n // Note: Token expires in 1 hour, client should handle refresh\n return {\n token: data.jwt,\n expiresAt: data.expiresAt,\n };\n } catch (fetchError) {\n if (fetchError instanceof Error && fetchError.name === 'AbortError') {\n strapi.log.error(`${ERROR_PREFIX} Request to AI server timed out`);\n throw new Error('AI token request failed. Check server logs for details.');\n }\n\n throw fetchError;\n }\n };\n\n const getAiUsage = async () => {\n const ERROR_PREFIX = 'AI usage data request failed:';\n\n const { eeLicense, projectId, aiServerUrl } = resolveAiContext(ERROR_PREFIX);\n\n strapi.log.http('Contacting AI Server for usage data');\n\n try {\n const response = await fetch(`${aiServerUrl}/cms/ai-data`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'X-Request-Id': crypto.randomUUID(),\n },\n body: JSON.stringify({\n eeKey: eeLicense,\n projectId,\n }),\n });\n\n if (!response.ok) {\n let errorData;\n let errorText;\n try {\n errorText = await response.text();\n errorData = JSON.parse(errorText);\n } catch {\n errorData = { error: errorText || 'Failed to parse error response' };\n }\n\n strapi.log.error(`${ERROR_PREFIX} ${errorData?.error || 'Unknown error'}`, {\n status: response.status,\n statusText: response.statusText,\n error: errorData,\n errorText,\n projectId,\n });\n\n throw new Error('AI usage data request failed. Check server logs for details.');\n }\n\n let data;\n try {\n data = (await response.json()) as {\n data: { cmsAiCreditsUsed: number };\n subscription: {\n subscriptionId: string;\n planPriceId: string;\n subscriptionStatus: string;\n isActiveSubscription: boolean;\n cmsAiEnabled: boolean;\n cmsAiCreditsBase: number;\n cmsAiCreditsMaxUsage: number;\n currentTermStart: string;\n currentTermEnd: string;\n };\n };\n } catch (parseError) {\n strapi.log.error(`${ERROR_PREFIX} Failed to parse AI server response`, parseError);\n throw new Error('AI usage data request failed. Check server logs for details.');\n }\n\n return {\n ...data.data,\n subscription: data.subscription,\n };\n } catch (fetchError) {\n if (fetchError instanceof Error && fetchError.name === 'AbortError') {\n strapi.log.error(`${ERROR_PREFIX} Request to AI server timed out`);\n throw new Error('AI usage data request failed. Check server logs for details.');\n }\n\n throw fetchError;\n }\n };\n\n return {\n /* Requires `ai.enabled=true` + license + no failed AI provider registration */\n isAvailable,\n /* `true` only when the license has the `cms-ai` entitlement to globally enable AI features.\n TODO: once all AI features are migrated to the providers architecture, consider removing this flag */\n isStrapiManagedAiEnabled,\n authorizeCustomProvider,\n /* Returns the status of each AI feature, flagging which are enabled. */\n getAiFeatureConfig,\n getAiToken,\n getAiUsage,\n };\n};\n\nexport { createAiAdminService };\n"],"names":["STRAPI_MANAGED_AI_LICENSE_FEATURE","CUSTOM_AI_PROVIDER_LICENSE_FEATURE","createAiAdminService","strapi","aiTokenCache","Map","isCustomProviderRejected","isConfigEnabled","config","get","isAvailable","ee","isEE","isStrapiManagedAiEnabled","features","isEnabled","authorizeCustomProvider","log","info","warn","isPluginAiFeatureConfigured","plugin","service","aiService","getAiFeatureConfig","isAiI18nConfigured","isAiMediaLibraryConfigured","Promise","all","resolveAiContext","errorPrefix","error","Error","replace","eeLicense","process","env","STRAPI_LICENSE","licensePath","path","join","dirs","app","root","fs","readFileSync","toString","projectId","aiServerUrl","STRAPI_AI_URL","getAiToken","ERROR_PREFIX","user","requestContext","state","userIdentifier","id","cacheKey","cachedToken","now","Date","bufferMs","expiresAtMs","token","expiresAt","delete","http","response","fetch","method","headers","crypto","randomUUID","body","JSON","stringify","ok","errorData","errorText","text","parse","status","statusText","data","json","parseError","jwt","userId","getTime","set","fetchError","name","getAiUsage","eeKey","subscription"],"mappings":"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"}
@@ -2,35 +2,57 @@ import crypto from 'crypto';
2
2
  import fs from 'fs';
3
3
  import path from 'path';
4
4
 
5
+ const STRAPI_MANAGED_AI_LICENSE_FEATURE = 'cms-ai';
6
+ const CUSTOM_AI_PROVIDER_LICENSE_FEATURE = 'cms-byok-ai';
5
7
  const createAiAdminService = ({ strapi })=>{
6
8
  /**
7
9
  * In-memory cache for AI tokens
8
10
  * Key format: `${projectId}:${userId}`
9
11
  */ const aiTokenCache = new Map();
10
- const isEnabled = ()=>{
11
- const configEnabled = strapi.config.get('admin.ai.enabled', true) === true;
12
- const licenseEnabled = strapi.ee?.features?.isEnabled('cms-ai') === true;
13
- return configEnabled && licenseEnabled;
12
+ let isCustomProviderRejected = false;
13
+ const isConfigEnabled = ()=>strapi.config.get('admin.ai.enabled', true) === true;
14
+ const isAvailable = ()=>isConfigEnabled() && strapi.ee?.isEE === true && !isCustomProviderRejected;
15
+ const isStrapiManagedAiEnabled = ()=>isConfigEnabled() && !isCustomProviderRejected && strapi.ee?.features?.isEnabled(STRAPI_MANAGED_AI_LICENSE_FEATURE) === true;
16
+ const authorizeCustomProvider = ()=>{
17
+ if (!isConfigEnabled()) {
18
+ strapi.log.info('A custom AI provider was ignored: AI is disabled by the "admin.ai.enabled" config.');
19
+ return false;
20
+ }
21
+ if (strapi.ee?.features?.isEnabled(CUSTOM_AI_PROVIDER_LICENSE_FEATURE) === true) {
22
+ return true;
23
+ }
24
+ isCustomProviderRejected = true;
25
+ strapi.log.warn(`A custom AI provider was rejected: the Strapi license does not include the "${CUSTOM_AI_PROVIDER_LICENSE_FEATURE}" feature. All AI features are disabled.`);
26
+ return false;
27
+ };
28
+ const isPluginAiFeatureConfigured = async (plugin, service)=>{
29
+ const aiService = strapi.plugin(plugin)?.service(service);
30
+ if (typeof aiService?.isEnabled !== 'function') {
31
+ return false;
32
+ }
33
+ return await aiService.isEnabled() === true;
14
34
  };
15
35
  const getAiFeatureConfig = async ()=>{
16
- if (!isEnabled()) {
36
+ if (!isAvailable()) {
17
37
  return {
18
38
  isAiI18nConfigured: false,
19
39
  isAiMediaLibraryConfigured: false
20
40
  };
21
41
  }
22
- const i18nSettings = await strapi.plugin('i18n').service('settings').getSettings();
23
- const uploadSettings = await strapi.plugin('upload').service('upload').getSettings();
42
+ const [isAiI18nConfigured, isAiMediaLibraryConfigured] = await Promise.all([
43
+ isPluginAiFeatureConfigured('i18n', 'ai-localizations'),
44
+ isPluginAiFeatureConfigured('upload', 'aiMetadata')
45
+ ]);
24
46
  return {
25
- isAiI18nConfigured: Boolean(i18nSettings?.aiLocalizations),
26
- isAiMediaLibraryConfigured: Boolean(uploadSettings?.aiMetadata)
47
+ isAiI18nConfigured,
48
+ isAiMediaLibraryConfigured
27
49
  };
28
50
  };
29
51
  /**
30
52
  * Resolves the shared context required by both getAiToken and getAiUsage:
31
53
  * EE license, project ID, and AI server URL.
32
54
  */ const resolveAiContext = (errorPrefix)=>{
33
- if (!isEnabled()) {
55
+ if (!isStrapiManagedAiEnabled()) {
34
56
  strapi.log.error(`${errorPrefix} AI is not enabled`);
35
57
  throw new Error(`${errorPrefix.replace(/:$/, '')}. Check server logs for details.`);
36
58
  }
@@ -218,8 +240,11 @@ const createAiAdminService = ({ strapi })=>{
218
240
  }
219
241
  };
220
242
  return {
221
- isEnabled,
222
- getAiFeatureConfig,
243
+ /* Requires `ai.enabled=true` + license + no failed AI provider registration */ isAvailable,
244
+ /* `true` only when the license has the `cms-ai` entitlement to globally enable AI features.
245
+ TODO: once all AI features are migrated to the providers architecture, consider removing this flag */ isStrapiManagedAiEnabled,
246
+ authorizeCustomProvider,
247
+ /* Returns the status of each AI feature, flagging which are enabled. */ getAiFeatureConfig,
223
248
  getAiToken,
224
249
  getAiUsage
225
250
  };