@strapi/admin 5.31.2 → 5.32.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 (162) hide show
  1. package/dist/admin/admin/src/components/FormInputs/Boolean.js +22 -3
  2. package/dist/admin/admin/src/components/FormInputs/Boolean.js.map +1 -1
  3. package/dist/admin/admin/src/components/FormInputs/Boolean.mjs +23 -4
  4. package/dist/admin/admin/src/components/FormInputs/Boolean.mjs.map +1 -1
  5. package/dist/admin/admin/src/components/GuidedTour/Overview.js +1 -1
  6. package/dist/admin/admin/src/components/GuidedTour/Overview.js.map +1 -1
  7. package/dist/admin/admin/src/components/GuidedTour/Overview.mjs +1 -1
  8. package/dist/admin/admin/src/components/GuidedTour/Overview.mjs.map +1 -1
  9. package/dist/admin/admin/src/components/GuidedTour/Steps/ContentTypeBuilderSteps.js +2 -2
  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 +1 -1
  12. package/dist/admin/admin/src/components/GuidedTour/Steps/ContentTypeBuilderSteps.mjs.map +1 -1
  13. package/dist/admin/admin/src/components/GuidedTour/Tours.js +1 -1
  14. package/dist/admin/admin/src/components/GuidedTour/Tours.js.map +1 -1
  15. package/dist/admin/admin/src/components/GuidedTour/Tours.mjs +1 -1
  16. package/dist/admin/admin/src/components/GuidedTour/Tours.mjs.map +1 -1
  17. package/dist/admin/admin/src/pages/Auth/components/Register.js +2 -1
  18. package/dist/admin/admin/src/pages/Auth/components/Register.js.map +1 -1
  19. package/dist/admin/admin/src/pages/Auth/components/Register.mjs +2 -1
  20. package/dist/admin/admin/src/pages/Auth/components/Register.mjs.map +1 -1
  21. package/dist/admin/admin/src/pages/Home/HomePage.js +1 -1
  22. package/dist/admin/admin/src/pages/Home/HomePage.js.map +1 -1
  23. package/dist/admin/admin/src/pages/Home/HomePage.mjs +1 -1
  24. package/dist/admin/admin/src/pages/Home/HomePage.mjs.map +1 -1
  25. package/dist/admin/admin/src/pages/ProfilePage.js +7 -1
  26. package/dist/admin/admin/src/pages/ProfilePage.js.map +1 -1
  27. package/dist/admin/admin/src/pages/ProfilePage.mjs +7 -1
  28. package/dist/admin/admin/src/pages/ProfilePage.mjs.map +1 -1
  29. package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/EditView/components/ActionBoundRoutes.js +2 -0
  30. package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/EditView/components/ActionBoundRoutes.js.map +1 -1
  31. package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/EditView/components/ActionBoundRoutes.mjs +2 -0
  32. package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/EditView/components/ActionBoundRoutes.mjs.map +1 -1
  33. package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/EditView/components/CollapsableContentType.js +2 -1
  34. package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/EditView/components/CollapsableContentType.js.map +1 -1
  35. package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/EditView/components/CollapsableContentType.mjs +2 -1
  36. package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/EditView/components/CollapsableContentType.mjs.map +1 -1
  37. package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/EditView/components/FormApiTokenContainer.js +4 -4
  38. package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/EditView/components/FormApiTokenContainer.js.map +1 -1
  39. package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/EditView/components/FormApiTokenContainer.mjs +4 -4
  40. package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/EditView/components/FormApiTokenContainer.mjs.map +1 -1
  41. package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/EditView/components/Permissions.js +1 -0
  42. package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/EditView/components/Permissions.js.map +1 -1
  43. package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/EditView/components/Permissions.mjs +1 -0
  44. package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/EditView/components/Permissions.mjs.map +1 -1
  45. package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/ApplicationInfoPage.js +5 -5
  46. package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/ApplicationInfoPage.js.map +1 -1
  47. package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/ApplicationInfoPage.mjs +5 -5
  48. package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/ApplicationInfoPage.mjs.map +1 -1
  49. package/dist/admin/admin/src/pages/Settings/pages/PurchaseAuditLogs.js +4 -4
  50. package/dist/admin/admin/src/pages/Settings/pages/PurchaseAuditLogs.js.map +1 -1
  51. package/dist/admin/admin/src/pages/Settings/pages/PurchaseAuditLogs.mjs +4 -4
  52. package/dist/admin/admin/src/pages/Settings/pages/PurchaseAuditLogs.mjs.map +1 -1
  53. package/dist/admin/admin/src/pages/Settings/pages/PurchaseContentHistory.js +4 -4
  54. package/dist/admin/admin/src/pages/Settings/pages/PurchaseContentHistory.js.map +1 -1
  55. package/dist/admin/admin/src/pages/Settings/pages/PurchaseContentHistory.mjs +4 -4
  56. package/dist/admin/admin/src/pages/Settings/pages/PurchaseContentHistory.mjs.map +1 -1
  57. package/dist/admin/admin/src/pages/Settings/pages/PurchaseSingleSignOn.js +4 -2
  58. package/dist/admin/admin/src/pages/Settings/pages/PurchaseSingleSignOn.js.map +1 -1
  59. package/dist/admin/admin/src/pages/Settings/pages/PurchaseSingleSignOn.mjs +4 -2
  60. package/dist/admin/admin/src/pages/Settings/pages/PurchaseSingleSignOn.mjs.map +1 -1
  61. package/dist/admin/admin/src/pages/Settings/pages/Roles/CreatePage.js +4 -2
  62. package/dist/admin/admin/src/pages/Settings/pages/Roles/CreatePage.js.map +1 -1
  63. package/dist/admin/admin/src/pages/Settings/pages/Roles/CreatePage.mjs +4 -2
  64. package/dist/admin/admin/src/pages/Settings/pages/Roles/CreatePage.mjs.map +1 -1
  65. package/dist/admin/admin/src/pages/Settings/pages/Roles/components/PluginsAndSettings.js +3 -1
  66. package/dist/admin/admin/src/pages/Settings/pages/Roles/components/PluginsAndSettings.js.map +1 -1
  67. package/dist/admin/admin/src/pages/Settings/pages/Roles/components/PluginsAndSettings.mjs +3 -1
  68. package/dist/admin/admin/src/pages/Settings/pages/Roles/components/PluginsAndSettings.mjs.map +1 -1
  69. package/dist/admin/admin/src/pages/Settings/pages/Roles/components/RoleForm.js +2 -0
  70. package/dist/admin/admin/src/pages/Settings/pages/Roles/components/RoleForm.js.map +1 -1
  71. package/dist/admin/admin/src/pages/Settings/pages/Roles/components/RoleForm.mjs +2 -0
  72. package/dist/admin/admin/src/pages/Settings/pages/Roles/components/RoleForm.mjs.map +1 -1
  73. package/dist/admin/admin/src/pages/Settings/pages/Users/EditPage.js +2 -1
  74. package/dist/admin/admin/src/pages/Settings/pages/Users/EditPage.js.map +1 -1
  75. package/dist/admin/admin/src/pages/Settings/pages/Users/EditPage.mjs +2 -1
  76. package/dist/admin/admin/src/pages/Settings/pages/Users/EditPage.mjs.map +1 -1
  77. package/dist/admin/admin/src/pages/Settings/pages/Users/components/NewUserForm.js +2 -1
  78. package/dist/admin/admin/src/pages/Settings/pages/Users/components/NewUserForm.js.map +1 -1
  79. package/dist/admin/admin/src/pages/Settings/pages/Users/components/NewUserForm.mjs +2 -1
  80. package/dist/admin/admin/src/pages/Settings/pages/Users/components/NewUserForm.mjs.map +1 -1
  81. package/dist/admin/admin/src/pages/Settings/pages/Webhooks/components/HeadersInput.js +2 -0
  82. package/dist/admin/admin/src/pages/Settings/pages/Webhooks/components/HeadersInput.js.map +1 -1
  83. package/dist/admin/admin/src/pages/Settings/pages/Webhooks/components/HeadersInput.mjs +2 -0
  84. package/dist/admin/admin/src/pages/Settings/pages/Webhooks/components/HeadersInput.mjs.map +1 -1
  85. package/dist/admin/admin/src/pages/Settings/pages/Webhooks/components/WebhookForm.js +1 -0
  86. package/dist/admin/admin/src/pages/Settings/pages/Webhooks/components/WebhookForm.js.map +1 -1
  87. package/dist/admin/admin/src/pages/Settings/pages/Webhooks/components/WebhookForm.mjs +1 -0
  88. package/dist/admin/admin/src/pages/Settings/pages/Webhooks/components/WebhookForm.mjs.map +1 -1
  89. package/dist/admin/admin/src/services/auth.js +1 -12
  90. package/dist/admin/admin/src/services/auth.js.map +1 -1
  91. package/dist/admin/admin/src/services/auth.mjs +2 -11
  92. package/dist/admin/admin/src/services/auth.mjs.map +1 -1
  93. package/dist/admin/admin/src/translations/vi.json.js +772 -129
  94. package/dist/admin/admin/src/translations/vi.json.js.map +1 -1
  95. package/dist/admin/admin/src/translations/vi.json.mjs +764 -130
  96. package/dist/admin/admin/src/translations/vi.json.mjs.map +1 -1
  97. package/dist/admin/ee/admin/src/pages/AuthPage/components/SSOProviders.js +7 -0
  98. package/dist/admin/ee/admin/src/pages/AuthPage/components/SSOProviders.js.map +1 -1
  99. package/dist/admin/ee/admin/src/pages/AuthPage/components/SSOProviders.mjs +7 -0
  100. package/dist/admin/ee/admin/src/pages/AuthPage/components/SSOProviders.mjs.map +1 -1
  101. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/ApplicationInfoPage/components/AdminSeatInfo.js +1 -1
  102. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/ApplicationInfoPage/components/AdminSeatInfo.js.map +1 -1
  103. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/ApplicationInfoPage/components/AdminSeatInfo.mjs +1 -1
  104. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/ApplicationInfoPage/components/AdminSeatInfo.mjs.map +1 -1
  105. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/SingleSignOnPage.js +1 -0
  106. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/SingleSignOnPage.js.map +1 -1
  107. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/SingleSignOnPage.mjs +1 -0
  108. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/SingleSignOnPage.mjs.map +1 -1
  109. package/dist/admin/index.js +0 -2
  110. package/dist/admin/index.js.map +1 -1
  111. package/dist/admin/index.mjs +0 -1
  112. package/dist/admin/index.mjs.map +1 -1
  113. package/dist/admin/src/index.d.ts +0 -2
  114. package/dist/admin/src/services/auth.d.ts +2 -11
  115. package/dist/ee/server/src/ai/containers/ai.d.ts +4 -0
  116. package/dist/ee/server/src/ai/containers/ai.d.ts.map +1 -1
  117. package/dist/ee/server/src/ai/controllers/ai.d.ts.map +1 -1
  118. package/dist/ee/server/src/ai/routes/ai.d.ts.map +1 -1
  119. package/dist/server/ee/server/src/ai/containers/ai.js +143 -1
  120. package/dist/server/ee/server/src/ai/containers/ai.js.map +1 -1
  121. package/dist/server/ee/server/src/ai/containers/ai.mjs +143 -1
  122. package/dist/server/ee/server/src/ai/containers/ai.mjs.map +1 -1
  123. package/dist/server/ee/server/src/ai/controllers/ai.js +7 -106
  124. package/dist/server/ee/server/src/ai/controllers/ai.js.map +1 -1
  125. package/dist/server/ee/server/src/ai/controllers/ai.mjs +7 -106
  126. package/dist/server/ee/server/src/ai/controllers/ai.mjs.map +1 -1
  127. package/dist/server/ee/server/src/ai/routes/ai.js +0 -3
  128. package/dist/server/ee/server/src/ai/routes/ai.js.map +1 -1
  129. package/dist/server/ee/server/src/ai/routes/ai.mjs +0 -3
  130. package/dist/server/ee/server/src/ai/routes/ai.mjs.map +1 -1
  131. package/dist/server/server/src/controllers/authenticated-user.js +0 -15
  132. package/dist/server/server/src/controllers/authenticated-user.js.map +1 -1
  133. package/dist/server/server/src/controllers/authenticated-user.mjs +0 -15
  134. package/dist/server/server/src/controllers/authenticated-user.mjs.map +1 -1
  135. package/dist/server/server/src/routes/users.js +0 -10
  136. package/dist/server/server/src/routes/users.js.map +1 -1
  137. package/dist/server/server/src/routes/users.mjs +0 -10
  138. package/dist/server/server/src/routes/users.mjs.map +1 -1
  139. package/dist/server/server/src/services/user.js +1 -143
  140. package/dist/server/server/src/services/user.js.map +1 -1
  141. package/dist/server/server/src/services/user.mjs +1 -143
  142. package/dist/server/server/src/services/user.mjs.map +1 -1
  143. package/dist/server/src/controllers/authenticated-user.d.ts +0 -1
  144. package/dist/server/src/controllers/authenticated-user.d.ts.map +1 -1
  145. package/dist/server/src/controllers/index.d.ts +0 -1
  146. package/dist/server/src/controllers/index.d.ts.map +1 -1
  147. package/dist/server/src/index.d.ts +0 -5
  148. package/dist/server/src/index.d.ts.map +1 -1
  149. package/dist/server/src/routes/users.d.ts.map +1 -1
  150. package/dist/server/src/services/index.d.ts +0 -4
  151. package/dist/server/src/services/index.d.ts.map +1 -1
  152. package/dist/server/src/services/user.d.ts +0 -4
  153. package/dist/server/src/services/user.d.ts.map +1 -1
  154. package/dist/shared/contracts/ai.d.ts +1 -1
  155. package/dist/shared/contracts/users.d.ts +0 -32
  156. package/dist/shared/contracts/users.d.ts.map +1 -1
  157. package/package.json +12 -12
  158. package/dist/admin/admin/src/hooks/useAIAvailability.js +0 -13
  159. package/dist/admin/admin/src/hooks/useAIAvailability.js.map +0 -1
  160. package/dist/admin/admin/src/hooks/useAIAvailability.mjs +0 -11
  161. package/dist/admin/admin/src/hooks/useAIAvailability.mjs.map +0 -1
  162. package/dist/admin/src/hooks/useAIAvailability.d.ts +0 -5
@@ -33,9 +33,6 @@ declare const useCheckPermissionsQuery: import("@reduxjs/toolkit/dist/query/reac
33
33
  rememberMe?: boolean | undefined;
34
34
  }, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("..").QueryArguments, unknown, import("..").BaseQueryError>, "GuidedTourMeta" | "HomepageKeyStatistics" | "AIUsage" | "AIFeatureConfig" | "User" | "Me" | "ProvidersOptions", {
35
35
  token: string;
36
- /**
37
- * Auth methods
38
- */
39
36
  accessToken?: string | undefined;
40
37
  user: Omit<import("..").SanitizedAdminUser, "permissions">;
41
38
  }, "adminApi">>, useRegisterUserMutation: import("@reduxjs/toolkit/dist/query/react/buildHooks").UseMutation<import("@reduxjs/toolkit/query").MutationDefinition<{
@@ -53,13 +50,7 @@ declare const useCheckPermissionsQuery: import("@reduxjs/toolkit/dist/query/reac
53
50
  lastname?: string | undefined;
54
51
  }, "adminApi">>, useForgotPasswordMutation: import("@reduxjs/toolkit/dist/query/react/buildHooks").UseMutation<import("@reduxjs/toolkit/query").MutationDefinition<{
55
52
  email: string;
56
- }, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("..").QueryArguments, unknown, import("..").BaseQueryError>, "GuidedTourMeta" | "HomepageKeyStatistics" | "AIUsage" | "AIFeatureConfig" | "User" | "Me" | "ProvidersOptions", ForgotPassword.Response, "adminApi">>, useGetMyPermissionsQuery: import("@reduxjs/toolkit/dist/query/react/buildHooks").UseQuery<import("@reduxjs/toolkit/query").QueryDefinition<void, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("..").QueryArguments, unknown, import("..").BaseQueryError>, "GuidedTourMeta" | "HomepageKeyStatistics" | "AIUsage" | "AIFeatureConfig" | "User" | "Me" | "ProvidersOptions", import("../../../shared/contracts/shared").Permission[], "adminApi">>, useGetAiTokenQuery: import("@reduxjs/toolkit/dist/query/react/buildHooks").UseQuery<import("@reduxjs/toolkit/query").QueryDefinition<void, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("..").QueryArguments, unknown, import("..").BaseQueryError>, "GuidedTourMeta" | "HomepageKeyStatistics" | "AIUsage" | "AIFeatureConfig" | "User" | "Me" | "ProvidersOptions", {
57
- token: string;
58
- expiresAt?: string | undefined;
59
- }, "adminApi">>, useLazyGetAiTokenQuery: import("@reduxjs/toolkit/dist/query/react/buildHooks").UseLazyQuery<import("@reduxjs/toolkit/query").QueryDefinition<void, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("..").QueryArguments, unknown, import("..").BaseQueryError>, "GuidedTourMeta" | "HomepageKeyStatistics" | "AIUsage" | "AIFeatureConfig" | "User" | "Me" | "ProvidersOptions", {
60
- token: string;
61
- expiresAt?: string | undefined;
62
- }, "adminApi">>, useIsSSOLockedQuery: import("@reduxjs/toolkit/dist/query/react/buildHooks").UseQuery<import("@reduxjs/toolkit/query").QueryDefinition<void, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("..").QueryArguments, unknown, import("..").BaseQueryError>, "GuidedTourMeta" | "HomepageKeyStatistics" | "AIUsage" | "AIFeatureConfig" | "User" | "Me" | "ProvidersOptions", {
53
+ }, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("..").QueryArguments, unknown, import("..").BaseQueryError>, "GuidedTourMeta" | "HomepageKeyStatistics" | "AIUsage" | "AIFeatureConfig" | "User" | "Me" | "ProvidersOptions", ForgotPassword.Response, "adminApi">>, useGetMyPermissionsQuery: import("@reduxjs/toolkit/dist/query/react/buildHooks").UseQuery<import("@reduxjs/toolkit/query").QueryDefinition<void, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("..").QueryArguments, unknown, import("..").BaseQueryError>, "GuidedTourMeta" | "HomepageKeyStatistics" | "AIUsage" | "AIFeatureConfig" | "User" | "Me" | "ProvidersOptions", import("../../../shared/contracts/shared").Permission[], "adminApi">>, useIsSSOLockedQuery: import("@reduxjs/toolkit/dist/query/react/buildHooks").UseQuery<import("@reduxjs/toolkit/query").QueryDefinition<void, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("..").QueryArguments, unknown, import("..").BaseQueryError>, "GuidedTourMeta" | "HomepageKeyStatistics" | "AIUsage" | "AIFeatureConfig" | "User" | "Me" | "ProvidersOptions", {
63
54
  isSSOLocked: boolean;
64
55
  }, "adminApi">>, useGetProvidersQuery: import("@reduxjs/toolkit/dist/query/react/buildHooks").UseQuery<import("@reduxjs/toolkit/query").QueryDefinition<void, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("..").QueryArguments, unknown, import("..").BaseQueryError>, "GuidedTourMeta" | "HomepageKeyStatistics" | "AIUsage" | "AIFeatureConfig" | "User" | "Me" | "ProvidersOptions", GetProviders.Response, "adminApi">>, useGetProviderOptionsQuery: import("@reduxjs/toolkit/dist/query/react/buildHooks").UseQuery<import("@reduxjs/toolkit/query").QueryDefinition<void, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("..").QueryArguments, unknown, import("..").BaseQueryError>, "GuidedTourMeta" | "HomepageKeyStatistics" | "AIUsage" | "AIFeatureConfig" | "User" | "Me" | "ProvidersOptions", ProvidersOptions.SSOProviderOptions, "adminApi">>, useUpdateProviderOptionsMutation: import("@reduxjs/toolkit/dist/query/react/buildHooks").UseMutation<import("@reduxjs/toolkit/query").MutationDefinition<ProvidersOptions.SSOProviderOptions, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("..").QueryArguments, unknown, import("..").BaseQueryError>, "GuidedTourMeta" | "HomepageKeyStatistics" | "AIUsage" | "AIFeatureConfig" | "User" | "Me" | "ProvidersOptions", ProvidersOptions.SSOProviderOptions, "adminApi">>;
65
- export { useCheckPermissionsQuery, useLazyCheckPermissionsQuery, useGetMeQuery, useLoginMutation, useAccessTokenExchangeMutation, useLogoutMutation, useUpdateMeMutation, useResetPasswordMutation, useRegisterAdminMutation, useRegisterUserMutation, useGetRegistrationInfoQuery, useForgotPasswordMutation, useGetMyPermissionsQuery, useGetAiTokenQuery, useLazyGetAiTokenQuery, useIsSSOLockedQuery, useGetProvidersQuery, useGetProviderOptionsQuery, useUpdateProviderOptionsMutation, };
56
+ export { useCheckPermissionsQuery, useLazyCheckPermissionsQuery, useGetMeQuery, useLoginMutation, useAccessTokenExchangeMutation, useLogoutMutation, useUpdateMeMutation, useResetPasswordMutation, useRegisterAdminMutation, useRegisterUserMutation, useGetRegistrationInfoQuery, useForgotPasswordMutation, useGetMyPermissionsQuery, useIsSSOLockedQuery, useGetProvidersQuery, useGetProviderOptionsQuery, useUpdateProviderOptionsMutation, };
@@ -6,6 +6,10 @@ declare const createAIContainer: ({ strapi }: {
6
6
  isAIi18nConfigured: boolean;
7
7
  isAIMediaLibraryConfigured: boolean;
8
8
  }>;
9
+ getAiToken: () => Promise<{
10
+ token: string;
11
+ expiresAt: string | undefined;
12
+ }>;
9
13
  };
10
14
  export { createAIContainer };
11
15
  //# sourceMappingURL=ai.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ai.d.ts","sourceRoot":"","sources":["../../../../../../ee/server/src/ai/containers/ai.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAE1C,QAAA,MAAM,iBAAiB,eAAgB;IAAE,MAAM,EAAE,KAAK,MAAM,CAAA;CAAE;;;;;CAc7D,CAAC;AAEF,OAAO,EAAE,iBAAiB,EAAE,CAAC"}
1
+ {"version":3,"file":"ai.d.ts","sourceRoot":"","sources":["../../../../../../ee/server/src/ai/containers/ai.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAmB1C,QAAA,MAAM,iBAAiB,eAAgB;IAAE,MAAM,EAAE,KAAK,MAAM,CAAA;CAAE;;;;;;;;;CAoL7D,CAAC;AAEF,OAAO,EAAE,iBAAiB,EAAE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"ai.d.ts","sourceRoot":"","sources":["../../../../../../ee/server/src/ai/controllers/ai.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;;oBASX,OAAO;oBA+IP,OAAO;4BA2HC,OAAO;;AA3QvC,wBAkRE"}
1
+ {"version":3,"file":"ai.d.ts","sourceRoot":"","sources":["../../../../../../ee/server/src/ai/controllers/ai.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;;oBAOX,OAAO;oBAmBP,OAAO;4BA4HC,OAAO;;AAhJvC,wBAuJE"}
@@ -1 +1 @@
1
- {"version":3,"file":"ai.d.ts","sourceRoot":"","sources":["../../../../../../ee/server/src/ai/routes/ai.ts"],"names":[],"mappings":";;;;;;;;;;;AAAA,wBA+BE"}
1
+ {"version":3,"file":"ai.d.ts","sourceRoot":"","sources":["../../../../../../ee/server/src/ai/routes/ai.ts"],"names":[],"mappings":";;;;;;;;;;;AAAA,wBA4BE"}
@@ -1,5 +1,13 @@
1
1
  'use strict';
2
2
 
3
+ var crypto = require('crypto');
4
+ var fs = require('fs');
5
+ var path = require('path');
6
+
7
+ /**
8
+ * In-memory cache for AI tokens
9
+ * Key format: `${projectId}:${userId}`
10
+ */ const aiTokenCache = new Map();
3
11
  const createAIContainer = ({ strapi })=>{
4
12
  const getAIFeatureConfig = async ()=>{
5
13
  const i18nSettings = await strapi.plugin('i18n').service('settings').getSettings();
@@ -9,8 +17,142 @@ const createAIContainer = ({ strapi })=>{
9
17
  isAIMediaLibraryConfigured: Boolean(uploadSettings?.aiMetadata)
10
18
  };
11
19
  };
20
+ const getAiToken = async ()=>{
21
+ const ERROR_PREFIX = 'AI token request failed:';
22
+ // Check if EE features are enabled first
23
+ if (!strapi.ee?.isEE) {
24
+ strapi.log.error(`${ERROR_PREFIX} Enterprise Edition features are not enabled`);
25
+ throw new Error('AI token request failed. Check server logs for details.');
26
+ }
27
+ // Get the EE license
28
+ // First try environment variable, then try reading from file
29
+ let eeLicense = process.env.STRAPI_LICENSE;
30
+ if (!eeLicense) {
31
+ try {
32
+ const licensePath = path.join(strapi.dirs.app.root, 'license.txt');
33
+ eeLicense = fs.readFileSync(licensePath).toString();
34
+ } catch (error) {
35
+ // License file doesn't exist or can't be read
36
+ }
37
+ }
38
+ if (!eeLicense) {
39
+ strapi.log.error(`${ERROR_PREFIX} No EE license found. Please ensure STRAPI_LICENSE environment variable is set or license.txt file exists.`);
40
+ throw new Error('AI token request failed. Check server logs for details.');
41
+ }
42
+ const aiServerUrl = process.env.STRAPI_AI_URL || 'https://strapi-ai.apps.strapi.io';
43
+ if (!aiServerUrl) {
44
+ strapi.log.error(`${ERROR_PREFIX} AI server URL not configured. Please set STRAPI_AI_URL environment variable.`);
45
+ throw new Error('AI token request failed. Check server logs for details.');
46
+ }
47
+ // Get the current user
48
+ const user = strapi.requestContext.get()?.state?.user;
49
+ if (!user) {
50
+ strapi.log.error(`${ERROR_PREFIX} No authenticated user in request context`);
51
+ throw new Error('AI token request failed. Check server logs for details.');
52
+ }
53
+ // Create a secure user identifier using only user ID
54
+ const userIdentifier = user.id.toString();
55
+ // Get project ID
56
+ const projectId = strapi.config.get('uuid');
57
+ if (!projectId) {
58
+ strapi.log.error(`${ERROR_PREFIX} Project ID not configured`);
59
+ throw new Error('AI token request failed. Check server logs for details.');
60
+ }
61
+ // Check cache for existing valid token
62
+ const cacheKey = `${projectId}:${userIdentifier}`;
63
+ const cachedToken = aiTokenCache.get(cacheKey);
64
+ if (cachedToken) {
65
+ const now = Date.now();
66
+ // Check if token is still valid (with buffer so it has time to to be used)
67
+ const bufferMs = 2 * 60 * 1000; // 2 minutes
68
+ if (cachedToken.expiresAtMs && cachedToken.expiresAtMs - bufferMs > now) {
69
+ strapi.log.info('Using cached AI token');
70
+ return {
71
+ token: cachedToken.token,
72
+ expiresAt: cachedToken.expiresAt
73
+ };
74
+ }
75
+ // Token expired or will expire soon, remove from cache
76
+ aiTokenCache.delete(cacheKey);
77
+ }
78
+ strapi.log.http('Contacting AI Server for token generation');
79
+ try {
80
+ // Call the AI server's getAiJWT endpoint
81
+ const response = await fetch(`${aiServerUrl}/auth/getAiJWT`, {
82
+ method: 'POST',
83
+ headers: {
84
+ 'Content-Type': 'application/json',
85
+ // No authorization header needed for public endpoint
86
+ // Add request ID for tracing
87
+ 'X-Request-Id': crypto.randomUUID()
88
+ },
89
+ body: JSON.stringify({
90
+ eeLicense,
91
+ userIdentifier,
92
+ projectId
93
+ })
94
+ });
95
+ if (!response.ok) {
96
+ let errorData;
97
+ let errorText;
98
+ try {
99
+ errorText = await response.text();
100
+ errorData = JSON.parse(errorText);
101
+ } catch {
102
+ errorData = {
103
+ error: errorText || 'Failed to parse error response'
104
+ };
105
+ }
106
+ strapi.log.error(`${ERROR_PREFIX} ${errorData?.error || 'Unknown error'}`, {
107
+ status: response.status,
108
+ statusText: response.statusText,
109
+ error: errorData,
110
+ errorText,
111
+ projectId
112
+ });
113
+ throw new Error('AI token request failed. Check server logs for details.');
114
+ }
115
+ let data;
116
+ try {
117
+ data = await response.json();
118
+ } catch (parseError) {
119
+ strapi.log.error(`${ERROR_PREFIX} Failed to parse AI server response`, parseError);
120
+ throw new Error('AI token request failed. Check server logs for details.');
121
+ }
122
+ if (!data.jwt) {
123
+ strapi.log.error(`${ERROR_PREFIX} Invalid response: missing JWT token`);
124
+ throw new Error('AI token request failed. Check server logs for details.');
125
+ }
126
+ strapi.log.info('AI token generated successfully', {
127
+ userId: user.id,
128
+ expiresAt: data.expiresAt
129
+ });
130
+ // Cache the token if it has an expiration time
131
+ if (data.expiresAt) {
132
+ const expiresAtMs = new Date(data.expiresAt).getTime();
133
+ aiTokenCache.set(cacheKey, {
134
+ token: data.jwt,
135
+ expiresAt: data.expiresAt,
136
+ expiresAtMs
137
+ });
138
+ }
139
+ // Return the AI JWT with metadata
140
+ // Note: Token expires in 1 hour, client should handle refresh
141
+ return {
142
+ token: data.jwt,
143
+ expiresAt: data.expiresAt
144
+ };
145
+ } catch (fetchError) {
146
+ if (fetchError instanceof Error && fetchError.name === 'AbortError') {
147
+ strapi.log.error(`${ERROR_PREFIX} Request to AI server timed out`);
148
+ throw new Error('AI token request failed. Check server logs for details.');
149
+ }
150
+ throw fetchError;
151
+ }
152
+ };
12
153
  return {
13
- getAIFeatureConfig
154
+ getAIFeatureConfig,
155
+ getAiToken
14
156
  };
15
157
  };
16
158
 
@@ -1 +1 @@
1
- {"version":3,"file":"ai.js","sources":["../../../../../../../ee/server/src/ai/containers/ai.ts"],"sourcesContent":["import type { Core } from '@strapi/types';\n\nconst createAIContainer = ({ strapi }: { strapi: Core.Strapi }) => {\n const getAIFeatureConfig = async () => {\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 return {\n getAIFeatureConfig,\n };\n};\n\nexport { createAIContainer };\n"],"names":["createAIContainer","strapi","getAIFeatureConfig","i18nSettings","plugin","service","getSettings","uploadSettings","isAIi18nConfigured","Boolean","aiLocalizations","isAIMediaLibraryConfigured","aiMetadata"],"mappings":";;AAEA,MAAMA,iBAAoB,GAAA,CAAC,EAAEC,MAAM,EAA2B,GAAA;AAC5D,IAAA,MAAMC,kBAAqB,GAAA,UAAA;QACzB,MAAMC,YAAAA,GAAe,MAAMF,MAAOG,CAAAA,MAAM,CAAC,MAAQC,CAAAA,CAAAA,OAAO,CAAC,UAAA,CAAA,CAAYC,WAAW,EAAA;QAChF,MAAMC,cAAAA,GAAiB,MAAMN,MAAOG,CAAAA,MAAM,CAAC,QAAUC,CAAAA,CAAAA,OAAO,CAAC,QAAA,CAAA,CAAUC,WAAW,EAAA;QAElF,OAAO;AACLE,YAAAA,kBAAAA,EAAoBC,QAAQN,YAAcO,EAAAA,eAAAA,CAAAA;AAC1CC,YAAAA,0BAAAA,EAA4BF,QAAQF,cAAgBK,EAAAA,UAAAA;AACtD,SAAA;AACF,KAAA;IAEA,OAAO;AACLV,QAAAA;AACF,KAAA;AACF;;;;"}
1
+ {"version":3,"file":"ai.js","sources":["../../../../../../../ee/server/src/ai/containers/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\n/**\n * In-memory cache for AI tokens\n * Key format: `${projectId}:${userId}`\n */\nconst aiTokenCache = new Map<\n string,\n {\n token: string;\n expiresAt?: string;\n expiresAtMs?: number;\n }\n>();\n\nconst createAIContainer = ({ strapi }: { strapi: Core.Strapi }) => {\n const getAIFeatureConfig = async () => {\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 const getAiToken = async () => {\n const ERROR_PREFIX = 'AI token request failed:';\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 throw new Error('AI token request failed. Check server logs for details.');\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\n throw new Error('AI token request failed. Check server logs for details.');\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 throw new Error('AI token request failed. Check server logs for details.');\n }\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 // Get project ID\n const projectId = strapi.config.get('uuid');\n if (!projectId) {\n strapi.log.error(`${ERROR_PREFIX} Project ID not configured`);\n throw new Error('AI token request failed. Check server logs for details.');\n }\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 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 // 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 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 // Return the AI JWT with metadata\n // Note: Token expires in 1 hour, client should handle refresh\n return {\n token: data.jwt,\n expiresAt: data.expiresAt, // 1 hour from generation\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 return {\n getAIFeatureConfig,\n getAiToken,\n };\n};\n\nexport { createAIContainer };\n"],"names":["aiTokenCache","Map","createAIContainer","strapi","getAIFeatureConfig","i18nSettings","plugin","service","getSettings","uploadSettings","isAIi18nConfigured","Boolean","aiLocalizations","isAIMediaLibraryConfigured","aiMetadata","getAiToken","ERROR_PREFIX","ee","isEE","log","error","Error","eeLicense","process","env","STRAPI_LICENSE","licensePath","path","join","dirs","app","root","fs","readFileSync","toString","aiServerUrl","STRAPI_AI_URL","user","requestContext","get","state","userIdentifier","id","projectId","config","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"],"mappings":";;;;;;AAMA;;;IAIA,MAAMA,eAAe,IAAIC,GAAAA,EAAAA;AASzB,MAAMC,iBAAoB,GAAA,CAAC,EAAEC,MAAM,EAA2B,GAAA;AAC5D,IAAA,MAAMC,kBAAqB,GAAA,UAAA;QACzB,MAAMC,YAAAA,GAAe,MAAMF,MAAOG,CAAAA,MAAM,CAAC,MAAQC,CAAAA,CAAAA,OAAO,CAAC,UAAA,CAAA,CAAYC,WAAW,EAAA;QAChF,MAAMC,cAAAA,GAAiB,MAAMN,MAAOG,CAAAA,MAAM,CAAC,QAAUC,CAAAA,CAAAA,OAAO,CAAC,QAAA,CAAA,CAAUC,WAAW,EAAA;QAElF,OAAO;AACLE,YAAAA,kBAAAA,EAAoBC,QAAQN,YAAcO,EAAAA,eAAAA,CAAAA;AAC1CC,YAAAA,0BAAAA,EAA4BF,QAAQF,cAAgBK,EAAAA,UAAAA;AACtD,SAAA;AACF,KAAA;AAEA,IAAA,MAAMC,UAAa,GAAA,UAAA;AACjB,QAAA,MAAMC,YAAe,GAAA,0BAAA;;AAGrB,QAAA,IAAI,CAACb,MAAAA,CAAOc,EAAE,EAAEC,IAAM,EAAA;AACpBf,YAAAA,MAAAA,CAAOgB,GAAG,CAACC,KAAK,CAAC,CAAGJ,EAAAA,YAAAA,CAAa,4CAA4C,CAAC,CAAA;AAC9E,YAAA,MAAM,IAAIK,KAAM,CAAA,yDAAA,CAAA;AAClB;;;AAIA,QAAA,IAAIC,SAAYC,GAAAA,OAAAA,CAAQC,GAAG,CAACC,cAAc;AAE1C,QAAA,IAAI,CAACH,SAAW,EAAA;YACd,IAAI;gBACF,MAAMI,WAAAA,GAAcC,IAAKC,CAAAA,IAAI,CAACzB,MAAAA,CAAO0B,IAAI,CAACC,GAAG,CAACC,IAAI,EAAE,aAAA,CAAA;AACpDT,gBAAAA,SAAAA,GAAYU,EAAGC,CAAAA,YAAY,CAACP,WAAAA,CAAAA,CAAaQ,QAAQ,EAAA;AACnD,aAAA,CAAE,OAAOd,KAAO,EAAA;;AAEhB;AACF;AAEA,QAAA,IAAI,CAACE,SAAW,EAAA;AACdnB,YAAAA,MAAAA,CAAOgB,GAAG,CAACC,KAAK,CACd,CAAGJ,EAAAA,YAAAA,CAAa,0GAA0G,CAAC,CAAA;AAG7H,YAAA,MAAM,IAAIK,KAAM,CAAA,yDAAA,CAAA;AAClB;AAEA,QAAA,MAAMc,WAAcZ,GAAAA,OAAAA,CAAQC,GAAG,CAACY,aAAa,IAAI,kCAAA;AAEjD,QAAA,IAAI,CAACD,WAAa,EAAA;AAChBhC,YAAAA,MAAAA,CAAOgB,GAAG,CAACC,KAAK,CACd,CAAGJ,EAAAA,YAAAA,CAAa,6EAA6E,CAAC,CAAA;AAEhG,YAAA,MAAM,IAAIK,KAAM,CAAA,yDAAA,CAAA;AAClB;;AAGA,QAAA,MAAMgB,OAAOlC,MAAOmC,CAAAA,cAAc,CAACC,GAAG,IAAIC,KAAOH,EAAAA,IAAAA;AACjD,QAAA,IAAI,CAACA,IAAM,EAAA;AACTlC,YAAAA,MAAAA,CAAOgB,GAAG,CAACC,KAAK,CAAC,CAAGJ,EAAAA,YAAAA,CAAa,yCAAyC,CAAC,CAAA;AAC3E,YAAA,MAAM,IAAIK,KAAM,CAAA,yDAAA,CAAA;AAClB;;AAGA,QAAA,MAAMoB,cAAiBJ,GAAAA,IAAAA,CAAKK,EAAE,CAACR,QAAQ,EAAA;;AAGvC,QAAA,MAAMS,SAAYxC,GAAAA,MAAAA,CAAOyC,MAAM,CAACL,GAAG,CAAC,MAAA,CAAA;AACpC,QAAA,IAAI,CAACI,SAAW,EAAA;AACdxC,YAAAA,MAAAA,CAAOgB,GAAG,CAACC,KAAK,CAAC,CAAGJ,EAAAA,YAAAA,CAAa,0BAA0B,CAAC,CAAA;AAC5D,YAAA,MAAM,IAAIK,KAAM,CAAA,yDAAA,CAAA;AAClB;;AAGA,QAAA,MAAMwB,QAAW,GAAA,CAAA,EAAGF,SAAU,CAAA,CAAC,EAAEF,cAAgB,CAAA,CAAA;QACjD,MAAMK,WAAAA,GAAc9C,YAAauC,CAAAA,GAAG,CAACM,QAAAA,CAAAA;AAErC,QAAA,IAAIC,WAAa,EAAA;YACf,MAAMC,GAAAA,GAAMC,KAAKD,GAAG,EAAA;;AAEpB,YAAA,MAAME,QAAW,GAAA,CAAA,GAAI,EAAK,GAAA,IAAA,CAAA;AAE1B,YAAA,IAAIH,YAAYI,WAAW,IAAIJ,YAAYI,WAAW,GAAGD,WAAWF,GAAK,EAAA;gBACvE5C,MAAOgB,CAAAA,GAAG,CAACgC,IAAI,CAAC,uBAAA,CAAA;gBAEhB,OAAO;AACLC,oBAAAA,KAAAA,EAAON,YAAYM,KAAK;AACxBC,oBAAAA,SAAAA,EAAWP,YAAYO;AACzB,iBAAA;AACF;;AAGArD,YAAAA,YAAAA,CAAasD,MAAM,CAACT,QAAAA,CAAAA;AACtB;QAEA1C,MAAOgB,CAAAA,GAAG,CAACoC,IAAI,CAAC,2CAAA,CAAA;QAEhB,IAAI;;AAEF,YAAA,MAAMC,WAAW,MAAMC,KAAAA,CAAM,GAAGtB,WAAY,CAAA,cAAc,CAAC,EAAE;gBAC3DuB,MAAQ,EAAA,MAAA;gBACRC,OAAS,EAAA;oBACP,cAAgB,EAAA,kBAAA;;;AAGhB,oBAAA,cAAA,EAAgBC,OAAOC,UAAU;AACnC,iBAAA;gBACAC,IAAMC,EAAAA,IAAAA,CAAKC,SAAS,CAAC;AACnB1C,oBAAAA,SAAAA;AACAmB,oBAAAA,cAAAA;AACAE,oBAAAA;AACF,iBAAA;AACF,aAAA,CAAA;YAEA,IAAI,CAACa,QAASS,CAAAA,EAAE,EAAE;gBAChB,IAAIC,SAAAA;gBACJ,IAAIC,SAAAA;gBACJ,IAAI;oBACFA,SAAY,GAAA,MAAMX,SAASY,IAAI,EAAA;oBAC/BF,SAAYH,GAAAA,IAAAA,CAAKM,KAAK,CAACF,SAAAA,CAAAA;AACzB,iBAAA,CAAE,OAAM;oBACND,SAAY,GAAA;AAAE9C,wBAAAA,KAAAA,EAAO+C,SAAa,IAAA;AAAiC,qBAAA;AACrE;gBAEAhE,MAAOgB,CAAAA,GAAG,CAACC,KAAK,CAAC,CAAA,EAAGJ,YAAa,CAAA,CAAC,EAAEkD,SAAAA,EAAW9C,KAAS,IAAA,eAAA,CAAA,CAAiB,EAAE;AACzEkD,oBAAAA,MAAAA,EAAQd,SAASc,MAAM;AACvBC,oBAAAA,UAAAA,EAAYf,SAASe,UAAU;oBAC/BnD,KAAO8C,EAAAA,SAAAA;AACPC,oBAAAA,SAAAA;AACAxB,oBAAAA;AACF,iBAAA,CAAA;AAEA,gBAAA,MAAM,IAAItB,KAAM,CAAA,yDAAA,CAAA;AAClB;YAEA,IAAImD,IAAAA;YACJ,IAAI;gBACFA,IAAQ,GAAA,MAAMhB,SAASiB,IAAI,EAAA;AAI7B,aAAA,CAAE,OAAOC,UAAY,EAAA;gBACnBvE,MAAOgB,CAAAA,GAAG,CAACC,KAAK,CAAC,GAAGJ,YAAa,CAAA,mCAAmC,CAAC,EAAE0D,UAAAA,CAAAA;AACvE,gBAAA,MAAM,IAAIrD,KAAM,CAAA,yDAAA,CAAA;AAClB;YAEA,IAAI,CAACmD,IAAKG,CAAAA,GAAG,EAAE;AACbxE,gBAAAA,MAAAA,CAAOgB,GAAG,CAACC,KAAK,CAAC,CAAGJ,EAAAA,YAAAA,CAAa,oCAAoC,CAAC,CAAA;AACtE,gBAAA,MAAM,IAAIK,KAAM,CAAA,yDAAA,CAAA;AAClB;AAEAlB,YAAAA,MAAAA,CAAOgB,GAAG,CAACgC,IAAI,CAAC,iCAAmC,EAAA;AACjDyB,gBAAAA,MAAAA,EAAQvC,KAAKK,EAAE;AACfW,gBAAAA,SAAAA,EAAWmB,KAAKnB;AAClB,aAAA,CAAA;;YAGA,IAAImB,IAAAA,CAAKnB,SAAS,EAAE;AAClB,gBAAA,MAAMH,cAAc,IAAIF,IAAAA,CAAKwB,IAAKnB,CAAAA,SAAS,EAAEwB,OAAO,EAAA;gBACpD7E,YAAa8E,CAAAA,GAAG,CAACjC,QAAU,EAAA;AACzBO,oBAAAA,KAAAA,EAAOoB,KAAKG,GAAG;AACftB,oBAAAA,SAAAA,EAAWmB,KAAKnB,SAAS;AACzBH,oBAAAA;AACF,iBAAA,CAAA;AACF;;;YAIA,OAAO;AACLE,gBAAAA,KAAAA,EAAOoB,KAAKG,GAAG;AACftB,gBAAAA,SAAAA,EAAWmB,KAAKnB;AAClB,aAAA;AACF,SAAA,CAAE,OAAO0B,UAAY,EAAA;AACnB,YAAA,IAAIA,UAAsB1D,YAAAA,KAAAA,IAAS0D,UAAWC,CAAAA,IAAI,KAAK,YAAc,EAAA;AACnE7E,gBAAAA,MAAAA,CAAOgB,GAAG,CAACC,KAAK,CAAC,CAAGJ,EAAAA,YAAAA,CAAa,+BAA+B,CAAC,CAAA;AACjE,gBAAA,MAAM,IAAIK,KAAM,CAAA,yDAAA,CAAA;AAClB;YAEA,MAAM0D,UAAAA;AACR;AACF,KAAA;IAEA,OAAO;AACL3E,QAAAA,kBAAAA;AACAW,QAAAA;AACF,KAAA;AACF;;;;"}
@@ -1,3 +1,11 @@
1
+ import crypto from 'crypto';
2
+ import fs from 'fs';
3
+ import path from 'path';
4
+
5
+ /**
6
+ * In-memory cache for AI tokens
7
+ * Key format: `${projectId}:${userId}`
8
+ */ const aiTokenCache = new Map();
1
9
  const createAIContainer = ({ strapi })=>{
2
10
  const getAIFeatureConfig = async ()=>{
3
11
  const i18nSettings = await strapi.plugin('i18n').service('settings').getSettings();
@@ -7,8 +15,142 @@ const createAIContainer = ({ strapi })=>{
7
15
  isAIMediaLibraryConfigured: Boolean(uploadSettings?.aiMetadata)
8
16
  };
9
17
  };
18
+ const getAiToken = async ()=>{
19
+ const ERROR_PREFIX = 'AI token request failed:';
20
+ // Check if EE features are enabled first
21
+ if (!strapi.ee?.isEE) {
22
+ strapi.log.error(`${ERROR_PREFIX} Enterprise Edition features are not enabled`);
23
+ throw new Error('AI token request failed. Check server logs for details.');
24
+ }
25
+ // Get the EE license
26
+ // First try environment variable, then try reading from file
27
+ let eeLicense = process.env.STRAPI_LICENSE;
28
+ if (!eeLicense) {
29
+ try {
30
+ const licensePath = path.join(strapi.dirs.app.root, 'license.txt');
31
+ eeLicense = fs.readFileSync(licensePath).toString();
32
+ } catch (error) {
33
+ // License file doesn't exist or can't be read
34
+ }
35
+ }
36
+ if (!eeLicense) {
37
+ strapi.log.error(`${ERROR_PREFIX} No EE license found. Please ensure STRAPI_LICENSE environment variable is set or license.txt file exists.`);
38
+ throw new Error('AI token request failed. Check server logs for details.');
39
+ }
40
+ const aiServerUrl = process.env.STRAPI_AI_URL || 'https://strapi-ai.apps.strapi.io';
41
+ if (!aiServerUrl) {
42
+ strapi.log.error(`${ERROR_PREFIX} AI server URL not configured. Please set STRAPI_AI_URL environment variable.`);
43
+ throw new Error('AI token request failed. Check server logs for details.');
44
+ }
45
+ // Get the current user
46
+ const user = strapi.requestContext.get()?.state?.user;
47
+ if (!user) {
48
+ strapi.log.error(`${ERROR_PREFIX} No authenticated user in request context`);
49
+ throw new Error('AI token request failed. Check server logs for details.');
50
+ }
51
+ // Create a secure user identifier using only user ID
52
+ const userIdentifier = user.id.toString();
53
+ // Get project ID
54
+ const projectId = strapi.config.get('uuid');
55
+ if (!projectId) {
56
+ strapi.log.error(`${ERROR_PREFIX} Project ID not configured`);
57
+ throw new Error('AI token request failed. Check server logs for details.');
58
+ }
59
+ // Check cache for existing valid token
60
+ const cacheKey = `${projectId}:${userIdentifier}`;
61
+ const cachedToken = aiTokenCache.get(cacheKey);
62
+ if (cachedToken) {
63
+ const now = Date.now();
64
+ // Check if token is still valid (with buffer so it has time to to be used)
65
+ const bufferMs = 2 * 60 * 1000; // 2 minutes
66
+ if (cachedToken.expiresAtMs && cachedToken.expiresAtMs - bufferMs > now) {
67
+ strapi.log.info('Using cached AI token');
68
+ return {
69
+ token: cachedToken.token,
70
+ expiresAt: cachedToken.expiresAt
71
+ };
72
+ }
73
+ // Token expired or will expire soon, remove from cache
74
+ aiTokenCache.delete(cacheKey);
75
+ }
76
+ strapi.log.http('Contacting AI Server for token generation');
77
+ try {
78
+ // Call the AI server's getAiJWT endpoint
79
+ const response = await fetch(`${aiServerUrl}/auth/getAiJWT`, {
80
+ method: 'POST',
81
+ headers: {
82
+ 'Content-Type': 'application/json',
83
+ // No authorization header needed for public endpoint
84
+ // Add request ID for tracing
85
+ 'X-Request-Id': crypto.randomUUID()
86
+ },
87
+ body: JSON.stringify({
88
+ eeLicense,
89
+ userIdentifier,
90
+ projectId
91
+ })
92
+ });
93
+ if (!response.ok) {
94
+ let errorData;
95
+ let errorText;
96
+ try {
97
+ errorText = await response.text();
98
+ errorData = JSON.parse(errorText);
99
+ } catch {
100
+ errorData = {
101
+ error: errorText || 'Failed to parse error response'
102
+ };
103
+ }
104
+ strapi.log.error(`${ERROR_PREFIX} ${errorData?.error || 'Unknown error'}`, {
105
+ status: response.status,
106
+ statusText: response.statusText,
107
+ error: errorData,
108
+ errorText,
109
+ projectId
110
+ });
111
+ throw new Error('AI token request failed. Check server logs for details.');
112
+ }
113
+ let data;
114
+ try {
115
+ data = await response.json();
116
+ } catch (parseError) {
117
+ strapi.log.error(`${ERROR_PREFIX} Failed to parse AI server response`, parseError);
118
+ throw new Error('AI token request failed. Check server logs for details.');
119
+ }
120
+ if (!data.jwt) {
121
+ strapi.log.error(`${ERROR_PREFIX} Invalid response: missing JWT token`);
122
+ throw new Error('AI token request failed. Check server logs for details.');
123
+ }
124
+ strapi.log.info('AI token generated successfully', {
125
+ userId: user.id,
126
+ expiresAt: data.expiresAt
127
+ });
128
+ // Cache the token if it has an expiration time
129
+ if (data.expiresAt) {
130
+ const expiresAtMs = new Date(data.expiresAt).getTime();
131
+ aiTokenCache.set(cacheKey, {
132
+ token: data.jwt,
133
+ expiresAt: data.expiresAt,
134
+ expiresAtMs
135
+ });
136
+ }
137
+ // Return the AI JWT with metadata
138
+ // Note: Token expires in 1 hour, client should handle refresh
139
+ return {
140
+ token: data.jwt,
141
+ expiresAt: data.expiresAt
142
+ };
143
+ } catch (fetchError) {
144
+ if (fetchError instanceof Error && fetchError.name === 'AbortError') {
145
+ strapi.log.error(`${ERROR_PREFIX} Request to AI server timed out`);
146
+ throw new Error('AI token request failed. Check server logs for details.');
147
+ }
148
+ throw fetchError;
149
+ }
150
+ };
10
151
  return {
11
- getAIFeatureConfig
152
+ getAIFeatureConfig,
153
+ getAiToken
12
154
  };
13
155
  };
14
156
 
@@ -1 +1 @@
1
- {"version":3,"file":"ai.mjs","sources":["../../../../../../../ee/server/src/ai/containers/ai.ts"],"sourcesContent":["import type { Core } from '@strapi/types';\n\nconst createAIContainer = ({ strapi }: { strapi: Core.Strapi }) => {\n const getAIFeatureConfig = async () => {\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 return {\n getAIFeatureConfig,\n };\n};\n\nexport { createAIContainer };\n"],"names":["createAIContainer","strapi","getAIFeatureConfig","i18nSettings","plugin","service","getSettings","uploadSettings","isAIi18nConfigured","Boolean","aiLocalizations","isAIMediaLibraryConfigured","aiMetadata"],"mappings":"AAEA,MAAMA,iBAAoB,GAAA,CAAC,EAAEC,MAAM,EAA2B,GAAA;AAC5D,IAAA,MAAMC,kBAAqB,GAAA,UAAA;QACzB,MAAMC,YAAAA,GAAe,MAAMF,MAAOG,CAAAA,MAAM,CAAC,MAAQC,CAAAA,CAAAA,OAAO,CAAC,UAAA,CAAA,CAAYC,WAAW,EAAA;QAChF,MAAMC,cAAAA,GAAiB,MAAMN,MAAOG,CAAAA,MAAM,CAAC,QAAUC,CAAAA,CAAAA,OAAO,CAAC,QAAA,CAAA,CAAUC,WAAW,EAAA;QAElF,OAAO;AACLE,YAAAA,kBAAAA,EAAoBC,QAAQN,YAAcO,EAAAA,eAAAA,CAAAA;AAC1CC,YAAAA,0BAAAA,EAA4BF,QAAQF,cAAgBK,EAAAA,UAAAA;AACtD,SAAA;AACF,KAAA;IAEA,OAAO;AACLV,QAAAA;AACF,KAAA;AACF;;;;"}
1
+ {"version":3,"file":"ai.mjs","sources":["../../../../../../../ee/server/src/ai/containers/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\n/**\n * In-memory cache for AI tokens\n * Key format: `${projectId}:${userId}`\n */\nconst aiTokenCache = new Map<\n string,\n {\n token: string;\n expiresAt?: string;\n expiresAtMs?: number;\n }\n>();\n\nconst createAIContainer = ({ strapi }: { strapi: Core.Strapi }) => {\n const getAIFeatureConfig = async () => {\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 const getAiToken = async () => {\n const ERROR_PREFIX = 'AI token request failed:';\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 throw new Error('AI token request failed. Check server logs for details.');\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\n throw new Error('AI token request failed. Check server logs for details.');\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 throw new Error('AI token request failed. Check server logs for details.');\n }\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 // Get project ID\n const projectId = strapi.config.get('uuid');\n if (!projectId) {\n strapi.log.error(`${ERROR_PREFIX} Project ID not configured`);\n throw new Error('AI token request failed. Check server logs for details.');\n }\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 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 // 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 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 // Return the AI JWT with metadata\n // Note: Token expires in 1 hour, client should handle refresh\n return {\n token: data.jwt,\n expiresAt: data.expiresAt, // 1 hour from generation\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 return {\n getAIFeatureConfig,\n getAiToken,\n };\n};\n\nexport { createAIContainer };\n"],"names":["aiTokenCache","Map","createAIContainer","strapi","getAIFeatureConfig","i18nSettings","plugin","service","getSettings","uploadSettings","isAIi18nConfigured","Boolean","aiLocalizations","isAIMediaLibraryConfigured","aiMetadata","getAiToken","ERROR_PREFIX","ee","isEE","log","error","Error","eeLicense","process","env","STRAPI_LICENSE","licensePath","path","join","dirs","app","root","fs","readFileSync","toString","aiServerUrl","STRAPI_AI_URL","user","requestContext","get","state","userIdentifier","id","projectId","config","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"],"mappings":"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"}
@@ -6,118 +6,19 @@ var crypto = require('crypto');
6
6
 
7
7
  var aiController = {
8
8
  async getAiToken (ctx) {
9
- const ERROR_PREFIX = 'AI token request failed:';
10
- const USER_ERROR_MESSAGE = 'AI token request failed. Check server logs for details.';
11
9
  try {
10
+ // TODO: auth check is not necessary? Already protected by route middleware?
12
11
  // Security check: Ensure user is authenticated and has proper permissions
13
12
  if (!ctx.state.user) {
14
13
  return ctx.unauthorized('Authentication required');
15
14
  }
16
- // Check if EE features are enabled first
17
- if (!strapi.ee?.isEE) {
18
- strapi.log.error(`${ERROR_PREFIX} Enterprise Edition features are not enabled`);
19
- return ctx.internalServerError(USER_ERROR_MESSAGE);
20
- }
21
- // Get the EE license
22
- // First try environment variable, then try reading from file
23
- let eeLicense = process.env.STRAPI_LICENSE;
24
- if (!eeLicense) {
25
- try {
26
- const licensePath = path.join(strapi.dirs.app.root, 'license.txt');
27
- eeLicense = fs.readFileSync(licensePath).toString();
28
- } catch (error) {
29
- // License file doesn't exist or can't be read
30
- }
31
- }
32
- if (!eeLicense) {
33
- strapi.log.error(`${ERROR_PREFIX} No EE license found. Please ensure STRAPI_LICENSE environment variable is set or license.txt file exists.`);
34
- return ctx.internalServerError(USER_ERROR_MESSAGE);
35
- }
36
- const aiServerUrl = process.env.STRAPI_AI_URL || 'https://strapi-ai.apps.strapi.io';
37
- if (!aiServerUrl) {
38
- strapi.log.error(`${ERROR_PREFIX} AI server URL not configured. Please set STRAPI_AI_URL environment variable.`);
39
- return ctx.internalServerError(USER_ERROR_MESSAGE);
40
- }
41
- // Get the current user
42
- const user = ctx.state.user;
43
- // Create a secure user identifier using only user ID
44
- const userIdentifier = user.id.toString();
45
- // Get project ID
46
- const projectId = strapi.config.get('uuid');
47
- if (!projectId) {
48
- strapi.log.error(`${ERROR_PREFIX} Project ID not configured`);
49
- return ctx.internalServerError(USER_ERROR_MESSAGE);
50
- }
51
- strapi.log.http('Contacting AI Server for token generation');
52
- try {
53
- // Call the AI server's getAiJWT endpoint
54
- const response = await fetch(`${aiServerUrl}/auth/getAiJWT`, {
55
- method: 'POST',
56
- headers: {
57
- 'Content-Type': 'application/json',
58
- // No authorization header needed for public endpoint
59
- // Add request ID for tracing
60
- 'X-Request-Id': crypto.randomUUID()
61
- },
62
- body: JSON.stringify({
63
- eeLicense,
64
- userIdentifier,
65
- projectId
66
- })
67
- });
68
- if (!response.ok) {
69
- let errorData;
70
- let errorText;
71
- try {
72
- errorText = await response.text();
73
- errorData = JSON.parse(errorText);
74
- } catch {
75
- errorData = {
76
- error: errorText || 'Failed to parse error response'
77
- };
78
- }
79
- strapi.log.error(`${ERROR_PREFIX} ${errorData?.error || 'Unknown error'}`, {
80
- status: response.status,
81
- statusText: response.statusText,
82
- error: errorData,
83
- errorText,
84
- projectId
85
- });
86
- return ctx.internalServerError(USER_ERROR_MESSAGE);
87
- }
88
- let data;
89
- try {
90
- data = await response.json();
91
- } catch (parseError) {
92
- strapi.log.error(`${ERROR_PREFIX} Failed to parse AI server response`, parseError);
93
- return ctx.internalServerError(USER_ERROR_MESSAGE);
94
- }
95
- if (!data.jwt) {
96
- strapi.log.error(`${ERROR_PREFIX} Invalid response: missing JWT token`);
97
- return ctx.internalServerError(USER_ERROR_MESSAGE);
98
- }
99
- strapi.log.info('AI token generated successfully', {
100
- userId: user.id,
101
- expiresAt: data.expiresAt
102
- });
103
- // Return the AI JWT with metadata
104
- // Note: Token expires in 1 hour, client should handle refresh
105
- ctx.body = {
106
- data: {
107
- token: data.jwt,
108
- expiresAt: data.expiresAt
109
- }
110
- };
111
- } catch (fetchError) {
112
- if (fetchError instanceof Error && fetchError.name === 'AbortError') {
113
- strapi.log.error(`${ERROR_PREFIX} Request to AI server timed out`);
114
- return ctx.internalServerError(USER_ERROR_MESSAGE);
115
- }
116
- throw fetchError;
117
- }
15
+ const aiToken = await strapi.get('ai').getAiToken();
16
+ ctx.body = {
17
+ data: aiToken
18
+ };
118
19
  } catch (error) {
119
- strapi.log.error(`${ERROR_PREFIX} ${error instanceof Error ? error.message : 'Unknown error'}`, error);
120
- return ctx.internalServerError(USER_ERROR_MESSAGE);
20
+ const errorMessage = 'AI token request failed. Check server logs for details.';
21
+ return ctx.internalServerError(errorMessage);
121
22
  }
122
23
  },
123
24
  async getAiUsage (ctx) {