@strapi/admin 5.54.0 → 5.55.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/components/LanguageProvider.js +35 -1
- package/dist/admin/admin/src/components/LanguageProvider.js.map +1 -1
- package/dist/admin/admin/src/components/LanguageProvider.mjs +17 -2
- package/dist/admin/admin/src/components/LanguageProvider.mjs.map +1 -1
- package/dist/admin/admin/src/components/SubNav.js +113 -35
- package/dist/admin/admin/src/components/SubNav.js.map +1 -1
- package/dist/admin/admin/src/components/SubNav.mjs +115 -37
- package/dist/admin/admin/src/components/SubNav.mjs.map +1 -1
- package/dist/admin/admin/src/components/SubNavFolder.js +188 -0
- package/dist/admin/admin/src/components/SubNavFolder.js.map +1 -0
- package/dist/admin/admin/src/components/SubNavFolder.mjs +186 -0
- package/dist/admin/admin/src/components/SubNavFolder.mjs.map +1 -0
- package/dist/admin/admin/src/features/Tracking.js.map +1 -1
- package/dist/admin/admin/src/features/Tracking.mjs.map +1 -1
- package/dist/admin/admin/src/render.js +1 -1
- package/dist/admin/admin/src/render.js.map +1 -1
- package/dist/admin/admin/src/render.mjs +1 -1
- package/dist/admin/admin/src/render.mjs.map +1 -1
- package/dist/admin/admin/src/translations/en.json.js +4 -0
- package/dist/admin/admin/src/translations/en.json.js.map +1 -1
- package/dist/admin/admin/src/translations/en.json.mjs +4 -0
- package/dist/admin/admin/src/translations/en.json.mjs.map +1 -1
- package/dist/admin/ee/admin/src/hooks/useAIAvailability.js +1 -6
- package/dist/admin/ee/admin/src/hooks/useAIAvailability.js.map +1 -1
- package/dist/admin/ee/admin/src/hooks/useAIAvailability.mjs +1 -6
- package/dist/admin/ee/admin/src/hooks/useAIAvailability.mjs.map +1 -1
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/ApplicationInfoPage/components/AIUsage.js +7 -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 +7 -1
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/ApplicationInfoPage/components/AIUsage.mjs.map +1 -1
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/utils/getActionTypesDefaultMessages.js +5 -1
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/utils/getActionTypesDefaultMessages.js.map +1 -1
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/utils/getActionTypesDefaultMessages.mjs +5 -1
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/utils/getActionTypesDefaultMessages.mjs.map +1 -1
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/SingleSignOnPage.js +0 -4
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/SingleSignOnPage.js.map +1 -1
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/SingleSignOnPage.mjs +0 -4
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/SingleSignOnPage.mjs.map +1 -1
- package/dist/admin/src/components/SubNav.d.ts +27 -8
- package/dist/admin/src/components/SubNavFolder.d.ts +15 -0
- package/dist/admin/src/features/Tracking.d.ts +2 -1
- package/dist/admin/src/services/admin.d.ts +1 -0
- package/dist/ee/admin/src/pages/SettingsPage/pages/AuditLogs/utils/getActionTypesDefaultMessages.d.ts +4 -0
- package/dist/ee/server/src/controllers/admin.d.ts.map +1 -1
- package/dist/ee/server/src/index.d.ts.map +1 -1
- package/dist/server/ee/server/src/controllers/admin.js +1 -5
- package/dist/server/ee/server/src/controllers/admin.js.map +1 -1
- package/dist/server/ee/server/src/controllers/admin.mjs +1 -5
- package/dist/server/ee/server/src/controllers/admin.mjs.map +1 -1
- package/dist/server/ee/server/src/index.js +2 -0
- package/dist/server/ee/server/src/index.js.map +1 -1
- package/dist/server/ee/server/src/index.mjs +2 -0
- package/dist/server/ee/server/src/index.mjs.map +1 -1
- package/dist/server/server/src/ai/controllers/ai.js +3 -3
- package/dist/server/server/src/ai/controllers/ai.js.map +1 -1
- package/dist/server/server/src/ai/controllers/ai.mjs +3 -3
- package/dist/server/server/src/ai/controllers/ai.mjs.map +1 -1
- package/dist/server/server/src/ai/services/ai.js +37 -12
- package/dist/server/server/src/ai/services/ai.js.map +1 -1
- package/dist/server/server/src/ai/services/ai.mjs +37 -12
- package/dist/server/server/src/ai/services/ai.mjs.map +1 -1
- package/dist/server/server/src/audit-logs/tokens.js +106 -0
- package/dist/server/server/src/audit-logs/tokens.js.map +1 -0
- package/dist/server/server/src/audit-logs/tokens.mjs +99 -0
- package/dist/server/server/src/audit-logs/tokens.mjs.map +1 -0
- package/dist/server/server/src/controllers/admin.js +10 -1
- package/dist/server/server/src/controllers/admin.js.map +1 -1
- package/dist/server/server/src/controllers/admin.mjs +10 -1
- package/dist/server/server/src/controllers/admin.mjs.map +1 -1
- package/dist/server/server/src/services/api-token.js +106 -4
- package/dist/server/server/src/services/api-token.js.map +1 -1
- package/dist/server/server/src/services/api-token.mjs +107 -5
- package/dist/server/server/src/services/api-token.mjs.map +1 -1
- package/dist/server/server/src/services/transfer/token.js +56 -4
- package/dist/server/server/src/services/transfer/token.js.map +1 -1
- package/dist/server/server/src/services/transfer/token.mjs +57 -5
- package/dist/server/server/src/services/transfer/token.mjs.map +1 -1
- package/dist/server/src/ai/services/ai.d.ts +3 -1
- package/dist/server/src/ai/services/ai.d.ts.map +1 -1
- package/dist/server/src/audit-logs/tokens.d.ts +86 -0
- package/dist/server/src/audit-logs/tokens.d.ts.map +1 -0
- package/dist/server/src/controllers/admin.d.ts +1 -0
- package/dist/server/src/controllers/admin.d.ts.map +1 -1
- package/dist/server/src/controllers/index.d.ts +1 -0
- package/dist/server/src/controllers/index.d.ts.map +1 -1
- package/dist/server/src/index.d.ts +1 -0
- package/dist/server/src/index.d.ts.map +1 -1
- package/dist/server/src/services/api-token.d.ts.map +1 -1
- package/dist/server/src/services/transfer/token.d.ts.map +1 -1
- package/dist/shared/contracts/admin.d.ts +1 -0
- package/dist/shared/contracts/admin.d.ts.map +1 -1
- package/package.json +7 -7
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai.mjs","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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"}
|
|
1
|
+
{"version":3,"file":"ai.mjs","sources":["../../../../../../server/src/ai/services/ai.ts"],"sourcesContent":["import type { Core } from '@strapi/types';\nimport crypto from 'crypto';\nimport fs from 'fs';\nimport path from 'path';\nimport { AdminUser } from '../../../../shared/contracts/shared';\n\nconst STRAPI_MANAGED_AI_LICENSE_FEATURE = 'cms-ai';\nconst CUSTOM_AI_PROVIDER_LICENSE_FEATURE = 'cms-byok-ai';\n\nconst createAiAdminService = ({ strapi }: { strapi: Core.Strapi }) => {\n /**\n * In-memory cache for AI tokens\n * Key format: `${projectId}:${userId}`\n */\n const aiTokenCache = new Map<\n string,\n {\n token: string;\n expiresAt?: string;\n expiresAtMs?: number;\n }\n >();\n\n let isCustomProviderRejected = false;\n\n const isConfigEnabled = (): boolean => strapi.config.get('admin.ai.enabled', true) === true;\n\n const isAvailable = (): boolean =>\n isConfigEnabled() && strapi.ee?.isEE === true && !isCustomProviderRejected;\n\n const isStrapiManagedAiEnabled = (): boolean =>\n isConfigEnabled() &&\n !isCustomProviderRejected &&\n strapi.ee?.features?.isEnabled(STRAPI_MANAGED_AI_LICENSE_FEATURE) === true;\n\n const authorizeCustomProvider = (): boolean => {\n if (!isConfigEnabled()) {\n strapi.log.info(\n 'A custom AI provider was ignored: AI is disabled by the \"admin.ai.enabled\" config.'\n );\n return false;\n }\n\n if (strapi.ee?.features?.isEnabled(CUSTOM_AI_PROVIDER_LICENSE_FEATURE) === true) {\n return true;\n }\n\n isCustomProviderRejected = true;\n strapi.log.warn(\n `A custom AI provider was rejected: the Strapi license does not include the \"${CUSTOM_AI_PROVIDER_LICENSE_FEATURE}\" feature. All AI features are disabled.`\n );\n return false;\n };\n\n const isPluginAiFeatureConfigured = async (plugin: string, service: string): Promise<boolean> => {\n const aiService = strapi.plugin(plugin)?.service(service) as\n | { isEnabled?: () => Promise<boolean> | boolean }\n | undefined;\n\n if (typeof aiService?.isEnabled !== 'function') {\n return false;\n }\n\n return (await aiService.isEnabled()) === true;\n };\n\n const getAiFeatureConfig = async () => {\n if (!isAvailable()) {\n return {\n isAiI18nConfigured: false,\n isAiMediaLibraryConfigured: false,\n };\n }\n\n const [isAiI18nConfigured, isAiMediaLibraryConfigured] = await Promise.all([\n isPluginAiFeatureConfigured('i18n', 'ai-localizations'),\n isPluginAiFeatureConfigured('upload', 'aiMetadata'),\n ]);\n\n return { isAiI18nConfigured, isAiMediaLibraryConfigured };\n };\n\n /**\n * Resolves the shared context required by both getAiToken and getAiUsage:\n * EE license, project ID, and AI server URL.\n */\n const resolveAiContext = (errorPrefix: string) => {\n if (!isStrapiManagedAiEnabled()) {\n strapi.log.error(`${errorPrefix} AI is not enabled`);\n throw new Error(`${errorPrefix.replace(/:$/, '')}. Check server logs for details.`);\n }\n\n if (!strapi.ee?.isEE) {\n strapi.log.error(`${errorPrefix} Enterprise Edition features are not enabled`);\n throw new Error(`${errorPrefix.replace(/:$/, '')}. Check server logs for details.`);\n }\n\n let eeLicense = process.env.STRAPI_LICENSE;\n\n if (!eeLicense) {\n try {\n const licensePath = path.join(strapi.dirs.app.root, 'license.txt');\n eeLicense = fs.readFileSync(licensePath).toString();\n } catch {\n // License file doesn't exist or can't be read\n }\n }\n\n if (!eeLicense) {\n strapi.log.error(\n `${errorPrefix} No EE license found. Please ensure STRAPI_LICENSE environment variable is set or license.txt file exists.`\n );\n throw new Error(`${errorPrefix.replace(/:$/, '')}. Check server logs for details.`);\n }\n\n const projectId = strapi.config.get('uuid');\n if (!projectId) {\n strapi.log.error(`${errorPrefix} Project ID not configured`);\n throw new Error(`${errorPrefix.replace(/:$/, '')}. Check server logs for details.`);\n }\n\n const aiServerUrl = process.env.STRAPI_AI_URL || 'https://strapi-ai.apps.strapi.io';\n\n return { eeLicense, projectId, aiServerUrl };\n };\n\n const getAiToken = async () => {\n const ERROR_PREFIX = 'AI token request failed:';\n\n const { eeLicense, projectId, aiServerUrl } = resolveAiContext(ERROR_PREFIX);\n\n // Get the current user\n const user = strapi.requestContext.get()?.state?.user as AdminUser | undefined;\n if (!user) {\n strapi.log.error(`${ERROR_PREFIX} No authenticated user in request context`);\n throw new Error('AI token request failed. Check server logs for details.');\n }\n\n // Create a secure user identifier using only user ID\n const userIdentifier = user.id.toString();\n\n // Check cache for existing valid token\n const cacheKey = `${projectId}:${userIdentifier}`;\n const cachedToken = aiTokenCache.get(cacheKey);\n\n if (cachedToken) {\n const now = Date.now();\n // Check if token is still valid (with buffer so it has time to be used)\n const bufferMs = 2 * 60 * 1000; // 2 minutes\n\n if (cachedToken.expiresAtMs && cachedToken.expiresAtMs - bufferMs > now) {\n strapi.log.info('Using cached AI token');\n\n return {\n token: cachedToken.token,\n expiresAt: cachedToken.expiresAt,\n };\n }\n\n // Token expired or will expire soon, remove from cache\n aiTokenCache.delete(cacheKey);\n }\n\n strapi.log.http('Contacting AI Server for token generation');\n\n try {\n const response = await fetch(`${aiServerUrl}/auth/getAiJWT`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'X-Request-Id': crypto.randomUUID(),\n },\n body: JSON.stringify({\n eeLicense,\n userIdentifier,\n projectId,\n }),\n });\n\n if (!response.ok) {\n let errorData;\n let errorText;\n try {\n errorText = await response.text();\n errorData = JSON.parse(errorText);\n } catch {\n errorData = { error: errorText || 'Failed to parse error response' };\n }\n\n strapi.log.error(`${ERROR_PREFIX} ${errorData?.error || 'Unknown error'}`, {\n status: response.status,\n statusText: response.statusText,\n error: errorData,\n errorText,\n projectId,\n });\n\n throw new Error('AI token request failed. Check server logs for details.');\n }\n\n let data;\n try {\n data = (await response.json()) as {\n jwt: string;\n expiresAt?: string;\n };\n } catch (parseError) {\n strapi.log.error(`${ERROR_PREFIX} Failed to parse AI server response`, parseError);\n throw new Error('AI token request failed. Check server logs for details.');\n }\n\n if (!data.jwt) {\n strapi.log.error(`${ERROR_PREFIX} Invalid response: missing JWT token`);\n throw new Error('AI token request failed. Check server logs for details.');\n }\n\n strapi.log.info('AI token generated successfully', {\n userId: user.id,\n expiresAt: data.expiresAt,\n });\n\n // Cache the token if it has an expiration time\n if (data.expiresAt) {\n const expiresAtMs = new Date(data.expiresAt).getTime();\n aiTokenCache.set(cacheKey, {\n token: data.jwt,\n expiresAt: data.expiresAt,\n expiresAtMs,\n });\n }\n\n // Note: Token expires in 1 hour, client should handle refresh\n return {\n token: data.jwt,\n expiresAt: data.expiresAt,\n };\n } catch (fetchError) {\n if (fetchError instanceof Error && fetchError.name === 'AbortError') {\n strapi.log.error(`${ERROR_PREFIX} Request to AI server timed out`);\n throw new Error('AI token request failed. Check server logs for details.');\n }\n\n throw fetchError;\n }\n };\n\n const getAiUsage = async () => {\n const ERROR_PREFIX = 'AI usage data request failed:';\n\n const { eeLicense, projectId, aiServerUrl } = resolveAiContext(ERROR_PREFIX);\n\n strapi.log.http('Contacting AI Server for usage data');\n\n try {\n const response = await fetch(`${aiServerUrl}/cms/ai-data`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'X-Request-Id': crypto.randomUUID(),\n },\n body: JSON.stringify({\n eeKey: eeLicense,\n projectId,\n }),\n });\n\n if (!response.ok) {\n let errorData;\n let errorText;\n try {\n errorText = await response.text();\n errorData = JSON.parse(errorText);\n } catch {\n errorData = { error: errorText || 'Failed to parse error response' };\n }\n\n strapi.log.error(`${ERROR_PREFIX} ${errorData?.error || 'Unknown error'}`, {\n status: response.status,\n statusText: response.statusText,\n error: errorData,\n errorText,\n projectId,\n });\n\n throw new Error('AI usage data request failed. Check server logs for details.');\n }\n\n let data;\n try {\n data = (await response.json()) as {\n data: { cmsAiCreditsUsed: number };\n subscription: {\n subscriptionId: string;\n planPriceId: string;\n subscriptionStatus: string;\n isActiveSubscription: boolean;\n cmsAiEnabled: boolean;\n cmsAiCreditsBase: number;\n cmsAiCreditsMaxUsage: number;\n currentTermStart: string;\n currentTermEnd: string;\n };\n };\n } catch (parseError) {\n strapi.log.error(`${ERROR_PREFIX} Failed to parse AI server response`, parseError);\n throw new Error('AI usage data request failed. Check server logs for details.');\n }\n\n return {\n ...data.data,\n subscription: data.subscription,\n };\n } catch (fetchError) {\n if (fetchError instanceof Error && fetchError.name === 'AbortError') {\n strapi.log.error(`${ERROR_PREFIX} Request to AI server timed out`);\n throw new Error('AI usage data request failed. Check server logs for details.');\n }\n\n throw fetchError;\n }\n };\n\n return {\n /* Requires `ai.enabled=true` + license + no failed AI provider registration */\n isAvailable,\n /* `true` only when the license has the `cms-ai` entitlement to globally enable AI features.\n TODO: once all AI features are migrated to the providers architecture, consider removing this flag */\n isStrapiManagedAiEnabled,\n authorizeCustomProvider,\n /* Returns the status of each AI feature, flagging which are enabled. */\n getAiFeatureConfig,\n getAiToken,\n getAiUsage,\n };\n};\n\nexport { createAiAdminService };\n"],"names":["STRAPI_MANAGED_AI_LICENSE_FEATURE","CUSTOM_AI_PROVIDER_LICENSE_FEATURE","createAiAdminService","strapi","aiTokenCache","Map","isCustomProviderRejected","isConfigEnabled","config","get","isAvailable","ee","isEE","isStrapiManagedAiEnabled","features","isEnabled","authorizeCustomProvider","log","info","warn","isPluginAiFeatureConfigured","plugin","service","aiService","getAiFeatureConfig","isAiI18nConfigured","isAiMediaLibraryConfigured","Promise","all","resolveAiContext","errorPrefix","error","Error","replace","eeLicense","process","env","STRAPI_LICENSE","licensePath","path","join","dirs","app","root","fs","readFileSync","toString","projectId","aiServerUrl","STRAPI_AI_URL","getAiToken","ERROR_PREFIX","user","requestContext","state","userIdentifier","id","cacheKey","cachedToken","now","Date","bufferMs","expiresAtMs","token","expiresAt","delete","http","response","fetch","method","headers","crypto","randomUUID","body","JSON","stringify","ok","errorData","errorText","text","parse","status","statusText","data","json","parseError","jwt","userId","getTime","set","fetchError","name","getAiUsage","eeKey","subscription"],"mappings":"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"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var fp = require('lodash/fp');
|
|
4
|
+
|
|
5
|
+
const AUDITED_EVENTS = {
|
|
6
|
+
TOKEN_CREATE: 'token.create',
|
|
7
|
+
TOKEN_UPDATE: 'token.update',
|
|
8
|
+
TOKEN_DELETE: 'token.delete',
|
|
9
|
+
TOKEN_REGENERATE: 'token.regenerate'
|
|
10
|
+
};
|
|
11
|
+
const toAdminPermissionRefs = (permissions)=>(permissions ?? []).map((permission)=>({
|
|
12
|
+
action: permission.action,
|
|
13
|
+
subject: permission.subject ?? null,
|
|
14
|
+
properties: permission.properties ?? {}
|
|
15
|
+
}));
|
|
16
|
+
const toActionRefs = (permissions)=>(permissions ?? []).map((permission)=>typeof permission === 'string' ? permission : permission.action);
|
|
17
|
+
const TOKEN_EDITABLE_FIELDS = [
|
|
18
|
+
'name',
|
|
19
|
+
'description',
|
|
20
|
+
'type'
|
|
21
|
+
];
|
|
22
|
+
/**
|
|
23
|
+
* Sorted, and passed through JSON so undefined fields drop: neither order nor an absent
|
|
24
|
+
* field counts as a change.
|
|
25
|
+
*/ const sortRefs = (refs)=>fp.sortBy((ref)=>JSON.stringify(ref), JSON.parse(JSON.stringify(refs)));
|
|
26
|
+
const getTokenChanges = (previous, next)=>{
|
|
27
|
+
const changes = {};
|
|
28
|
+
for (const field of TOKEN_EDITABLE_FIELDS){
|
|
29
|
+
const before = previous[field] ?? null;
|
|
30
|
+
const after = next[field] ?? null;
|
|
31
|
+
if (before !== after) {
|
|
32
|
+
changes[field] = {
|
|
33
|
+
before,
|
|
34
|
+
after
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
if (previous.permissions !== undefined || next.permissions !== undefined) {
|
|
39
|
+
const before = sortRefs(previous.permissions ?? []);
|
|
40
|
+
const after = sortRefs(next.permissions ?? []);
|
|
41
|
+
if (!fp.isEqual(before, after)) {
|
|
42
|
+
changes.permissions = {
|
|
43
|
+
before,
|
|
44
|
+
after
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return changes;
|
|
49
|
+
};
|
|
50
|
+
const toIso = (value)=>value == null ? null : new Date(value).toISOString();
|
|
51
|
+
const registerTokenAuditEvents = (auditLogsLifecycle)=>{
|
|
52
|
+
const tokenResource = (event)=>({
|
|
53
|
+
type: event.kind,
|
|
54
|
+
id: event.tokenId,
|
|
55
|
+
name: event.name
|
|
56
|
+
});
|
|
57
|
+
const owner = (event)=>event.adminUserOwner != null ? {
|
|
58
|
+
adminUserOwner: event.adminUserOwner
|
|
59
|
+
} : {};
|
|
60
|
+
auditLogsLifecycle.registerEvent(AUDITED_EVENTS.TOKEN_CREATE, (event)=>({
|
|
61
|
+
resource: tokenResource(event),
|
|
62
|
+
details: {
|
|
63
|
+
description: event.description ?? null,
|
|
64
|
+
lifespan: event.lifespan == null ? null : Number(event.lifespan),
|
|
65
|
+
expiresAt: toIso(event.expiresAt),
|
|
66
|
+
...event.type !== undefined && {
|
|
67
|
+
type: event.type
|
|
68
|
+
},
|
|
69
|
+
...event.permissions !== undefined && {
|
|
70
|
+
permissions: sortRefs(event.permissions)
|
|
71
|
+
},
|
|
72
|
+
...owner(event)
|
|
73
|
+
}
|
|
74
|
+
}));
|
|
75
|
+
auditLogsLifecycle.registerEvent(AUDITED_EVENTS.TOKEN_UPDATE, (event)=>({
|
|
76
|
+
resource: tokenResource(event),
|
|
77
|
+
details: {
|
|
78
|
+
changes: event.changes,
|
|
79
|
+
...owner(event)
|
|
80
|
+
}
|
|
81
|
+
}));
|
|
82
|
+
auditLogsLifecycle.registerEvent(AUDITED_EVENTS.TOKEN_DELETE, (event)=>({
|
|
83
|
+
resource: tokenResource(event),
|
|
84
|
+
...event.adminUserOwner != null && {
|
|
85
|
+
details: {
|
|
86
|
+
adminUserOwner: event.adminUserOwner
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}));
|
|
90
|
+
auditLogsLifecycle.registerEvent(AUDITED_EVENTS.TOKEN_REGENERATE, (event)=>({
|
|
91
|
+
resource: tokenResource(event),
|
|
92
|
+
...event.adminUserOwner != null && {
|
|
93
|
+
details: {
|
|
94
|
+
adminUserOwner: event.adminUserOwner
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}));
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
exports.AUDITED_EVENTS = AUDITED_EVENTS;
|
|
101
|
+
exports.TOKEN_EDITABLE_FIELDS = TOKEN_EDITABLE_FIELDS;
|
|
102
|
+
exports.getTokenChanges = getTokenChanges;
|
|
103
|
+
exports.registerTokenAuditEvents = registerTokenAuditEvents;
|
|
104
|
+
exports.toActionRefs = toActionRefs;
|
|
105
|
+
exports.toAdminPermissionRefs = toAdminPermissionRefs;
|
|
106
|
+
//# sourceMappingURL=tokens.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tokens.js","sources":["../../../../../server/src/audit-logs/tokens.ts"],"sourcesContent":["import { isEqual, sortBy } from 'lodash/fp';\nimport type { Data, Modules } from '@strapi/types';\n\nimport type { Permission } from '../../../shared/contracts/shared';\n\nexport const AUDITED_EVENTS = {\n TOKEN_CREATE: 'token.create',\n TOKEN_UPDATE: 'token.update',\n TOKEN_DELETE: 'token.delete',\n TOKEN_REGENERATE: 'token.regenerate',\n} as const;\n\nexport type TokenKind = 'content-api' | 'admin' | 'transfer';\n\n/**\n * A token permission as recorded in the audit log: action, subject and properties.\n * The row id says nothing to an auditor, and conditions are not part of the token:\n * they are copied from the owner's role and cannot be set per token.\n */\nexport interface AdminPermissionRef {\n action: string;\n subject: string | null;\n properties: Permission['properties'];\n}\n\nexport type PermissionRef = string | AdminPermissionRef;\n\nexport const toAdminPermissionRefs = (\n permissions: Array<Pick<Permission, 'action' | 'subject' | 'properties'>> | null | undefined\n): AdminPermissionRef[] =>\n (permissions ?? []).map((permission) => ({\n action: permission.action,\n subject: permission.subject ?? null,\n properties: permission.properties ?? {},\n }));\n\nexport const toActionRefs = (\n permissions: Array<string | { action: string }> | null | undefined\n): string[] =>\n (permissions ?? []).map((permission) =>\n typeof permission === 'string' ? permission : permission.action\n );\n\n/**\n * The owner is recorded as an id: the user object carries the email, which has no place\n * in the log.\n */\nexport interface TokenEvent {\n tokenId: Data.ID;\n name: string;\n kind: TokenKind;\n adminUserOwner?: Data.ID;\n}\n\nexport interface TokenResource extends Modules.AuditLogs.Resource {\n type: TokenKind;\n}\n\nexport interface CreateDetails {\n description: string | null;\n /** Milliseconds. The column is a biginteger and comes back as a string. */\n lifespan: number | null;\n expiresAt: string | null;\n /** content-api only: read-only | full-access | custom */\n type?: string;\n /** content-api (custom), transfer and admin tokens */\n permissions?: PermissionRef[];\n adminUserOwner?: Data.ID;\n}\n\nexport type CreateEvent = TokenEvent & {\n description?: string | null;\n lifespan?: string | number | null;\n expiresAt?: string | number | Date | null;\n type?: string;\n permissions?: PermissionRef[];\n};\n\nexport const TOKEN_EDITABLE_FIELDS = ['name', 'description', 'type'] as const;\n\nexport type TokenChanges = Partial<{\n name: Modules.AuditLogs.FieldChange<string | null>;\n description: Modules.AuditLogs.FieldChange<string | null>;\n type: Modules.AuditLogs.FieldChange<string | null>;\n permissions: Modules.AuditLogs.FieldChange<PermissionRef[]>;\n}>;\n\nexport interface UpdateDetails {\n changes: TokenChanges;\n adminUserOwner?: Data.ID;\n}\n\nexport type UpdateEvent = TokenEvent & { changes: TokenChanges };\n\nexport interface TokenSnapshot {\n name?: string | null;\n description?: string | null;\n type?: string | null;\n permissions?: PermissionRef[];\n}\n\n/**\n * Sorted, and passed through JSON so undefined fields drop: neither order nor an absent\n * field counts as a change.\n */\nconst sortRefs = (refs: PermissionRef[]): PermissionRef[] =>\n sortBy((ref: PermissionRef) => JSON.stringify(ref), JSON.parse(JSON.stringify(refs)));\n\nexport const getTokenChanges = (previous: TokenSnapshot, next: TokenSnapshot): TokenChanges => {\n const changes: TokenChanges = {};\n\n for (const field of TOKEN_EDITABLE_FIELDS) {\n const before = previous[field] ?? null;\n const after = next[field] ?? null;\n\n if (before !== after) {\n changes[field] = { before, after };\n }\n }\n\n if (previous.permissions !== undefined || next.permissions !== undefined) {\n const before = sortRefs(previous.permissions ?? []);\n const after = sortRefs(next.permissions ?? []);\n\n if (!isEqual(before, after)) {\n changes.permissions = { before, after };\n }\n }\n\n return changes;\n};\n\nconst toIso = (value: string | number | Date | null | undefined): string | null =>\n value == null ? null : new Date(value).toISOString();\n\n/**\n * The part of the audit-logs lifecycle service used here.\n * The full service type lives in the Admin EE package.\n */\ninterface AuditLogsLifecycle {\n registerEvent<TDetails>(\n name: string,\n transform: Modules.AuditLogs.EventTransformer<TDetails>\n ): void;\n}\n\nexport const registerTokenAuditEvents = (auditLogsLifecycle: AuditLogsLifecycle) => {\n const tokenResource = (event: TokenEvent): TokenResource => ({\n type: event.kind,\n id: event.tokenId,\n name: event.name,\n });\n\n const owner = (event: TokenEvent) =>\n event.adminUserOwner != null ? { adminUserOwner: event.adminUserOwner } : {};\n\n auditLogsLifecycle.registerEvent<CreateDetails>(\n AUDITED_EVENTS.TOKEN_CREATE,\n (event: CreateEvent) => ({\n resource: tokenResource(event),\n details: {\n description: event.description ?? null,\n lifespan: event.lifespan == null ? null : Number(event.lifespan),\n expiresAt: toIso(event.expiresAt),\n ...(event.type !== undefined && { type: event.type }),\n ...(event.permissions !== undefined && { permissions: sortRefs(event.permissions) }),\n ...owner(event),\n },\n })\n );\n\n auditLogsLifecycle.registerEvent<UpdateDetails>(\n AUDITED_EVENTS.TOKEN_UPDATE,\n (event: UpdateEvent) => ({\n resource: tokenResource(event),\n details: { changes: event.changes, ...owner(event) },\n })\n );\n\n auditLogsLifecycle.registerEvent<{ adminUserOwner: Data.ID } | undefined>(\n AUDITED_EVENTS.TOKEN_DELETE,\n (event: TokenEvent) => ({\n resource: tokenResource(event),\n ...(event.adminUserOwner != null && { details: { adminUserOwner: event.adminUserOwner } }),\n })\n );\n\n auditLogsLifecycle.registerEvent<{ adminUserOwner: Data.ID } | undefined>(\n AUDITED_EVENTS.TOKEN_REGENERATE,\n (event: TokenEvent) => ({\n resource: tokenResource(event),\n ...(event.adminUserOwner != null && { details: { adminUserOwner: event.adminUserOwner } }),\n })\n );\n};\n"],"names":["AUDITED_EVENTS","TOKEN_CREATE","TOKEN_UPDATE","TOKEN_DELETE","TOKEN_REGENERATE","toAdminPermissionRefs","permissions","map","permission","action","subject","properties","toActionRefs","TOKEN_EDITABLE_FIELDS","sortRefs","refs","sortBy","ref","JSON","stringify","parse","getTokenChanges","previous","next","changes","field","before","after","undefined","isEqual","toIso","value","Date","toISOString","registerTokenAuditEvents","auditLogsLifecycle","tokenResource","event","type","kind","id","tokenId","name","owner","adminUserOwner","registerEvent","resource","details","description","lifespan","Number","expiresAt"],"mappings":"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"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { isEqual, sortBy } from 'lodash/fp';
|
|
2
|
+
|
|
3
|
+
const AUDITED_EVENTS = {
|
|
4
|
+
TOKEN_CREATE: 'token.create',
|
|
5
|
+
TOKEN_UPDATE: 'token.update',
|
|
6
|
+
TOKEN_DELETE: 'token.delete',
|
|
7
|
+
TOKEN_REGENERATE: 'token.regenerate'
|
|
8
|
+
};
|
|
9
|
+
const toAdminPermissionRefs = (permissions)=>(permissions ?? []).map((permission)=>({
|
|
10
|
+
action: permission.action,
|
|
11
|
+
subject: permission.subject ?? null,
|
|
12
|
+
properties: permission.properties ?? {}
|
|
13
|
+
}));
|
|
14
|
+
const toActionRefs = (permissions)=>(permissions ?? []).map((permission)=>typeof permission === 'string' ? permission : permission.action);
|
|
15
|
+
const TOKEN_EDITABLE_FIELDS = [
|
|
16
|
+
'name',
|
|
17
|
+
'description',
|
|
18
|
+
'type'
|
|
19
|
+
];
|
|
20
|
+
/**
|
|
21
|
+
* Sorted, and passed through JSON so undefined fields drop: neither order nor an absent
|
|
22
|
+
* field counts as a change.
|
|
23
|
+
*/ const sortRefs = (refs)=>sortBy((ref)=>JSON.stringify(ref), JSON.parse(JSON.stringify(refs)));
|
|
24
|
+
const getTokenChanges = (previous, next)=>{
|
|
25
|
+
const changes = {};
|
|
26
|
+
for (const field of TOKEN_EDITABLE_FIELDS){
|
|
27
|
+
const before = previous[field] ?? null;
|
|
28
|
+
const after = next[field] ?? null;
|
|
29
|
+
if (before !== after) {
|
|
30
|
+
changes[field] = {
|
|
31
|
+
before,
|
|
32
|
+
after
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
if (previous.permissions !== undefined || next.permissions !== undefined) {
|
|
37
|
+
const before = sortRefs(previous.permissions ?? []);
|
|
38
|
+
const after = sortRefs(next.permissions ?? []);
|
|
39
|
+
if (!isEqual(before, after)) {
|
|
40
|
+
changes.permissions = {
|
|
41
|
+
before,
|
|
42
|
+
after
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return changes;
|
|
47
|
+
};
|
|
48
|
+
const toIso = (value)=>value == null ? null : new Date(value).toISOString();
|
|
49
|
+
const registerTokenAuditEvents = (auditLogsLifecycle)=>{
|
|
50
|
+
const tokenResource = (event)=>({
|
|
51
|
+
type: event.kind,
|
|
52
|
+
id: event.tokenId,
|
|
53
|
+
name: event.name
|
|
54
|
+
});
|
|
55
|
+
const owner = (event)=>event.adminUserOwner != null ? {
|
|
56
|
+
adminUserOwner: event.adminUserOwner
|
|
57
|
+
} : {};
|
|
58
|
+
auditLogsLifecycle.registerEvent(AUDITED_EVENTS.TOKEN_CREATE, (event)=>({
|
|
59
|
+
resource: tokenResource(event),
|
|
60
|
+
details: {
|
|
61
|
+
description: event.description ?? null,
|
|
62
|
+
lifespan: event.lifespan == null ? null : Number(event.lifespan),
|
|
63
|
+
expiresAt: toIso(event.expiresAt),
|
|
64
|
+
...event.type !== undefined && {
|
|
65
|
+
type: event.type
|
|
66
|
+
},
|
|
67
|
+
...event.permissions !== undefined && {
|
|
68
|
+
permissions: sortRefs(event.permissions)
|
|
69
|
+
},
|
|
70
|
+
...owner(event)
|
|
71
|
+
}
|
|
72
|
+
}));
|
|
73
|
+
auditLogsLifecycle.registerEvent(AUDITED_EVENTS.TOKEN_UPDATE, (event)=>({
|
|
74
|
+
resource: tokenResource(event),
|
|
75
|
+
details: {
|
|
76
|
+
changes: event.changes,
|
|
77
|
+
...owner(event)
|
|
78
|
+
}
|
|
79
|
+
}));
|
|
80
|
+
auditLogsLifecycle.registerEvent(AUDITED_EVENTS.TOKEN_DELETE, (event)=>({
|
|
81
|
+
resource: tokenResource(event),
|
|
82
|
+
...event.adminUserOwner != null && {
|
|
83
|
+
details: {
|
|
84
|
+
adminUserOwner: event.adminUserOwner
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}));
|
|
88
|
+
auditLogsLifecycle.registerEvent(AUDITED_EVENTS.TOKEN_REGENERATE, (event)=>({
|
|
89
|
+
resource: tokenResource(event),
|
|
90
|
+
...event.adminUserOwner != null && {
|
|
91
|
+
details: {
|
|
92
|
+
adminUserOwner: event.adminUserOwner
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}));
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
export { AUDITED_EVENTS, TOKEN_EDITABLE_FIELDS, getTokenChanges, registerTokenAuditEvents, toActionRefs, toAdminPermissionRefs };
|
|
99
|
+
//# sourceMappingURL=tokens.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tokens.mjs","sources":["../../../../../server/src/audit-logs/tokens.ts"],"sourcesContent":["import { isEqual, sortBy } from 'lodash/fp';\nimport type { Data, Modules } from '@strapi/types';\n\nimport type { Permission } from '../../../shared/contracts/shared';\n\nexport const AUDITED_EVENTS = {\n TOKEN_CREATE: 'token.create',\n TOKEN_UPDATE: 'token.update',\n TOKEN_DELETE: 'token.delete',\n TOKEN_REGENERATE: 'token.regenerate',\n} as const;\n\nexport type TokenKind = 'content-api' | 'admin' | 'transfer';\n\n/**\n * A token permission as recorded in the audit log: action, subject and properties.\n * The row id says nothing to an auditor, and conditions are not part of the token:\n * they are copied from the owner's role and cannot be set per token.\n */\nexport interface AdminPermissionRef {\n action: string;\n subject: string | null;\n properties: Permission['properties'];\n}\n\nexport type PermissionRef = string | AdminPermissionRef;\n\nexport const toAdminPermissionRefs = (\n permissions: Array<Pick<Permission, 'action' | 'subject' | 'properties'>> | null | undefined\n): AdminPermissionRef[] =>\n (permissions ?? []).map((permission) => ({\n action: permission.action,\n subject: permission.subject ?? null,\n properties: permission.properties ?? {},\n }));\n\nexport const toActionRefs = (\n permissions: Array<string | { action: string }> | null | undefined\n): string[] =>\n (permissions ?? []).map((permission) =>\n typeof permission === 'string' ? permission : permission.action\n );\n\n/**\n * The owner is recorded as an id: the user object carries the email, which has no place\n * in the log.\n */\nexport interface TokenEvent {\n tokenId: Data.ID;\n name: string;\n kind: TokenKind;\n adminUserOwner?: Data.ID;\n}\n\nexport interface TokenResource extends Modules.AuditLogs.Resource {\n type: TokenKind;\n}\n\nexport interface CreateDetails {\n description: string | null;\n /** Milliseconds. The column is a biginteger and comes back as a string. */\n lifespan: number | null;\n expiresAt: string | null;\n /** content-api only: read-only | full-access | custom */\n type?: string;\n /** content-api (custom), transfer and admin tokens */\n permissions?: PermissionRef[];\n adminUserOwner?: Data.ID;\n}\n\nexport type CreateEvent = TokenEvent & {\n description?: string | null;\n lifespan?: string | number | null;\n expiresAt?: string | number | Date | null;\n type?: string;\n permissions?: PermissionRef[];\n};\n\nexport const TOKEN_EDITABLE_FIELDS = ['name', 'description', 'type'] as const;\n\nexport type TokenChanges = Partial<{\n name: Modules.AuditLogs.FieldChange<string | null>;\n description: Modules.AuditLogs.FieldChange<string | null>;\n type: Modules.AuditLogs.FieldChange<string | null>;\n permissions: Modules.AuditLogs.FieldChange<PermissionRef[]>;\n}>;\n\nexport interface UpdateDetails {\n changes: TokenChanges;\n adminUserOwner?: Data.ID;\n}\n\nexport type UpdateEvent = TokenEvent & { changes: TokenChanges };\n\nexport interface TokenSnapshot {\n name?: string | null;\n description?: string | null;\n type?: string | null;\n permissions?: PermissionRef[];\n}\n\n/**\n * Sorted, and passed through JSON so undefined fields drop: neither order nor an absent\n * field counts as a change.\n */\nconst sortRefs = (refs: PermissionRef[]): PermissionRef[] =>\n sortBy((ref: PermissionRef) => JSON.stringify(ref), JSON.parse(JSON.stringify(refs)));\n\nexport const getTokenChanges = (previous: TokenSnapshot, next: TokenSnapshot): TokenChanges => {\n const changes: TokenChanges = {};\n\n for (const field of TOKEN_EDITABLE_FIELDS) {\n const before = previous[field] ?? null;\n const after = next[field] ?? null;\n\n if (before !== after) {\n changes[field] = { before, after };\n }\n }\n\n if (previous.permissions !== undefined || next.permissions !== undefined) {\n const before = sortRefs(previous.permissions ?? []);\n const after = sortRefs(next.permissions ?? []);\n\n if (!isEqual(before, after)) {\n changes.permissions = { before, after };\n }\n }\n\n return changes;\n};\n\nconst toIso = (value: string | number | Date | null | undefined): string | null =>\n value == null ? null : new Date(value).toISOString();\n\n/**\n * The part of the audit-logs lifecycle service used here.\n * The full service type lives in the Admin EE package.\n */\ninterface AuditLogsLifecycle {\n registerEvent<TDetails>(\n name: string,\n transform: Modules.AuditLogs.EventTransformer<TDetails>\n ): void;\n}\n\nexport const registerTokenAuditEvents = (auditLogsLifecycle: AuditLogsLifecycle) => {\n const tokenResource = (event: TokenEvent): TokenResource => ({\n type: event.kind,\n id: event.tokenId,\n name: event.name,\n });\n\n const owner = (event: TokenEvent) =>\n event.adminUserOwner != null ? { adminUserOwner: event.adminUserOwner } : {};\n\n auditLogsLifecycle.registerEvent<CreateDetails>(\n AUDITED_EVENTS.TOKEN_CREATE,\n (event: CreateEvent) => ({\n resource: tokenResource(event),\n details: {\n description: event.description ?? null,\n lifespan: event.lifespan == null ? null : Number(event.lifespan),\n expiresAt: toIso(event.expiresAt),\n ...(event.type !== undefined && { type: event.type }),\n ...(event.permissions !== undefined && { permissions: sortRefs(event.permissions) }),\n ...owner(event),\n },\n })\n );\n\n auditLogsLifecycle.registerEvent<UpdateDetails>(\n AUDITED_EVENTS.TOKEN_UPDATE,\n (event: UpdateEvent) => ({\n resource: tokenResource(event),\n details: { changes: event.changes, ...owner(event) },\n })\n );\n\n auditLogsLifecycle.registerEvent<{ adminUserOwner: Data.ID } | undefined>(\n AUDITED_EVENTS.TOKEN_DELETE,\n (event: TokenEvent) => ({\n resource: tokenResource(event),\n ...(event.adminUserOwner != null && { details: { adminUserOwner: event.adminUserOwner } }),\n })\n );\n\n auditLogsLifecycle.registerEvent<{ adminUserOwner: Data.ID } | undefined>(\n AUDITED_EVENTS.TOKEN_REGENERATE,\n (event: TokenEvent) => ({\n resource: tokenResource(event),\n ...(event.adminUserOwner != null && { details: { adminUserOwner: event.adminUserOwner } }),\n })\n );\n};\n"],"names":["AUDITED_EVENTS","TOKEN_CREATE","TOKEN_UPDATE","TOKEN_DELETE","TOKEN_REGENERATE","toAdminPermissionRefs","permissions","map","permission","action","subject","properties","toActionRefs","TOKEN_EDITABLE_FIELDS","sortRefs","refs","sortBy","ref","JSON","stringify","parse","getTokenChanges","previous","next","changes","field","before","after","undefined","isEqual","toIso","value","Date","toISOString","registerTokenAuditEvents","auditLogsLifecycle","tokenResource","event","type","kind","id","tokenId","name","owner","adminUserOwner","registerEvent","resource","details","description","lifespan","Number","expiresAt"],"mappings":"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"}
|
|
@@ -90,6 +90,14 @@ const isUsingTypeScript = (...args)=>{
|
|
|
90
90
|
return fp.pipe(fp.map('attributes'), fp.flatMap(fp.values), // @ts-expect-error lodash types
|
|
91
91
|
fp.sumBy(fp.propEq('type', 'dynamiczone')))(strapi.contentTypes);
|
|
92
92
|
};
|
|
93
|
+
const getNumberOfFolders = async ()=>{
|
|
94
|
+
try {
|
|
95
|
+
const contentStructure = strapi.get('content-structure');
|
|
96
|
+
return await contentStructure?.countGroups?.() ?? 0;
|
|
97
|
+
} catch {
|
|
98
|
+
return 0;
|
|
99
|
+
}
|
|
100
|
+
};
|
|
93
101
|
return {
|
|
94
102
|
data: {
|
|
95
103
|
useTypescriptOnServer,
|
|
@@ -97,7 +105,8 @@ const isUsingTypeScript = (...args)=>{
|
|
|
97
105
|
isHostedOnStrapiCloud,
|
|
98
106
|
numberOfAllContentTypes,
|
|
99
107
|
numberOfComponents,
|
|
100
|
-
numberOfDynamicZones: getNumberOfDynamicZones()
|
|
108
|
+
numberOfDynamicZones: getNumberOfDynamicZones(),
|
|
109
|
+
numberOfContentTypeFolders: await getNumberOfFolders()
|
|
101
110
|
}
|
|
102
111
|
};
|
|
103
112
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"admin.js","sources":["../../../../../server/src/controllers/admin.ts"],"sourcesContent":["import type { Context } from 'koa';\n\nimport path from 'path';\n\nimport { map, values, sumBy, pipe, flatMap, propEq } from 'lodash/fp';\nimport _ from 'lodash';\nimport { exists } from 'fs-extra';\nimport { env } from '@strapi/utils';\nimport {\n validateUpdateProjectSettings,\n validateUpdateProjectSettingsFiles,\n validateUpdateProjectSettingsImagesDimensions,\n} from '../validation/project-settings';\nimport { getService } from '../utils';\n\nimport type {\n Init,\n GetProjectSettings,\n Information,\n Plugins,\n TelemetryProperties,\n UpdateProjectSettings,\n GetGuidedTourMeta,\n} from '../../../shared/contracts/admin';\n\n// Lazy: only resolved on first GET /admin/project-type request\ntype TsUtilsModule = typeof import('@strapi/typescript-utils');\nlet lazyTsUtils: TsUtilsModule | undefined;\nconst isUsingTypeScript: TsUtilsModule['isUsingTypeScript'] = (\n ...args: Parameters<TsUtilsModule['isUsingTypeScript']>\n) => {\n if (!lazyTsUtils) {\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n lazyTsUtils = require('@strapi/typescript-utils');\n }\n return (lazyTsUtils as TsUtilsModule).isUsingTypeScript(...args);\n};\n\n/**\n * A set of functions called \"actions\" for `Admin`\n */\nexport default {\n // TODO very temporary to check the switch ee/ce\n // When removing this we need to update the /admin/src/index.js file\n // whe,re we set the strapi.window.isEE value\n\n // NOTE: admin/ee/server overrides this controller, and adds the EE features\n // This returns an empty feature list for CE\n async getProjectType() {\n const flags = strapi.config.get('admin.flags', {});\n return { data: { isEE: false, features: [], flags, ai: { enabled: false } } };\n },\n\n async init() {\n let uuid = strapi.config.get('uuid', false);\n const hasAdmin = await getService('user').exists();\n const { menuLogo, authLogo } = await getService('project-settings').getProjectSettings();\n // set to null if telemetryDisabled flag not avaialble in package.json\n const telemetryDisabled: boolean | null = strapi.config.get(\n 'packageJsonStrapi.telemetryDisabled',\n null\n );\n\n if (telemetryDisabled !== null && telemetryDisabled === true) {\n uuid = false;\n }\n\n return {\n data: {\n uuid,\n hasAdmin,\n menuLogo: menuLogo ? menuLogo.url : null,\n authLogo: authLogo ? authLogo.url : null,\n },\n } satisfies Init.Response;\n },\n\n async getProjectSettings() {\n return getService(\n 'project-settings'\n ).getProjectSettings() satisfies Promise<GetProjectSettings.Response>;\n },\n\n async updateProjectSettings(ctx: Context) {\n const {\n request: { files, body },\n } = ctx as { request: UpdateProjectSettings.Request };\n\n const projectSettingsService = getService('project-settings');\n\n await validateUpdateProjectSettings(body);\n await validateUpdateProjectSettingsFiles(files);\n\n const formatedFiles = await projectSettingsService.parseFilesData(files);\n await validateUpdateProjectSettingsImagesDimensions(formatedFiles);\n\n return projectSettingsService.updateProjectSettings({\n ...body,\n ...formatedFiles,\n }) satisfies Promise<UpdateProjectSettings.Response>;\n },\n\n async telemetryProperties(ctx: Context) {\n // If the telemetry is disabled, ignore the request and return early\n if (strapi.telemetry.isDisabled) {\n ctx.status = 204;\n return;\n }\n\n const useTypescriptOnServer = await isUsingTypeScript(strapi.dirs.app.root);\n const useTypescriptOnAdmin = await isUsingTypeScript(\n path.join(strapi.dirs.app.root, 'src', 'admin')\n );\n const isHostedOnStrapiCloud = env('STRAPI_HOSTING', null) === 'strapi.cloud';\n\n const numberOfAllContentTypes = _.size(strapi.contentTypes);\n const numberOfComponents = _.size(strapi.components);\n\n const getNumberOfDynamicZones = () => {\n return pipe(\n map('attributes'),\n flatMap(values),\n // @ts-expect-error lodash types\n sumBy(propEq('type', 'dynamiczone'))\n )(strapi.contentTypes as any);\n };\n\n return {\n data: {\n useTypescriptOnServer,\n useTypescriptOnAdmin,\n isHostedOnStrapiCloud,\n numberOfAllContentTypes, // TODO: V5: This event should be renamed numberOfContentTypes in V5 as the name is already taken to describe the number of content types using i18n.\n numberOfComponents,\n numberOfDynamicZones: getNumberOfDynamicZones(),\n },\n } satisfies TelemetryProperties.Response;\n },\n\n async information() {\n const currentEnvironment: string = strapi.config.get('environment');\n const autoReload = strapi.config.get('autoReload', false);\n const strapiVersion = strapi.config.get('info.strapi', null);\n const dependencies = strapi.config.get('info.dependencies', {});\n const projectId = strapi.config.get('uuid', null);\n const nodeVersion = process.version;\n const communityEdition = !strapi.EE;\n const useYarn: boolean = await exists(path.join(process.cwd(), 'yarn.lock'));\n\n return {\n data: {\n currentEnvironment,\n autoReload,\n strapiVersion,\n dependencies,\n projectId,\n nodeVersion,\n communityEdition,\n useYarn,\n },\n } satisfies Information.Response;\n },\n\n async plugins(ctx: Context) {\n const enabledPlugins = strapi.config.get('enabledPlugins') as any;\n\n // List of core plugins that are always enabled,\n // and so it's not necessary to display them in the plugins list\n const CORE_PLUGINS = [\n 'content-manager',\n 'content-type-builder',\n 'email',\n 'upload',\n 'i18n',\n 'content-releases',\n 'review-workflows',\n ];\n\n const plugins = Object.entries(enabledPlugins)\n .filter(([key]: any) => !CORE_PLUGINS.includes(key))\n .map(([key, plugin]: any) => ({\n name: plugin.info.name || key,\n displayName: plugin.info.displayName || plugin.info.name || key,\n description: plugin.info.description || '',\n packageName: plugin.info.packageName,\n }));\n\n ctx.send({ plugins } satisfies Plugins.Response);\n },\n\n async licenseTrialTimeLeft() {\n const data = await strapi.ee.getTrialEndDate({\n strapi,\n });\n\n return data;\n },\n\n async getGuidedTourMeta(ctx: Context) {\n const isFirstSuperAdminUser = await getService('user').isFirstSuperAdminUser(ctx.state.user.id);\n\n return {\n data: {\n isFirstSuperAdminUser,\n schemas: strapi.contentTypes,\n },\n } satisfies GetGuidedTourMeta.Response;\n },\n};\n"],"names":["lazyTsUtils","isUsingTypeScript","args","require","getProjectType","flags","strapi","config","get","data","isEE","features","ai","enabled","init","uuid","hasAdmin","getService","exists","menuLogo","authLogo","getProjectSettings","telemetryDisabled","url","updateProjectSettings","ctx","request","files","body","projectSettingsService","validateUpdateProjectSettings","validateUpdateProjectSettingsFiles","formatedFiles","parseFilesData","validateUpdateProjectSettingsImagesDimensions","telemetryProperties","telemetry","isDisabled","status","useTypescriptOnServer","dirs","app","root","useTypescriptOnAdmin","path","join","isHostedOnStrapiCloud","env","numberOfAllContentTypes","_","size","contentTypes","numberOfComponents","components","getNumberOfDynamicZones","pipe","map","flatMap","values","sumBy","propEq","numberOfDynamicZones","information","currentEnvironment","autoReload","strapiVersion","dependencies","projectId","nodeVersion","process","version","communityEdition","EE","useYarn","cwd","plugins","enabledPlugins","CORE_PLUGINS","Object","entries","filter","key","includes","plugin","name","info","displayName","description","packageName","send","licenseTrialTimeLeft","ee","getTrialEndDate","getGuidedTourMeta","isFirstSuperAdminUser","state","user","id","schemas"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"admin.js","sources":["../../../../../server/src/controllers/admin.ts"],"sourcesContent":["import type { Context } from 'koa';\n\nimport path from 'path';\n\nimport { map, values, sumBy, pipe, flatMap, propEq } from 'lodash/fp';\nimport _ from 'lodash';\nimport { exists } from 'fs-extra';\nimport { env } from '@strapi/utils';\nimport {\n validateUpdateProjectSettings,\n validateUpdateProjectSettingsFiles,\n validateUpdateProjectSettingsImagesDimensions,\n} from '../validation/project-settings';\nimport { getService } from '../utils';\n\nimport type {\n Init,\n GetProjectSettings,\n Information,\n Plugins,\n TelemetryProperties,\n UpdateProjectSettings,\n GetGuidedTourMeta,\n} from '../../../shared/contracts/admin';\n\n// Lazy: only resolved on first GET /admin/project-type request\ntype TsUtilsModule = typeof import('@strapi/typescript-utils');\nlet lazyTsUtils: TsUtilsModule | undefined;\nconst isUsingTypeScript: TsUtilsModule['isUsingTypeScript'] = (\n ...args: Parameters<TsUtilsModule['isUsingTypeScript']>\n) => {\n if (!lazyTsUtils) {\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n lazyTsUtils = require('@strapi/typescript-utils');\n }\n return (lazyTsUtils as TsUtilsModule).isUsingTypeScript(...args);\n};\n\n/**\n * A set of functions called \"actions\" for `Admin`\n */\nexport default {\n // TODO very temporary to check the switch ee/ce\n // When removing this we need to update the /admin/src/index.js file\n // whe,re we set the strapi.window.isEE value\n\n // NOTE: admin/ee/server overrides this controller, and adds the EE features\n // This returns an empty feature list for CE\n async getProjectType() {\n const flags = strapi.config.get('admin.flags', {});\n return { data: { isEE: false, features: [], flags, ai: { enabled: false } } };\n },\n\n async init() {\n let uuid = strapi.config.get('uuid', false);\n const hasAdmin = await getService('user').exists();\n const { menuLogo, authLogo } = await getService('project-settings').getProjectSettings();\n // set to null if telemetryDisabled flag not avaialble in package.json\n const telemetryDisabled: boolean | null = strapi.config.get(\n 'packageJsonStrapi.telemetryDisabled',\n null\n );\n\n if (telemetryDisabled !== null && telemetryDisabled === true) {\n uuid = false;\n }\n\n return {\n data: {\n uuid,\n hasAdmin,\n menuLogo: menuLogo ? menuLogo.url : null,\n authLogo: authLogo ? authLogo.url : null,\n },\n } satisfies Init.Response;\n },\n\n async getProjectSettings() {\n return getService(\n 'project-settings'\n ).getProjectSettings() satisfies Promise<GetProjectSettings.Response>;\n },\n\n async updateProjectSettings(ctx: Context) {\n const {\n request: { files, body },\n } = ctx as { request: UpdateProjectSettings.Request };\n\n const projectSettingsService = getService('project-settings');\n\n await validateUpdateProjectSettings(body);\n await validateUpdateProjectSettingsFiles(files);\n\n const formatedFiles = await projectSettingsService.parseFilesData(files);\n await validateUpdateProjectSettingsImagesDimensions(formatedFiles);\n\n return projectSettingsService.updateProjectSettings({\n ...body,\n ...formatedFiles,\n }) satisfies Promise<UpdateProjectSettings.Response>;\n },\n\n async telemetryProperties(ctx: Context) {\n // If the telemetry is disabled, ignore the request and return early\n if (strapi.telemetry.isDisabled) {\n ctx.status = 204;\n return;\n }\n\n const useTypescriptOnServer = await isUsingTypeScript(strapi.dirs.app.root);\n const useTypescriptOnAdmin = await isUsingTypeScript(\n path.join(strapi.dirs.app.root, 'src', 'admin')\n );\n const isHostedOnStrapiCloud = env('STRAPI_HOSTING', null) === 'strapi.cloud';\n\n const numberOfAllContentTypes = _.size(strapi.contentTypes);\n const numberOfComponents = _.size(strapi.components);\n\n const getNumberOfDynamicZones = () => {\n return pipe(\n map('attributes'),\n flatMap(values),\n // @ts-expect-error lodash types\n sumBy(propEq('type', 'dynamiczone'))\n )(strapi.contentTypes as any);\n };\n\n const getNumberOfFolders = async (): Promise<number> => {\n try {\n const contentStructure = strapi.get('content-structure') as\n | { countGroups?: () => Promise<number> }\n | undefined;\n\n return (await contentStructure?.countGroups?.()) ?? 0;\n } catch {\n return 0;\n }\n };\n\n return {\n data: {\n useTypescriptOnServer,\n useTypescriptOnAdmin,\n isHostedOnStrapiCloud,\n numberOfAllContentTypes, // TODO: V5: This event should be renamed numberOfContentTypes in V5 as the name is already taken to describe the number of content types using i18n.\n numberOfComponents,\n numberOfDynamicZones: getNumberOfDynamicZones(),\n numberOfContentTypeFolders: await getNumberOfFolders(),\n },\n } satisfies TelemetryProperties.Response;\n },\n\n async information() {\n const currentEnvironment: string = strapi.config.get('environment');\n const autoReload = strapi.config.get('autoReload', false);\n const strapiVersion = strapi.config.get('info.strapi', null);\n const dependencies = strapi.config.get('info.dependencies', {});\n const projectId = strapi.config.get('uuid', null);\n const nodeVersion = process.version;\n const communityEdition = !strapi.EE;\n const useYarn: boolean = await exists(path.join(process.cwd(), 'yarn.lock'));\n\n return {\n data: {\n currentEnvironment,\n autoReload,\n strapiVersion,\n dependencies,\n projectId,\n nodeVersion,\n communityEdition,\n useYarn,\n },\n } satisfies Information.Response;\n },\n\n async plugins(ctx: Context) {\n const enabledPlugins = strapi.config.get('enabledPlugins') as any;\n\n // List of core plugins that are always enabled,\n // and so it's not necessary to display them in the plugins list\n const CORE_PLUGINS = [\n 'content-manager',\n 'content-type-builder',\n 'email',\n 'upload',\n 'i18n',\n 'content-releases',\n 'review-workflows',\n ];\n\n const plugins = Object.entries(enabledPlugins)\n .filter(([key]: any) => !CORE_PLUGINS.includes(key))\n .map(([key, plugin]: any) => ({\n name: plugin.info.name || key,\n displayName: plugin.info.displayName || plugin.info.name || key,\n description: plugin.info.description || '',\n packageName: plugin.info.packageName,\n }));\n\n ctx.send({ plugins } satisfies Plugins.Response);\n },\n\n async licenseTrialTimeLeft() {\n const data = await strapi.ee.getTrialEndDate({\n strapi,\n });\n\n return data;\n },\n\n async getGuidedTourMeta(ctx: Context) {\n const isFirstSuperAdminUser = await getService('user').isFirstSuperAdminUser(ctx.state.user.id);\n\n return {\n data: {\n isFirstSuperAdminUser,\n schemas: strapi.contentTypes,\n },\n } satisfies GetGuidedTourMeta.Response;\n },\n};\n"],"names":["lazyTsUtils","isUsingTypeScript","args","require","getProjectType","flags","strapi","config","get","data","isEE","features","ai","enabled","init","uuid","hasAdmin","getService","exists","menuLogo","authLogo","getProjectSettings","telemetryDisabled","url","updateProjectSettings","ctx","request","files","body","projectSettingsService","validateUpdateProjectSettings","validateUpdateProjectSettingsFiles","formatedFiles","parseFilesData","validateUpdateProjectSettingsImagesDimensions","telemetryProperties","telemetry","isDisabled","status","useTypescriptOnServer","dirs","app","root","useTypescriptOnAdmin","path","join","isHostedOnStrapiCloud","env","numberOfAllContentTypes","_","size","contentTypes","numberOfComponents","components","getNumberOfDynamicZones","pipe","map","flatMap","values","sumBy","propEq","getNumberOfFolders","contentStructure","countGroups","numberOfDynamicZones","numberOfContentTypeFolders","information","currentEnvironment","autoReload","strapiVersion","dependencies","projectId","nodeVersion","process","version","communityEdition","EE","useYarn","cwd","plugins","enabledPlugins","CORE_PLUGINS","Object","entries","filter","key","includes","plugin","name","info","displayName","description","packageName","send","licenseTrialTimeLeft","ee","getTrialEndDate","getGuidedTourMeta","isFirstSuperAdminUser","state","user","id","schemas"],"mappings":"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"}
|
|
@@ -83,6 +83,14 @@ const isUsingTypeScript = (...args)=>{
|
|
|
83
83
|
return pipe(map('attributes'), flatMap(values), // @ts-expect-error lodash types
|
|
84
84
|
sumBy(propEq('type', 'dynamiczone')))(strapi.contentTypes);
|
|
85
85
|
};
|
|
86
|
+
const getNumberOfFolders = async ()=>{
|
|
87
|
+
try {
|
|
88
|
+
const contentStructure = strapi.get('content-structure');
|
|
89
|
+
return await contentStructure?.countGroups?.() ?? 0;
|
|
90
|
+
} catch {
|
|
91
|
+
return 0;
|
|
92
|
+
}
|
|
93
|
+
};
|
|
86
94
|
return {
|
|
87
95
|
data: {
|
|
88
96
|
useTypescriptOnServer,
|
|
@@ -90,7 +98,8 @@ const isUsingTypeScript = (...args)=>{
|
|
|
90
98
|
isHostedOnStrapiCloud,
|
|
91
99
|
numberOfAllContentTypes,
|
|
92
100
|
numberOfComponents,
|
|
93
|
-
numberOfDynamicZones: getNumberOfDynamicZones()
|
|
101
|
+
numberOfDynamicZones: getNumberOfDynamicZones(),
|
|
102
|
+
numberOfContentTypeFolders: await getNumberOfFolders()
|
|
94
103
|
}
|
|
95
104
|
};
|
|
96
105
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"admin.mjs","sources":["../../../../../server/src/controllers/admin.ts"],"sourcesContent":["import type { Context } from 'koa';\n\nimport path from 'path';\n\nimport { map, values, sumBy, pipe, flatMap, propEq } from 'lodash/fp';\nimport _ from 'lodash';\nimport { exists } from 'fs-extra';\nimport { env } from '@strapi/utils';\nimport {\n validateUpdateProjectSettings,\n validateUpdateProjectSettingsFiles,\n validateUpdateProjectSettingsImagesDimensions,\n} from '../validation/project-settings';\nimport { getService } from '../utils';\n\nimport type {\n Init,\n GetProjectSettings,\n Information,\n Plugins,\n TelemetryProperties,\n UpdateProjectSettings,\n GetGuidedTourMeta,\n} from '../../../shared/contracts/admin';\n\n// Lazy: only resolved on first GET /admin/project-type request\ntype TsUtilsModule = typeof import('@strapi/typescript-utils');\nlet lazyTsUtils: TsUtilsModule | undefined;\nconst isUsingTypeScript: TsUtilsModule['isUsingTypeScript'] = (\n ...args: Parameters<TsUtilsModule['isUsingTypeScript']>\n) => {\n if (!lazyTsUtils) {\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n lazyTsUtils = require('@strapi/typescript-utils');\n }\n return (lazyTsUtils as TsUtilsModule).isUsingTypeScript(...args);\n};\n\n/**\n * A set of functions called \"actions\" for `Admin`\n */\nexport default {\n // TODO very temporary to check the switch ee/ce\n // When removing this we need to update the /admin/src/index.js file\n // whe,re we set the strapi.window.isEE value\n\n // NOTE: admin/ee/server overrides this controller, and adds the EE features\n // This returns an empty feature list for CE\n async getProjectType() {\n const flags = strapi.config.get('admin.flags', {});\n return { data: { isEE: false, features: [], flags, ai: { enabled: false } } };\n },\n\n async init() {\n let uuid = strapi.config.get('uuid', false);\n const hasAdmin = await getService('user').exists();\n const { menuLogo, authLogo } = await getService('project-settings').getProjectSettings();\n // set to null if telemetryDisabled flag not avaialble in package.json\n const telemetryDisabled: boolean | null = strapi.config.get(\n 'packageJsonStrapi.telemetryDisabled',\n null\n );\n\n if (telemetryDisabled !== null && telemetryDisabled === true) {\n uuid = false;\n }\n\n return {\n data: {\n uuid,\n hasAdmin,\n menuLogo: menuLogo ? menuLogo.url : null,\n authLogo: authLogo ? authLogo.url : null,\n },\n } satisfies Init.Response;\n },\n\n async getProjectSettings() {\n return getService(\n 'project-settings'\n ).getProjectSettings() satisfies Promise<GetProjectSettings.Response>;\n },\n\n async updateProjectSettings(ctx: Context) {\n const {\n request: { files, body },\n } = ctx as { request: UpdateProjectSettings.Request };\n\n const projectSettingsService = getService('project-settings');\n\n await validateUpdateProjectSettings(body);\n await validateUpdateProjectSettingsFiles(files);\n\n const formatedFiles = await projectSettingsService.parseFilesData(files);\n await validateUpdateProjectSettingsImagesDimensions(formatedFiles);\n\n return projectSettingsService.updateProjectSettings({\n ...body,\n ...formatedFiles,\n }) satisfies Promise<UpdateProjectSettings.Response>;\n },\n\n async telemetryProperties(ctx: Context) {\n // If the telemetry is disabled, ignore the request and return early\n if (strapi.telemetry.isDisabled) {\n ctx.status = 204;\n return;\n }\n\n const useTypescriptOnServer = await isUsingTypeScript(strapi.dirs.app.root);\n const useTypescriptOnAdmin = await isUsingTypeScript(\n path.join(strapi.dirs.app.root, 'src', 'admin')\n );\n const isHostedOnStrapiCloud = env('STRAPI_HOSTING', null) === 'strapi.cloud';\n\n const numberOfAllContentTypes = _.size(strapi.contentTypes);\n const numberOfComponents = _.size(strapi.components);\n\n const getNumberOfDynamicZones = () => {\n return pipe(\n map('attributes'),\n flatMap(values),\n // @ts-expect-error lodash types\n sumBy(propEq('type', 'dynamiczone'))\n )(strapi.contentTypes as any);\n };\n\n return {\n data: {\n useTypescriptOnServer,\n useTypescriptOnAdmin,\n isHostedOnStrapiCloud,\n numberOfAllContentTypes, // TODO: V5: This event should be renamed numberOfContentTypes in V5 as the name is already taken to describe the number of content types using i18n.\n numberOfComponents,\n numberOfDynamicZones: getNumberOfDynamicZones(),\n },\n } satisfies TelemetryProperties.Response;\n },\n\n async information() {\n const currentEnvironment: string = strapi.config.get('environment');\n const autoReload = strapi.config.get('autoReload', false);\n const strapiVersion = strapi.config.get('info.strapi', null);\n const dependencies = strapi.config.get('info.dependencies', {});\n const projectId = strapi.config.get('uuid', null);\n const nodeVersion = process.version;\n const communityEdition = !strapi.EE;\n const useYarn: boolean = await exists(path.join(process.cwd(), 'yarn.lock'));\n\n return {\n data: {\n currentEnvironment,\n autoReload,\n strapiVersion,\n dependencies,\n projectId,\n nodeVersion,\n communityEdition,\n useYarn,\n },\n } satisfies Information.Response;\n },\n\n async plugins(ctx: Context) {\n const enabledPlugins = strapi.config.get('enabledPlugins') as any;\n\n // List of core plugins that are always enabled,\n // and so it's not necessary to display them in the plugins list\n const CORE_PLUGINS = [\n 'content-manager',\n 'content-type-builder',\n 'email',\n 'upload',\n 'i18n',\n 'content-releases',\n 'review-workflows',\n ];\n\n const plugins = Object.entries(enabledPlugins)\n .filter(([key]: any) => !CORE_PLUGINS.includes(key))\n .map(([key, plugin]: any) => ({\n name: plugin.info.name || key,\n displayName: plugin.info.displayName || plugin.info.name || key,\n description: plugin.info.description || '',\n packageName: plugin.info.packageName,\n }));\n\n ctx.send({ plugins } satisfies Plugins.Response);\n },\n\n async licenseTrialTimeLeft() {\n const data = await strapi.ee.getTrialEndDate({\n strapi,\n });\n\n return data;\n },\n\n async getGuidedTourMeta(ctx: Context) {\n const isFirstSuperAdminUser = await getService('user').isFirstSuperAdminUser(ctx.state.user.id);\n\n return {\n data: {\n isFirstSuperAdminUser,\n schemas: strapi.contentTypes,\n },\n } satisfies GetGuidedTourMeta.Response;\n },\n};\n"],"names":["lazyTsUtils","isUsingTypeScript","args","require","getProjectType","flags","strapi","config","get","data","isEE","features","ai","enabled","init","uuid","hasAdmin","getService","exists","menuLogo","authLogo","getProjectSettings","telemetryDisabled","url","updateProjectSettings","ctx","request","files","body","projectSettingsService","validateUpdateProjectSettings","validateUpdateProjectSettingsFiles","formatedFiles","parseFilesData","validateUpdateProjectSettingsImagesDimensions","telemetryProperties","telemetry","isDisabled","status","useTypescriptOnServer","dirs","app","root","useTypescriptOnAdmin","path","join","isHostedOnStrapiCloud","env","numberOfAllContentTypes","_","size","contentTypes","numberOfComponents","components","getNumberOfDynamicZones","pipe","map","flatMap","values","sumBy","propEq","numberOfDynamicZones","information","currentEnvironment","autoReload","strapiVersion","dependencies","projectId","nodeVersion","process","version","communityEdition","EE","useYarn","cwd","plugins","enabledPlugins","CORE_PLUGINS","Object","entries","filter","key","includes","plugin","name","info","displayName","description","packageName","send","licenseTrialTimeLeft","ee","getTrialEndDate","getGuidedTourMeta","isFirstSuperAdminUser","state","user","id","schemas"],"mappings":";;;;;;;;AA2BA,IAAIA,WAAAA;AACJ,MAAMC,iBAAAA,GAAwD,CAC5D,GAAGC,IAAAA,GAAAA;AAEH,IAAA,IAAI,CAACF,WAAAA,EAAa;;AAEhBA,QAAAA,WAAAA,GAAcG,OAAAA,CAAQ,0BAAA,CAAA;AACxB,IAAA;IACA,OAAQH,WAAAA,CAA8BC,iBAAiB,CAAA,GAAIC,IAAAA,CAAAA;AAC7D,CAAA;AAEA;;AAEC,IACD,YAAe;;;;;;IAOb,MAAME,cAAAA,CAAAA,GAAAA;AACJ,QAAA,MAAMC,QAAQC,MAAAA,CAAOC,MAAM,CAACC,GAAG,CAAC,eAAe,EAAC,CAAA;QAChD,OAAO;YAAEC,IAAAA,EAAM;gBAAEC,IAAAA,EAAM,KAAA;AAAOC,gBAAAA,QAAAA,EAAU,EAAE;AAAEN,gBAAAA,KAAAA;gBAAOO,EAAAA,EAAI;oBAAEC,OAAAA,EAAS;AAAM;AAAE;AAAE,SAAA;AAC9E,IAAA,CAAA;IAEA,MAAMC,IAAAA,CAAAA,GAAAA;AACJ,QAAA,IAAIC,OAAOT,MAAAA,CAAOC,MAAM,CAACC,GAAG,CAAC,MAAA,EAAQ,KAAA,CAAA;AACrC,QAAA,MAAMQ,QAAAA,GAAW,MAAMC,UAAAA,CAAW,MAAA,CAAA,CAAQC,MAAM,EAAA;QAChD,MAAM,EAAEC,QAAQ,EAAEC,QAAQ,EAAE,GAAG,MAAMH,UAAAA,CAAW,kBAAA,CAAA,CAAoBI,kBAAkB,EAAA;;AAEtF,QAAA,MAAMC,oBAAoChB,MAAAA,CAAOC,MAAM,CAACC,GAAG,CACzD,qCAAA,EACA,IAAA,CAAA;QAGF,IAAIc,iBAAAA,KAAsB,IAAA,IAAQA,iBAAAA,KAAsB,IAAA,EAAM;YAC5DP,IAAAA,GAAO,KAAA;AACT,QAAA;QAEA,OAAO;YACLN,IAAAA,EAAM;AACJM,gBAAAA,IAAAA;AACAC,gBAAAA,QAAAA;gBACAG,QAAAA,EAAUA,QAAAA,GAAWA,QAAAA,CAASI,GAAG,GAAG,IAAA;gBACpCH,QAAAA,EAAUA,QAAAA,GAAWA,QAAAA,CAASG,GAAG,GAAG;AACtC;AACF,SAAA;AACF,IAAA,CAAA;IAEA,MAAMF,kBAAAA,CAAAA,GAAAA;QACJ,OAAOJ,UAAAA,CACL,oBACAI,kBAAkB,EAAA;AACtB,IAAA,CAAA;AAEA,IAAA,MAAMG,uBAAsBC,GAAY,EAAA;QACtC,MAAM,EACJC,SAAS,EAAEC,KAAK,EAAEC,IAAI,EAAE,EACzB,GAAGH,GAAAA;AAEJ,QAAA,MAAMI,yBAAyBZ,UAAAA,CAAW,kBAAA,CAAA;AAE1C,QAAA,MAAMa,6BAAAA,CAA8BF,IAAAA,CAAAA;AACpC,QAAA,MAAMG,kCAAAA,CAAmCJ,KAAAA,CAAAA;AAEzC,QAAA,MAAMK,aAAAA,GAAgB,MAAMH,sBAAAA,CAAuBI,cAAc,CAACN,KAAAA,CAAAA;AAClE,QAAA,MAAMO,6CAAAA,CAA8CF,aAAAA,CAAAA;QAEpD,OAAOH,sBAAAA,CAAuBL,qBAAqB,CAAC;AAClD,YAAA,GAAGI,IAAI;AACP,YAAA,GAAGI;AACL,SAAA,CAAA;AACF,IAAA,CAAA;AAEA,IAAA,MAAMG,qBAAoBV,GAAY,EAAA;;AAEpC,QAAA,IAAInB,MAAAA,CAAO8B,SAAS,CAACC,UAAU,EAAE;AAC/BZ,YAAAA,GAAAA,CAAIa,MAAM,GAAG,GAAA;AACb,YAAA;AACF,QAAA;QAEA,MAAMC,qBAAAA,GAAwB,MAAMtC,iBAAAA,CAAkBK,MAAAA,CAAOkC,IAAI,CAACC,GAAG,CAACC,IAAI,CAAA;AAC1E,QAAA,MAAMC,oBAAAA,GAAuB,MAAM1C,iBAAAA,CACjC2C,IAAAA,CAAKC,IAAI,CAACvC,MAAAA,CAAOkC,IAAI,CAACC,GAAG,CAACC,IAAI,EAAE,KAAA,EAAO,OAAA,CAAA,CAAA;QAEzC,MAAMI,qBAAAA,GAAwBC,GAAAA,CAAI,gBAAA,EAAkB,IAAA,CAAA,KAAU,cAAA;AAE9D,QAAA,MAAMC,uBAAAA,GAA0BC,UAAAA,CAAEC,IAAI,CAAC5C,OAAO6C,YAAY,CAAA;AAC1D,QAAA,MAAMC,kBAAAA,GAAqBH,UAAAA,CAAEC,IAAI,CAAC5C,OAAO+C,UAAU,CAAA;AAEnD,QAAA,MAAMC,uBAAAA,GAA0B,IAAA;AAC9B,YAAA,OAAOC,IAAAA,CACLC,GAAAA,CAAI,YAAA,CAAA,EACJC,OAAAA,CAAQC;AAERC,YAAAA,KAAAA,CAAMC,MAAAA,CAAO,MAAA,EAAQ,aAAA,CAAA,CAAA,CAAA,CACrBtD,MAAAA,CAAO6C,YAAY,CAAA;AACvB,QAAA,CAAA;QAEA,OAAO;YACL1C,IAAAA,EAAM;AACJ8B,gBAAAA,qBAAAA;AACAI,gBAAAA,oBAAAA;AACAG,gBAAAA,qBAAAA;AACAE,gBAAAA,uBAAAA;AACAI,gBAAAA,kBAAAA;gBACAS,oBAAAA,EAAsBP,uBAAAA;AACxB;AACF,SAAA;AACF,IAAA,CAAA;IAEA,MAAMQ,WAAAA,CAAAA,GAAAA;AACJ,QAAA,MAAMC,kBAAAA,GAA6BzD,MAAAA,CAAOC,MAAM,CAACC,GAAG,CAAC,aAAA,CAAA;AACrD,QAAA,MAAMwD,aAAa1D,MAAAA,CAAOC,MAAM,CAACC,GAAG,CAAC,YAAA,EAAc,KAAA,CAAA;AACnD,QAAA,MAAMyD,gBAAgB3D,MAAAA,CAAOC,MAAM,CAACC,GAAG,CAAC,aAAA,EAAe,IAAA,CAAA;AACvD,QAAA,MAAM0D,eAAe5D,MAAAA,CAAOC,MAAM,CAACC,GAAG,CAAC,qBAAqB,EAAC,CAAA;AAC7D,QAAA,MAAM2D,YAAY7D,MAAAA,CAAOC,MAAM,CAACC,GAAG,CAAC,MAAA,EAAQ,IAAA,CAAA;QAC5C,MAAM4D,WAAAA,GAAcC,QAAQC,OAAO;QACnC,MAAMC,gBAAAA,GAAmB,CAACjE,MAAAA,CAAOkE,EAAE;QACnC,MAAMC,OAAAA,GAAmB,MAAMvD,MAAAA,CAAO0B,IAAAA,CAAKC,IAAI,CAACwB,OAAAA,CAAQK,GAAG,EAAA,EAAI,WAAA,CAAA,CAAA;QAE/D,OAAO;YACLjE,IAAAA,EAAM;AACJsD,gBAAAA,kBAAAA;AACAC,gBAAAA,UAAAA;AACAC,gBAAAA,aAAAA;AACAC,gBAAAA,YAAAA;AACAC,gBAAAA,SAAAA;AACAC,gBAAAA,WAAAA;AACAG,gBAAAA,gBAAAA;AACAE,gBAAAA;AACF;AACF,SAAA;AACF,IAAA,CAAA;AAEA,IAAA,MAAME,SAAQlD,GAAY,EAAA;AACxB,QAAA,MAAMmD,cAAAA,GAAiBtE,MAAAA,CAAOC,MAAM,CAACC,GAAG,CAAC,gBAAA,CAAA;;;AAIzC,QAAA,MAAMqE,YAAAA,GAAe;AACnB,YAAA,iBAAA;AACA,YAAA,sBAAA;AACA,YAAA,OAAA;AACA,YAAA,QAAA;AACA,YAAA,MAAA;AACA,YAAA,kBAAA;AACA,YAAA;AACD,SAAA;QAED,MAAMF,OAAAA,GAAUG,OAAOC,OAAO,CAACH,gBAC5BI,MAAM,CAAC,CAAC,CAACC,GAAAA,CAAS,GAAK,CAACJ,YAAAA,CAAaK,QAAQ,CAACD,GAAAA,CAAAA,CAAAA,CAC9CzB,GAAG,CAAC,CAAC,CAACyB,GAAAA,EAAKE,MAAAA,CAAY,IAAM;AAC5BC,gBAAAA,IAAAA,EAAMD,MAAAA,CAAOE,IAAI,CAACD,IAAI,IAAIH,GAAAA;gBAC1BK,WAAAA,EAAaH,MAAAA,CAAOE,IAAI,CAACC,WAAW,IAAIH,MAAAA,CAAOE,IAAI,CAACD,IAAI,IAAIH,GAAAA;AAC5DM,gBAAAA,WAAAA,EAAaJ,MAAAA,CAAOE,IAAI,CAACE,WAAW,IAAI,EAAA;gBACxCC,WAAAA,EAAaL,MAAAA,CAAOE,IAAI,CAACG;aAC3B,CAAA,CAAA;AAEF/D,QAAAA,GAAAA,CAAIgE,IAAI,CAAC;AAAEd,YAAAA;AAAQ,SAAA,CAAA;AACrB,IAAA,CAAA;IAEA,MAAMe,oBAAAA,CAAAA,GAAAA;AACJ,QAAA,MAAMjF,OAAO,MAAMH,MAAAA,CAAOqF,EAAE,CAACC,eAAe,CAAC;AAC3CtF,YAAAA;AACF,SAAA,CAAA;QAEA,OAAOG,IAAAA;AACT,IAAA,CAAA;AAEA,IAAA,MAAMoF,mBAAkBpE,GAAY,EAAA;QAClC,MAAMqE,qBAAAA,GAAwB,MAAM7E,UAAAA,CAAW,MAAA,CAAA,CAAQ6E,qBAAqB,CAACrE,GAAAA,CAAIsE,KAAK,CAACC,IAAI,CAACC,EAAE,CAAA;QAE9F,OAAO;YACLxF,IAAAA,EAAM;AACJqF,gBAAAA,qBAAAA;AACAI,gBAAAA,OAAAA,EAAS5F,OAAO6C;AAClB;AACF,SAAA;AACF,IAAA;AACF,CAAA;;;;"}
|
|
1
|
+
{"version":3,"file":"admin.mjs","sources":["../../../../../server/src/controllers/admin.ts"],"sourcesContent":["import type { Context } from 'koa';\n\nimport path from 'path';\n\nimport { map, values, sumBy, pipe, flatMap, propEq } from 'lodash/fp';\nimport _ from 'lodash';\nimport { exists } from 'fs-extra';\nimport { env } from '@strapi/utils';\nimport {\n validateUpdateProjectSettings,\n validateUpdateProjectSettingsFiles,\n validateUpdateProjectSettingsImagesDimensions,\n} from '../validation/project-settings';\nimport { getService } from '../utils';\n\nimport type {\n Init,\n GetProjectSettings,\n Information,\n Plugins,\n TelemetryProperties,\n UpdateProjectSettings,\n GetGuidedTourMeta,\n} from '../../../shared/contracts/admin';\n\n// Lazy: only resolved on first GET /admin/project-type request\ntype TsUtilsModule = typeof import('@strapi/typescript-utils');\nlet lazyTsUtils: TsUtilsModule | undefined;\nconst isUsingTypeScript: TsUtilsModule['isUsingTypeScript'] = (\n ...args: Parameters<TsUtilsModule['isUsingTypeScript']>\n) => {\n if (!lazyTsUtils) {\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n lazyTsUtils = require('@strapi/typescript-utils');\n }\n return (lazyTsUtils as TsUtilsModule).isUsingTypeScript(...args);\n};\n\n/**\n * A set of functions called \"actions\" for `Admin`\n */\nexport default {\n // TODO very temporary to check the switch ee/ce\n // When removing this we need to update the /admin/src/index.js file\n // whe,re we set the strapi.window.isEE value\n\n // NOTE: admin/ee/server overrides this controller, and adds the EE features\n // This returns an empty feature list for CE\n async getProjectType() {\n const flags = strapi.config.get('admin.flags', {});\n return { data: { isEE: false, features: [], flags, ai: { enabled: false } } };\n },\n\n async init() {\n let uuid = strapi.config.get('uuid', false);\n const hasAdmin = await getService('user').exists();\n const { menuLogo, authLogo } = await getService('project-settings').getProjectSettings();\n // set to null if telemetryDisabled flag not avaialble in package.json\n const telemetryDisabled: boolean | null = strapi.config.get(\n 'packageJsonStrapi.telemetryDisabled',\n null\n );\n\n if (telemetryDisabled !== null && telemetryDisabled === true) {\n uuid = false;\n }\n\n return {\n data: {\n uuid,\n hasAdmin,\n menuLogo: menuLogo ? menuLogo.url : null,\n authLogo: authLogo ? authLogo.url : null,\n },\n } satisfies Init.Response;\n },\n\n async getProjectSettings() {\n return getService(\n 'project-settings'\n ).getProjectSettings() satisfies Promise<GetProjectSettings.Response>;\n },\n\n async updateProjectSettings(ctx: Context) {\n const {\n request: { files, body },\n } = ctx as { request: UpdateProjectSettings.Request };\n\n const projectSettingsService = getService('project-settings');\n\n await validateUpdateProjectSettings(body);\n await validateUpdateProjectSettingsFiles(files);\n\n const formatedFiles = await projectSettingsService.parseFilesData(files);\n await validateUpdateProjectSettingsImagesDimensions(formatedFiles);\n\n return projectSettingsService.updateProjectSettings({\n ...body,\n ...formatedFiles,\n }) satisfies Promise<UpdateProjectSettings.Response>;\n },\n\n async telemetryProperties(ctx: Context) {\n // If the telemetry is disabled, ignore the request and return early\n if (strapi.telemetry.isDisabled) {\n ctx.status = 204;\n return;\n }\n\n const useTypescriptOnServer = await isUsingTypeScript(strapi.dirs.app.root);\n const useTypescriptOnAdmin = await isUsingTypeScript(\n path.join(strapi.dirs.app.root, 'src', 'admin')\n );\n const isHostedOnStrapiCloud = env('STRAPI_HOSTING', null) === 'strapi.cloud';\n\n const numberOfAllContentTypes = _.size(strapi.contentTypes);\n const numberOfComponents = _.size(strapi.components);\n\n const getNumberOfDynamicZones = () => {\n return pipe(\n map('attributes'),\n flatMap(values),\n // @ts-expect-error lodash types\n sumBy(propEq('type', 'dynamiczone'))\n )(strapi.contentTypes as any);\n };\n\n const getNumberOfFolders = async (): Promise<number> => {\n try {\n const contentStructure = strapi.get('content-structure') as\n | { countGroups?: () => Promise<number> }\n | undefined;\n\n return (await contentStructure?.countGroups?.()) ?? 0;\n } catch {\n return 0;\n }\n };\n\n return {\n data: {\n useTypescriptOnServer,\n useTypescriptOnAdmin,\n isHostedOnStrapiCloud,\n numberOfAllContentTypes, // TODO: V5: This event should be renamed numberOfContentTypes in V5 as the name is already taken to describe the number of content types using i18n.\n numberOfComponents,\n numberOfDynamicZones: getNumberOfDynamicZones(),\n numberOfContentTypeFolders: await getNumberOfFolders(),\n },\n } satisfies TelemetryProperties.Response;\n },\n\n async information() {\n const currentEnvironment: string = strapi.config.get('environment');\n const autoReload = strapi.config.get('autoReload', false);\n const strapiVersion = strapi.config.get('info.strapi', null);\n const dependencies = strapi.config.get('info.dependencies', {});\n const projectId = strapi.config.get('uuid', null);\n const nodeVersion = process.version;\n const communityEdition = !strapi.EE;\n const useYarn: boolean = await exists(path.join(process.cwd(), 'yarn.lock'));\n\n return {\n data: {\n currentEnvironment,\n autoReload,\n strapiVersion,\n dependencies,\n projectId,\n nodeVersion,\n communityEdition,\n useYarn,\n },\n } satisfies Information.Response;\n },\n\n async plugins(ctx: Context) {\n const enabledPlugins = strapi.config.get('enabledPlugins') as any;\n\n // List of core plugins that are always enabled,\n // and so it's not necessary to display them in the plugins list\n const CORE_PLUGINS = [\n 'content-manager',\n 'content-type-builder',\n 'email',\n 'upload',\n 'i18n',\n 'content-releases',\n 'review-workflows',\n ];\n\n const plugins = Object.entries(enabledPlugins)\n .filter(([key]: any) => !CORE_PLUGINS.includes(key))\n .map(([key, plugin]: any) => ({\n name: plugin.info.name || key,\n displayName: plugin.info.displayName || plugin.info.name || key,\n description: plugin.info.description || '',\n packageName: plugin.info.packageName,\n }));\n\n ctx.send({ plugins } satisfies Plugins.Response);\n },\n\n async licenseTrialTimeLeft() {\n const data = await strapi.ee.getTrialEndDate({\n strapi,\n });\n\n return data;\n },\n\n async getGuidedTourMeta(ctx: Context) {\n const isFirstSuperAdminUser = await getService('user').isFirstSuperAdminUser(ctx.state.user.id);\n\n return {\n data: {\n isFirstSuperAdminUser,\n schemas: strapi.contentTypes,\n },\n } satisfies GetGuidedTourMeta.Response;\n },\n};\n"],"names":["lazyTsUtils","isUsingTypeScript","args","require","getProjectType","flags","strapi","config","get","data","isEE","features","ai","enabled","init","uuid","hasAdmin","getService","exists","menuLogo","authLogo","getProjectSettings","telemetryDisabled","url","updateProjectSettings","ctx","request","files","body","projectSettingsService","validateUpdateProjectSettings","validateUpdateProjectSettingsFiles","formatedFiles","parseFilesData","validateUpdateProjectSettingsImagesDimensions","telemetryProperties","telemetry","isDisabled","status","useTypescriptOnServer","dirs","app","root","useTypescriptOnAdmin","path","join","isHostedOnStrapiCloud","env","numberOfAllContentTypes","_","size","contentTypes","numberOfComponents","components","getNumberOfDynamicZones","pipe","map","flatMap","values","sumBy","propEq","getNumberOfFolders","contentStructure","countGroups","numberOfDynamicZones","numberOfContentTypeFolders","information","currentEnvironment","autoReload","strapiVersion","dependencies","projectId","nodeVersion","process","version","communityEdition","EE","useYarn","cwd","plugins","enabledPlugins","CORE_PLUGINS","Object","entries","filter","key","includes","plugin","name","info","displayName","description","packageName","send","licenseTrialTimeLeft","ee","getTrialEndDate","getGuidedTourMeta","isFirstSuperAdminUser","state","user","id","schemas"],"mappings":"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"}
|