@strapi/admin 5.24.2 → 5.26.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (166) hide show
  1. package/dist/admin/admin/src/App.js +6 -2
  2. package/dist/admin/admin/src/App.js.map +1 -1
  3. package/dist/admin/admin/src/App.mjs +7 -3
  4. package/dist/admin/admin/src/App.mjs.map +1 -1
  5. package/dist/admin/admin/src/components/GuidedTour/Context.js +11 -1
  6. package/dist/admin/admin/src/components/GuidedTour/Context.js.map +1 -1
  7. package/dist/admin/admin/src/components/GuidedTour/Context.mjs +11 -1
  8. package/dist/admin/admin/src/components/GuidedTour/Context.mjs.map +1 -1
  9. package/dist/admin/admin/src/components/GuidedTour/Steps/ContentTypeBuilderSteps.js +160 -23
  10. package/dist/admin/admin/src/components/GuidedTour/Steps/ContentTypeBuilderSteps.js.map +1 -1
  11. package/dist/admin/admin/src/components/GuidedTour/Steps/ContentTypeBuilderSteps.mjs +162 -25
  12. package/dist/admin/admin/src/components/GuidedTour/Steps/ContentTypeBuilderSteps.mjs.map +1 -1
  13. package/dist/admin/admin/src/components/GuidedTour/Steps/Step.js +28 -9
  14. package/dist/admin/admin/src/components/GuidedTour/Steps/Step.js.map +1 -1
  15. package/dist/admin/admin/src/components/GuidedTour/Steps/Step.mjs +30 -11
  16. package/dist/admin/admin/src/components/GuidedTour/Steps/Step.mjs.map +1 -1
  17. package/dist/admin/admin/src/components/GuidedTour/utils/migrations.js +2 -1
  18. package/dist/admin/admin/src/components/GuidedTour/utils/migrations.js.map +1 -1
  19. package/dist/admin/admin/src/components/GuidedTour/utils/migrations.mjs +2 -1
  20. package/dist/admin/admin/src/components/GuidedTour/utils/migrations.mjs.map +1 -1
  21. package/dist/admin/admin/src/components/NpsSurvey.js +2 -1
  22. package/dist/admin/admin/src/components/NpsSurvey.js.map +1 -1
  23. package/dist/admin/admin/src/components/NpsSurvey.mjs +2 -1
  24. package/dist/admin/admin/src/components/NpsSurvey.mjs.map +1 -1
  25. package/dist/admin/admin/src/features/Tracking.js +2 -1
  26. package/dist/admin/admin/src/features/Tracking.js.map +1 -1
  27. package/dist/admin/admin/src/features/Tracking.mjs +2 -1
  28. package/dist/admin/admin/src/features/Tracking.mjs.map +1 -1
  29. package/dist/admin/admin/src/hooks/useAIAvailability.js +13 -0
  30. package/dist/admin/admin/src/hooks/useAIAvailability.js.map +1 -0
  31. package/dist/admin/admin/src/hooks/useAIAvailability.mjs +11 -0
  32. package/dist/admin/admin/src/hooks/useAIAvailability.mjs.map +1 -0
  33. package/dist/admin/admin/src/pages/Home/HomePage.js +1 -0
  34. package/dist/admin/admin/src/pages/Home/HomePage.js.map +1 -1
  35. package/dist/admin/admin/src/pages/Home/HomePage.mjs +1 -0
  36. package/dist/admin/admin/src/pages/Home/HomePage.mjs.map +1 -1
  37. package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/ApplicationInfoPage.js +12 -1
  38. package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/ApplicationInfoPage.js.map +1 -1
  39. package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/ApplicationInfoPage.mjs +12 -1
  40. package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/ApplicationInfoPage.mjs.map +1 -1
  41. package/dist/admin/admin/src/render.js +6 -1
  42. package/dist/admin/admin/src/render.js.map +1 -1
  43. package/dist/admin/admin/src/render.mjs +6 -1
  44. package/dist/admin/admin/src/render.mjs.map +1 -1
  45. package/dist/admin/admin/src/services/homepage.js +15 -1
  46. package/dist/admin/admin/src/services/homepage.js.map +1 -1
  47. package/dist/admin/admin/src/services/homepage.mjs +14 -2
  48. package/dist/admin/admin/src/services/homepage.mjs.map +1 -1
  49. package/dist/admin/admin/src/translations/en.json.js +2 -0
  50. package/dist/admin/admin/src/translations/en.json.js.map +1 -1
  51. package/dist/admin/admin/src/translations/en.json.mjs +2 -0
  52. package/dist/admin/admin/src/translations/en.json.mjs.map +1 -1
  53. package/dist/admin/ee/admin/src/components/GlobalNotifications.js +11 -0
  54. package/dist/admin/ee/admin/src/components/GlobalNotifications.js.map +1 -0
  55. package/dist/admin/ee/admin/src/components/GlobalNotifications.mjs +9 -0
  56. package/dist/admin/ee/admin/src/components/GlobalNotifications.mjs.map +1 -0
  57. package/dist/admin/ee/admin/src/hooks/useAIAvailability.js +11 -0
  58. package/dist/admin/ee/admin/src/hooks/useAIAvailability.js.map +1 -0
  59. package/dist/admin/ee/admin/src/hooks/useAIAvailability.mjs +9 -0
  60. package/dist/admin/ee/admin/src/hooks/useAIAvailability.mjs.map +1 -0
  61. package/dist/admin/ee/admin/src/hooks/useAIUsageWarning.js +82 -0
  62. package/dist/admin/ee/admin/src/hooks/useAIUsageWarning.js.map +1 -0
  63. package/dist/admin/ee/admin/src/hooks/useAIUsageWarning.mjs +80 -0
  64. package/dist/admin/ee/admin/src/hooks/useAIUsageWarning.mjs.map +1 -0
  65. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/ApplicationInfoPage/components/AIUsage.js +102 -0
  66. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/ApplicationInfoPage/components/AIUsage.js.map +1 -0
  67. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/ApplicationInfoPage/components/AIUsage.mjs +100 -0
  68. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/ApplicationInfoPage/components/AIUsage.mjs.map +1 -0
  69. package/dist/admin/ee/admin/src/services/ai.js +30 -0
  70. package/dist/admin/ee/admin/src/services/ai.js.map +1 -0
  71. package/dist/admin/ee/admin/src/services/ai.mjs +26 -0
  72. package/dist/admin/ee/admin/src/services/ai.mjs.map +1 -0
  73. package/dist/admin/ee.js +4 -0
  74. package/dist/admin/ee.js.map +1 -1
  75. package/dist/admin/ee.mjs +2 -0
  76. package/dist/admin/ee.mjs.map +1 -1
  77. package/dist/admin/index.js +2 -0
  78. package/dist/admin/index.js.map +1 -1
  79. package/dist/admin/index.mjs +1 -0
  80. package/dist/admin/index.mjs.map +1 -1
  81. package/dist/admin/src/components/GuidedTour/Context.d.ts +7 -0
  82. package/dist/admin/src/components/GuidedTour/Steps/ContentTypeBuilderSteps.d.ts +7 -16
  83. package/dist/admin/src/components/GuidedTour/Tours.d.ts +1 -22
  84. package/dist/admin/src/ee.d.ts +2 -0
  85. package/dist/admin/src/features/Tracking.d.ts +21 -2
  86. package/dist/admin/src/hooks/useAIAvailability.d.ts +5 -0
  87. package/dist/admin/src/index.d.ts +2 -0
  88. package/dist/admin/src/pages/Marketplace/hooks/useMarketplaceData.d.ts +2 -2
  89. package/dist/admin/src/services/admin.d.ts +1 -0
  90. package/dist/admin/src/services/homepage.d.ts +3 -2
  91. package/dist/ee/admin/src/components/GlobalNotifications.d.ts +1 -0
  92. package/dist/ee/admin/src/hooks/useAIAvailability.d.ts +1 -0
  93. package/dist/ee/admin/src/hooks/useAIUsageWarning.d.ts +5 -0
  94. package/dist/ee/admin/src/hooks/useLicenseLimits.d.ts +1 -1
  95. package/dist/ee/admin/src/pages/SettingsPage/pages/ApplicationInfoPage/components/AIUsage.d.ts +1 -0
  96. package/dist/ee/admin/src/services/ai.d.ts +9 -0
  97. package/dist/ee/server/src/ai/controllers/ai.d.ts +7 -0
  98. package/dist/ee/server/src/ai/controllers/ai.d.ts.map +1 -0
  99. package/dist/ee/server/src/ai/routes/ai.d.ts +13 -0
  100. package/dist/ee/server/src/ai/routes/ai.d.ts.map +1 -0
  101. package/dist/ee/server/src/controllers/admin.d.ts +3 -0
  102. package/dist/ee/server/src/controllers/admin.d.ts.map +1 -1
  103. package/dist/ee/server/src/controllers/index.d.ts +3 -0
  104. package/dist/ee/server/src/controllers/index.d.ts.map +1 -1
  105. package/dist/ee/server/src/index.d.ts +15 -187
  106. package/dist/ee/server/src/index.d.ts.map +1 -1
  107. package/dist/server/ee/server/src/ai/controllers/ai.js +218 -0
  108. package/dist/server/ee/server/src/ai/controllers/ai.js.map +1 -0
  109. package/dist/server/ee/server/src/ai/controllers/ai.mjs +216 -0
  110. package/dist/server/ee/server/src/ai/controllers/ai.mjs.map +1 -0
  111. package/dist/server/ee/server/src/ai/routes/ai.js +32 -0
  112. package/dist/server/ee/server/src/ai/routes/ai.js.map +1 -0
  113. package/dist/server/ee/server/src/ai/routes/ai.mjs +30 -0
  114. package/dist/server/ee/server/src/ai/routes/ai.mjs.map +1 -0
  115. package/dist/server/ee/server/src/controllers/admin.js +4 -1
  116. package/dist/server/ee/server/src/controllers/admin.js.map +1 -1
  117. package/dist/server/ee/server/src/controllers/admin.mjs +4 -1
  118. package/dist/server/ee/server/src/controllers/admin.mjs.map +1 -1
  119. package/dist/server/ee/server/src/index.js +37 -23
  120. package/dist/server/ee/server/src/index.js.map +1 -1
  121. package/dist/server/ee/server/src/index.mjs +37 -23
  122. package/dist/server/ee/server/src/index.mjs.map +1 -1
  123. package/dist/server/server/src/controllers/admin.js +5 -1
  124. package/dist/server/server/src/controllers/admin.js.map +1 -1
  125. package/dist/server/server/src/controllers/admin.mjs +5 -1
  126. package/dist/server/server/src/controllers/admin.mjs.map +1 -1
  127. package/dist/server/server/src/controllers/homepage.js +17 -0
  128. package/dist/server/server/src/controllers/homepage.js.map +1 -1
  129. package/dist/server/server/src/controllers/homepage.mjs +17 -0
  130. package/dist/server/server/src/controllers/homepage.mjs.map +1 -1
  131. package/dist/server/server/src/controllers/validation/schema.js +30 -0
  132. package/dist/server/server/src/controllers/validation/schema.js.map +1 -0
  133. package/dist/server/server/src/controllers/validation/schema.mjs +26 -0
  134. package/dist/server/server/src/controllers/validation/schema.mjs.map +1 -0
  135. package/dist/server/server/src/routes/homepage.js +20 -0
  136. package/dist/server/server/src/routes/homepage.js.map +1 -1
  137. package/dist/server/server/src/routes/homepage.mjs +20 -0
  138. package/dist/server/server/src/routes/homepage.mjs.map +1 -1
  139. package/dist/server/server/src/services/homepage.js +48 -1
  140. package/dist/server/server/src/services/homepage.js.map +1 -1
  141. package/dist/server/server/src/services/homepage.mjs +48 -1
  142. package/dist/server/server/src/services/homepage.mjs.map +1 -1
  143. package/dist/server/src/controllers/admin.d.ts +2 -0
  144. package/dist/server/src/controllers/admin.d.ts.map +1 -1
  145. package/dist/server/src/controllers/homepage.d.ts +8 -0
  146. package/dist/server/src/controllers/homepage.d.ts.map +1 -1
  147. package/dist/server/src/controllers/index.d.ts +22 -0
  148. package/dist/server/src/controllers/index.d.ts.map +1 -1
  149. package/dist/server/src/controllers/validation/schema.d.ts +61 -0
  150. package/dist/server/src/controllers/validation/schema.d.ts.map +1 -0
  151. package/dist/server/src/index.d.ts +38 -0
  152. package/dist/server/src/index.d.ts.map +1 -1
  153. package/dist/server/src/routes/homepage.d.ts.map +1 -1
  154. package/dist/server/src/services/homepage.d.ts +3 -0
  155. package/dist/server/src/services/homepage.d.ts.map +1 -1
  156. package/dist/server/src/services/index.d.ts +16 -0
  157. package/dist/server/src/services/index.d.ts.map +1 -1
  158. package/dist/shared/contracts/admin.d.ts +1 -0
  159. package/dist/shared/contracts/admin.d.ts.map +1 -1
  160. package/dist/shared/contracts/ai.d.ts +40 -0
  161. package/dist/shared/contracts/ai.d.ts.map +1 -0
  162. package/dist/shared/contracts/homepage.d.ts +27 -0
  163. package/dist/shared/contracts/homepage.d.ts.map +1 -1
  164. package/dist/shared/contracts/users.d.ts +16 -0
  165. package/dist/shared/contracts/users.d.ts.map +1 -1
  166. package/package.json +9 -9
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai.js","sources":["../../../../../../../ee/server/src/ai/controllers/ai.ts"],"sourcesContent":["import type { Context } from 'koa';\nimport path from 'path';\nimport fs from 'fs';\nimport crypto from 'crypto';\nimport type { AdminUser } from '../../../../../shared/contracts/shared';\nimport { GetAiToken } from '../../../../../shared/contracts/ai';\n\nexport default {\n async getAiToken(ctx: Context) {\n const ERROR_PREFIX = 'AI token request failed:';\n const USER_ERROR_MESSAGE = 'AI token request failed. Check server logs for details.';\n\n try {\n // Security check: Ensure user is authenticated and has proper permissions\n if (!ctx.state.user) {\n return ctx.unauthorized('Authentication required');\n }\n\n // Check if EE features are enabled first\n if (!strapi.ee?.isEE) {\n strapi.log.error(`${ERROR_PREFIX} Enterprise Edition features are not enabled`);\n return ctx.internalServerError(USER_ERROR_MESSAGE);\n }\n\n // Get the EE license\n // First try environment variable, then try reading from file\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 (error) {\n // License file doesn't exist or can't be read\n }\n }\n\n if (!eeLicense) {\n strapi.log.error(\n `${ERROR_PREFIX} No EE license found. Please ensure STRAPI_LICENSE environment variable is set or license.txt file exists.`\n );\n return ctx.internalServerError(USER_ERROR_MESSAGE);\n }\n\n const aiServerUrl = process.env.STRAPI_AI_URL || 'https://strapi-ai.apps.strapi.io';\n\n if (!aiServerUrl) {\n strapi.log.error(\n `${ERROR_PREFIX} AI server URL not configured. Please set STRAPI_AI_URL environment variable.`\n );\n return ctx.internalServerError(USER_ERROR_MESSAGE);\n }\n\n // Get the current user\n const user = ctx.state.user as AdminUser;\n\n // Create a secure user identifier using only user ID\n const userIdentifier = user.id.toString();\n\n // Get project ID\n const projectId = strapi.config.get('uuid');\n if (!projectId) {\n strapi.log.error(`${ERROR_PREFIX} Project ID not configured`);\n return ctx.internalServerError(USER_ERROR_MESSAGE);\n }\n\n strapi.log.http('Contacting AI Server for token generation');\n\n try {\n // Call the AI server's getAiJWT endpoint\n const response = await fetch(`${aiServerUrl}/auth/getAiJWT`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n // No authorization header needed for public endpoint\n // Add request ID for tracing\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 return ctx.internalServerError(USER_ERROR_MESSAGE);\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 return ctx.internalServerError(USER_ERROR_MESSAGE);\n }\n\n if (!data.jwt) {\n strapi.log.error(`${ERROR_PREFIX} Invalid response: missing JWT token`);\n return ctx.internalServerError(USER_ERROR_MESSAGE);\n }\n\n strapi.log.info('AI token generated successfully', {\n userId: user.id,\n expiresAt: data.expiresAt,\n });\n\n // Return the AI JWT with metadata\n // Note: Token expires in 1 hour, client should handle refresh\n ctx.body = {\n data: {\n token: data.jwt,\n expiresAt: data.expiresAt, // 1 hour from generation\n },\n } satisfies GetAiToken.Response;\n } catch (fetchError) {\n if (fetchError instanceof Error && fetchError.name === 'AbortError') {\n strapi.log.error(`${ERROR_PREFIX} Request to AI server timed out`);\n return ctx.internalServerError(USER_ERROR_MESSAGE);\n }\n\n throw fetchError;\n }\n } catch (error) {\n strapi.log.error(\n `${ERROR_PREFIX} ${error instanceof Error ? error.message : 'Unknown error'}`,\n error\n );\n return ctx.internalServerError(USER_ERROR_MESSAGE);\n }\n },\n async getAiUsage(ctx: Context) {\n const ERROR_PREFIX = 'AI usage data request failed:';\n const USER_ERROR_MESSAGE = 'AI usage data request failed. Check server logs for details.';\n // Security check: Ensure user is authenticated and has proper permissions\n if (!ctx.state.user) {\n return ctx.unauthorized('Authentication required');\n }\n\n // Check if EE features are enabled first\n if (!strapi.ee?.isEE) {\n strapi.log.error(`${ERROR_PREFIX} Enterprise Edition features are not enabled`);\n return ctx.internalServerError(USER_ERROR_MESSAGE);\n }\n\n // Get the EE license\n // First try environment variable, then try reading from file\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 (error) {\n // License file doesn't exist or can't be read\n }\n }\n\n if (!eeLicense) {\n strapi.log.error(\n `${ERROR_PREFIX} No EE license found. Please ensure STRAPI_LICENSE environment variable is set or license.txt file exists.`\n );\n return ctx.internalServerError(USER_ERROR_MESSAGE);\n }\n\n const aiServerUrl = process.env.STRAPI_AI_URL || 'https://strapi-ai.apps.strapi.io';\n\n if (!aiServerUrl) {\n strapi.log.error(\n `${ERROR_PREFIX} AI server URL not configured. Please set STRAPI_AI_URL or STRAPI_AI_URL environment variable.`\n );\n return ctx.internalServerError(USER_ERROR_MESSAGE);\n }\n\n // Get project ID\n const projectId = strapi.config.get('uuid');\n if (!projectId) {\n strapi.log.error(`${ERROR_PREFIX} Project ID not configured`);\n return ctx.internalServerError(USER_ERROR_MESSAGE);\n }\n\n try {\n // Call the AI server's getAiJWT endpoint\n const response = await fetch(`${aiServerUrl}/cms/ai-data`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n // No authorization header needed for public endpoint\n // Add request ID for tracing\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 return ctx.internalServerError(USER_ERROR_MESSAGE);\n }\n\n let data;\n try {\n data = (await response.json()) as {\n data: {\n cmsAiCreditsUsed: number;\n };\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 return ctx.internalServerError(USER_ERROR_MESSAGE);\n }\n\n ctx.body = {\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 return ctx.internalServerError(USER_ERROR_MESSAGE);\n }\n\n throw fetchError;\n }\n },\n};\n"],"names":["getAiToken","ctx","ERROR_PREFIX","USER_ERROR_MESSAGE","state","user","unauthorized","strapi","ee","isEE","log","error","internalServerError","eeLicense","process","env","STRAPI_LICENSE","licensePath","path","join","dirs","app","root","fs","readFileSync","toString","aiServerUrl","STRAPI_AI_URL","userIdentifier","id","projectId","config","get","http","response","fetch","method","headers","crypto","randomUUID","body","JSON","stringify","ok","errorData","errorText","text","parse","status","statusText","data","json","parseError","jwt","info","userId","expiresAt","token","fetchError","Error","name","message","getAiUsage","eeKey","subscription"],"mappings":"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"}
@@ -0,0 +1,216 @@
1
+ import path from 'path';
2
+ import fs from 'fs';
3
+ import crypto from 'crypto';
4
+
5
+ var aiController = {
6
+ async getAiToken (ctx) {
7
+ const ERROR_PREFIX = 'AI token request failed:';
8
+ const USER_ERROR_MESSAGE = 'AI token request failed. Check server logs for details.';
9
+ try {
10
+ // Security check: Ensure user is authenticated and has proper permissions
11
+ if (!ctx.state.user) {
12
+ return ctx.unauthorized('Authentication required');
13
+ }
14
+ // Check if EE features are enabled first
15
+ if (!strapi.ee?.isEE) {
16
+ strapi.log.error(`${ERROR_PREFIX} Enterprise Edition features are not enabled`);
17
+ return ctx.internalServerError(USER_ERROR_MESSAGE);
18
+ }
19
+ // Get the EE license
20
+ // First try environment variable, then try reading from file
21
+ let eeLicense = process.env.STRAPI_LICENSE;
22
+ if (!eeLicense) {
23
+ try {
24
+ const licensePath = path.join(strapi.dirs.app.root, 'license.txt');
25
+ eeLicense = fs.readFileSync(licensePath).toString();
26
+ } catch (error) {
27
+ // License file doesn't exist or can't be read
28
+ }
29
+ }
30
+ if (!eeLicense) {
31
+ strapi.log.error(`${ERROR_PREFIX} No EE license found. Please ensure STRAPI_LICENSE environment variable is set or license.txt file exists.`);
32
+ return ctx.internalServerError(USER_ERROR_MESSAGE);
33
+ }
34
+ const aiServerUrl = process.env.STRAPI_AI_URL || 'https://strapi-ai.apps.strapi.io';
35
+ if (!aiServerUrl) {
36
+ strapi.log.error(`${ERROR_PREFIX} AI server URL not configured. Please set STRAPI_AI_URL environment variable.`);
37
+ return ctx.internalServerError(USER_ERROR_MESSAGE);
38
+ }
39
+ // Get the current user
40
+ const user = ctx.state.user;
41
+ // Create a secure user identifier using only user ID
42
+ const userIdentifier = user.id.toString();
43
+ // Get project ID
44
+ const projectId = strapi.config.get('uuid');
45
+ if (!projectId) {
46
+ strapi.log.error(`${ERROR_PREFIX} Project ID not configured`);
47
+ return ctx.internalServerError(USER_ERROR_MESSAGE);
48
+ }
49
+ strapi.log.http('Contacting AI Server for token generation');
50
+ try {
51
+ // Call the AI server's getAiJWT endpoint
52
+ const response = await fetch(`${aiServerUrl}/auth/getAiJWT`, {
53
+ method: 'POST',
54
+ headers: {
55
+ 'Content-Type': 'application/json',
56
+ // No authorization header needed for public endpoint
57
+ // Add request ID for tracing
58
+ 'X-Request-Id': crypto.randomUUID()
59
+ },
60
+ body: JSON.stringify({
61
+ eeLicense,
62
+ userIdentifier,
63
+ projectId
64
+ })
65
+ });
66
+ if (!response.ok) {
67
+ let errorData;
68
+ let errorText;
69
+ try {
70
+ errorText = await response.text();
71
+ errorData = JSON.parse(errorText);
72
+ } catch {
73
+ errorData = {
74
+ error: errorText || 'Failed to parse error response'
75
+ };
76
+ }
77
+ strapi.log.error(`${ERROR_PREFIX} ${errorData?.error || 'Unknown error'}`, {
78
+ status: response.status,
79
+ statusText: response.statusText,
80
+ error: errorData,
81
+ errorText,
82
+ projectId
83
+ });
84
+ return ctx.internalServerError(USER_ERROR_MESSAGE);
85
+ }
86
+ let data;
87
+ try {
88
+ data = await response.json();
89
+ } catch (parseError) {
90
+ strapi.log.error(`${ERROR_PREFIX} Failed to parse AI server response`, parseError);
91
+ return ctx.internalServerError(USER_ERROR_MESSAGE);
92
+ }
93
+ if (!data.jwt) {
94
+ strapi.log.error(`${ERROR_PREFIX} Invalid response: missing JWT token`);
95
+ return ctx.internalServerError(USER_ERROR_MESSAGE);
96
+ }
97
+ strapi.log.info('AI token generated successfully', {
98
+ userId: user.id,
99
+ expiresAt: data.expiresAt
100
+ });
101
+ // Return the AI JWT with metadata
102
+ // Note: Token expires in 1 hour, client should handle refresh
103
+ ctx.body = {
104
+ data: {
105
+ token: data.jwt,
106
+ expiresAt: data.expiresAt
107
+ }
108
+ };
109
+ } catch (fetchError) {
110
+ if (fetchError instanceof Error && fetchError.name === 'AbortError') {
111
+ strapi.log.error(`${ERROR_PREFIX} Request to AI server timed out`);
112
+ return ctx.internalServerError(USER_ERROR_MESSAGE);
113
+ }
114
+ throw fetchError;
115
+ }
116
+ } catch (error) {
117
+ strapi.log.error(`${ERROR_PREFIX} ${error instanceof Error ? error.message : 'Unknown error'}`, error);
118
+ return ctx.internalServerError(USER_ERROR_MESSAGE);
119
+ }
120
+ },
121
+ async getAiUsage (ctx) {
122
+ const ERROR_PREFIX = 'AI usage data request failed:';
123
+ const USER_ERROR_MESSAGE = 'AI usage data request failed. Check server logs for details.';
124
+ // Security check: Ensure user is authenticated and has proper permissions
125
+ if (!ctx.state.user) {
126
+ return ctx.unauthorized('Authentication required');
127
+ }
128
+ // Check if EE features are enabled first
129
+ if (!strapi.ee?.isEE) {
130
+ strapi.log.error(`${ERROR_PREFIX} Enterprise Edition features are not enabled`);
131
+ return ctx.internalServerError(USER_ERROR_MESSAGE);
132
+ }
133
+ // Get the EE license
134
+ // First try environment variable, then try reading from file
135
+ let eeLicense = process.env.STRAPI_LICENSE;
136
+ if (!eeLicense) {
137
+ try {
138
+ const licensePath = path.join(strapi.dirs.app.root, 'license.txt');
139
+ eeLicense = fs.readFileSync(licensePath).toString();
140
+ } catch (error) {
141
+ // License file doesn't exist or can't be read
142
+ }
143
+ }
144
+ if (!eeLicense) {
145
+ strapi.log.error(`${ERROR_PREFIX} No EE license found. Please ensure STRAPI_LICENSE environment variable is set or license.txt file exists.`);
146
+ return ctx.internalServerError(USER_ERROR_MESSAGE);
147
+ }
148
+ const aiServerUrl = process.env.STRAPI_AI_URL || 'https://strapi-ai.apps.strapi.io';
149
+ if (!aiServerUrl) {
150
+ strapi.log.error(`${ERROR_PREFIX} AI server URL not configured. Please set STRAPI_AI_URL or STRAPI_AI_URL environment variable.`);
151
+ return ctx.internalServerError(USER_ERROR_MESSAGE);
152
+ }
153
+ // Get project ID
154
+ const projectId = strapi.config.get('uuid');
155
+ if (!projectId) {
156
+ strapi.log.error(`${ERROR_PREFIX} Project ID not configured`);
157
+ return ctx.internalServerError(USER_ERROR_MESSAGE);
158
+ }
159
+ try {
160
+ // Call the AI server's getAiJWT endpoint
161
+ const response = await fetch(`${aiServerUrl}/cms/ai-data`, {
162
+ method: 'POST',
163
+ headers: {
164
+ 'Content-Type': 'application/json',
165
+ // No authorization header needed for public endpoint
166
+ // Add request ID for tracing
167
+ 'X-Request-Id': crypto.randomUUID()
168
+ },
169
+ body: JSON.stringify({
170
+ eeKey: eeLicense,
171
+ projectId
172
+ })
173
+ });
174
+ if (!response.ok) {
175
+ let errorData;
176
+ let errorText;
177
+ try {
178
+ errorText = await response.text();
179
+ errorData = JSON.parse(errorText);
180
+ } catch {
181
+ errorData = {
182
+ error: errorText || 'Failed to parse error response'
183
+ };
184
+ }
185
+ strapi.log.error(`${ERROR_PREFIX} ${errorData?.error || 'Unknown error'}`, {
186
+ status: response.status,
187
+ statusText: response.statusText,
188
+ error: errorData,
189
+ errorText,
190
+ projectId
191
+ });
192
+ return ctx.internalServerError(USER_ERROR_MESSAGE);
193
+ }
194
+ let data;
195
+ try {
196
+ data = await response.json();
197
+ } catch (parseError) {
198
+ strapi.log.error(`${ERROR_PREFIX} Failed to parse AI server response`, parseError);
199
+ return ctx.internalServerError(USER_ERROR_MESSAGE);
200
+ }
201
+ ctx.body = {
202
+ ...data.data,
203
+ subscription: data.subscription
204
+ };
205
+ } catch (fetchError) {
206
+ if (fetchError instanceof Error && fetchError.name === 'AbortError') {
207
+ strapi.log.error(`${ERROR_PREFIX} Request to AI server timed out`);
208
+ return ctx.internalServerError(USER_ERROR_MESSAGE);
209
+ }
210
+ throw fetchError;
211
+ }
212
+ }
213
+ };
214
+
215
+ export { aiController as default };
216
+ //# sourceMappingURL=ai.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai.mjs","sources":["../../../../../../../ee/server/src/ai/controllers/ai.ts"],"sourcesContent":["import type { Context } from 'koa';\nimport path from 'path';\nimport fs from 'fs';\nimport crypto from 'crypto';\nimport type { AdminUser } from '../../../../../shared/contracts/shared';\nimport { GetAiToken } from '../../../../../shared/contracts/ai';\n\nexport default {\n async getAiToken(ctx: Context) {\n const ERROR_PREFIX = 'AI token request failed:';\n const USER_ERROR_MESSAGE = 'AI token request failed. Check server logs for details.';\n\n try {\n // Security check: Ensure user is authenticated and has proper permissions\n if (!ctx.state.user) {\n return ctx.unauthorized('Authentication required');\n }\n\n // Check if EE features are enabled first\n if (!strapi.ee?.isEE) {\n strapi.log.error(`${ERROR_PREFIX} Enterprise Edition features are not enabled`);\n return ctx.internalServerError(USER_ERROR_MESSAGE);\n }\n\n // Get the EE license\n // First try environment variable, then try reading from file\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 (error) {\n // License file doesn't exist or can't be read\n }\n }\n\n if (!eeLicense) {\n strapi.log.error(\n `${ERROR_PREFIX} No EE license found. Please ensure STRAPI_LICENSE environment variable is set or license.txt file exists.`\n );\n return ctx.internalServerError(USER_ERROR_MESSAGE);\n }\n\n const aiServerUrl = process.env.STRAPI_AI_URL || 'https://strapi-ai.apps.strapi.io';\n\n if (!aiServerUrl) {\n strapi.log.error(\n `${ERROR_PREFIX} AI server URL not configured. Please set STRAPI_AI_URL environment variable.`\n );\n return ctx.internalServerError(USER_ERROR_MESSAGE);\n }\n\n // Get the current user\n const user = ctx.state.user as AdminUser;\n\n // Create a secure user identifier using only user ID\n const userIdentifier = user.id.toString();\n\n // Get project ID\n const projectId = strapi.config.get('uuid');\n if (!projectId) {\n strapi.log.error(`${ERROR_PREFIX} Project ID not configured`);\n return ctx.internalServerError(USER_ERROR_MESSAGE);\n }\n\n strapi.log.http('Contacting AI Server for token generation');\n\n try {\n // Call the AI server's getAiJWT endpoint\n const response = await fetch(`${aiServerUrl}/auth/getAiJWT`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n // No authorization header needed for public endpoint\n // Add request ID for tracing\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 return ctx.internalServerError(USER_ERROR_MESSAGE);\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 return ctx.internalServerError(USER_ERROR_MESSAGE);\n }\n\n if (!data.jwt) {\n strapi.log.error(`${ERROR_PREFIX} Invalid response: missing JWT token`);\n return ctx.internalServerError(USER_ERROR_MESSAGE);\n }\n\n strapi.log.info('AI token generated successfully', {\n userId: user.id,\n expiresAt: data.expiresAt,\n });\n\n // Return the AI JWT with metadata\n // Note: Token expires in 1 hour, client should handle refresh\n ctx.body = {\n data: {\n token: data.jwt,\n expiresAt: data.expiresAt, // 1 hour from generation\n },\n } satisfies GetAiToken.Response;\n } catch (fetchError) {\n if (fetchError instanceof Error && fetchError.name === 'AbortError') {\n strapi.log.error(`${ERROR_PREFIX} Request to AI server timed out`);\n return ctx.internalServerError(USER_ERROR_MESSAGE);\n }\n\n throw fetchError;\n }\n } catch (error) {\n strapi.log.error(\n `${ERROR_PREFIX} ${error instanceof Error ? error.message : 'Unknown error'}`,\n error\n );\n return ctx.internalServerError(USER_ERROR_MESSAGE);\n }\n },\n async getAiUsage(ctx: Context) {\n const ERROR_PREFIX = 'AI usage data request failed:';\n const USER_ERROR_MESSAGE = 'AI usage data request failed. Check server logs for details.';\n // Security check: Ensure user is authenticated and has proper permissions\n if (!ctx.state.user) {\n return ctx.unauthorized('Authentication required');\n }\n\n // Check if EE features are enabled first\n if (!strapi.ee?.isEE) {\n strapi.log.error(`${ERROR_PREFIX} Enterprise Edition features are not enabled`);\n return ctx.internalServerError(USER_ERROR_MESSAGE);\n }\n\n // Get the EE license\n // First try environment variable, then try reading from file\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 (error) {\n // License file doesn't exist or can't be read\n }\n }\n\n if (!eeLicense) {\n strapi.log.error(\n `${ERROR_PREFIX} No EE license found. Please ensure STRAPI_LICENSE environment variable is set or license.txt file exists.`\n );\n return ctx.internalServerError(USER_ERROR_MESSAGE);\n }\n\n const aiServerUrl = process.env.STRAPI_AI_URL || 'https://strapi-ai.apps.strapi.io';\n\n if (!aiServerUrl) {\n strapi.log.error(\n `${ERROR_PREFIX} AI server URL not configured. Please set STRAPI_AI_URL or STRAPI_AI_URL environment variable.`\n );\n return ctx.internalServerError(USER_ERROR_MESSAGE);\n }\n\n // Get project ID\n const projectId = strapi.config.get('uuid');\n if (!projectId) {\n strapi.log.error(`${ERROR_PREFIX} Project ID not configured`);\n return ctx.internalServerError(USER_ERROR_MESSAGE);\n }\n\n try {\n // Call the AI server's getAiJWT endpoint\n const response = await fetch(`${aiServerUrl}/cms/ai-data`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n // No authorization header needed for public endpoint\n // Add request ID for tracing\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 return ctx.internalServerError(USER_ERROR_MESSAGE);\n }\n\n let data;\n try {\n data = (await response.json()) as {\n data: {\n cmsAiCreditsUsed: number;\n };\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 return ctx.internalServerError(USER_ERROR_MESSAGE);\n }\n\n ctx.body = {\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 return ctx.internalServerError(USER_ERROR_MESSAGE);\n }\n\n throw fetchError;\n }\n },\n};\n"],"names":["getAiToken","ctx","ERROR_PREFIX","USER_ERROR_MESSAGE","state","user","unauthorized","strapi","ee","isEE","log","error","internalServerError","eeLicense","process","env","STRAPI_LICENSE","licensePath","path","join","dirs","app","root","fs","readFileSync","toString","aiServerUrl","STRAPI_AI_URL","userIdentifier","id","projectId","config","get","http","response","fetch","method","headers","crypto","randomUUID","body","JSON","stringify","ok","errorData","errorText","text","parse","status","statusText","data","json","parseError","jwt","info","userId","expiresAt","token","fetchError","Error","name","message","getAiUsage","eeKey","subscription"],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ 'use strict';
2
+
3
+ var aiRoutes = {
4
+ type: 'admin',
5
+ routes: [
6
+ // ai data usage
7
+ {
8
+ method: 'GET',
9
+ path: '/ai-usage',
10
+ handler: 'ai.getAiUsage',
11
+ config: {
12
+ policies: [
13
+ 'admin::isAuthenticatedAdmin'
14
+ ]
15
+ }
16
+ },
17
+ // get ai token
18
+ {
19
+ method: 'GET',
20
+ path: '/ai-token',
21
+ handler: 'ai.getAiToken',
22
+ config: {
23
+ policies: [
24
+ 'admin::isAuthenticatedAdmin'
25
+ ]
26
+ }
27
+ }
28
+ ]
29
+ };
30
+
31
+ module.exports = aiRoutes;
32
+ //# sourceMappingURL=ai.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai.js","sources":["../../../../../../../ee/server/src/ai/routes/ai.ts"],"sourcesContent":["export default {\n type: 'admin',\n routes: [\n // ai data usage\n {\n method: 'GET',\n path: '/ai-usage',\n handler: 'ai.getAiUsage',\n config: {\n policies: ['admin::isAuthenticatedAdmin'],\n },\n },\n // get ai token\n {\n method: 'GET',\n path: '/ai-token',\n handler: 'ai.getAiToken',\n config: {\n policies: ['admin::isAuthenticatedAdmin'],\n },\n },\n ],\n};\n"],"names":["type","routes","method","path","handler","config","policies"],"mappings":";;AAAA,eAAe;IACbA,IAAM,EAAA,OAAA;IACNC,MAAQ,EAAA;;AAEN,QAAA;YACEC,MAAQ,EAAA,KAAA;YACRC,IAAM,EAAA,WAAA;YACNC,OAAS,EAAA,eAAA;YACTC,MAAQ,EAAA;gBACNC,QAAU,EAAA;AAAC,oBAAA;AAA8B;AAC3C;AACF,SAAA;;AAEA,QAAA;YACEJ,MAAQ,EAAA,KAAA;YACRC,IAAM,EAAA,WAAA;YACNC,OAAS,EAAA,eAAA;YACTC,MAAQ,EAAA;gBACNC,QAAU,EAAA;AAAC,oBAAA;AAA8B;AAC3C;AACF;AACD;AACH,CAAE;;;;"}
@@ -0,0 +1,30 @@
1
+ var aiRoutes = {
2
+ type: 'admin',
3
+ routes: [
4
+ // ai data usage
5
+ {
6
+ method: 'GET',
7
+ path: '/ai-usage',
8
+ handler: 'ai.getAiUsage',
9
+ config: {
10
+ policies: [
11
+ 'admin::isAuthenticatedAdmin'
12
+ ]
13
+ }
14
+ },
15
+ // get ai token
16
+ {
17
+ method: 'GET',
18
+ path: '/ai-token',
19
+ handler: 'ai.getAiToken',
20
+ config: {
21
+ policies: [
22
+ 'admin::isAuthenticatedAdmin'
23
+ ]
24
+ }
25
+ }
26
+ ]
27
+ };
28
+
29
+ export { aiRoutes as default };
30
+ //# sourceMappingURL=ai.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai.mjs","sources":["../../../../../../../ee/server/src/ai/routes/ai.ts"],"sourcesContent":["export default {\n type: 'admin',\n routes: [\n // ai data usage\n {\n method: 'GET',\n path: '/ai-usage',\n handler: 'ai.getAiUsage',\n config: {\n policies: ['admin::isAuthenticatedAdmin'],\n },\n },\n // get ai token\n {\n method: 'GET',\n path: '/ai-token',\n handler: 'ai.getAiToken',\n config: {\n policies: ['admin::isAuthenticatedAdmin'],\n },\n },\n ],\n};\n"],"names":["type","routes","method","path","handler","config","policies"],"mappings":"AAAA,eAAe;IACbA,IAAM,EAAA,OAAA;IACNC,MAAQ,EAAA;;AAEN,QAAA;YACEC,MAAQ,EAAA,KAAA;YACRC,IAAM,EAAA,WAAA;YACNC,OAAS,EAAA,eAAA;YACTC,MAAQ,EAAA;gBACNC,QAAU,EAAA;AAAC,oBAAA;AAA8B;AAC3C;AACF,SAAA;;AAEA,QAAA;YACEJ,MAAQ,EAAA,KAAA;YACRC,IAAM,EAAA,WAAA;YACNC,OAAS,EAAA,eAAA;YACTC,MAAQ,EAAA;gBACNC,QAAU,EAAA;AAAC,oBAAA;AAA8B;AAC3C;AACF;AACD;AACH,CAAE;;;;"}
@@ -8,6 +8,7 @@ var admin = {
8
8
  // NOTE: Overrides CE admin controller
9
9
  async getProjectType () {
10
10
  const flags = strapi.config.get('admin.flags', {});
11
+ const ai = strapi.config.get('admin.ai', {});
11
12
  try {
12
13
  return {
13
14
  data: {
@@ -15,7 +16,8 @@ var admin = {
15
16
  isTrial: strapi.ee.isTrial,
16
17
  features: strapi.ee.features.list(),
17
18
  flags,
18
- type: strapi.ee.type
19
+ type: strapi.ee.type,
20
+ ai
19
21
  }
20
22
  };
21
23
  } catch (err) {
@@ -56,6 +58,7 @@ var admin = {
56
58
  shouldStopCreate: fp.isNil(permittedSeats) ? false : currentActiveUserCount >= permittedSeats,
57
59
  licenseLimitStatus,
58
60
  isHostedOnStrapiCloud: utils.env('STRAPI_HOSTING', null) === 'strapi.cloud',
61
+ aiLicenseKey: utils.env('STRAPI_ADMIN_AI_LICENSE'),
59
62
  type: strapi.ee.type,
60
63
  isTrial: strapi.ee.isTrial,
61
64
  features: strapi.ee.features.list() ?? []
@@ -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';\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 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 },\n };\n } catch (err) {\n return { data: { isEE: false, features: [], flags } };\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","err","licenseLimitInformation","permittedSeats","seats","shouldNotify","licenseLimitStatus","enforcementUserCount","currentActiveUserCount","getService","getCurrentActiveUserCount","eeDisabledUsers","getDisabledUserList","length","isNil","shouldStopCreate","isHostedOnStrapiCloud","env"],"mappings":";;;;;;AAIA,YAAe;;IAEb,MAAMA,cAAAA,CAAAA,GAAAA;AACJ,QAAA,MAAMC,QAAQC,MAAOC,CAAAA,MAAM,CAACC,GAAG,CAAC,eAAe,EAAC,CAAA;QAChD,IAAI;YACF,OAAO;gBACLC,IAAM,EAAA;AACJC,oBAAAA,IAAAA,EAAMJ,OAAOK,EAAE;oBACfC,OAASN,EAAAA,MAAAA,CAAOO,EAAE,CAACD,OAAO;AAC1BE,oBAAAA,QAAAA,EAAUR,MAAOO,CAAAA,EAAE,CAACC,QAAQ,CAACC,IAAI,EAAA;AACjCV,oBAAAA,KAAAA;oBACAW,IAAMV,EAAAA,MAAAA,CAAOO,EAAE,CAACG;AAClB;AACF,aAAA;AACF,SAAA,CAAE,OAAOC,GAAK,EAAA;YACZ,OAAO;gBAAER,IAAM,EAAA;oBAAEC,IAAM,EAAA,KAAA;AAAOI,oBAAAA,QAAAA,EAAU,EAAE;AAAET,oBAAAA;AAAM;AAAE,aAAA;AACtD;AACF,KAAA;IAEA,MAAMa,uBAAAA,CAAAA,GAAAA;AACJ,QAAA,MAAMC,cAAiBb,GAAAA,MAAAA,CAAOO,EAAE,CAACO,KAAK;AAEtC,QAAA,IAAIC,YAAe,GAAA,KAAA;AACnB,QAAA,IAAIC,kBAAqB,GAAA,IAAA;QACzB,IAAIC,oBAAAA;AAEJ,QAAA,MAAMC,sBAAyB,GAAA,MAAMC,gBAAW,CAAA,MAAA,CAAA,CAAQC,yBAAyB,EAAA;AAEjF,QAAA,MAAMC,eAAkB,GAAA,MAAMF,gBAAW,CAAA,kBAAA,CAAA,CAAoBG,mBAAmB,EAAA;AAEhF,QAAA,IAAID,eAAiB,EAAA;YACnBJ,oBAAuBC,GAAAA,sBAAAA,GAAyBG,gBAAgBE,MAAM;SACjE,MAAA;YACLN,oBAAuBC,GAAAA,sBAAAA;AACzB;AAEA,QAAA,IAAI,CAACM,QAAAA,CAAMX,cAAmBI,CAAAA,IAAAA,oBAAAA,GAAuBJ,cAAgB,EAAA;YACnEE,YAAe,GAAA,IAAA;YACfC,kBAAqB,GAAA,YAAA;AACvB;AAEA,QAAA,IAAI,CAACQ,QAAAA,CAAMX,cAAmBI,CAAAA,IAAAA,oBAAAA,KAAyBJ,cAAgB,EAAA;YACrEE,YAAe,GAAA,IAAA;YACfC,kBAAqB,GAAA,UAAA;AACvB;AAEA,QAAA,MAAMb,IAAO,GAAA;AACXc,YAAAA,oBAAAA;AACAC,YAAAA,sBAAAA;AACAL,YAAAA,cAAAA;AACAE,YAAAA,YAAAA;YACAU,gBAAkBD,EAAAA,QAAAA,CAAMX,cAAkB,CAAA,GAAA,KAAA,GAAQK,sBAA0BL,IAAAA,cAAAA;AAC5EG,YAAAA,kBAAAA;YACAU,qBAAuBC,EAAAA,SAAAA,CAAI,kBAAkB,IAAU,CAAA,KAAA,cAAA;YACvDjB,IAAMV,EAAAA,MAAAA,CAAOO,EAAE,CAACG,IAAI;YACpBJ,OAASN,EAAAA,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;AACF,CAAE;;;;"}
1
+ {"version":3,"file":"admin.js","sources":["../../../../../../ee/server/src/controllers/admin.ts"],"sourcesContent":["import type { Context } from 'koa';\nimport { isNil } from 'lodash/fp';\nimport { env } from '@strapi/utils';\nimport { getService } from '../utils';\nimport path from 'path';\nimport fs from 'fs';\nimport crypto from 'crypto';\n\nexport default {\n // NOTE: Overrides CE admin controller\n async getProjectType() {\n const flags = strapi.config.get('admin.flags', {});\n const ai = strapi.config.get('admin.ai', {});\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 ai,\n },\n };\n } catch (err) {\n return { data: { isEE: false, features: [], flags } };\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 aiLicenseKey: env('STRAPI_ADMIN_AI_LICENSE'),\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","ai","data","isEE","EE","isTrial","ee","features","list","type","err","licenseLimitInformation","permittedSeats","seats","shouldNotify","licenseLimitStatus","enforcementUserCount","currentActiveUserCount","getService","getCurrentActiveUserCount","eeDisabledUsers","getDisabledUserList","length","isNil","shouldStopCreate","isHostedOnStrapiCloud","env","aiLicenseKey"],"mappings":";;;;;;AAQA,YAAe;;IAEb,MAAMA,cAAAA,CAAAA,GAAAA;AACJ,QAAA,MAAMC,QAAQC,MAAOC,CAAAA,MAAM,CAACC,GAAG,CAAC,eAAe,EAAC,CAAA;AAChD,QAAA,MAAMC,KAAKH,MAAOC,CAAAA,MAAM,CAACC,GAAG,CAAC,YAAY,EAAC,CAAA;QAC1C,IAAI;YACF,OAAO;gBACLE,IAAM,EAAA;AACJC,oBAAAA,IAAAA,EAAML,OAAOM,EAAE;oBACfC,OAASP,EAAAA,MAAAA,CAAOQ,EAAE,CAACD,OAAO;AAC1BE,oBAAAA,QAAAA,EAAUT,MAAOQ,CAAAA,EAAE,CAACC,QAAQ,CAACC,IAAI,EAAA;AACjCX,oBAAAA,KAAAA;oBACAY,IAAMX,EAAAA,MAAAA,CAAOQ,EAAE,CAACG,IAAI;AACpBR,oBAAAA;AACF;AACF,aAAA;AACF,SAAA,CAAE,OAAOS,GAAK,EAAA;YACZ,OAAO;gBAAER,IAAM,EAAA;oBAAEC,IAAM,EAAA,KAAA;AAAOI,oBAAAA,QAAAA,EAAU,EAAE;AAAEV,oBAAAA;AAAM;AAAE,aAAA;AACtD;AACF,KAAA;IAEA,MAAMc,uBAAAA,CAAAA,GAAAA;AACJ,QAAA,MAAMC,cAAiBd,GAAAA,MAAAA,CAAOQ,EAAE,CAACO,KAAK;AAEtC,QAAA,IAAIC,YAAe,GAAA,KAAA;AACnB,QAAA,IAAIC,kBAAqB,GAAA,IAAA;QACzB,IAAIC,oBAAAA;AAEJ,QAAA,MAAMC,sBAAyB,GAAA,MAAMC,gBAAW,CAAA,MAAA,CAAA,CAAQC,yBAAyB,EAAA;AAEjF,QAAA,MAAMC,eAAkB,GAAA,MAAMF,gBAAW,CAAA,kBAAA,CAAA,CAAoBG,mBAAmB,EAAA;AAEhF,QAAA,IAAID,eAAiB,EAAA;YACnBJ,oBAAuBC,GAAAA,sBAAAA,GAAyBG,gBAAgBE,MAAM;SACjE,MAAA;YACLN,oBAAuBC,GAAAA,sBAAAA;AACzB;AAEA,QAAA,IAAI,CAACM,QAAAA,CAAMX,cAAmBI,CAAAA,IAAAA,oBAAAA,GAAuBJ,cAAgB,EAAA;YACnEE,YAAe,GAAA,IAAA;YACfC,kBAAqB,GAAA,YAAA;AACvB;AAEA,QAAA,IAAI,CAACQ,QAAAA,CAAMX,cAAmBI,CAAAA,IAAAA,oBAAAA,KAAyBJ,cAAgB,EAAA;YACrEE,YAAe,GAAA,IAAA;YACfC,kBAAqB,GAAA,UAAA;AACvB;AAEA,QAAA,MAAMb,IAAO,GAAA;AACXc,YAAAA,oBAAAA;AACAC,YAAAA,sBAAAA;AACAL,YAAAA,cAAAA;AACAE,YAAAA,YAAAA;YACAU,gBAAkBD,EAAAA,QAAAA,CAAMX,cAAkB,CAAA,GAAA,KAAA,GAAQK,sBAA0BL,IAAAA,cAAAA;AAC5EG,YAAAA,kBAAAA;YACAU,qBAAuBC,EAAAA,SAAAA,CAAI,kBAAkB,IAAU,CAAA,KAAA,cAAA;AACvDC,YAAAA,YAAAA,EAAcD,SAAI,CAAA,yBAAA,CAAA;YAClBjB,IAAMX,EAAAA,MAAAA,CAAOQ,EAAE,CAACG,IAAI;YACpBJ,OAASP,EAAAA,MAAAA,CAAOQ,EAAE,CAACD,OAAO;AAC1BE,YAAAA,QAAAA,EAAUT,OAAOQ,EAAE,CAACC,QAAQ,CAACC,IAAI,MAAM;AACzC,SAAA;QAEA,OAAO;AAAEN,YAAAA;AAAK,SAAA;AAChB;AACF,CAAE;;;;"}
@@ -6,6 +6,7 @@ var admin = {
6
6
  // NOTE: Overrides CE admin controller
7
7
  async getProjectType () {
8
8
  const flags = strapi.config.get('admin.flags', {});
9
+ const ai = strapi.config.get('admin.ai', {});
9
10
  try {
10
11
  return {
11
12
  data: {
@@ -13,7 +14,8 @@ var admin = {
13
14
  isTrial: strapi.ee.isTrial,
14
15
  features: strapi.ee.features.list(),
15
16
  flags,
16
- type: strapi.ee.type
17
+ type: strapi.ee.type,
18
+ ai
17
19
  }
18
20
  };
19
21
  } catch (err) {
@@ -54,6 +56,7 @@ var admin = {
54
56
  shouldStopCreate: isNil(permittedSeats) ? false : currentActiveUserCount >= permittedSeats,
55
57
  licenseLimitStatus,
56
58
  isHostedOnStrapiCloud: env('STRAPI_HOSTING', null) === 'strapi.cloud',
59
+ aiLicenseKey: env('STRAPI_ADMIN_AI_LICENSE'),
57
60
  type: strapi.ee.type,
58
61
  isTrial: strapi.ee.isTrial,
59
62
  features: strapi.ee.features.list() ?? []
@@ -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';\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 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 },\n };\n } catch (err) {\n return { data: { isEE: false, features: [], flags } };\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","err","licenseLimitInformation","permittedSeats","seats","shouldNotify","licenseLimitStatus","enforcementUserCount","currentActiveUserCount","getService","getCurrentActiveUserCount","eeDisabledUsers","getDisabledUserList","length","isNil","shouldStopCreate","isHostedOnStrapiCloud","env"],"mappings":";;;;AAIA,YAAe;;IAEb,MAAMA,cAAAA,CAAAA,GAAAA;AACJ,QAAA,MAAMC,QAAQC,MAAOC,CAAAA,MAAM,CAACC,GAAG,CAAC,eAAe,EAAC,CAAA;QAChD,IAAI;YACF,OAAO;gBACLC,IAAM,EAAA;AACJC,oBAAAA,IAAAA,EAAMJ,OAAOK,EAAE;oBACfC,OAASN,EAAAA,MAAAA,CAAOO,EAAE,CAACD,OAAO;AAC1BE,oBAAAA,QAAAA,EAAUR,MAAOO,CAAAA,EAAE,CAACC,QAAQ,CAACC,IAAI,EAAA;AACjCV,oBAAAA,KAAAA;oBACAW,IAAMV,EAAAA,MAAAA,CAAOO,EAAE,CAACG;AAClB;AACF,aAAA;AACF,SAAA,CAAE,OAAOC,GAAK,EAAA;YACZ,OAAO;gBAAER,IAAM,EAAA;oBAAEC,IAAM,EAAA,KAAA;AAAOI,oBAAAA,QAAAA,EAAU,EAAE;AAAET,oBAAAA;AAAM;AAAE,aAAA;AACtD;AACF,KAAA;IAEA,MAAMa,uBAAAA,CAAAA,GAAAA;AACJ,QAAA,MAAMC,cAAiBb,GAAAA,MAAAA,CAAOO,EAAE,CAACO,KAAK;AAEtC,QAAA,IAAIC,YAAe,GAAA,KAAA;AACnB,QAAA,IAAIC,kBAAqB,GAAA,IAAA;QACzB,IAAIC,oBAAAA;AAEJ,QAAA,MAAMC,sBAAyB,GAAA,MAAMC,UAAW,CAAA,MAAA,CAAA,CAAQC,yBAAyB,EAAA;AAEjF,QAAA,MAAMC,eAAkB,GAAA,MAAMF,UAAW,CAAA,kBAAA,CAAA,CAAoBG,mBAAmB,EAAA;AAEhF,QAAA,IAAID,eAAiB,EAAA;YACnBJ,oBAAuBC,GAAAA,sBAAAA,GAAyBG,gBAAgBE,MAAM;SACjE,MAAA;YACLN,oBAAuBC,GAAAA,sBAAAA;AACzB;AAEA,QAAA,IAAI,CAACM,KAAAA,CAAMX,cAAmBI,CAAAA,IAAAA,oBAAAA,GAAuBJ,cAAgB,EAAA;YACnEE,YAAe,GAAA,IAAA;YACfC,kBAAqB,GAAA,YAAA;AACvB;AAEA,QAAA,IAAI,CAACQ,KAAAA,CAAMX,cAAmBI,CAAAA,IAAAA,oBAAAA,KAAyBJ,cAAgB,EAAA;YACrEE,YAAe,GAAA,IAAA;YACfC,kBAAqB,GAAA,UAAA;AACvB;AAEA,QAAA,MAAMb,IAAO,GAAA;AACXc,YAAAA,oBAAAA;AACAC,YAAAA,sBAAAA;AACAL,YAAAA,cAAAA;AACAE,YAAAA,YAAAA;YACAU,gBAAkBD,EAAAA,KAAAA,CAAMX,cAAkB,CAAA,GAAA,KAAA,GAAQK,sBAA0BL,IAAAA,cAAAA;AAC5EG,YAAAA,kBAAAA;YACAU,qBAAuBC,EAAAA,GAAAA,CAAI,kBAAkB,IAAU,CAAA,KAAA,cAAA;YACvDjB,IAAMV,EAAAA,MAAAA,CAAOO,EAAE,CAACG,IAAI;YACpBJ,OAASN,EAAAA,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;AACF,CAAE;;;;"}
1
+ {"version":3,"file":"admin.mjs","sources":["../../../../../../ee/server/src/controllers/admin.ts"],"sourcesContent":["import type { Context } from 'koa';\nimport { isNil } from 'lodash/fp';\nimport { env } from '@strapi/utils';\nimport { getService } from '../utils';\nimport path from 'path';\nimport fs from 'fs';\nimport crypto from 'crypto';\n\nexport default {\n // NOTE: Overrides CE admin controller\n async getProjectType() {\n const flags = strapi.config.get('admin.flags', {});\n const ai = strapi.config.get('admin.ai', {});\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 ai,\n },\n };\n } catch (err) {\n return { data: { isEE: false, features: [], flags } };\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 aiLicenseKey: env('STRAPI_ADMIN_AI_LICENSE'),\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","ai","data","isEE","EE","isTrial","ee","features","list","type","err","licenseLimitInformation","permittedSeats","seats","shouldNotify","licenseLimitStatus","enforcementUserCount","currentActiveUserCount","getService","getCurrentActiveUserCount","eeDisabledUsers","getDisabledUserList","length","isNil","shouldStopCreate","isHostedOnStrapiCloud","env","aiLicenseKey"],"mappings":";;;;AAQA,YAAe;;IAEb,MAAMA,cAAAA,CAAAA,GAAAA;AACJ,QAAA,MAAMC,QAAQC,MAAOC,CAAAA,MAAM,CAACC,GAAG,CAAC,eAAe,EAAC,CAAA;AAChD,QAAA,MAAMC,KAAKH,MAAOC,CAAAA,MAAM,CAACC,GAAG,CAAC,YAAY,EAAC,CAAA;QAC1C,IAAI;YACF,OAAO;gBACLE,IAAM,EAAA;AACJC,oBAAAA,IAAAA,EAAML,OAAOM,EAAE;oBACfC,OAASP,EAAAA,MAAAA,CAAOQ,EAAE,CAACD,OAAO;AAC1BE,oBAAAA,QAAAA,EAAUT,MAAOQ,CAAAA,EAAE,CAACC,QAAQ,CAACC,IAAI,EAAA;AACjCX,oBAAAA,KAAAA;oBACAY,IAAMX,EAAAA,MAAAA,CAAOQ,EAAE,CAACG,IAAI;AACpBR,oBAAAA;AACF;AACF,aAAA;AACF,SAAA,CAAE,OAAOS,GAAK,EAAA;YACZ,OAAO;gBAAER,IAAM,EAAA;oBAAEC,IAAM,EAAA,KAAA;AAAOI,oBAAAA,QAAAA,EAAU,EAAE;AAAEV,oBAAAA;AAAM;AAAE,aAAA;AACtD;AACF,KAAA;IAEA,MAAMc,uBAAAA,CAAAA,GAAAA;AACJ,QAAA,MAAMC,cAAiBd,GAAAA,MAAAA,CAAOQ,EAAE,CAACO,KAAK;AAEtC,QAAA,IAAIC,YAAe,GAAA,KAAA;AACnB,QAAA,IAAIC,kBAAqB,GAAA,IAAA;QACzB,IAAIC,oBAAAA;AAEJ,QAAA,MAAMC,sBAAyB,GAAA,MAAMC,UAAW,CAAA,MAAA,CAAA,CAAQC,yBAAyB,EAAA;AAEjF,QAAA,MAAMC,eAAkB,GAAA,MAAMF,UAAW,CAAA,kBAAA,CAAA,CAAoBG,mBAAmB,EAAA;AAEhF,QAAA,IAAID,eAAiB,EAAA;YACnBJ,oBAAuBC,GAAAA,sBAAAA,GAAyBG,gBAAgBE,MAAM;SACjE,MAAA;YACLN,oBAAuBC,GAAAA,sBAAAA;AACzB;AAEA,QAAA,IAAI,CAACM,KAAAA,CAAMX,cAAmBI,CAAAA,IAAAA,oBAAAA,GAAuBJ,cAAgB,EAAA;YACnEE,YAAe,GAAA,IAAA;YACfC,kBAAqB,GAAA,YAAA;AACvB;AAEA,QAAA,IAAI,CAACQ,KAAAA,CAAMX,cAAmBI,CAAAA,IAAAA,oBAAAA,KAAyBJ,cAAgB,EAAA;YACrEE,YAAe,GAAA,IAAA;YACfC,kBAAqB,GAAA,UAAA;AACvB;AAEA,QAAA,MAAMb,IAAO,GAAA;AACXc,YAAAA,oBAAAA;AACAC,YAAAA,sBAAAA;AACAL,YAAAA,cAAAA;AACAE,YAAAA,YAAAA;YACAU,gBAAkBD,EAAAA,KAAAA,CAAMX,cAAkB,CAAA,GAAA,KAAA,GAAQK,sBAA0BL,IAAAA,cAAAA;AAC5EG,YAAAA,kBAAAA;YACAU,qBAAuBC,EAAAA,GAAAA,CAAI,kBAAkB,IAAU,CAAA,KAAA,cAAA;AACvDC,YAAAA,YAAAA,EAAcD,GAAI,CAAA,yBAAA,CAAA;YAClBjB,IAAMX,EAAAA,MAAAA,CAAOQ,EAAE,CAACG,IAAI;YACpBJ,OAASP,EAAAA,MAAAA,CAAOQ,EAAE,CAACD,OAAO;AAC1BE,YAAAA,QAAAA,EAAUT,OAAOQ,EAAE,CAACC,QAAQ,CAACC,IAAI,MAAM;AACzC,SAAA;QAEA,OAAO;AAAEN,YAAAA;AAAK,SAAA;AAChB;AACF,CAAE;;;;"}
@@ -12,6 +12,8 @@ var auditLogs = require('./audit-logs/controllers/audit-logs.js');
12
12
  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
+ var ai$1 = require('./ai/routes/ai.js');
16
+ var ai = require('./ai/controllers/ai.js');
15
17
 
16
18
  const getAdminEE = ()=>{
17
19
  const eeAdmin = {
@@ -27,39 +29,51 @@ const getAdminEE = ()=>{
27
29
  controllers: index$2,
28
30
  routes: index$3
29
31
  };
30
- // Only add the other audit-logs APIs if the feature is enabled by the user and the license
31
- if (strapi.config.get('admin.auditLogs.enabled', true) && strapi.ee.features.isEnabled('audit-logs')) {
32
- return {
33
- ...eeAdmin,
34
- controllers: {
35
- ...eeAdmin.controllers,
32
+ const isAIEnabled = strapi.config.get('admin.ai.enabled', true) && strapi.ee.features.isEnabled('cms-ai');
33
+ const isAuditLogsEnabled = strapi.config.get('admin.auditLogs.enabled', true) && strapi.ee.features.isEnabled('audit-logs');
34
+ return {
35
+ ...eeAdmin,
36
+ controllers: {
37
+ ...eeAdmin.controllers,
38
+ ...isAuditLogsEnabled ? {
36
39
  'audit-logs': auditLogs
37
- },
38
- routes: {
39
- ...eeAdmin.routes,
40
+ } : {},
41
+ ...isAIEnabled ? {
42
+ ai: ai
43
+ } : {}
44
+ },
45
+ routes: {
46
+ ...eeAdmin.routes,
47
+ ...isAuditLogsEnabled ? {
40
48
  'audit-logs': auditLogs$1
41
- },
42
- async register ({ strapi: strapi1 }) {
43
- // Run the the default registration
44
- await eeAdmin.register({
45
- strapi: strapi1
46
- });
49
+ } : {},
50
+ ...isAIEnabled ? {
51
+ ai: ai$1
52
+ } : {}
53
+ },
54
+ async register ({ strapi: strapi1 }) {
55
+ // Run the the default registration
56
+ await eeAdmin.register({
57
+ strapi: strapi1
58
+ });
59
+ if (isAuditLogsEnabled) {
47
60
  // Register an internal audit logs service
48
61
  strapi1.add('audit-logs', auditLogs$2.createAuditLogsService(strapi1));
49
62
  // Register an internal audit logs lifecycle service
50
63
  const auditLogsLifecycle = lifecycles.createAuditLogsLifecycleService(strapi1);
51
64
  strapi1.add('audit-logs-lifecycle', auditLogsLifecycle);
52
65
  await auditLogsLifecycle.register();
53
- },
54
- async destroy ({ strapi: strapi1 }) {
66
+ }
67
+ },
68
+ async destroy ({ strapi: strapi1 }) {
69
+ if (isAuditLogsEnabled) {
55
70
  strapi1.get('audit-logs-lifecycle').destroy();
56
- await eeAdmin.destroy({
57
- strapi: strapi1
58
- });
59
71
  }
60
- };
61
- }
62
- return eeAdmin;
72
+ await eeAdmin.destroy({
73
+ strapi: strapi1
74
+ });
75
+ }
76
+ };
63
77
  };
64
78
 
65
79
  module.exports = getAdminEE;
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../../../../ee/server/src/index.ts"],"sourcesContent":["import 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 type { Core } from '@strapi/types';\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 // Only add the other audit-logs APIs if the feature is enabled by the user and the license\n if (\n strapi.config.get('admin.auditLogs.enabled', true) &&\n strapi.ee.features.isEnabled('audit-logs')\n ) {\n return {\n ...eeAdmin,\n controllers: {\n ...eeAdmin.controllers,\n 'audit-logs': auditLogsController,\n },\n routes: {\n ...eeAdmin.routes,\n 'audit-logs': auditLogsRoutes,\n },\n async register({ strapi }: { strapi: Core.Strapi }) {\n // Run the the default registration\n await eeAdmin.register({ strapi });\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 await auditLogsLifecycle.register();\n },\n async destroy({ strapi }: { strapi: Core.Strapi }) {\n strapi.get('audit-logs-lifecycle').destroy();\n await eeAdmin.destroy({ strapi });\n },\n };\n }\n\n return eeAdmin;\n};\n\nexport default getAdminEE;\n"],"names":["getAdminEE","eeAdmin","register","bootstrap","destroy","contentTypes","auditLog","adminContentTypes","services","controllers","routes","strapi","config","get","ee","features","isEnabled","auditLogsController","auditLogsRoutes","add","createAuditLogsService","auditLogsLifecycle","createAuditLogsLifecycleService"],"mappings":";;;;;;;;;;;;;;;AAcA,MAAMA,UAAa,GAAA,IAAA;AACjB,IAAA,MAAMC,OAAU,GAAA;AACdC,QAAAA,QAAAA;AACAC,QAAAA,SAAAA;AACAC,QAAAA,OAAAA;QACAC,YAAc,EAAA;;YAEZ,WAAaC,EAAAA,iBAAAA;AACb,YAAA,GAAGC;AACL,SAAA;AACAC,kBAAAA,OAAAA;AACAC,qBAAAA,OAAAA;AACAC,gBAAAA;AACF,KAAA;;AAGA,IAAA,IACEC,MAAOC,CAAAA,MAAM,CAACC,GAAG,CAAC,yBAA2B,EAAA,IAAA,CAAA,IAC7CF,MAAOG,CAAAA,EAAE,CAACC,QAAQ,CAACC,SAAS,CAAC,YAC7B,CAAA,EAAA;QACA,OAAO;AACL,YAAA,GAAGf,OAAO;YACVQ,WAAa,EAAA;AACX,gBAAA,GAAGR,QAAQQ,WAAW;gBACtB,YAAcQ,EAAAA;AAChB,aAAA;YACAP,MAAQ,EAAA;AACN,gBAAA,GAAGT,QAAQS,MAAM;gBACjB,YAAcQ,EAAAA;AAChB,aAAA;AACA,YAAA,MAAMhB,QAAS,CAAA,CAAA,EAAES,MAAAA,EAAAA,OAAM,EAA2B,EAAA;;gBAEhD,MAAMV,OAAAA,CAAQC,QAAQ,CAAC;oBAAES,MAAAA,EAAAA;AAAO,iBAAA,CAAA;;gBAEhCA,OAAOQ,CAAAA,GAAG,CAAC,YAAA,EAAcC,kCAAuBT,CAAAA,OAAAA,CAAAA,CAAAA;;AAEhD,gBAAA,MAAMU,qBAAqBC,0CAAgCX,CAAAA,OAAAA,CAAAA;gBAC3DA,OAAOQ,CAAAA,GAAG,CAAC,sBAAwBE,EAAAA,kBAAAA,CAAAA;AAEnC,gBAAA,MAAMA,mBAAmBnB,QAAQ,EAAA;AACnC,aAAA;AACA,YAAA,MAAME,OAAQ,CAAA,CAAA,EAAEO,MAAAA,EAAAA,OAAM,EAA2B,EAAA;gBAC/CA,OAAOE,CAAAA,GAAG,CAAC,sBAAA,CAAA,CAAwBT,OAAO,EAAA;gBAC1C,MAAMH,OAAAA,CAAQG,OAAO,CAAC;oBAAEO,MAAAA,EAAAA;AAAO,iBAAA,CAAA;AACjC;AACF,SAAA;AACF;IAEA,OAAOV,OAAAA;AACT;;;;"}
1
+ {"version":3,"file":"index.js","sources":["../../../../../ee/server/src/index.ts"],"sourcesContent":["import 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 aiRoutes from './ai/routes/ai';\nimport aiController from './ai/controllers/ai';\nimport type { Core } from '@strapi/types';\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 isAIEnabled =\n strapi.config.get('admin.ai.enabled', true) && strapi.ee.features.isEnabled('cms-ai');\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 ...(isAIEnabled ? { ai: aiController } : {}),\n },\n routes: {\n ...eeAdmin.routes,\n ...(isAuditLogsEnabled ? { 'audit-logs': auditLogsRoutes } : {}),\n ...(isAIEnabled ? { ai: aiRoutes } : {}),\n },\n async register({ strapi }: { strapi: Core.Strapi }) {\n // Run the the default registration\n await eeAdmin.register({ strapi });\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 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({ strapi });\n },\n };\n};\n\nexport default getAdminEE;\n"],"names":["getAdminEE","eeAdmin","register","bootstrap","destroy","contentTypes","auditLog","adminContentTypes","services","controllers","routes","isAIEnabled","strapi","config","get","ee","features","isEnabled","isAuditLogsEnabled","auditLogsController","ai","aiController","auditLogsRoutes","aiRoutes","add","createAuditLogsService","auditLogsLifecycle","createAuditLogsLifecycleService"],"mappings":";;;;;;;;;;;;;;;;;AAgBA,MAAMA,UAAa,GAAA,IAAA;AACjB,IAAA,MAAMC,OAAU,GAAA;AACdC,QAAAA,QAAAA;AACAC,QAAAA,SAAAA;AACAC,QAAAA,OAAAA;QACAC,YAAc,EAAA;;YAEZ,WAAaC,EAAAA,iBAAAA;AACb,YAAA,GAAGC;AACL,SAAA;AACAC,kBAAAA,OAAAA;AACAC,qBAAAA,OAAAA;AACAC,gBAAAA;AACF,KAAA;AAEA,IAAA,MAAMC,WACJC,GAAAA,MAAAA,CAAOC,MAAM,CAACC,GAAG,CAAC,kBAAA,EAAoB,IAASF,CAAAA,IAAAA,MAAAA,CAAOG,EAAE,CAACC,QAAQ,CAACC,SAAS,CAAC,QAAA,CAAA;AAC9E,IAAA,MAAMC,kBACJN,GAAAA,MAAAA,CAAOC,MAAM,CAACC,GAAG,CAAC,yBAAA,EAA2B,IAC7CF,CAAAA,IAAAA,MAAAA,CAAOG,EAAE,CAACC,QAAQ,CAACC,SAAS,CAAC,YAAA,CAAA;IAC/B,OAAO;AACL,QAAA,GAAGhB,OAAO;QACVQ,WAAa,EAAA;AACX,YAAA,GAAGR,QAAQQ,WAAW;AACtB,YAAA,GAAIS,kBAAqB,GAAA;gBAAE,YAAcC,EAAAA;AAAoB,aAAA,GAAI,EAAE;AACnE,YAAA,GAAIR,WAAc,GAAA;gBAAES,EAAIC,EAAAA;AAAa,aAAA,GAAI;AAC3C,SAAA;QACAX,MAAQ,EAAA;AACN,YAAA,GAAGT,QAAQS,MAAM;AACjB,YAAA,GAAIQ,kBAAqB,GAAA;gBAAE,YAAcI,EAAAA;AAAgB,aAAA,GAAI,EAAE;AAC/D,YAAA,GAAIX,WAAc,GAAA;gBAAES,EAAIG,EAAAA;AAAS,aAAA,GAAI;AACvC,SAAA;AACA,QAAA,MAAMrB,QAAS,CAAA,CAAA,EAAEU,MAAAA,EAAAA,OAAM,EAA2B,EAAA;;YAEhD,MAAMX,OAAAA,CAAQC,QAAQ,CAAC;gBAAEU,MAAAA,EAAAA;AAAO,aAAA,CAAA;AAChC,YAAA,IAAIM,kBAAoB,EAAA;;gBAEtBN,OAAOY,CAAAA,GAAG,CAAC,YAAA,EAAcC,kCAAuBb,CAAAA,OAAAA,CAAAA,CAAAA;;AAEhD,gBAAA,MAAMc,qBAAqBC,0CAAgCf,CAAAA,OAAAA,CAAAA;gBAC3DA,OAAOY,CAAAA,GAAG,CAAC,sBAAwBE,EAAAA,kBAAAA,CAAAA;AAEnC,gBAAA,MAAMA,mBAAmBxB,QAAQ,EAAA;AACnC;AACF,SAAA;AACA,QAAA,MAAME,OAAQ,CAAA,CAAA,EAAEQ,MAAAA,EAAAA,OAAM,EAA2B,EAAA;AAC/C,YAAA,IAAIM,kBAAoB,EAAA;gBACtBN,OAAOE,CAAAA,GAAG,CAAC,sBAAA,CAAA,CAAwBV,OAAO,EAAA;AAC5C;YACA,MAAMH,OAAAA,CAAQG,OAAO,CAAC;gBAAEQ,MAAAA,EAAAA;AAAO,aAAA,CAAA;AACjC;AACF,KAAA;AACF;;;;"}