@strapi/admin 5.42.0 → 5.43.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/admin/admin/src/StrapiApp.js +1 -0
- package/dist/admin/admin/src/StrapiApp.js.map +1 -1
- package/dist/admin/admin/src/StrapiApp.mjs +1 -0
- package/dist/admin/admin/src/StrapiApp.mjs.map +1 -1
- package/dist/admin/admin/src/components/Form.js +11 -10
- package/dist/admin/admin/src/components/Form.js.map +1 -1
- package/dist/admin/admin/src/components/Form.mjs +11 -10
- package/dist/admin/admin/src/components/Form.mjs.map +1 -1
- package/dist/admin/admin/src/components/FormInputs/Date.js +2 -2
- package/dist/admin/admin/src/components/FormInputs/Date.js.map +1 -1
- package/dist/admin/admin/src/components/FormInputs/Date.mjs +2 -2
- package/dist/admin/admin/src/components/FormInputs/Date.mjs.map +1 -1
- package/dist/admin/admin/src/components/FormInputs/Time.js +6 -1
- package/dist/admin/admin/src/components/FormInputs/Time.js.map +1 -1
- package/dist/admin/admin/src/components/FormInputs/Time.mjs +6 -1
- package/dist/admin/admin/src/components/FormInputs/Time.mjs.map +1 -1
- package/dist/admin/admin/src/components/GuidedTour/Context.js +3 -2
- package/dist/admin/admin/src/components/GuidedTour/Context.js.map +1 -1
- package/dist/admin/admin/src/components/GuidedTour/Context.mjs +3 -2
- package/dist/admin/admin/src/components/GuidedTour/Context.mjs.map +1 -1
- package/dist/admin/admin/src/components/PageHelpers.js +1 -1
- package/dist/admin/admin/src/components/PageHelpers.js.map +1 -1
- package/dist/admin/admin/src/components/PageHelpers.mjs +1 -1
- package/dist/admin/admin/src/components/PageHelpers.mjs.map +1 -1
- package/dist/admin/admin/src/components/Table.js +28 -15
- package/dist/admin/admin/src/components/Table.js.map +1 -1
- package/dist/admin/admin/src/components/Table.mjs +29 -16
- package/dist/admin/admin/src/components/Table.mjs.map +1 -1
- package/dist/admin/admin/src/core/store/configure.js +3 -1
- package/dist/admin/admin/src/core/store/configure.js.map +1 -1
- package/dist/admin/admin/src/core/store/configure.mjs +3 -1
- package/dist/admin/admin/src/core/store/configure.mjs.map +1 -1
- package/dist/admin/admin/src/features/Widgets.js +1 -1
- package/dist/admin/admin/src/features/Widgets.js.map +1 -1
- package/dist/admin/admin/src/features/Widgets.mjs +1 -1
- package/dist/admin/admin/src/features/Widgets.mjs.map +1 -1
- package/dist/admin/admin/src/hooks/usePersistentState.js +9 -4
- package/dist/admin/admin/src/hooks/usePersistentState.js.map +1 -1
- package/dist/admin/admin/src/hooks/usePersistentState.mjs +10 -6
- package/dist/admin/admin/src/hooks/usePersistentState.mjs.map +1 -1
- package/dist/admin/admin/src/pages/ProfilePage.js +2 -2
- package/dist/admin/admin/src/pages/ProfilePage.js.map +1 -1
- package/dist/admin/admin/src/pages/ProfilePage.mjs +2 -2
- package/dist/admin/admin/src/pages/ProfilePage.mjs.map +1 -1
- package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/components/LogoInput.js +4 -1
- package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/components/LogoInput.js.map +1 -1
- package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/components/LogoInput.mjs +4 -1
- package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/components/LogoInput.mjs.map +1 -1
- package/dist/admin/admin/src/pages/Settings/pages/Roles/utils/forms.js +1 -1
- package/dist/admin/admin/src/pages/Settings/pages/Roles/utils/forms.js.map +1 -1
- package/dist/admin/admin/src/pages/Settings/pages/Roles/utils/forms.mjs +1 -1
- package/dist/admin/admin/src/pages/Settings/pages/Roles/utils/forms.mjs.map +1 -1
- package/dist/admin/admin/src/pages/Settings/pages/TransferTokens/ListView.js +1 -1
- package/dist/admin/admin/src/pages/Settings/pages/TransferTokens/ListView.js.map +1 -1
- package/dist/admin/admin/src/pages/Settings/pages/TransferTokens/ListView.mjs +1 -1
- package/dist/admin/admin/src/pages/Settings/pages/TransferTokens/ListView.mjs.map +1 -1
- package/dist/admin/admin/src/render.js +2 -0
- package/dist/admin/admin/src/render.js.map +1 -1
- package/dist/admin/admin/src/render.mjs +2 -0
- package/dist/admin/admin/src/render.mjs.map +1 -1
- package/dist/admin/admin/src/services/api.js +2 -2
- package/dist/admin/admin/src/services/api.js.map +1 -1
- package/dist/admin/admin/src/services/api.mjs +2 -2
- package/dist/admin/admin/src/services/api.mjs.map +1 -1
- package/dist/admin/admin/src/translations/fi.json.js +890 -0
- package/dist/admin/admin/src/translations/fi.json.js.map +1 -0
- package/dist/admin/admin/src/translations/fi.json.mjs +868 -0
- package/dist/admin/admin/src/translations/fi.json.mjs.map +1 -0
- package/dist/admin/admin/src/translations/languageNativeNames.js +2 -1
- package/dist/admin/admin/src/translations/languageNativeNames.js.map +1 -1
- package/dist/admin/admin/src/translations/languageNativeNames.mjs +2 -1
- package/dist/admin/admin/src/translations/languageNativeNames.mjs.map +1 -1
- package/dist/admin/admin/src/translations/nl.json.js +394 -89
- package/dist/admin/admin/src/translations/nl.json.js.map +1 -1
- package/dist/admin/admin/src/translations/nl.json.mjs +393 -90
- package/dist/admin/admin/src/translations/nl.json.mjs.map +1 -1
- package/dist/admin/admin/src/translations/pl.json.js +411 -37
- package/dist/admin/admin/src/translations/pl.json.js.map +1 -1
- package/dist/admin/admin/src/translations/pl.json.mjs +408 -38
- package/dist/admin/admin/src/translations/pl.json.mjs.map +1 -1
- package/dist/admin/ee/admin/src/hooks/useAIUsageWarning.js +1 -1
- package/dist/admin/ee/admin/src/hooks/useAIUsageWarning.js.map +1 -1
- package/dist/admin/ee/admin/src/hooks/useAIUsageWarning.mjs +2 -2
- package/dist/admin/ee/admin/src/hooks/useAIUsageWarning.mjs.map +1 -1
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/ApplicationInfoPage/components/AIUsage.js +1 -1
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/ApplicationInfoPage/components/AIUsage.js.map +1 -1
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/ApplicationInfoPage/components/AIUsage.mjs +2 -2
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/ApplicationInfoPage/components/AIUsage.mjs.map +1 -1
- package/dist/admin/ee/admin/src/services/ai.js +7 -7
- package/dist/admin/ee/admin/src/services/ai.js.map +1 -1
- package/dist/admin/ee/admin/src/services/ai.mjs +6 -6
- package/dist/admin/ee/admin/src/services/ai.mjs.map +1 -1
- package/dist/admin/ee.js +2 -2
- package/dist/admin/ee.mjs +1 -1
- package/dist/admin/index.js +1 -0
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/index.mjs +1 -1
- package/dist/admin/src/core/store/configure.d.ts +2 -2
- package/dist/admin/src/core/store/hooks.d.ts +2 -2
- package/dist/admin/src/ee.d.ts +1 -1
- package/dist/admin/src/hooks/useAdminRoles.d.ts +1 -1
- package/dist/admin/src/hooks/usePersistentState.d.ts +2 -1
- package/dist/admin/src/index.d.ts +1 -1
- package/dist/admin/src/pages/Settings/pages/Roles/utils/forms.d.ts +1 -1
- package/dist/admin/src/pages/Settings/pages/Webhooks/hooks/useWebhooks.d.ts +4 -4
- package/dist/admin/src/selectors.d.ts +2 -2
- package/dist/admin/src/services/admin.d.ts +6 -6
- package/dist/admin/src/services/api.d.ts +1 -1
- package/dist/admin/src/services/apiTokens.d.ts +1 -1
- package/dist/admin/src/services/auth.d.ts +11 -11
- package/dist/admin/src/services/contentApi.d.ts +1 -1
- package/dist/admin/src/services/contentManager.d.ts +1 -1
- package/dist/admin/src/services/homepage.d.ts +3 -3
- package/dist/admin/src/services/transferTokens.d.ts +1 -1
- package/dist/admin/src/services/users.d.ts +8 -8
- package/dist/admin/src/services/webhooks.d.ts +2 -2
- package/dist/admin/src/translations/languageNativeNames.d.ts +1 -0
- package/dist/admin/tests/utils.d.ts +1 -1
- package/dist/ee/admin/src/services/ai.d.ts +6 -6
- package/dist/ee/admin/src/services/auditLogs.d.ts +1 -1
- package/dist/ee/server/src/audit-logs/services/lifecycles.d.ts +1 -1
- package/dist/ee/server/src/index.d.ts +0 -16
- package/dist/ee/server/src/index.d.ts.map +1 -1
- package/dist/server/ee/server/src/audit-logs/services/lifecycles.js +1 -1
- package/dist/server/ee/server/src/audit-logs/services/lifecycles.js.map +1 -1
- package/dist/server/ee/server/src/audit-logs/services/lifecycles.mjs +1 -1
- package/dist/server/ee/server/src/audit-logs/services/lifecycles.mjs.map +1 -1
- package/dist/server/ee/server/src/index.js +1 -17
- package/dist/server/ee/server/src/index.js.map +1 -1
- package/dist/server/ee/server/src/index.mjs +1 -17
- package/dist/server/ee/server/src/index.mjs.map +1 -1
- package/dist/server/server/src/ai/controllers/ai.js +52 -0
- package/dist/server/server/src/ai/controllers/ai.js.map +1 -0
- package/dist/server/server/src/ai/controllers/ai.mjs +50 -0
- package/dist/server/server/src/ai/controllers/ai.mjs.map +1 -0
- package/dist/server/{ee/server → server}/src/ai/routes/ai.js +1 -2
- package/dist/server/server/src/ai/routes/ai.js.map +1 -0
- package/dist/server/{ee/server → server}/src/ai/routes/ai.mjs +1 -2
- package/dist/server/server/src/ai/routes/ai.mjs.map +1 -0
- package/dist/server/{ee/server/src/ai/containers → server/src/ai/services}/ai.js +107 -32
- package/dist/server/server/src/ai/services/ai.js.map +1 -0
- package/dist/server/{ee/server/src/ai/containers → server/src/ai/services}/ai.mjs +107 -32
- package/dist/server/server/src/ai/services/ai.mjs.map +1 -0
- package/dist/server/server/src/controllers/index.js +3 -1
- package/dist/server/server/src/controllers/index.js.map +1 -1
- package/dist/server/server/src/controllers/index.mjs +3 -1
- package/dist/server/server/src/controllers/index.mjs.map +1 -1
- package/dist/server/server/src/register.js +4 -0
- package/dist/server/server/src/register.js.map +1 -1
- package/dist/server/server/src/register.mjs +4 -0
- package/dist/server/server/src/register.mjs.map +1 -1
- package/dist/server/server/src/routes/index.js +3 -1
- package/dist/server/server/src/routes/index.js.map +1 -1
- package/dist/server/server/src/routes/index.mjs +3 -1
- package/dist/server/server/src/routes/index.mjs.map +1 -1
- package/dist/{ee/server → server}/src/ai/controllers/ai.d.ts +1 -1
- package/dist/server/src/ai/controllers/ai.d.ts.map +1 -0
- package/dist/server/src/ai/routes/ai.d.ts.map +1 -0
- package/dist/server/src/ai/services/ai.d.ts +30 -0
- package/dist/server/src/ai/services/ai.d.ts.map +1 -0
- package/dist/server/src/controllers/index.d.ts +5 -0
- package/dist/server/src/controllers/index.d.ts.map +1 -1
- package/dist/server/src/index.d.ts +5 -0
- package/dist/server/src/index.d.ts.map +1 -1
- package/dist/server/src/register.d.ts.map +1 -1
- package/dist/server/src/routes/index.d.ts.map +1 -1
- package/dist/shared/contracts/ai.d.ts +3 -3
- package/package.json +9 -9
- package/dist/ee/server/src/ai/containers/ai.d.ts +0 -15
- package/dist/ee/server/src/ai/containers/ai.d.ts.map +0 -1
- package/dist/ee/server/src/ai/controllers/ai.d.ts.map +0 -1
- package/dist/ee/server/src/ai/routes/ai.d.ts.map +0 -1
- package/dist/server/ee/server/src/ai/containers/ai.js.map +0 -1
- package/dist/server/ee/server/src/ai/containers/ai.mjs.map +0 -1
- package/dist/server/ee/server/src/ai/controllers/ai.js +0 -121
- package/dist/server/ee/server/src/ai/controllers/ai.js.map +0 -1
- package/dist/server/ee/server/src/ai/controllers/ai.mjs +0 -119
- package/dist/server/ee/server/src/ai/controllers/ai.mjs.map +0 -1
- package/dist/server/ee/server/src/ai/routes/ai.js.map +0 -1
- package/dist/server/ee/server/src/ai/routes/ai.mjs.map +0 -1
- /package/dist/{ee/server → server}/src/ai/routes/ai.d.ts +0 -0
|
@@ -10,9 +10,6 @@ import auditLogsController from './audit-logs/controllers/audit-logs.mjs';
|
|
|
10
10
|
import { createAuditLogsService } from './audit-logs/services/audit-logs.mjs';
|
|
11
11
|
import { createAuditLogsLifecycleService } from './audit-logs/services/lifecycles.mjs';
|
|
12
12
|
import { auditLog } from './audit-logs/content-types/audit-log.mjs';
|
|
13
|
-
import aiRoutes from './ai/routes/ai.mjs';
|
|
14
|
-
import aiController from './ai/controllers/ai.mjs';
|
|
15
|
-
import { createAIContainer } from './ai/containers/ai.mjs';
|
|
16
13
|
|
|
17
14
|
const getAdminEE = ()=>{
|
|
18
15
|
const eeAdmin = {
|
|
@@ -28,7 +25,6 @@ const getAdminEE = ()=>{
|
|
|
28
25
|
controllers,
|
|
29
26
|
routes
|
|
30
27
|
};
|
|
31
|
-
const isAIEnabled = strapi.config.get('admin.ai.enabled', true) && strapi.ee.features.isEnabled('cms-ai');
|
|
32
28
|
const isAuditLogsEnabled = strapi.config.get('admin.auditLogs.enabled', true) && strapi.ee.features.isEnabled('audit-logs');
|
|
33
29
|
return {
|
|
34
30
|
...eeAdmin,
|
|
@@ -36,31 +32,19 @@ const getAdminEE = ()=>{
|
|
|
36
32
|
...eeAdmin.controllers,
|
|
37
33
|
...isAuditLogsEnabled ? {
|
|
38
34
|
'audit-logs': auditLogsController
|
|
39
|
-
} : {},
|
|
40
|
-
...isAIEnabled ? {
|
|
41
|
-
ai: aiController
|
|
42
35
|
} : {}
|
|
43
36
|
},
|
|
44
37
|
routes: {
|
|
45
38
|
...eeAdmin.routes,
|
|
46
39
|
...isAuditLogsEnabled ? {
|
|
47
40
|
'audit-logs': auditLogsRoutes
|
|
48
|
-
} : {},
|
|
49
|
-
...isAIEnabled ? {
|
|
50
|
-
ai: aiRoutes
|
|
51
41
|
} : {}
|
|
52
42
|
},
|
|
53
43
|
async register ({ strapi: strapi1 }) {
|
|
54
|
-
// Run the
|
|
44
|
+
// Run the default registration
|
|
55
45
|
await eeAdmin.register({
|
|
56
46
|
strapi: strapi1
|
|
57
47
|
});
|
|
58
|
-
// Register internal ai service
|
|
59
|
-
if (isAIEnabled) {
|
|
60
|
-
strapi1.add('ai', createAIContainer({
|
|
61
|
-
strapi: strapi1
|
|
62
|
-
}));
|
|
63
|
-
}
|
|
64
48
|
if (isAuditLogsEnabled) {
|
|
65
49
|
// Register an internal audit logs service
|
|
66
50
|
strapi1.add('audit-logs', createAuditLogsService(strapi1));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","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
|
|
1
|
+
{"version":3,"file":"index.mjs","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 const isAuditLogsEnabled =\n strapi.config.get('admin.auditLogs.enabled', true) &&\n strapi.ee.features.isEnabled('audit-logs');\n return {\n ...eeAdmin,\n controllers: {\n ...eeAdmin.controllers,\n ...(isAuditLogsEnabled ? { 'audit-logs': auditLogsController } : {}),\n },\n routes: {\n ...eeAdmin.routes,\n ...(isAuditLogsEnabled ? { 'audit-logs': auditLogsRoutes } : {}),\n },\n async register({ strapi }: { strapi: Core.Strapi }) {\n // Run the default registration\n await eeAdmin.register({ strapi });\n\n if (isAuditLogsEnabled) {\n // Register an internal audit logs service\n strapi.add('audit-logs', createAuditLogsService(strapi));\n // Register an internal audit logs lifecycle service\n const auditLogsLifecycle = createAuditLogsLifecycleService(strapi);\n strapi.add('audit-logs-lifecycle', auditLogsLifecycle);\n\n 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","isAuditLogsEnabled","strapi","config","get","ee","features","isEnabled","auditLogsController","auditLogsRoutes","add","createAuditLogsService","auditLogsLifecycle","createAuditLogsLifecycleService"],"mappings":";;;;;;;;;;;;;AAcA,MAAMA,UAAAA,GAAa,IAAA;AACjB,IAAA,MAAMC,OAAAA,GAAU;AACdC,QAAAA,QAAAA;AACAC,QAAAA,SAAAA;AACAC,QAAAA,OAAAA;QACAC,YAAAA,EAAc;;YAEZ,WAAA,EAAaC,QAAAA;AACb,YAAA,GAAGC;AACL,SAAA;AACAC,QAAAA,QAAAA;AACAC,QAAAA,WAAAA;AACAC,QAAAA;AACF,KAAA;AAEA,IAAA,MAAMC,kBAAAA,GACJC,MAAAA,CAAOC,MAAM,CAACC,GAAG,CAAC,yBAAA,EAA2B,IAAA,CAAA,IAC7CF,MAAAA,CAAOG,EAAE,CAACC,QAAQ,CAACC,SAAS,CAAC,YAAA,CAAA;IAC/B,OAAO;AACL,QAAA,GAAGhB,OAAO;QACVQ,WAAAA,EAAa;AACX,YAAA,GAAGR,QAAQQ,WAAW;AACtB,YAAA,GAAIE,kBAAAA,GAAqB;gBAAE,YAAA,EAAcO;AAAoB,aAAA,GAAI;AACnE,SAAA;QACAR,MAAAA,EAAQ;AACN,YAAA,GAAGT,QAAQS,MAAM;AACjB,YAAA,GAAIC,kBAAAA,GAAqB;gBAAE,YAAA,EAAcQ;AAAgB,aAAA,GAAI;AAC/D,SAAA;AACA,QAAA,MAAMjB,QAAAA,CAAAA,CAAS,EAAEU,MAAAA,EAAAA,OAAM,EAA2B,EAAA;;YAEhD,MAAMX,OAAAA,CAAQC,QAAQ,CAAC;gBAAEU,MAAAA,EAAAA;AAAO,aAAA,CAAA;AAEhC,YAAA,IAAID,kBAAAA,EAAoB;;gBAEtBC,OAAAA,CAAOQ,GAAG,CAAC,YAAA,EAAcC,sBAAAA,CAAuBT,OAAAA,CAAAA,CAAAA;;AAEhD,gBAAA,MAAMU,qBAAqBC,+BAAAA,CAAgCX,OAAAA,CAAAA;gBAC3DA,OAAAA,CAAOQ,GAAG,CAAC,sBAAA,EAAwBE,kBAAAA,CAAAA;AAEnC,gBAAA,MAAMA,mBAAmBpB,QAAQ,EAAA;AACnC,YAAA;AACF,QAAA,CAAA;AACA,QAAA,MAAME,OAAAA,CAAAA,CAAQ,EAAEQ,MAAAA,EAAAA,OAAM,EAA2B,EAAA;AAC/C,YAAA,IAAID,kBAAAA,EAAoB;gBACtBC,OAAAA,CAAOE,GAAG,CAAC,sBAAA,CAAA,CAAwBV,OAAO,EAAA;AAC5C,YAAA;YACA,MAAMH,OAAAA,CAAQG,OAAO,CAAC;gBAAEQ,MAAAA,EAAAA;AAAO,aAAA,CAAA;AACjC,QAAA;AACF,KAAA;AACF;;;;"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var ai = {
|
|
4
|
+
async getAiToken (ctx) {
|
|
5
|
+
if (strapi.ai.admin.isEnabled() === false) {
|
|
6
|
+
return ctx.notFound();
|
|
7
|
+
}
|
|
8
|
+
try {
|
|
9
|
+
// `admin::isAuthenticatedAdmin` only checks `ctx.state.isAuthenticated`, not `ctx.state.user`.
|
|
10
|
+
// With the current admin JWT strategy, a successful auth run always sets both; this handler
|
|
11
|
+
// still requires `user` because `getAiToken()` needs an admin identity. Keeps us safe if the
|
|
12
|
+
// strategy/policy contract ever diverges or this action is invoked outside the normal pipeline.
|
|
13
|
+
if (!ctx.state.user) {
|
|
14
|
+
return ctx.unauthorized('Authentication required');
|
|
15
|
+
}
|
|
16
|
+
const aiToken = await strapi.ai.admin.getAiToken();
|
|
17
|
+
ctx.body = {
|
|
18
|
+
data: aiToken
|
|
19
|
+
};
|
|
20
|
+
} catch (error) {
|
|
21
|
+
return ctx.internalServerError('AI token request failed. Check server logs for details.');
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
async getAiUsage (ctx) {
|
|
25
|
+
if (strapi.ai.admin.isEnabled() === false) {
|
|
26
|
+
return ctx.notFound();
|
|
27
|
+
}
|
|
28
|
+
try {
|
|
29
|
+
const usage = await strapi.ai.admin.getAiUsage();
|
|
30
|
+
ctx.body = usage;
|
|
31
|
+
} catch (error) {
|
|
32
|
+
return ctx.internalServerError('AI usage data request failed. Check server logs for details.');
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
async getAiFeatureConfig (ctx) {
|
|
36
|
+
if (strapi.ai.admin.isEnabled() === false) {
|
|
37
|
+
return ctx.notFound();
|
|
38
|
+
}
|
|
39
|
+
try {
|
|
40
|
+
const aiFeatureConfig = await strapi.ai.admin.getAiFeatureConfig();
|
|
41
|
+
ctx.body = {
|
|
42
|
+
data: aiFeatureConfig
|
|
43
|
+
};
|
|
44
|
+
} catch (error) {
|
|
45
|
+
strapi.log.error('AI feature config request failed', error);
|
|
46
|
+
return ctx.internalServerError('AI feature config request failed. Check server logs for details.');
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
module.exports = ai;
|
|
52
|
+
//# sourceMappingURL=ai.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai.js","sources":["../../../../../../server/src/ai/controllers/ai.ts"],"sourcesContent":["import type { Context } from 'koa';\nimport { GetAiFeatureConfig, GetAiToken } from '../../../../shared/contracts/ai';\n\nexport default {\n async getAiToken(ctx: Context) {\n if (strapi.ai.admin.isEnabled() === false) {\n return ctx.notFound();\n }\n\n try {\n // `admin::isAuthenticatedAdmin` only checks `ctx.state.isAuthenticated`, not `ctx.state.user`.\n // With the current admin JWT strategy, a successful auth run always sets both; this handler\n // still requires `user` because `getAiToken()` needs an admin identity. Keeps us safe if the\n // strategy/policy contract ever diverges or this action is invoked outside the normal pipeline.\n if (!ctx.state.user) {\n return ctx.unauthorized('Authentication required');\n }\n\n const aiToken = await strapi.ai.admin.getAiToken();\n\n ctx.body = {\n data: aiToken,\n } satisfies GetAiToken.Response;\n } catch (error) {\n return ctx.internalServerError('AI token request failed. Check server logs for details.');\n }\n },\n\n async getAiUsage(ctx: Context) {\n if (strapi.ai.admin.isEnabled() === false) {\n return ctx.notFound();\n }\n\n try {\n const usage = await strapi.ai.admin.getAiUsage();\n ctx.body = usage;\n } catch (error) {\n return ctx.internalServerError(\n 'AI usage data request failed. Check server logs for details.'\n );\n }\n },\n\n async getAiFeatureConfig(ctx: Context) {\n if (strapi.ai.admin.isEnabled() === false) {\n return ctx.notFound();\n }\n\n try {\n const aiFeatureConfig = await strapi.ai.admin.getAiFeatureConfig();\n\n ctx.body = {\n data: aiFeatureConfig,\n } satisfies GetAiFeatureConfig.Response;\n } catch (error) {\n strapi.log.error('AI feature config request failed', error);\n return ctx.internalServerError(\n 'AI feature config request failed. Check server logs for details.'\n );\n }\n },\n};\n"],"names":["getAiToken","ctx","strapi","ai","admin","isEnabled","notFound","state","user","unauthorized","aiToken","body","data","error","internalServerError","getAiUsage","usage","getAiFeatureConfig","aiFeatureConfig","log"],"mappings":";;AAGA,SAAe;AACb,IAAA,MAAMA,YAAWC,GAAY,EAAA;AAC3B,QAAA,IAAIC,OAAOC,EAAE,CAACC,KAAK,CAACC,SAAS,OAAO,KAAA,EAAO;AACzC,YAAA,OAAOJ,IAAIK,QAAQ,EAAA;AACrB,QAAA;QAEA,IAAI;;;;;AAKF,YAAA,IAAI,CAACL,GAAAA,CAAIM,KAAK,CAACC,IAAI,EAAE;gBACnB,OAAOP,GAAAA,CAAIQ,YAAY,CAAC,yBAAA,CAAA;AAC1B,YAAA;AAEA,YAAA,MAAMC,UAAU,MAAMR,MAAAA,CAAOC,EAAE,CAACC,KAAK,CAACJ,UAAU,EAAA;AAEhDC,YAAAA,GAAAA,CAAIU,IAAI,GAAG;gBACTC,IAAAA,EAAMF;AACR,aAAA;AACF,QAAA,CAAA,CAAE,OAAOG,KAAAA,EAAO;YACd,OAAOZ,GAAAA,CAAIa,mBAAmB,CAAC,yDAAA,CAAA;AACjC,QAAA;AACF,IAAA,CAAA;AAEA,IAAA,MAAMC,YAAWd,GAAY,EAAA;AAC3B,QAAA,IAAIC,OAAOC,EAAE,CAACC,KAAK,CAACC,SAAS,OAAO,KAAA,EAAO;AACzC,YAAA,OAAOJ,IAAIK,QAAQ,EAAA;AACrB,QAAA;QAEA,IAAI;AACF,YAAA,MAAMU,QAAQ,MAAMd,MAAAA,CAAOC,EAAE,CAACC,KAAK,CAACW,UAAU,EAAA;AAC9Cd,YAAAA,GAAAA,CAAIU,IAAI,GAAGK,KAAAA;AACb,QAAA,CAAA,CAAE,OAAOH,KAAAA,EAAO;YACd,OAAOZ,GAAAA,CAAIa,mBAAmB,CAC5B,8DAAA,CAAA;AAEJ,QAAA;AACF,IAAA,CAAA;AAEA,IAAA,MAAMG,oBAAmBhB,GAAY,EAAA;AACnC,QAAA,IAAIC,OAAOC,EAAE,CAACC,KAAK,CAACC,SAAS,OAAO,KAAA,EAAO;AACzC,YAAA,OAAOJ,IAAIK,QAAQ,EAAA;AACrB,QAAA;QAEA,IAAI;AACF,YAAA,MAAMY,kBAAkB,MAAMhB,MAAAA,CAAOC,EAAE,CAACC,KAAK,CAACa,kBAAkB,EAAA;AAEhEhB,YAAAA,GAAAA,CAAIU,IAAI,GAAG;gBACTC,IAAAA,EAAMM;AACR,aAAA;AACF,QAAA,CAAA,CAAE,OAAOL,KAAAA,EAAO;AACdX,YAAAA,MAAAA,CAAOiB,GAAG,CAACN,KAAK,CAAC,kCAAA,EAAoCA,KAAAA,CAAAA;YACrD,OAAOZ,GAAAA,CAAIa,mBAAmB,CAC5B,kEAAA,CAAA;AAEJ,QAAA;AACF,IAAA;AACF,CAAA;;;;"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
var ai = {
|
|
2
|
+
async getAiToken (ctx) {
|
|
3
|
+
if (strapi.ai.admin.isEnabled() === false) {
|
|
4
|
+
return ctx.notFound();
|
|
5
|
+
}
|
|
6
|
+
try {
|
|
7
|
+
// `admin::isAuthenticatedAdmin` only checks `ctx.state.isAuthenticated`, not `ctx.state.user`.
|
|
8
|
+
// With the current admin JWT strategy, a successful auth run always sets both; this handler
|
|
9
|
+
// still requires `user` because `getAiToken()` needs an admin identity. Keeps us safe if the
|
|
10
|
+
// strategy/policy contract ever diverges or this action is invoked outside the normal pipeline.
|
|
11
|
+
if (!ctx.state.user) {
|
|
12
|
+
return ctx.unauthorized('Authentication required');
|
|
13
|
+
}
|
|
14
|
+
const aiToken = await strapi.ai.admin.getAiToken();
|
|
15
|
+
ctx.body = {
|
|
16
|
+
data: aiToken
|
|
17
|
+
};
|
|
18
|
+
} catch (error) {
|
|
19
|
+
return ctx.internalServerError('AI token request failed. Check server logs for details.');
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
async getAiUsage (ctx) {
|
|
23
|
+
if (strapi.ai.admin.isEnabled() === false) {
|
|
24
|
+
return ctx.notFound();
|
|
25
|
+
}
|
|
26
|
+
try {
|
|
27
|
+
const usage = await strapi.ai.admin.getAiUsage();
|
|
28
|
+
ctx.body = usage;
|
|
29
|
+
} catch (error) {
|
|
30
|
+
return ctx.internalServerError('AI usage data request failed. Check server logs for details.');
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
async getAiFeatureConfig (ctx) {
|
|
34
|
+
if (strapi.ai.admin.isEnabled() === false) {
|
|
35
|
+
return ctx.notFound();
|
|
36
|
+
}
|
|
37
|
+
try {
|
|
38
|
+
const aiFeatureConfig = await strapi.ai.admin.getAiFeatureConfig();
|
|
39
|
+
ctx.body = {
|
|
40
|
+
data: aiFeatureConfig
|
|
41
|
+
};
|
|
42
|
+
} catch (error) {
|
|
43
|
+
strapi.log.error('AI feature config request failed', error);
|
|
44
|
+
return ctx.internalServerError('AI feature config request failed. Check server logs for details.');
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export { ai as default };
|
|
50
|
+
//# sourceMappingURL=ai.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai.mjs","sources":["../../../../../../server/src/ai/controllers/ai.ts"],"sourcesContent":["import type { Context } from 'koa';\nimport { GetAiFeatureConfig, GetAiToken } from '../../../../shared/contracts/ai';\n\nexport default {\n async getAiToken(ctx: Context) {\n if (strapi.ai.admin.isEnabled() === false) {\n return ctx.notFound();\n }\n\n try {\n // `admin::isAuthenticatedAdmin` only checks `ctx.state.isAuthenticated`, not `ctx.state.user`.\n // With the current admin JWT strategy, a successful auth run always sets both; this handler\n // still requires `user` because `getAiToken()` needs an admin identity. Keeps us safe if the\n // strategy/policy contract ever diverges or this action is invoked outside the normal pipeline.\n if (!ctx.state.user) {\n return ctx.unauthorized('Authentication required');\n }\n\n const aiToken = await strapi.ai.admin.getAiToken();\n\n ctx.body = {\n data: aiToken,\n } satisfies GetAiToken.Response;\n } catch (error) {\n return ctx.internalServerError('AI token request failed. Check server logs for details.');\n }\n },\n\n async getAiUsage(ctx: Context) {\n if (strapi.ai.admin.isEnabled() === false) {\n return ctx.notFound();\n }\n\n try {\n const usage = await strapi.ai.admin.getAiUsage();\n ctx.body = usage;\n } catch (error) {\n return ctx.internalServerError(\n 'AI usage data request failed. Check server logs for details.'\n );\n }\n },\n\n async getAiFeatureConfig(ctx: Context) {\n if (strapi.ai.admin.isEnabled() === false) {\n return ctx.notFound();\n }\n\n try {\n const aiFeatureConfig = await strapi.ai.admin.getAiFeatureConfig();\n\n ctx.body = {\n data: aiFeatureConfig,\n } satisfies GetAiFeatureConfig.Response;\n } catch (error) {\n strapi.log.error('AI feature config request failed', error);\n return ctx.internalServerError(\n 'AI feature config request failed. Check server logs for details.'\n );\n }\n },\n};\n"],"names":["getAiToken","ctx","strapi","ai","admin","isEnabled","notFound","state","user","unauthorized","aiToken","body","data","error","internalServerError","getAiUsage","usage","getAiFeatureConfig","aiFeatureConfig","log"],"mappings":"AAGA,SAAe;AACb,IAAA,MAAMA,YAAWC,GAAY,EAAA;AAC3B,QAAA,IAAIC,OAAOC,EAAE,CAACC,KAAK,CAACC,SAAS,OAAO,KAAA,EAAO;AACzC,YAAA,OAAOJ,IAAIK,QAAQ,EAAA;AACrB,QAAA;QAEA,IAAI;;;;;AAKF,YAAA,IAAI,CAACL,GAAAA,CAAIM,KAAK,CAACC,IAAI,EAAE;gBACnB,OAAOP,GAAAA,CAAIQ,YAAY,CAAC,yBAAA,CAAA;AAC1B,YAAA;AAEA,YAAA,MAAMC,UAAU,MAAMR,MAAAA,CAAOC,EAAE,CAACC,KAAK,CAACJ,UAAU,EAAA;AAEhDC,YAAAA,GAAAA,CAAIU,IAAI,GAAG;gBACTC,IAAAA,EAAMF;AACR,aAAA;AACF,QAAA,CAAA,CAAE,OAAOG,KAAAA,EAAO;YACd,OAAOZ,GAAAA,CAAIa,mBAAmB,CAAC,yDAAA,CAAA;AACjC,QAAA;AACF,IAAA,CAAA;AAEA,IAAA,MAAMC,YAAWd,GAAY,EAAA;AAC3B,QAAA,IAAIC,OAAOC,EAAE,CAACC,KAAK,CAACC,SAAS,OAAO,KAAA,EAAO;AACzC,YAAA,OAAOJ,IAAIK,QAAQ,EAAA;AACrB,QAAA;QAEA,IAAI;AACF,YAAA,MAAMU,QAAQ,MAAMd,MAAAA,CAAOC,EAAE,CAACC,KAAK,CAACW,UAAU,EAAA;AAC9Cd,YAAAA,GAAAA,CAAIU,IAAI,GAAGK,KAAAA;AACb,QAAA,CAAA,CAAE,OAAOH,KAAAA,EAAO;YACd,OAAOZ,GAAAA,CAAIa,mBAAmB,CAC5B,8DAAA,CAAA;AAEJ,QAAA;AACF,IAAA,CAAA;AAEA,IAAA,MAAMG,oBAAmBhB,GAAY,EAAA;AACnC,QAAA,IAAIC,OAAOC,EAAE,CAACC,KAAK,CAACC,SAAS,OAAO,KAAA,EAAO;AACzC,YAAA,OAAOJ,IAAIK,QAAQ,EAAA;AACrB,QAAA;QAEA,IAAI;AACF,YAAA,MAAMY,kBAAkB,MAAMhB,MAAAA,CAAOC,EAAE,CAACC,KAAK,CAACa,kBAAkB,EAAA;AAEhEhB,YAAAA,GAAAA,CAAIU,IAAI,GAAG;gBACTC,IAAAA,EAAMM;AACR,aAAA;AACF,QAAA,CAAA,CAAE,OAAOL,KAAAA,EAAO;AACdX,YAAAA,MAAAA,CAAOiB,GAAG,CAACN,KAAK,CAAC,kCAAA,EAAoCA,KAAAA,CAAAA;YACrD,OAAOZ,GAAAA,CAAIa,mBAAmB,CAC5B,kEAAA,CAAA;AAEJ,QAAA;AACF,IAAA;AACF,CAAA;;;;"}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var aiRoutes = {
|
|
4
|
-
type: 'admin',
|
|
5
4
|
routes: [
|
|
6
5
|
{
|
|
7
6
|
method: 'GET',
|
|
@@ -26,7 +25,7 @@ var aiRoutes = {
|
|
|
26
25
|
{
|
|
27
26
|
method: 'GET',
|
|
28
27
|
path: '/ai-feature-config',
|
|
29
|
-
handler: 'ai.
|
|
28
|
+
handler: 'ai.getAiFeatureConfig',
|
|
30
29
|
config: {
|
|
31
30
|
policies: [
|
|
32
31
|
'admin::isAuthenticatedAdmin'
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai.js","sources":["../../../../../../server/src/ai/routes/ai.ts"],"sourcesContent":["export default {\n type: 'admin',\n routes: [\n {\n method: 'GET',\n path: '/ai-usage',\n handler: 'ai.getAiUsage',\n config: {\n policies: ['admin::isAuthenticatedAdmin'],\n },\n },\n {\n method: 'GET',\n path: '/ai-token',\n handler: 'ai.getAiToken',\n config: {\n policies: ['admin::isAuthenticatedAdmin'],\n },\n },\n {\n method: 'GET',\n path: '/ai-feature-config',\n handler: 'ai.getAiFeatureConfig',\n config: {\n policies: ['admin::isAuthenticatedAdmin'],\n },\n },\n ],\n};\n"],"names":["routes","method","path","handler","config","policies"],"mappings":";;AAAA,eAAe;IAEbA,MAAAA,EAAQ;AACN,QAAA;YACEC,MAAAA,EAAQ,KAAA;YACRC,IAAAA,EAAM,WAAA;YACNC,OAAAA,EAAS,eAAA;YACTC,MAAAA,EAAQ;gBACNC,QAAAA,EAAU;AAAC,oBAAA;AAA8B;AAC3C;AACF,SAAA;AACA,QAAA;YACEJ,MAAAA,EAAQ,KAAA;YACRC,IAAAA,EAAM,WAAA;YACNC,OAAAA,EAAS,eAAA;YACTC,MAAAA,EAAQ;gBACNC,QAAAA,EAAU;AAAC,oBAAA;AAA8B;AAC3C;AACF,SAAA;AACA,QAAA;YACEJ,MAAAA,EAAQ,KAAA;YACRC,IAAAA,EAAM,oBAAA;YACNC,OAAAA,EAAS,uBAAA;YACTC,MAAAA,EAAQ;gBACNC,QAAAA,EAAU;AAAC,oBAAA;AAA8B;AAC3C;AACF;AACD;AACH,CAAA;;;;"}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
var aiRoutes = {
|
|
2
|
-
type: 'admin',
|
|
3
2
|
routes: [
|
|
4
3
|
{
|
|
5
4
|
method: 'GET',
|
|
@@ -24,7 +23,7 @@ var aiRoutes = {
|
|
|
24
23
|
{
|
|
25
24
|
method: 'GET',
|
|
26
25
|
path: '/ai-feature-config',
|
|
27
|
-
handler: 'ai.
|
|
26
|
+
handler: 'ai.getAiFeatureConfig',
|
|
28
27
|
config: {
|
|
29
28
|
policies: [
|
|
30
29
|
'admin::isAuthenticatedAdmin'
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai.mjs","sources":["../../../../../../server/src/ai/routes/ai.ts"],"sourcesContent":["export default {\n type: 'admin',\n routes: [\n {\n method: 'GET',\n path: '/ai-usage',\n handler: 'ai.getAiUsage',\n config: {\n policies: ['admin::isAuthenticatedAdmin'],\n },\n },\n {\n method: 'GET',\n path: '/ai-token',\n handler: 'ai.getAiToken',\n config: {\n policies: ['admin::isAuthenticatedAdmin'],\n },\n },\n {\n method: 'GET',\n path: '/ai-feature-config',\n handler: 'ai.getAiFeatureConfig',\n config: {\n policies: ['admin::isAuthenticatedAdmin'],\n },\n },\n ],\n};\n"],"names":["routes","method","path","handler","config","policies"],"mappings":"AAAA,eAAe;IAEbA,MAAAA,EAAQ;AACN,QAAA;YACEC,MAAAA,EAAQ,KAAA;YACRC,IAAAA,EAAM,WAAA;YACNC,OAAAA,EAAS,eAAA;YACTC,MAAAA,EAAQ;gBACNC,QAAAA,EAAU;AAAC,oBAAA;AAA8B;AAC3C;AACF,SAAA;AACA,QAAA;YACEJ,MAAAA,EAAQ,KAAA;YACRC,IAAAA,EAAM,WAAA;YACNC,OAAAA,EAAS,eAAA;YACTC,MAAAA,EAAQ;gBACNC,QAAAA,EAAU;AAAC,oBAAA;AAA8B;AAC3C;AACF,SAAA;AACA,QAAA;YACEJ,MAAAA,EAAQ,KAAA;YACRC,IAAAA,EAAM,oBAAA;YACNC,OAAAA,EAAS,uBAAA;YACTC,MAAAA,EAAQ;gBACNC,QAAAA,EAAU;AAAC,oBAAA;AAA8B;AAC3C;AACF;AACD;AACH,CAAA;;;;"}
|
|
@@ -4,42 +4,70 @@ var crypto = require('crypto');
|
|
|
4
4
|
var fs = require('fs');
|
|
5
5
|
var path = require('path');
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const
|
|
12
|
-
const
|
|
7
|
+
const createAiAdminService = ({ strapi })=>{
|
|
8
|
+
/**
|
|
9
|
+
* In-memory cache for AI tokens
|
|
10
|
+
* Key format: `${projectId}:${userId}`
|
|
11
|
+
*/ const aiTokenCache = new Map();
|
|
12
|
+
const isEnabled = ()=>{
|
|
13
|
+
const configEnabled = strapi.config.get('admin.ai.enabled', true) === true;
|
|
14
|
+
const licenseEnabled = strapi.ee?.features?.isEnabled('cms-ai') === true;
|
|
15
|
+
return configEnabled && licenseEnabled;
|
|
16
|
+
};
|
|
17
|
+
const getAiFeatureConfig = async ()=>{
|
|
18
|
+
if (!isEnabled()) {
|
|
19
|
+
return {
|
|
20
|
+
isAiI18nConfigured: false,
|
|
21
|
+
isAiMediaLibraryConfigured: false
|
|
22
|
+
};
|
|
23
|
+
}
|
|
13
24
|
const i18nSettings = await strapi.plugin('i18n').service('settings').getSettings();
|
|
14
25
|
const uploadSettings = await strapi.plugin('upload').service('upload').getSettings();
|
|
15
26
|
return {
|
|
16
|
-
|
|
17
|
-
|
|
27
|
+
isAiI18nConfigured: Boolean(i18nSettings?.aiLocalizations),
|
|
28
|
+
isAiMediaLibraryConfigured: Boolean(uploadSettings?.aiMetadata)
|
|
18
29
|
};
|
|
19
30
|
};
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
31
|
+
/**
|
|
32
|
+
* Resolves the shared context required by both getAiToken and getAiUsage:
|
|
33
|
+
* EE license, project ID, and AI server URL.
|
|
34
|
+
*/ const resolveAiContext = (errorPrefix)=>{
|
|
35
|
+
if (!isEnabled()) {
|
|
36
|
+
strapi.log.error(`${errorPrefix} AI is not enabled`);
|
|
37
|
+
throw new Error(`${errorPrefix.replace(/:$/, '')}. Check server logs for details.`);
|
|
38
|
+
}
|
|
23
39
|
if (!strapi.ee?.isEE) {
|
|
24
|
-
strapi.log.error(`${
|
|
25
|
-
throw new Error('
|
|
40
|
+
strapi.log.error(`${errorPrefix} Enterprise Edition features are not enabled`);
|
|
41
|
+
throw new Error(`${errorPrefix.replace(/:$/, '')}. Check server logs for details.`);
|
|
26
42
|
}
|
|
27
|
-
// Get the EE license
|
|
28
|
-
// First try environment variable, then try reading from file
|
|
29
43
|
let eeLicense = process.env.STRAPI_LICENSE;
|
|
30
44
|
if (!eeLicense) {
|
|
31
45
|
try {
|
|
32
46
|
const licensePath = path.join(strapi.dirs.app.root, 'license.txt');
|
|
33
47
|
eeLicense = fs.readFileSync(licensePath).toString();
|
|
34
|
-
} catch
|
|
48
|
+
} catch {
|
|
35
49
|
// License file doesn't exist or can't be read
|
|
36
50
|
}
|
|
37
51
|
}
|
|
38
52
|
if (!eeLicense) {
|
|
39
|
-
strapi.log.error(`${
|
|
40
|
-
throw new Error('
|
|
53
|
+
strapi.log.error(`${errorPrefix} No EE license found. Please ensure STRAPI_LICENSE environment variable is set or license.txt file exists.`);
|
|
54
|
+
throw new Error(`${errorPrefix.replace(/:$/, '')}. Check server logs for details.`);
|
|
55
|
+
}
|
|
56
|
+
const projectId = strapi.config.get('uuid');
|
|
57
|
+
if (!projectId) {
|
|
58
|
+
strapi.log.error(`${errorPrefix} Project ID not configured`);
|
|
59
|
+
throw new Error(`${errorPrefix.replace(/:$/, '')}. Check server logs for details.`);
|
|
41
60
|
}
|
|
42
61
|
const aiServerUrl = process.env.STRAPI_AI_URL || 'https://strapi-ai.apps.strapi.io';
|
|
62
|
+
return {
|
|
63
|
+
eeLicense,
|
|
64
|
+
projectId,
|
|
65
|
+
aiServerUrl
|
|
66
|
+
};
|
|
67
|
+
};
|
|
68
|
+
const getAiToken = async ()=>{
|
|
69
|
+
const ERROR_PREFIX = 'AI token request failed:';
|
|
70
|
+
const { eeLicense, projectId, aiServerUrl } = resolveAiContext(ERROR_PREFIX);
|
|
43
71
|
// Get the current user
|
|
44
72
|
const user = strapi.requestContext.get()?.state?.user;
|
|
45
73
|
if (!user) {
|
|
@@ -48,18 +76,12 @@ const createAIContainer = ({ strapi })=>{
|
|
|
48
76
|
}
|
|
49
77
|
// Create a secure user identifier using only user ID
|
|
50
78
|
const userIdentifier = user.id.toString();
|
|
51
|
-
// Get project ID
|
|
52
|
-
const projectId = strapi.config.get('uuid');
|
|
53
|
-
if (!projectId) {
|
|
54
|
-
strapi.log.error(`${ERROR_PREFIX} Project ID not configured`);
|
|
55
|
-
throw new Error('AI token request failed. Check server logs for details.');
|
|
56
|
-
}
|
|
57
79
|
// Check cache for existing valid token
|
|
58
80
|
const cacheKey = `${projectId}:${userIdentifier}`;
|
|
59
81
|
const cachedToken = aiTokenCache.get(cacheKey);
|
|
60
82
|
if (cachedToken) {
|
|
61
83
|
const now = Date.now();
|
|
62
|
-
// Check if token is still valid (with buffer so it has time to
|
|
84
|
+
// Check if token is still valid (with buffer so it has time to be used)
|
|
63
85
|
const bufferMs = 2 * 60 * 1000; // 2 minutes
|
|
64
86
|
if (cachedToken.expiresAtMs && cachedToken.expiresAtMs - bufferMs > now) {
|
|
65
87
|
strapi.log.info('Using cached AI token');
|
|
@@ -73,13 +95,10 @@ const createAIContainer = ({ strapi })=>{
|
|
|
73
95
|
}
|
|
74
96
|
strapi.log.http('Contacting AI Server for token generation');
|
|
75
97
|
try {
|
|
76
|
-
// Call the AI server's getAiJWT endpoint
|
|
77
98
|
const response = await fetch(`${aiServerUrl}/auth/getAiJWT`, {
|
|
78
99
|
method: 'POST',
|
|
79
100
|
headers: {
|
|
80
101
|
'Content-Type': 'application/json',
|
|
81
|
-
// No authorization header needed for public endpoint
|
|
82
|
-
// Add request ID for tracing
|
|
83
102
|
'X-Request-Id': crypto.randomUUID()
|
|
84
103
|
},
|
|
85
104
|
body: JSON.stringify({
|
|
@@ -132,7 +151,6 @@ const createAIContainer = ({ strapi })=>{
|
|
|
132
151
|
expiresAtMs
|
|
133
152
|
});
|
|
134
153
|
}
|
|
135
|
-
// Return the AI JWT with metadata
|
|
136
154
|
// Note: Token expires in 1 hour, client should handle refresh
|
|
137
155
|
return {
|
|
138
156
|
token: data.jwt,
|
|
@@ -146,11 +164,68 @@ const createAIContainer = ({ strapi })=>{
|
|
|
146
164
|
throw fetchError;
|
|
147
165
|
}
|
|
148
166
|
};
|
|
167
|
+
const getAiUsage = async ()=>{
|
|
168
|
+
const ERROR_PREFIX = 'AI usage data request failed:';
|
|
169
|
+
const { eeLicense, projectId, aiServerUrl } = resolveAiContext(ERROR_PREFIX);
|
|
170
|
+
strapi.log.http('Contacting AI Server for usage data');
|
|
171
|
+
try {
|
|
172
|
+
const response = await fetch(`${aiServerUrl}/cms/ai-data`, {
|
|
173
|
+
method: 'POST',
|
|
174
|
+
headers: {
|
|
175
|
+
'Content-Type': 'application/json',
|
|
176
|
+
'X-Request-Id': crypto.randomUUID()
|
|
177
|
+
},
|
|
178
|
+
body: JSON.stringify({
|
|
179
|
+
eeKey: eeLicense,
|
|
180
|
+
projectId
|
|
181
|
+
})
|
|
182
|
+
});
|
|
183
|
+
if (!response.ok) {
|
|
184
|
+
let errorData;
|
|
185
|
+
let errorText;
|
|
186
|
+
try {
|
|
187
|
+
errorText = await response.text();
|
|
188
|
+
errorData = JSON.parse(errorText);
|
|
189
|
+
} catch {
|
|
190
|
+
errorData = {
|
|
191
|
+
error: errorText || 'Failed to parse error response'
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
strapi.log.error(`${ERROR_PREFIX} ${errorData?.error || 'Unknown error'}`, {
|
|
195
|
+
status: response.status,
|
|
196
|
+
statusText: response.statusText,
|
|
197
|
+
error: errorData,
|
|
198
|
+
errorText,
|
|
199
|
+
projectId
|
|
200
|
+
});
|
|
201
|
+
throw new Error('AI usage data request failed. Check server logs for details.');
|
|
202
|
+
}
|
|
203
|
+
let data;
|
|
204
|
+
try {
|
|
205
|
+
data = await response.json();
|
|
206
|
+
} catch (parseError) {
|
|
207
|
+
strapi.log.error(`${ERROR_PREFIX} Failed to parse AI server response`, parseError);
|
|
208
|
+
throw new Error('AI usage data request failed. Check server logs for details.');
|
|
209
|
+
}
|
|
210
|
+
return {
|
|
211
|
+
...data.data,
|
|
212
|
+
subscription: data.subscription
|
|
213
|
+
};
|
|
214
|
+
} catch (fetchError) {
|
|
215
|
+
if (fetchError instanceof Error && fetchError.name === 'AbortError') {
|
|
216
|
+
strapi.log.error(`${ERROR_PREFIX} Request to AI server timed out`);
|
|
217
|
+
throw new Error('AI usage data request failed. Check server logs for details.');
|
|
218
|
+
}
|
|
219
|
+
throw fetchError;
|
|
220
|
+
}
|
|
221
|
+
};
|
|
149
222
|
return {
|
|
150
|
-
|
|
151
|
-
|
|
223
|
+
isEnabled,
|
|
224
|
+
getAiFeatureConfig,
|
|
225
|
+
getAiToken,
|
|
226
|
+
getAiUsage
|
|
152
227
|
};
|
|
153
228
|
};
|
|
154
229
|
|
|
155
|
-
exports.
|
|
230
|
+
exports.createAiAdminService = createAiAdminService;
|
|
156
231
|
//# sourceMappingURL=ai.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai.js","sources":["../../../../../../server/src/ai/services/ai.ts"],"sourcesContent":["import type { Core } from '@strapi/types';\nimport crypto from 'crypto';\nimport fs from 'fs';\nimport path from 'path';\nimport { AdminUser } from '../../../../shared/contracts/shared';\n\nconst createAiAdminService = ({ strapi }: { strapi: Core.Strapi }) => {\n /**\n * In-memory cache for AI tokens\n * Key format: `${projectId}:${userId}`\n */\n const aiTokenCache = new Map<\n string,\n {\n token: string;\n expiresAt?: string;\n expiresAtMs?: number;\n }\n >();\n\n const isEnabled = (): boolean => {\n const configEnabled = strapi.config.get('admin.ai.enabled', true) === true;\n const licenseEnabled = strapi.ee?.features?.isEnabled('cms-ai') === true;\n return configEnabled && licenseEnabled;\n };\n\n const getAiFeatureConfig = async () => {\n if (!isEnabled()) {\n return {\n isAiI18nConfigured: false,\n isAiMediaLibraryConfigured: false,\n };\n }\n\n const i18nSettings = await strapi.plugin('i18n').service('settings').getSettings();\n const uploadSettings = await strapi.plugin('upload').service('upload').getSettings();\n\n return {\n isAiI18nConfigured: Boolean(i18nSettings?.aiLocalizations),\n isAiMediaLibraryConfigured: Boolean(uploadSettings?.aiMetadata),\n };\n };\n\n /**\n * Resolves the shared context required by both getAiToken and getAiUsage:\n * EE license, project ID, and AI server URL.\n */\n const resolveAiContext = (errorPrefix: string) => {\n if (!isEnabled()) {\n strapi.log.error(`${errorPrefix} AI is not enabled`);\n throw new Error(`${errorPrefix.replace(/:$/, '')}. Check server logs for details.`);\n }\n\n if (!strapi.ee?.isEE) {\n strapi.log.error(`${errorPrefix} Enterprise Edition features are not enabled`);\n throw new Error(`${errorPrefix.replace(/:$/, '')}. Check server logs for details.`);\n }\n\n let eeLicense = process.env.STRAPI_LICENSE;\n\n if (!eeLicense) {\n try {\n const licensePath = path.join(strapi.dirs.app.root, 'license.txt');\n eeLicense = fs.readFileSync(licensePath).toString();\n } catch {\n // License file doesn't exist or can't be read\n }\n }\n\n if (!eeLicense) {\n strapi.log.error(\n `${errorPrefix} No EE license found. Please ensure STRAPI_LICENSE environment variable is set or license.txt file exists.`\n );\n throw new Error(`${errorPrefix.replace(/:$/, '')}. Check server logs for details.`);\n }\n\n const projectId = strapi.config.get('uuid');\n if (!projectId) {\n strapi.log.error(`${errorPrefix} Project ID not configured`);\n throw new Error(`${errorPrefix.replace(/:$/, '')}. Check server logs for details.`);\n }\n\n const aiServerUrl = process.env.STRAPI_AI_URL || 'https://strapi-ai.apps.strapi.io';\n\n return { eeLicense, projectId, aiServerUrl };\n };\n\n const getAiToken = async () => {\n const ERROR_PREFIX = 'AI token request failed:';\n\n const { eeLicense, projectId, aiServerUrl } = resolveAiContext(ERROR_PREFIX);\n\n // Get the current user\n const user = strapi.requestContext.get()?.state?.user as AdminUser | undefined;\n if (!user) {\n strapi.log.error(`${ERROR_PREFIX} No authenticated user in request context`);\n throw new Error('AI token request failed. Check server logs for details.');\n }\n\n // Create a secure user identifier using only user ID\n const userIdentifier = user.id.toString();\n\n // Check cache for existing valid token\n const cacheKey = `${projectId}:${userIdentifier}`;\n const cachedToken = aiTokenCache.get(cacheKey);\n\n if (cachedToken) {\n const now = Date.now();\n // Check if token is still valid (with buffer so it has time to be used)\n const bufferMs = 2 * 60 * 1000; // 2 minutes\n\n if (cachedToken.expiresAtMs && cachedToken.expiresAtMs - bufferMs > now) {\n strapi.log.info('Using cached AI token');\n\n return {\n token: cachedToken.token,\n expiresAt: cachedToken.expiresAt,\n };\n }\n\n // Token expired or will expire soon, remove from cache\n aiTokenCache.delete(cacheKey);\n }\n\n strapi.log.http('Contacting AI Server for token generation');\n\n try {\n const response = await fetch(`${aiServerUrl}/auth/getAiJWT`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'X-Request-Id': crypto.randomUUID(),\n },\n body: JSON.stringify({\n eeLicense,\n userIdentifier,\n projectId,\n }),\n });\n\n if (!response.ok) {\n let errorData;\n let errorText;\n try {\n errorText = await response.text();\n errorData = JSON.parse(errorText);\n } catch {\n errorData = { error: errorText || 'Failed to parse error response' };\n }\n\n strapi.log.error(`${ERROR_PREFIX} ${errorData?.error || 'Unknown error'}`, {\n status: response.status,\n statusText: response.statusText,\n error: errorData,\n errorText,\n projectId,\n });\n\n throw new Error('AI token request failed. Check server logs for details.');\n }\n\n let data;\n try {\n data = (await response.json()) as {\n jwt: string;\n expiresAt?: string;\n };\n } catch (parseError) {\n strapi.log.error(`${ERROR_PREFIX} Failed to parse AI server response`, parseError);\n throw new Error('AI token request failed. Check server logs for details.');\n }\n\n if (!data.jwt) {\n strapi.log.error(`${ERROR_PREFIX} Invalid response: missing JWT token`);\n throw new Error('AI token request failed. Check server logs for details.');\n }\n\n strapi.log.info('AI token generated successfully', {\n userId: user.id,\n expiresAt: data.expiresAt,\n });\n\n // Cache the token if it has an expiration time\n if (data.expiresAt) {\n const expiresAtMs = new Date(data.expiresAt).getTime();\n aiTokenCache.set(cacheKey, {\n token: data.jwt,\n expiresAt: data.expiresAt,\n expiresAtMs,\n });\n }\n\n // Note: Token expires in 1 hour, client should handle refresh\n return {\n token: data.jwt,\n expiresAt: data.expiresAt,\n };\n } catch (fetchError) {\n if (fetchError instanceof Error && fetchError.name === 'AbortError') {\n strapi.log.error(`${ERROR_PREFIX} Request to AI server timed out`);\n throw new Error('AI token request failed. Check server logs for details.');\n }\n\n throw fetchError;\n }\n };\n\n const getAiUsage = async () => {\n const ERROR_PREFIX = 'AI usage data request failed:';\n\n const { eeLicense, projectId, aiServerUrl } = resolveAiContext(ERROR_PREFIX);\n\n strapi.log.http('Contacting AI Server for usage data');\n\n try {\n const response = await fetch(`${aiServerUrl}/cms/ai-data`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'X-Request-Id': crypto.randomUUID(),\n },\n body: JSON.stringify({\n eeKey: eeLicense,\n projectId,\n }),\n });\n\n if (!response.ok) {\n let errorData;\n let errorText;\n try {\n errorText = await response.text();\n errorData = JSON.parse(errorText);\n } catch {\n errorData = { error: errorText || 'Failed to parse error response' };\n }\n\n strapi.log.error(`${ERROR_PREFIX} ${errorData?.error || 'Unknown error'}`, {\n status: response.status,\n statusText: response.statusText,\n error: errorData,\n errorText,\n projectId,\n });\n\n throw new Error('AI usage data request failed. Check server logs for details.');\n }\n\n let data;\n try {\n data = (await response.json()) as {\n data: { cmsAiCreditsUsed: number };\n subscription: {\n subscriptionId: string;\n planPriceId: string;\n subscriptionStatus: string;\n isActiveSubscription: boolean;\n cmsAiEnabled: boolean;\n cmsAiCreditsBase: number;\n cmsAiCreditsMaxUsage: number;\n currentTermStart: string;\n currentTermEnd: string;\n };\n };\n } catch (parseError) {\n strapi.log.error(`${ERROR_PREFIX} Failed to parse AI server response`, parseError);\n throw new Error('AI usage data request failed. Check server logs for details.');\n }\n\n return {\n ...data.data,\n subscription: data.subscription,\n };\n } catch (fetchError) {\n if (fetchError instanceof Error && fetchError.name === 'AbortError') {\n strapi.log.error(`${ERROR_PREFIX} Request to AI server timed out`);\n throw new Error('AI usage data request failed. Check server logs for details.');\n }\n\n throw fetchError;\n }\n };\n\n return {\n isEnabled,\n getAiFeatureConfig,\n getAiToken,\n getAiUsage,\n };\n};\n\nexport { createAiAdminService };\n"],"names":["createAiAdminService","strapi","aiTokenCache","Map","isEnabled","configEnabled","config","get","licenseEnabled","ee","features","getAiFeatureConfig","isAiI18nConfigured","isAiMediaLibraryConfigured","i18nSettings","plugin","service","getSettings","uploadSettings","Boolean","aiLocalizations","aiMetadata","resolveAiContext","errorPrefix","log","error","Error","replace","isEE","eeLicense","process","env","STRAPI_LICENSE","licensePath","path","join","dirs","app","root","fs","readFileSync","toString","projectId","aiServerUrl","STRAPI_AI_URL","getAiToken","ERROR_PREFIX","user","requestContext","state","userIdentifier","id","cacheKey","cachedToken","now","Date","bufferMs","expiresAtMs","info","token","expiresAt","delete","http","response","fetch","method","headers","crypto","randomUUID","body","JSON","stringify","ok","errorData","errorText","text","parse","status","statusText","data","json","parseError","jwt","userId","getTime","set","fetchError","name","getAiUsage","eeKey","subscription"],"mappings":"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"}
|