@strapi/admin 5.56.0 → 5.58.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/Filters.js +1 -1
- package/dist/admin/admin/src/components/Filters.js.map +1 -1
- package/dist/admin/admin/src/components/Filters.mjs +1 -1
- package/dist/admin/admin/src/components/Filters.mjs.map +1 -1
- package/dist/admin/admin/src/components/FormInputs/Boolean.js +3 -2
- package/dist/admin/admin/src/components/FormInputs/Boolean.js.map +1 -1
- package/dist/admin/admin/src/components/FormInputs/Boolean.mjs +3 -2
- package/dist/admin/admin/src/components/FormInputs/Boolean.mjs.map +1 -1
- package/dist/admin/admin/src/components/FormInputs/Enumeration.js +2 -2
- package/dist/admin/admin/src/components/FormInputs/Enumeration.js.map +1 -1
- package/dist/admin/admin/src/components/FormInputs/Enumeration.mjs +2 -2
- package/dist/admin/admin/src/components/FormInputs/Enumeration.mjs.map +1 -1
- package/dist/admin/admin/src/components/MediaLibraryBanner.js +38 -2
- package/dist/admin/admin/src/components/MediaLibraryBanner.js.map +1 -1
- package/dist/admin/admin/src/components/MediaLibraryBanner.mjs +18 -2
- package/dist/admin/admin/src/components/MediaLibraryBanner.mjs.map +1 -1
- package/dist/admin/admin/src/components/RelativeTime.js +9 -0
- package/dist/admin/admin/src/components/RelativeTime.js.map +1 -1
- package/dist/admin/admin/src/components/RelativeTime.mjs +10 -1
- package/dist/admin/admin/src/components/RelativeTime.mjs.map +1 -1
- package/dist/admin/admin/src/components/TopBanners.js +52 -0
- package/dist/admin/admin/src/components/TopBanners.js.map +1 -0
- package/dist/admin/admin/src/components/TopBanners.mjs +30 -0
- package/dist/admin/admin/src/components/TopBanners.mjs.map +1 -0
- package/dist/admin/admin/src/constants.js +14 -0
- package/dist/admin/admin/src/constants.js.map +1 -1
- package/dist/admin/admin/src/constants.mjs +14 -0
- package/dist/admin/admin/src/constants.mjs.map +1 -1
- package/dist/admin/admin/src/features/Tracking.js +28 -8
- package/dist/admin/admin/src/features/Tracking.js.map +1 -1
- package/dist/admin/admin/src/features/Tracking.mjs +29 -10
- package/dist/admin/admin/src/features/Tracking.mjs.map +1 -1
- package/dist/admin/admin/src/layouts/AuthenticatedLayout.js +4 -20
- package/dist/admin/admin/src/layouts/AuthenticatedLayout.js.map +1 -1
- package/dist/admin/admin/src/layouts/AuthenticatedLayout.mjs +4 -20
- package/dist/admin/admin/src/layouts/AuthenticatedLayout.mjs.map +1 -1
- package/dist/admin/admin/src/layouts/useAuthenticatedAccessTracking.js +59 -0
- package/dist/admin/admin/src/layouts/useAuthenticatedAccessTracking.js.map +1 -0
- package/dist/admin/admin/src/layouts/useAuthenticatedAccessTracking.mjs +37 -0
- package/dist/admin/admin/src/layouts/useAuthenticatedAccessTracking.mjs.map +1 -0
- package/dist/admin/admin/src/pages/Auth/components/ResetPassword.js +6 -12
- package/dist/admin/admin/src/pages/Auth/components/ResetPassword.js.map +1 -1
- package/dist/admin/admin/src/pages/Auth/components/ResetPassword.mjs +6 -12
- package/dist/admin/admin/src/pages/Auth/components/ResetPassword.mjs.map +1 -1
- package/dist/admin/admin/src/pages/Settings/components/SettingsNav.js +10 -2
- package/dist/admin/admin/src/pages/Settings/components/SettingsNav.js.map +1 -1
- package/dist/admin/admin/src/pages/Settings/components/SettingsNav.mjs +10 -2
- package/dist/admin/admin/src/pages/Settings/components/SettingsNav.mjs.map +1 -1
- package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/ApplicationInfoPage.js +6 -56
- package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/ApplicationInfoPage.js.map +1 -1
- package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/ApplicationInfoPage.mjs +6 -56
- package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/ApplicationInfoPage.mjs.map +1 -1
- package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/components/DiagnosticSnapshotModal.js +217 -0
- package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/components/DiagnosticSnapshotModal.js.map +1 -0
- package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/components/DiagnosticSnapshotModal.mjs +195 -0
- package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/components/DiagnosticSnapshotModal.mjs.map +1 -0
- package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/components/PlanCard.js +185 -0
- package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/components/PlanCard.js.map +1 -0
- package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/components/PlanCard.mjs +162 -0
- package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/components/PlanCard.mjs.map +1 -0
- package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/components/SupportCard.js +342 -0
- package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/components/SupportCard.js.map +1 -0
- package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/components/SupportCard.mjs +320 -0
- package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/components/SupportCard.mjs.map +1 -0
- package/dist/admin/admin/src/services/admin.js +11 -1
- package/dist/admin/admin/src/services/admin.js.map +1 -1
- package/dist/admin/admin/src/services/admin.mjs +11 -2
- package/dist/admin/admin/src/services/admin.mjs.map +1 -1
- package/dist/admin/admin/src/translations/en.json.js +76 -4
- package/dist/admin/admin/src/translations/en.json.js.map +1 -1
- package/dist/admin/admin/src/translations/en.json.mjs +76 -4
- package/dist/admin/admin/src/translations/en.json.mjs.map +1 -1
- package/dist/admin/admin/src/utils/browserStrapi.js +1 -1
- package/dist/admin/admin/src/utils/browserStrapi.js.map +1 -1
- package/dist/admin/admin/src/utils/browserStrapi.mjs +1 -1
- package/dist/admin/admin/src/utils/browserStrapi.mjs.map +1 -1
- package/dist/admin/admin/src/utils/getFetchClient.js +27 -3
- package/dist/admin/admin/src/utils/getFetchClient.js.map +1 -1
- package/dist/admin/admin/src/utils/getFetchClient.mjs +26 -3
- package/dist/admin/admin/src/utils/getFetchClient.mjs.map +1 -1
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/ApplicationInfoPage/components/AIUsage.js +52 -22
- 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 +53 -23
- 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/ApplicationInfoPage/components/AdminSeatInfo.js +16 -29
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/ApplicationInfoPage/components/AdminSeatInfo.js.map +1 -1
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/ApplicationInfoPage/components/AdminSeatInfo.mjs +18 -31
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/ApplicationInfoPage/components/AdminSeatInfo.mjs.map +1 -1
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/ApplicationInfoPage/components/LicenseInfo.js +473 -0
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/ApplicationInfoPage/components/LicenseInfo.js.map +1 -0
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/ApplicationInfoPage/components/LicenseInfo.mjs +471 -0
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/ApplicationInfoPage/components/LicenseInfo.mjs.map +1 -0
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/utils/getActionTypesDefaultMessages.js +8 -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 +8 -1
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/utils/getActionTypesDefaultMessages.mjs.map +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/shared/utils/get-project-type.js +49 -0
- package/dist/admin/shared/utils/get-project-type.js.map +1 -0
- package/dist/admin/shared/utils/get-project-type.mjs +46 -0
- package/dist/admin/shared/utils/get-project-type.mjs.map +1 -0
- package/dist/admin/src/components/MediaLibraryBanner.d.ts +10 -1
- package/dist/admin/src/components/TopBanners.d.ts +8 -0
- package/dist/admin/src/constants.d.ts +10 -0
- package/dist/admin/src/features/Tracking.d.ts +12 -1
- package/dist/admin/src/layouts/useAuthenticatedAccessTracking.d.ts +6 -0
- package/dist/admin/src/pages/Settings/pages/ApplicationInfo/ApplicationInfoPage.d.ts +1 -1
- package/dist/admin/src/pages/Settings/pages/ApplicationInfo/components/DiagnosticSnapshotModal.d.ts +12 -0
- package/dist/admin/src/pages/Settings/pages/ApplicationInfo/components/PlanCard.d.ts +14 -0
- package/dist/admin/src/pages/Settings/pages/ApplicationInfo/components/SupportCard.d.ts +2 -0
- package/dist/admin/src/services/admin.d.ts +2 -2
- package/dist/admin/src/types/permissions.d.ts +1 -0
- package/dist/admin/src/utils/getFetchClient.d.ts +25 -0
- package/dist/ee/admin/src/hooks/useLicenseLimits.d.ts +29 -0
- package/dist/ee/admin/src/pages/SettingsPage/pages/ApplicationInfoPage/components/AIUsage.d.ts +6 -1
- package/dist/ee/admin/src/pages/SettingsPage/pages/ApplicationInfoPage/components/LicenseInfo.d.ts +2 -0
- package/dist/ee/admin/src/pages/SettingsPage/pages/AuditLogs/utils/getActionTypesDefaultMessages.d.ts +7 -0
- package/dist/ee/server/src/audit-logs/entitlements.d.ts +8 -0
- package/dist/ee/server/src/audit-logs/entitlements.d.ts.map +1 -0
- package/dist/ee/server/src/audit-logs/services/lifecycles.d.ts +16 -0
- package/dist/ee/server/src/audit-logs/services/lifecycles.d.ts.map +1 -1
- package/dist/ee/server/src/controllers/admin.d.ts +36 -10
- package/dist/ee/server/src/controllers/admin.d.ts.map +1 -1
- package/dist/ee/server/src/controllers/authentication-utils/middlewares.d.ts.map +1 -1
- package/dist/ee/server/src/controllers/authentication-utils/utils.d.ts +8 -2
- package/dist/ee/server/src/controllers/authentication-utils/utils.d.ts.map +1 -1
- package/dist/ee/server/src/controllers/authentication.d.ts.map +1 -1
- package/dist/ee/server/src/controllers/index.d.ts +36 -10
- package/dist/ee/server/src/controllers/index.d.ts.map +1 -1
- package/dist/ee/server/src/controllers/user.d.ts.map +1 -1
- package/dist/ee/server/src/index.d.ts +40 -11
- package/dist/ee/server/src/index.d.ts.map +1 -1
- package/dist/ee/server/src/services/index.d.ts +4 -1
- package/dist/ee/server/src/services/index.d.ts.map +1 -1
- package/dist/ee/server/src/services/metrics.d.ts.map +1 -1
- package/dist/ee/server/src/services/persist-tables.d.ts.map +1 -1
- package/dist/ee/server/src/services/seat-enforcement.d.ts +3 -1
- package/dist/ee/server/src/services/seat-enforcement.d.ts.map +1 -1
- package/dist/server/ee/server/src/audit-logs/entitlements.js +25 -0
- package/dist/server/ee/server/src/audit-logs/entitlements.js.map +1 -0
- package/dist/server/ee/server/src/audit-logs/entitlements.mjs +23 -0
- package/dist/server/ee/server/src/audit-logs/entitlements.mjs.map +1 -0
- package/dist/server/ee/server/src/audit-logs/services/lifecycles.js +20 -8
- 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 +19 -9
- package/dist/server/ee/server/src/audit-logs/services/lifecycles.mjs.map +1 -1
- package/dist/server/ee/server/src/controllers/admin.js +79 -7
- package/dist/server/ee/server/src/controllers/admin.js.map +1 -1
- package/dist/server/ee/server/src/controllers/admin.mjs +79 -7
- package/dist/server/ee/server/src/controllers/admin.mjs.map +1 -1
- package/dist/server/ee/server/src/controllers/authentication-utils/middlewares.js +28 -10
- package/dist/server/ee/server/src/controllers/authentication-utils/middlewares.js.map +1 -1
- package/dist/server/ee/server/src/controllers/authentication-utils/middlewares.mjs +28 -10
- package/dist/server/ee/server/src/controllers/authentication-utils/middlewares.mjs.map +1 -1
- package/dist/server/ee/server/src/controllers/authentication-utils/utils.js +2 -2
- package/dist/server/ee/server/src/controllers/authentication-utils/utils.js.map +1 -1
- package/dist/server/ee/server/src/controllers/authentication-utils/utils.mjs +2 -2
- package/dist/server/ee/server/src/controllers/authentication-utils/utils.mjs.map +1 -1
- package/dist/server/ee/server/src/controllers/authentication.js +11 -11
- package/dist/server/ee/server/src/controllers/authentication.js.map +1 -1
- package/dist/server/ee/server/src/controllers/authentication.mjs +11 -11
- package/dist/server/ee/server/src/controllers/authentication.mjs.map +1 -1
- package/dist/server/ee/server/src/controllers/user.js +7 -8
- package/dist/server/ee/server/src/controllers/user.js.map +1 -1
- package/dist/server/ee/server/src/controllers/user.mjs +8 -9
- package/dist/server/ee/server/src/controllers/user.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/ee/server/src/services/metrics.js +9 -7
- package/dist/server/ee/server/src/services/metrics.js.map +1 -1
- package/dist/server/ee/server/src/services/metrics.mjs +9 -7
- package/dist/server/ee/server/src/services/metrics.mjs.map +1 -1
- package/dist/server/ee/server/src/services/persist-tables.js +3 -4
- package/dist/server/ee/server/src/services/persist-tables.js.map +1 -1
- package/dist/server/ee/server/src/services/persist-tables.mjs +3 -4
- package/dist/server/ee/server/src/services/persist-tables.mjs.map +1 -1
- package/dist/server/ee/server/src/services/role.js +2 -2
- package/dist/server/ee/server/src/services/role.js.map +1 -1
- package/dist/server/ee/server/src/services/role.mjs +1 -1
- package/dist/server/ee/server/src/services/role.mjs.map +1 -1
- package/dist/server/ee/server/src/services/seat-enforcement.js +20 -20
- package/dist/server/ee/server/src/services/seat-enforcement.js.map +1 -1
- package/dist/server/ee/server/src/services/seat-enforcement.mjs +20 -20
- package/dist/server/ee/server/src/services/seat-enforcement.mjs.map +1 -1
- package/dist/server/ee/server/src/services/user.js +1 -2
- package/dist/server/ee/server/src/services/user.js.map +1 -1
- package/dist/server/ee/server/src/services/user.mjs +2 -3
- package/dist/server/ee/server/src/services/user.mjs.map +1 -1
- package/dist/server/ee/server/src/utils/sso-lock.js +2 -2
- package/dist/server/ee/server/src/utils/sso-lock.js.map +1 -1
- package/dist/server/ee/server/src/utils/sso-lock.mjs +1 -1
- package/dist/server/ee/server/src/utils/sso-lock.mjs.map +1 -1
- package/dist/server/server/src/audit-logs/admin-users.js +3 -3
- package/dist/server/server/src/audit-logs/admin-users.js.map +1 -1
- package/dist/server/server/src/audit-logs/admin-users.mjs +2 -2
- package/dist/server/server/src/audit-logs/admin-users.mjs.map +1 -1
- package/dist/server/server/src/audit-logs/auth.js +72 -0
- package/dist/server/server/src/audit-logs/auth.js.map +1 -0
- package/dist/server/server/src/audit-logs/auth.mjs +67 -0
- package/dist/server/server/src/audit-logs/auth.mjs.map +1 -0
- package/dist/server/server/src/audit-logs/tokens.js +3 -3
- package/dist/server/server/src/audit-logs/tokens.js.map +1 -1
- package/dist/server/server/src/audit-logs/tokens.mjs +2 -2
- package/dist/server/server/src/audit-logs/tokens.mjs.map +1 -1
- package/dist/server/server/src/audit-logs/webhooks.js +2 -2
- package/dist/server/server/src/audit-logs/webhooks.js.map +1 -1
- package/dist/server/server/src/audit-logs/webhooks.mjs +1 -1
- package/dist/server/server/src/audit-logs/webhooks.mjs.map +1 -1
- package/dist/server/server/src/bootstrap.js +6 -4
- package/dist/server/server/src/bootstrap.js.map +1 -1
- package/dist/server/server/src/bootstrap.mjs +6 -4
- package/dist/server/server/src/bootstrap.mjs.map +1 -1
- package/dist/server/server/src/config/admin-actions.js +7 -0
- package/dist/server/server/src/config/admin-actions.js.map +1 -1
- package/dist/server/server/src/config/admin-actions.mjs +7 -0
- package/dist/server/server/src/config/admin-actions.mjs.map +1 -1
- package/dist/server/server/src/controllers/admin-token.js +8 -8
- package/dist/server/server/src/controllers/admin-token.js.map +1 -1
- package/dist/server/server/src/controllers/admin-token.mjs +4 -4
- package/dist/server/server/src/controllers/admin-token.mjs.map +1 -1
- package/dist/server/server/src/controllers/admin.js +9 -5
- package/dist/server/server/src/controllers/admin.js.map +1 -1
- package/dist/server/server/src/controllers/admin.mjs +8 -4
- package/dist/server/server/src/controllers/admin.mjs.map +1 -1
- package/dist/server/server/src/controllers/api-token.js +8 -8
- package/dist/server/server/src/controllers/api-token.js.map +1 -1
- package/dist/server/server/src/controllers/api-token.mjs +4 -4
- package/dist/server/server/src/controllers/api-token.mjs.map +1 -1
- package/dist/server/server/src/controllers/authentication.js +34 -8
- package/dist/server/server/src/controllers/authentication.js.map +1 -1
- package/dist/server/server/src/controllers/authentication.mjs +34 -8
- package/dist/server/server/src/controllers/authentication.mjs.map +1 -1
- package/dist/server/server/src/controllers/formatters/conditions.js +2 -2
- package/dist/server/server/src/controllers/formatters/conditions.js.map +1 -1
- package/dist/server/server/src/controllers/formatters/conditions.mjs +2 -2
- package/dist/server/server/src/controllers/formatters/conditions.mjs.map +1 -1
- package/dist/server/server/src/controllers/transfer/index.js +2 -2
- package/dist/server/server/src/controllers/transfer/index.js.map +1 -1
- package/dist/server/server/src/controllers/transfer/index.mjs +2 -2
- package/dist/server/server/src/controllers/transfer/index.mjs.map +1 -1
- package/dist/server/server/src/controllers/transfer/token.js +8 -8
- package/dist/server/server/src/controllers/transfer/token.js.map +1 -1
- package/dist/server/server/src/controllers/transfer/token.mjs +4 -4
- package/dist/server/server/src/controllers/transfer/token.mjs.map +1 -1
- package/dist/server/server/src/domain/action/index.js +18 -16
- package/dist/server/server/src/domain/action/index.js.map +1 -1
- package/dist/server/server/src/domain/action/index.mjs +16 -14
- package/dist/server/server/src/domain/action/index.mjs.map +1 -1
- package/dist/server/server/src/domain/action/provider.mjs +4 -4
- package/dist/server/server/src/domain/action/provider.mjs.map +1 -1
- package/dist/server/server/src/domain/condition/index.js +7 -4
- package/dist/server/server/src/domain/condition/index.js.map +1 -1
- package/dist/server/server/src/domain/condition/index.mjs +7 -4
- package/dist/server/server/src/domain/condition/index.mjs.map +1 -1
- package/dist/server/server/src/domain/permission/index.js +24 -15
- package/dist/server/server/src/domain/permission/index.js.map +1 -1
- package/dist/server/server/src/domain/permission/index.mjs +21 -12
- package/dist/server/server/src/domain/permission/index.mjs.map +1 -1
- package/dist/server/server/src/middlewares/rateLimit.js +5 -5
- package/dist/server/server/src/middlewares/rateLimit.js.map +1 -1
- package/dist/server/server/src/middlewares/rateLimit.mjs +4 -4
- package/dist/server/server/src/middlewares/rateLimit.mjs.map +1 -1
- package/dist/server/server/src/register.js +10 -0
- package/dist/server/server/src/register.js.map +1 -1
- package/dist/server/server/src/register.mjs +10 -0
- package/dist/server/server/src/register.mjs.map +1 -1
- package/dist/server/server/src/routes/admin.js +18 -0
- package/dist/server/server/src/routes/admin.js.map +1 -1
- package/dist/server/server/src/routes/admin.mjs +18 -0
- package/dist/server/server/src/routes/admin.mjs.map +1 -1
- package/dist/server/server/src/services/action.js +1 -2
- package/dist/server/server/src/services/action.js.map +1 -1
- package/dist/server/server/src/services/action.mjs +1 -2
- package/dist/server/server/src/services/action.mjs.map +1 -1
- package/dist/server/server/src/services/api-token.js +61 -49
- package/dist/server/server/src/services/api-token.js.map +1 -1
- package/dist/server/server/src/services/api-token.mjs +53 -41
- package/dist/server/server/src/services/api-token.mjs.map +1 -1
- package/dist/server/server/src/services/auth.js +4 -2
- package/dist/server/server/src/services/auth.js.map +1 -1
- package/dist/server/server/src/services/auth.mjs +4 -3
- package/dist/server/server/src/services/auth.mjs.map +1 -1
- package/dist/server/server/src/services/condition.js +2 -2
- package/dist/server/server/src/services/condition.js.map +1 -1
- package/dist/server/server/src/services/condition.mjs +1 -1
- package/dist/server/server/src/services/condition.mjs.map +1 -1
- package/dist/server/server/src/services/content-type.js +5 -4
- package/dist/server/server/src/services/content-type.js.map +1 -1
- package/dist/server/server/src/services/content-type.mjs +8 -7
- package/dist/server/server/src/services/content-type.mjs.map +1 -1
- package/dist/server/server/src/services/debug-dump.js +173 -0
- package/dist/server/server/src/services/debug-dump.js.map +1 -0
- package/dist/server/server/src/services/debug-dump.mjs +166 -0
- package/dist/server/server/src/services/debug-dump.mjs.map +1 -0
- package/dist/server/server/src/services/homepage.js +2 -1
- package/dist/server/server/src/services/homepage.js.map +1 -1
- package/dist/server/server/src/services/homepage.mjs +2 -1
- package/dist/server/server/src/services/homepage.mjs.map +1 -1
- package/dist/server/server/src/services/index.js +3 -1
- package/dist/server/server/src/services/index.js.map +1 -1
- package/dist/server/server/src/services/index.mjs +3 -1
- package/dist/server/server/src/services/index.mjs.map +1 -1
- package/dist/server/server/src/services/passport/local-strategy.js +2 -2
- package/dist/server/server/src/services/passport/local-strategy.js.map +1 -1
- package/dist/server/server/src/services/passport/local-strategy.mjs +1 -1
- package/dist/server/server/src/services/passport/local-strategy.mjs.map +1 -1
- package/dist/server/server/src/services/passport.js +1 -2
- package/dist/server/server/src/services/passport.js.map +1 -1
- package/dist/server/server/src/services/passport.mjs +1 -2
- package/dist/server/server/src/services/passport.mjs.map +1 -1
- package/dist/server/server/src/services/permission/engine.js +4 -4
- package/dist/server/server/src/services/permission/engine.js.map +1 -1
- package/dist/server/server/src/services/permission/engine.mjs +2 -2
- package/dist/server/server/src/services/permission/engine.mjs.map +1 -1
- package/dist/server/server/src/services/permission/permissions-manager/index.js +2 -3
- package/dist/server/server/src/services/permission/permissions-manager/index.js.map +1 -1
- package/dist/server/server/src/services/permission/permissions-manager/index.mjs +1 -2
- package/dist/server/server/src/services/permission/permissions-manager/index.mjs.map +1 -1
- package/dist/server/server/src/services/permission/permissions-manager/permission-fields.js +6 -6
- package/dist/server/server/src/services/permission/permissions-manager/permission-fields.js.map +1 -1
- package/dist/server/server/src/services/permission/permissions-manager/permission-fields.mjs +4 -4
- package/dist/server/server/src/services/permission/permissions-manager/permission-fields.mjs.map +1 -1
- package/dist/server/server/src/services/permission/permissions-manager/sanitize.js +47 -41
- package/dist/server/server/src/services/permission/permissions-manager/sanitize.js.map +1 -1
- package/dist/server/server/src/services/permission/permissions-manager/sanitize.mjs +44 -38
- package/dist/server/server/src/services/permission/permissions-manager/sanitize.mjs.map +1 -1
- package/dist/server/server/src/services/permission/permissions-manager/validate.js +30 -26
- package/dist/server/server/src/services/permission/permissions-manager/validate.js.map +1 -1
- package/dist/server/server/src/services/permission/permissions-manager/validate.mjs +28 -24
- package/dist/server/server/src/services/permission/permissions-manager/validate.mjs.map +1 -1
- package/dist/server/server/src/services/permission/queries.js +9 -9
- package/dist/server/server/src/services/permission/queries.js.map +1 -1
- package/dist/server/server/src/services/permission/queries.mjs +9 -9
- package/dist/server/server/src/services/permission/queries.mjs.map +1 -1
- package/dist/server/server/src/services/permission/rename-fields.js +118 -0
- package/dist/server/server/src/services/permission/rename-fields.js.map +1 -0
- package/dist/server/server/src/services/permission/rename-fields.mjs +116 -0
- package/dist/server/server/src/services/permission/rename-fields.mjs.map +1 -0
- package/dist/server/server/src/services/permission/sections-builder/index.js +2 -2
- package/dist/server/server/src/services/permission/sections-builder/index.js.map +1 -1
- package/dist/server/server/src/services/permission/sections-builder/index.mjs +2 -2
- package/dist/server/server/src/services/permission/sections-builder/index.mjs.map +1 -1
- package/dist/server/server/src/services/permission/sections-builder/section.js +1 -2
- package/dist/server/server/src/services/permission/sections-builder/section.js.map +1 -1
- package/dist/server/server/src/services/permission/sections-builder/section.mjs +1 -2
- package/dist/server/server/src/services/permission/sections-builder/section.mjs.map +1 -1
- package/dist/server/server/src/services/permission/sections-builder/utils.js +6 -6
- package/dist/server/server/src/services/permission/sections-builder/utils.js.map +1 -1
- package/dist/server/server/src/services/permission/sections-builder/utils.mjs +4 -4
- package/dist/server/server/src/services/permission/sections-builder/utils.mjs.map +1 -1
- package/dist/server/server/src/services/role.js +20 -19
- package/dist/server/server/src/services/role.js.map +1 -1
- package/dist/server/server/src/services/role.mjs +20 -19
- package/dist/server/server/src/services/role.mjs.map +1 -1
- package/dist/server/server/src/services/transfer/token.js +20 -16
- package/dist/server/server/src/services/transfer/token.js.map +1 -1
- package/dist/server/server/src/services/transfer/token.mjs +14 -10
- package/dist/server/server/src/services/transfer/token.mjs.map +1 -1
- package/dist/server/server/src/services/user.js +2 -3
- package/dist/server/server/src/services/user.js.map +1 -1
- package/dist/server/server/src/services/user.mjs +3 -4
- package/dist/server/server/src/services/user.mjs.map +1 -1
- package/dist/server/server/src/strategies/api-token-utils.js +2 -3
- package/dist/server/server/src/strategies/api-token-utils.js.map +1 -1
- package/dist/server/server/src/strategies/api-token-utils.mjs +2 -3
- package/dist/server/server/src/strategies/api-token-utils.mjs.map +1 -1
- package/dist/server/server/src/strategies/content-api-token.js +3 -3
- package/dist/server/server/src/strategies/content-api-token.js.map +1 -1
- package/dist/server/server/src/strategies/content-api-token.mjs +1 -1
- package/dist/server/server/src/strategies/content-api-token.mjs.map +1 -1
- package/dist/server/server/src/strategies/data-transfer.js +4 -4
- package/dist/server/server/src/strategies/data-transfer.js.map +1 -1
- package/dist/server/server/src/strategies/data-transfer.mjs +3 -3
- package/dist/server/server/src/strategies/data-transfer.mjs.map +1 -1
- package/dist/server/server/src/utils/debug-dump/redact.js +197 -0
- package/dist/server/server/src/utils/debug-dump/redact.js.map +1 -0
- package/dist/server/server/src/utils/debug-dump/redact.mjs +194 -0
- package/dist/server/server/src/utils/debug-dump/redact.mjs.map +1 -0
- package/dist/server/server/src/validation/common-validators.js +9 -10
- package/dist/server/server/src/validation/common-validators.js.map +1 -1
- package/dist/server/server/src/validation/common-validators.mjs +13 -14
- package/dist/server/server/src/validation/common-validators.mjs.map +1 -1
- package/dist/server/server/src/validation/user.js +1 -2
- package/dist/server/server/src/validation/user.js.map +1 -1
- package/dist/server/server/src/validation/user.mjs +1 -2
- package/dist/server/server/src/validation/user.mjs.map +1 -1
- package/dist/server/shared/utils/get-project-type.js +49 -0
- package/dist/server/shared/utils/get-project-type.js.map +1 -0
- package/dist/server/shared/utils/get-project-type.mjs +46 -0
- package/dist/server/shared/utils/get-project-type.mjs.map +1 -0
- package/dist/server/src/audit-logs/auth.d.ts +72 -0
- package/dist/server/src/audit-logs/auth.d.ts.map +1 -0
- package/dist/server/src/audit-logs/tokens.d.ts.map +1 -1
- package/dist/server/src/bootstrap.d.ts.map +1 -1
- package/dist/server/src/config/admin-actions.d.ts.map +1 -1
- package/dist/server/src/controllers/admin-token.d.ts.map +1 -1
- package/dist/server/src/controllers/admin.d.ts +3 -0
- package/dist/server/src/controllers/admin.d.ts.map +1 -1
- package/dist/server/src/controllers/api-token.d.ts.map +1 -1
- package/dist/server/src/controllers/authentication.d.ts.map +1 -1
- package/dist/server/src/controllers/formatters/conditions.d.ts +1 -1
- package/dist/server/src/controllers/formatters/conditions.d.ts.map +1 -1
- package/dist/server/src/controllers/homepage.d.ts +1 -1
- package/dist/server/src/controllers/index.d.ts +4 -1
- package/dist/server/src/controllers/index.d.ts.map +1 -1
- package/dist/server/src/controllers/transfer/index.d.ts.map +1 -1
- package/dist/server/src/controllers/transfer/token.d.ts.map +1 -1
- package/dist/server/src/domain/action/index.d.ts +1 -0
- package/dist/server/src/domain/action/index.d.ts.map +1 -1
- package/dist/server/src/domain/condition/index.d.ts +2 -2
- package/dist/server/src/domain/condition/index.d.ts.map +1 -1
- package/dist/server/src/domain/permission/index.d.ts.map +1 -1
- package/dist/server/src/index.d.ts +11 -3
- package/dist/server/src/index.d.ts.map +1 -1
- package/dist/server/src/middlewares/index.d.ts.map +1 -1
- package/dist/server/src/middlewares/rateLimit.d.ts.map +1 -1
- package/dist/server/src/register.d.ts.map +1 -1
- package/dist/server/src/routes/admin.d.ts.map +1 -1
- package/dist/server/src/services/action.d.ts.map +1 -1
- package/dist/server/src/services/api-token.d.ts.map +1 -1
- package/dist/server/src/services/auth.d.ts +6 -0
- package/dist/server/src/services/auth.d.ts.map +1 -1
- package/dist/server/src/services/condition.d.ts.map +1 -1
- package/dist/server/src/services/content-type.d.ts.map +1 -1
- package/dist/server/src/services/debug-dump.d.ts +9 -0
- package/dist/server/src/services/debug-dump.d.ts.map +1 -0
- package/dist/server/src/services/homepage.d.ts +1 -1
- package/dist/server/src/services/homepage.d.ts.map +1 -1
- package/dist/server/src/services/index.d.ts +7 -2
- package/dist/server/src/services/index.d.ts.map +1 -1
- package/dist/server/src/services/passport/local-strategy.d.ts.map +1 -1
- package/dist/server/src/services/passport.d.ts.map +1 -1
- package/dist/server/src/services/permission/engine.d.ts.map +1 -1
- package/dist/server/src/services/permission/permissions-manager/permission-fields.d.ts.map +1 -1
- package/dist/server/src/services/permission/permissions-manager/sanitize.d.ts.map +1 -1
- package/dist/server/src/services/permission/permissions-manager/validate.d.ts.map +1 -1
- package/dist/server/src/services/permission/queries.d.ts.map +1 -1
- package/dist/server/src/services/permission/rename-fields.d.ts +21 -0
- package/dist/server/src/services/permission/rename-fields.d.ts.map +1 -0
- package/dist/server/src/services/permission/sections-builder/section.d.ts.map +1 -1
- package/dist/server/src/services/permission/sections-builder/utils.d.ts +1 -1
- package/dist/server/src/services/permission/sections-builder/utils.d.ts.map +1 -1
- package/dist/server/src/services/role.d.ts +1 -1
- package/dist/server/src/services/role.d.ts.map +1 -1
- package/dist/server/src/services/transfer/token.d.ts.map +1 -1
- package/dist/server/src/strategies/content-api-token.d.ts.map +1 -1
- package/dist/server/src/utils/debug-dump/redact.d.ts +8 -0
- package/dist/server/src/utils/debug-dump/redact.d.ts.map +1 -0
- package/dist/server/src/validation/user.d.ts.map +1 -1
- package/dist/shared/contracts/admin.d.ts +106 -0
- package/dist/shared/contracts/admin.d.ts.map +1 -1
- package/dist/shared/utils/__tests__/get-project-type.test.d.ts +1 -0
- package/dist/shared/utils/__tests__/get-project-type.test.d.ts.map +1 -0
- package/dist/shared/utils/get-project-type.d.ts +37 -0
- package/dist/shared/utils/get-project-type.d.ts.map +1 -0
- package/package.json +10 -10
- package/dist/admin/admin/src/utils/getProjectType.js +0 -22
- package/dist/admin/admin/src/utils/getProjectType.js.map +0 -1
- package/dist/admin/admin/src/utils/getProjectType.mjs +0 -20
- package/dist/admin/admin/src/utils/getProjectType.mjs.map +0 -1
- package/dist/admin/src/utils/getProjectType.d.ts +0 -16
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.mjs","sources":["../../../../../server/src/audit-logs/auth.ts"],"sourcesContent":["import type { Data, Modules } from '@strapi/types';\nimport { emitAudit } from '@strapi/utils';\n\nimport { toRoleIds, type AdminUserResource, type AdminUserSnapshot } from './admin-users';\n\n/**\n * Event hub events bound to the `admin.auth.events` config callbacks\n * (`onConnectionError`, `onSSOAutoRegistration`). Their names and payloads are public.\n */\nexport const AUTH_EVENTS = {\n LOGIN_FAILURE: 'admin.auth.error',\n AUTO_REGISTRATION: 'admin.auth.autoRegistration',\n} as const;\n\n/** One fixed value per emit site. */\nexport type LoginFailureReason =\n | 'login_not_allowed'\n | 'unexpected_error'\n | 'invalid_credentials'\n | 'account_inactive'\n | 'sso_connection_error'\n | 'sso_registration_disabled'\n | 'sso_role_misconfigured';\n\n/**\n * Payload of `admin.auth.error`, also passed to the `onConnectionError` callback.\n * The audit log stores `provider`, `reason` and the account, never `error`.\n */\nexport interface LoginFailureEvent {\n error: Error;\n provider: string;\n reason: LoginFailureReason;\n /** The account the login was for, when known. */\n user?: { id: Data.ID; email: string };\n}\n\n/** Payload of `admin.auth.autoRegistration`: the created `admin::user` row, roles populated. */\nexport interface AutoRegistrationEvent {\n user: { id: Data.ID; email?: string | null; roles?: AdminUserSnapshot['roles'] };\n provider: string;\n}\n\nexport interface LoginFailureDetails {\n provider: string;\n reason: LoginFailureReason;\n}\n\nexport interface AutoRegistrationDetails {\n provider: string;\n roles: Data.ID[];\n}\n\ntype AuditStrapi = Parameters<typeof emitAudit>[0]['strapi'];\n\n/**\n * Emits without waiting: listeners bound to the event, such as the `onConnectionError`\n * config callback, run before the audit subscriber and must not hold the login.\n */\nexport const emitLoginFailure = (\n { strapi }: { strapi: AuditStrapi },\n event: LoginFailureEvent\n): void => {\n emitAudit({ strapi }, AUTH_EVENTS.LOGIN_FAILURE, {\n error: event.error,\n provider: event.provider,\n reason: event.reason,\n ...(event.user ? { user: { id: event.user.id, email: event.user.email } } : {}),\n } satisfies LoginFailureEvent).catch((error) => {\n strapi.log.error(`Failed to emit ${AUTH_EVENTS.LOGIN_FAILURE}`, { error });\n });\n};\n\n/**\n * Whether the audit log records a failed login. Not recorded: failures anyone can produce\n * from outside before any verification, a local login for an email with no account and an\n * SSO connection with no valid profile.\n */\nexport const isRecordedLoginFailure = (event: LoginFailureEvent) =>\n event.reason !== 'sso_connection_error' && !(event.provider === 'local' && !event.user);\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 options?: {\n allowUnknownActor?: boolean;\n alwaysUnknownActor?: boolean;\n shouldRecord?: (...args: any[]) => boolean;\n }\n ): void;\n}\n\nconst toResource = (user: { id: Data.ID; email?: string | null }): AdminUserResource => ({\n type: 'admin-user',\n id: user.id,\n email: user.email as string,\n});\n\nexport const registerAuthAuditEvents = (auditLogsLifecycle: AuditLogsLifecycle) => {\n auditLogsLifecycle.registerEvent<LoginFailureDetails>(\n AUTH_EVENTS.LOGIN_FAILURE,\n (event: LoginFailureEvent) => ({\n ...(event.user ? { resource: toResource(event.user) } : {}),\n outcome: 'failure',\n details: { provider: event.provider, reason: event.reason },\n }),\n { alwaysUnknownActor: true, shouldRecord: isRecordedLoginFailure }\n );\n\n auditLogsLifecycle.registerEvent<AutoRegistrationDetails>(\n AUTH_EVENTS.AUTO_REGISTRATION,\n (event: AutoRegistrationEvent) => ({\n resource: toResource(event.user),\n details: { provider: event.provider, roles: toRoleIds(event.user.roles) },\n })\n );\n};\n"],"names":["AUTH_EVENTS","LOGIN_FAILURE","AUTO_REGISTRATION","emitLoginFailure","strapi","event","emitAudit","error","provider","reason","user","id","email","catch","log","isRecordedLoginFailure","toResource","type","registerAuthAuditEvents","auditLogsLifecycle","registerEvent","resource","outcome","details","alwaysUnknownActor","shouldRecord","roles","toRoleIds"],"mappings":";;;AAKA;;;UAIaA,WAAAA,GAAc;IACzBC,aAAAA,EAAe,kBAAA;IACfC,iBAAAA,EAAmB;AACrB;AA0CA;;;AAGC,IACM,MAAMC,gBAAAA,GAAmB,CAC9B,EAAEC,MAAM,EAA2B,EACnCC,KAAAA,GAAAA;IAEAC,SAAAA,CAAU;AAAEF,QAAAA;KAAO,EAAGJ,WAAAA,CAAYC,aAAa,EAAE;AAC/CM,QAAAA,KAAAA,EAAOF,MAAME,KAAK;AAClBC,QAAAA,QAAAA,EAAUH,MAAMG,QAAQ;AACxBC,QAAAA,MAAAA,EAAQJ,MAAMI,MAAM;QACpB,GAAIJ,KAAAA,CAAMK,IAAI,GAAG;YAAEA,IAAAA,EAAM;gBAAEC,EAAAA,EAAIN,KAAAA,CAAMK,IAAI,CAACC,EAAE;gBAAEC,KAAAA,EAAOP,KAAAA,CAAMK,IAAI,CAACE;AAAM;AAAE,SAAA,GAAI;KAC9E,CAAA,CAA+BC,KAAK,CAAC,CAACN,KAAAA,GAAAA;QACpCH,MAAAA,CAAOU,GAAG,CAACP,KAAK,CAAC,CAAC,eAAe,EAAEP,WAAAA,CAAYC,aAAa,CAAA,CAAE,EAAE;AAAEM,YAAAA;AAAM,SAAA,CAAA;AAC1E,IAAA,CAAA,CAAA;AACF;AAEA;;;;AAIC,IACM,MAAMQ,sBAAAA,GAAyB,CAACV,KAAAA,GACrCA,KAAAA,CAAMI,MAAM,KAAK,sBAAA,IAA0B,EAAEJ,KAAAA,CAAMG,QAAQ,KAAK,OAAA,IAAW,CAACH,KAAAA,CAAMK,IAAI;AAkBxF,MAAMM,UAAAA,GAAa,CAACN,IAAAA,IAAqE;QACvFO,IAAAA,EAAM,YAAA;AACNN,QAAAA,EAAAA,EAAID,KAAKC,EAAE;AACXC,QAAAA,KAAAA,EAAOF,KAAKE;KACd,CAAA;AAEO,MAAMM,0BAA0B,CAACC,kBAAAA,GAAAA;AACtCA,IAAAA,kBAAAA,CAAmBC,aAAa,CAC9BpB,WAAAA,CAAYC,aAAa,EACzB,CAACI,SAA8B;YAC7B,GAAIA,KAAAA,CAAMK,IAAI,GAAG;gBAAEW,QAAAA,EAAUL,UAAAA,CAAWX,MAAMK,IAAI;AAAE,aAAA,GAAI,EAAE;YAC1DY,OAAAA,EAAS,SAAA;YACTC,OAAAA,EAAS;AAAEf,gBAAAA,QAAAA,EAAUH,MAAMG,QAAQ;AAAEC,gBAAAA,MAAAA,EAAQJ,MAAMI;AAAO;AAC5D,SAAA,CAAA,EACA;QAAEe,kBAAAA,EAAoB,IAAA;QAAMC,YAAAA,EAAcV;AAAuB,KAAA,CAAA;AAGnEI,IAAAA,kBAAAA,CAAmBC,aAAa,CAC9BpB,WAAAA,CAAYE,iBAAiB,EAC7B,CAACG,SAAkC;YACjCgB,QAAAA,EAAUL,UAAAA,CAAWX,MAAMK,IAAI,CAAA;YAC/Ba,OAAAA,EAAS;AAAEf,gBAAAA,QAAAA,EAAUH,MAAMG,QAAQ;AAAEkB,gBAAAA,KAAAA,EAAOC,SAAAA,CAAUtB,KAAAA,CAAMK,IAAI,CAACgB,KAAK;AAAE;SAC1E,CAAA,CAAA;AAEJ;;;;"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var _ = require('lodash');
|
|
4
4
|
|
|
5
5
|
const AUDITED_EVENTS = {
|
|
6
6
|
TOKEN_CREATE: 'token.create',
|
|
@@ -22,7 +22,7 @@ const TOKEN_EDITABLE_FIELDS = [
|
|
|
22
22
|
/**
|
|
23
23
|
* Sorted, and passed through JSON so undefined fields drop: neither order nor an absent
|
|
24
24
|
* field counts as a change.
|
|
25
|
-
*/ const sortRefs = (refs)=>
|
|
25
|
+
*/ const sortRefs = (refs)=>_.sortBy(JSON.parse(JSON.stringify(refs)), (ref)=>JSON.stringify(ref));
|
|
26
26
|
const getTokenChanges = (previous, next)=>{
|
|
27
27
|
const changes = {};
|
|
28
28
|
for (const field of TOKEN_EDITABLE_FIELDS){
|
|
@@ -38,7 +38,7 @@ const getTokenChanges = (previous, next)=>{
|
|
|
38
38
|
if (previous.permissions !== undefined || next.permissions !== undefined) {
|
|
39
39
|
const before = sortRefs(previous.permissions ?? []);
|
|
40
40
|
const after = sortRefs(next.permissions ?? []);
|
|
41
|
-
if (!
|
|
41
|
+
if (!_.isEqual(before, after)) {
|
|
42
42
|
changes.permissions = {
|
|
43
43
|
before,
|
|
44
44
|
after
|
|
@@ -1 +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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"}
|
|
1
|
+
{"version":3,"file":"tokens.js","sources":["../../../../../server/src/audit-logs/tokens.ts"],"sourcesContent":["import { isEqual, sortBy } from 'lodash';\n\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(JSON.parse(JSON.stringify(refs)), (ref: PermissionRef) => JSON.stringify(ref));\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","JSON","parse","stringify","ref","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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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isEqual, sortBy } from 'lodash
|
|
1
|
+
import { isEqual, sortBy } from 'lodash';
|
|
2
2
|
|
|
3
3
|
const AUDITED_EVENTS = {
|
|
4
4
|
TOKEN_CREATE: 'token.create',
|
|
@@ -20,7 +20,7 @@ const TOKEN_EDITABLE_FIELDS = [
|
|
|
20
20
|
/**
|
|
21
21
|
* Sorted, and passed through JSON so undefined fields drop: neither order nor an absent
|
|
22
22
|
* field counts as a change.
|
|
23
|
-
*/ const sortRefs = (refs)=>sortBy((
|
|
23
|
+
*/ const sortRefs = (refs)=>sortBy(JSON.parse(JSON.stringify(refs)), (ref)=>JSON.stringify(ref));
|
|
24
24
|
const getTokenChanges = (previous, next)=>{
|
|
25
25
|
const changes = {};
|
|
26
26
|
for (const field of TOKEN_EDITABLE_FIELDS){
|
|
@@ -1 +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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"}
|
|
1
|
+
{"version":3,"file":"tokens.mjs","sources":["../../../../../server/src/audit-logs/tokens.ts"],"sourcesContent":["import { isEqual, sortBy } from 'lodash';\n\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(JSON.parse(JSON.stringify(refs)), (ref: PermissionRef) => JSON.stringify(ref));\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","JSON","parse","stringify","ref","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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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var _ = require('lodash');
|
|
4
4
|
|
|
5
5
|
const AUDITED_EVENTS = {
|
|
6
6
|
WEBHOOK_CREATE: 'webhook.create',
|
|
@@ -58,7 +58,7 @@ const getWebhookChanges = (previous, next)=>{
|
|
|
58
58
|
const changes = {};
|
|
59
59
|
for (const field of AUDITED_FIELDS){
|
|
60
60
|
// The url is compared as stored, so a change to its stripped part is recorded too.
|
|
61
|
-
const changed = field === 'url' ? previous.url !== next.url : !
|
|
61
|
+
const changed = field === 'url' ? previous.url !== next.url : !_.isEqual(before[field], after[field]);
|
|
62
62
|
if (changed) {
|
|
63
63
|
changes[field] = {
|
|
64
64
|
before: before[field],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webhooks.js","sources":["../../../../../server/src/audit-logs/webhooks.ts"],"sourcesContent":["import { isEqual } from 'lodash
|
|
1
|
+
{"version":3,"file":"webhooks.js","sources":["../../../../../server/src/audit-logs/webhooks.ts"],"sourcesContent":["import { isEqual } from 'lodash';\nimport type { Modules } from '@strapi/types';\n\nexport const AUDITED_EVENTS = {\n WEBHOOK_CREATE: 'webhook.create',\n WEBHOOK_UPDATE: 'webhook.update',\n WEBHOOK_DELETE: 'webhook.delete',\n} as const;\n\ntype Webhook = Modules.WebhookStore.Webhook;\n\nexport interface WebhookEvent {\n webhookId: string;\n name: string;\n}\n\n/**\n * The webhook as it may enter a payload: header names only, sorted. Header values\n * carry `Authorization` tokens and are never recorded, not even on the event hub.\n */\nexport interface AuditedWebhook extends WebhookEvent {\n url: string;\n events: string[];\n headers: string[];\n isEnabled: boolean;\n}\n\nconst AUDITED_FIELDS = ['name', 'url', 'events', 'isEnabled'] as const;\n\n/**\n * Header values are secrets, so the diff lists names only. `changed`: headers whose\n * value changed.\n */\nexport interface HeaderChanges {\n added: string[];\n removed: string[];\n changed: string[];\n}\n\nexport type WebhookChanges = Partial<{\n name: Modules.AuditLogs.FieldChange<string>;\n url: Modules.AuditLogs.FieldChange<string>;\n events: Modules.AuditLogs.FieldChange<string[]>;\n headers: HeaderChanges;\n isEnabled: Modules.AuditLogs.FieldChange<boolean>;\n}>;\n\nexport type CreateDetails = Omit<AuditedWebhook, keyof WebhookEvent>;\n\nexport interface UpdateDetails {\n changes: WebhookChanges;\n}\n\nexport type UpdateEvent = WebhookEvent & UpdateDetails;\n\nconst sortStrings = (values: string[]): string[] => [...values].sort((a, b) => a.localeCompare(b));\n\n/**\n * Scheme and host only. The rest of a webhook URL is often the credential: userinfo,\n * `?token=`, or a path segment (Slack, Netlify, Discord hooks).\n */\nexport const toAuditedUrl = (url: string): string => {\n try {\n const { protocol, host } = new URL(url);\n return `${protocol}//${host}`;\n } catch {\n return url.replace(/\\/\\/[^/@]*@/, '//').match(/^[^:]+:\\/\\/[^/?#]*/)?.[0] ?? '';\n }\n};\n\nexport const toAuditedWebhook = (webhook: Webhook): AuditedWebhook => ({\n webhookId: webhook.id,\n name: webhook.name,\n url: toAuditedUrl(webhook.url),\n events: sortStrings(webhook.events ?? []),\n headers: sortStrings(Object.keys(webhook.headers ?? {})),\n isEnabled: webhook.isEnabled,\n});\n\nconst getHeaderChanges = (\n previous: Webhook['headers'],\n next: Webhook['headers']\n): HeaderChanges | undefined => {\n const before = previous ?? {};\n const after = next ?? {};\n const names = sortStrings([...new Set([...Object.keys(before), ...Object.keys(after)])]);\n\n const has = (headers: Webhook['headers'], name: string) => Object.hasOwn(headers, name);\n\n const changes: HeaderChanges = {\n added: names.filter((name) => !has(before, name)),\n removed: names.filter((name) => !has(after, name)),\n changed: names.filter(\n (name) => has(before, name) && has(after, name) && before[name] !== after[name]\n ),\n };\n\n return Object.values(changes).some((list) => list.length > 0) ? changes : undefined;\n};\n\nexport const getWebhookChanges = (previous: Webhook, next: Webhook): WebhookChanges => {\n const before = toAuditedWebhook(previous);\n const after = toAuditedWebhook(next);\n const changes: WebhookChanges = {};\n\n for (const field of AUDITED_FIELDS) {\n // The url is compared as stored, so a change to its stripped part is recorded too.\n const changed =\n field === 'url' ? previous.url !== next.url : !isEqual(before[field], after[field]);\n\n if (changed) {\n (changes as Record<string, unknown>)[field] = { before: before[field], after: after[field] };\n }\n }\n\n const headers = getHeaderChanges(previous.headers, next.headers);\n\n if (headers) {\n changes.headers = headers;\n }\n\n return changes;\n};\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 registerWebhookAuditEvents = (auditLogsLifecycle: AuditLogsLifecycle) => {\n const webhookResource = (event: WebhookEvent): Modules.AuditLogs.Resource => ({\n type: 'webhook',\n id: event.webhookId,\n name: event.name,\n });\n\n auditLogsLifecycle.registerEvent<CreateDetails>(\n AUDITED_EVENTS.WEBHOOK_CREATE,\n (event: AuditedWebhook) => ({\n resource: webhookResource(event),\n details: {\n url: event.url,\n events: event.events,\n headers: event.headers,\n isEnabled: event.isEnabled,\n },\n })\n );\n\n auditLogsLifecycle.registerEvent<UpdateDetails>(\n AUDITED_EVENTS.WEBHOOK_UPDATE,\n (event: UpdateEvent) => ({\n resource: webhookResource(event),\n details: { changes: event.changes },\n })\n );\n\n auditLogsLifecycle.registerEvent<undefined>(\n AUDITED_EVENTS.WEBHOOK_DELETE,\n (event: WebhookEvent) => ({\n resource: webhookResource(event),\n })\n );\n};\n"],"names":["AUDITED_EVENTS","WEBHOOK_CREATE","WEBHOOK_UPDATE","WEBHOOK_DELETE","AUDITED_FIELDS","sortStrings","values","sort","a","b","localeCompare","toAuditedUrl","url","protocol","host","URL","replace","match","toAuditedWebhook","webhook","webhookId","id","name","events","headers","Object","keys","isEnabled","getHeaderChanges","previous","next","before","after","names","Set","has","hasOwn","changes","added","filter","removed","changed","some","list","length","undefined","getWebhookChanges","field","isEqual","registerWebhookAuditEvents","auditLogsLifecycle","webhookResource","event","type","registerEvent","resource","details"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webhooks.mjs","sources":["../../../../../server/src/audit-logs/webhooks.ts"],"sourcesContent":["import { isEqual } from 'lodash
|
|
1
|
+
{"version":3,"file":"webhooks.mjs","sources":["../../../../../server/src/audit-logs/webhooks.ts"],"sourcesContent":["import { isEqual } from 'lodash';\nimport type { Modules } from '@strapi/types';\n\nexport const AUDITED_EVENTS = {\n WEBHOOK_CREATE: 'webhook.create',\n WEBHOOK_UPDATE: 'webhook.update',\n WEBHOOK_DELETE: 'webhook.delete',\n} as const;\n\ntype Webhook = Modules.WebhookStore.Webhook;\n\nexport interface WebhookEvent {\n webhookId: string;\n name: string;\n}\n\n/**\n * The webhook as it may enter a payload: header names only, sorted. Header values\n * carry `Authorization` tokens and are never recorded, not even on the event hub.\n */\nexport interface AuditedWebhook extends WebhookEvent {\n url: string;\n events: string[];\n headers: string[];\n isEnabled: boolean;\n}\n\nconst AUDITED_FIELDS = ['name', 'url', 'events', 'isEnabled'] as const;\n\n/**\n * Header values are secrets, so the diff lists names only. `changed`: headers whose\n * value changed.\n */\nexport interface HeaderChanges {\n added: string[];\n removed: string[];\n changed: string[];\n}\n\nexport type WebhookChanges = Partial<{\n name: Modules.AuditLogs.FieldChange<string>;\n url: Modules.AuditLogs.FieldChange<string>;\n events: Modules.AuditLogs.FieldChange<string[]>;\n headers: HeaderChanges;\n isEnabled: Modules.AuditLogs.FieldChange<boolean>;\n}>;\n\nexport type CreateDetails = Omit<AuditedWebhook, keyof WebhookEvent>;\n\nexport interface UpdateDetails {\n changes: WebhookChanges;\n}\n\nexport type UpdateEvent = WebhookEvent & UpdateDetails;\n\nconst sortStrings = (values: string[]): string[] => [...values].sort((a, b) => a.localeCompare(b));\n\n/**\n * Scheme and host only. The rest of a webhook URL is often the credential: userinfo,\n * `?token=`, or a path segment (Slack, Netlify, Discord hooks).\n */\nexport const toAuditedUrl = (url: string): string => {\n try {\n const { protocol, host } = new URL(url);\n return `${protocol}//${host}`;\n } catch {\n return url.replace(/\\/\\/[^/@]*@/, '//').match(/^[^:]+:\\/\\/[^/?#]*/)?.[0] ?? '';\n }\n};\n\nexport const toAuditedWebhook = (webhook: Webhook): AuditedWebhook => ({\n webhookId: webhook.id,\n name: webhook.name,\n url: toAuditedUrl(webhook.url),\n events: sortStrings(webhook.events ?? []),\n headers: sortStrings(Object.keys(webhook.headers ?? {})),\n isEnabled: webhook.isEnabled,\n});\n\nconst getHeaderChanges = (\n previous: Webhook['headers'],\n next: Webhook['headers']\n): HeaderChanges | undefined => {\n const before = previous ?? {};\n const after = next ?? {};\n const names = sortStrings([...new Set([...Object.keys(before), ...Object.keys(after)])]);\n\n const has = (headers: Webhook['headers'], name: string) => Object.hasOwn(headers, name);\n\n const changes: HeaderChanges = {\n added: names.filter((name) => !has(before, name)),\n removed: names.filter((name) => !has(after, name)),\n changed: names.filter(\n (name) => has(before, name) && has(after, name) && before[name] !== after[name]\n ),\n };\n\n return Object.values(changes).some((list) => list.length > 0) ? changes : undefined;\n};\n\nexport const getWebhookChanges = (previous: Webhook, next: Webhook): WebhookChanges => {\n const before = toAuditedWebhook(previous);\n const after = toAuditedWebhook(next);\n const changes: WebhookChanges = {};\n\n for (const field of AUDITED_FIELDS) {\n // The url is compared as stored, so a change to its stripped part is recorded too.\n const changed =\n field === 'url' ? previous.url !== next.url : !isEqual(before[field], after[field]);\n\n if (changed) {\n (changes as Record<string, unknown>)[field] = { before: before[field], after: after[field] };\n }\n }\n\n const headers = getHeaderChanges(previous.headers, next.headers);\n\n if (headers) {\n changes.headers = headers;\n }\n\n return changes;\n};\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 registerWebhookAuditEvents = (auditLogsLifecycle: AuditLogsLifecycle) => {\n const webhookResource = (event: WebhookEvent): Modules.AuditLogs.Resource => ({\n type: 'webhook',\n id: event.webhookId,\n name: event.name,\n });\n\n auditLogsLifecycle.registerEvent<CreateDetails>(\n AUDITED_EVENTS.WEBHOOK_CREATE,\n (event: AuditedWebhook) => ({\n resource: webhookResource(event),\n details: {\n url: event.url,\n events: event.events,\n headers: event.headers,\n isEnabled: event.isEnabled,\n },\n })\n );\n\n auditLogsLifecycle.registerEvent<UpdateDetails>(\n AUDITED_EVENTS.WEBHOOK_UPDATE,\n (event: UpdateEvent) => ({\n resource: webhookResource(event),\n details: { changes: event.changes },\n })\n );\n\n auditLogsLifecycle.registerEvent<undefined>(\n AUDITED_EVENTS.WEBHOOK_DELETE,\n (event: WebhookEvent) => ({\n resource: webhookResource(event),\n })\n );\n};\n"],"names":["AUDITED_EVENTS","WEBHOOK_CREATE","WEBHOOK_UPDATE","WEBHOOK_DELETE","AUDITED_FIELDS","sortStrings","values","sort","a","b","localeCompare","toAuditedUrl","url","protocol","host","URL","replace","match","toAuditedWebhook","webhook","webhookId","id","name","events","headers","Object","keys","isEnabled","getHeaderChanges","previous","next","before","after","names","Set","has","hasOwn","changes","added","filter","removed","changed","some","list","length","undefined","getWebhookChanges","field","isEqual","registerWebhookAuditEvents","auditLogsLifecycle","webhookResource","event","type","registerEvent","resource","details"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var _ = require('lodash');
|
|
4
4
|
var utils = require('@strapi/utils');
|
|
5
5
|
var index = require('./utils/index.js');
|
|
6
6
|
var token = require('./services/token.js');
|
|
@@ -77,7 +77,7 @@ const syncAuthSettings = async ()=>{
|
|
|
77
77
|
const adminAuthSettings = await adminStore.get({
|
|
78
78
|
key: 'auth'
|
|
79
79
|
});
|
|
80
|
-
const newAuthSettings =
|
|
80
|
+
const newAuthSettings = _.merge({}, defaultAdminAuthSettings, adminAuthSettings);
|
|
81
81
|
const roleExists = await index.getService('role').exists({
|
|
82
82
|
id: newAuthSettings.providers.defaultRole
|
|
83
83
|
});
|
|
@@ -92,8 +92,10 @@ const syncAuthSettings = async ()=>{
|
|
|
92
92
|
};
|
|
93
93
|
const syncAPITokensPermissions = async ()=>{
|
|
94
94
|
const validPermissions = strapi.contentAPI.permissions.providers.action.keys();
|
|
95
|
-
const permissionsInDB = await utils.async.pipe(strapi.db.query('admin::api-token-permission').findMany,
|
|
96
|
-
const unknownPermissions =
|
|
95
|
+
const permissionsInDB = await utils.async.pipe(strapi.db.query('admin::api-token-permission').findMany, (permissions)=>_.map(permissions, 'action'))();
|
|
96
|
+
const unknownPermissions = [
|
|
97
|
+
...new Set(_.difference(permissionsInDB, validPermissions))
|
|
98
|
+
];
|
|
97
99
|
if (unknownPermissions.length > 0) {
|
|
98
100
|
await strapi.db.query('admin::api-token-permission').deleteMany({
|
|
99
101
|
where: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bootstrap.js","sources":["../../../../server/src/bootstrap.ts"],"sourcesContent":["import { merge, map, difference, uniq } from 'lodash/fp';\nimport type { Core } from '@strapi/types';\nimport { async } from '@strapi/utils';\nimport { getService } from './utils';\nimport {\n getTokenOptions,\n expiresInToSeconds,\n hasUserConfiguredAuthOptionsExpiresIn,\n} from './services/token';\nimport adminActions from './config/admin-actions';\nimport adminConditions from './config/admin-conditions';\nimport constants from './services/constants';\nimport {\n DEFAULT_MAX_REFRESH_TOKEN_LIFESPAN,\n DEFAULT_IDLE_REFRESH_TOKEN_LIFESPAN,\n DEFAULT_MAX_SESSION_LIFESPAN,\n DEFAULT_IDLE_SESSION_LIFESPAN,\n} from '../../shared/utils/session-auth';\n\nconst defaultAdminAuthSettings = {\n providers: {\n autoRegister: false,\n defaultRole: null,\n ssoLockedRoles: null,\n },\n};\n\nconst registerPermissionActions = async () => {\n await getService('permission').actionProvider.registerMany(adminActions.actions);\n};\n\nconst registerAdminConditions = async () => {\n await getService('permission').conditionProvider.registerMany(adminConditions.conditions);\n};\n\nconst registerModelHooks = () => {\n const { sendDidChangeInterfaceLanguage } = getService('metrics');\n\n strapi.db.lifecycles.subscribe({\n models: ['admin::user'],\n afterCreate: sendDidChangeInterfaceLanguage,\n afterDelete: sendDidChangeInterfaceLanguage,\n async beforeDelete(event) {\n // Delete all admin API tokens owned by this user before the user row is removed\n await getService('api-token-admin').deleteTokensForUser(event.params.where.id);\n },\n async afterUpdate(event) {\n if (event.params.data?.preferedLanguage) {\n sendDidChangeInterfaceLanguage();\n }\n if (event.params.data?.roles !== undefined) {\n // We re-sync token permissions for all owner users with their role when the user is updated\n await getService('api-token-admin').syncPermissionsForUser(event.result.id);\n }\n },\n });\n\n strapi.db.lifecycles.subscribe({\n models: ['admin::role'],\n // We re-sync token permissions for all owner users with this role when the role is deleted\n async beforeDelete(event) {\n const users = await strapi.db.query('admin::user').findMany({\n where: { roles: { id: event.params.where.id } },\n select: ['id'],\n });\n event.state.affectedUserIds = users.map((u: { id: unknown }) => u.id);\n },\n async afterDelete(event) {\n for (const userId of (event.state.affectedUserIds as unknown[]) ?? []) {\n await getService('api-token-admin').syncPermissionsForUser(userId as string | number);\n }\n },\n });\n};\n\nconst syncAuthSettings = async () => {\n const adminStore = await strapi.store({ type: 'core', name: 'admin' });\n const adminAuthSettings = await adminStore.get({ key: 'auth' });\n const newAuthSettings = merge(defaultAdminAuthSettings, adminAuthSettings);\n\n const roleExists = await getService('role').exists({\n id: newAuthSettings.providers.defaultRole,\n });\n\n // Reset the default SSO role if it has been deleted manually\n if (!roleExists) {\n newAuthSettings.providers.defaultRole = null;\n }\n\n await adminStore.set({ key: 'auth', value: newAuthSettings });\n};\n\nconst syncAPITokensPermissions = async () => {\n const validPermissions = strapi.contentAPI.permissions.providers.action.keys();\n const permissionsInDB = await async.pipe(\n strapi.db.query('admin::api-token-permission').findMany,\n map('action')\n )();\n\n const unknownPermissions = uniq(difference(permissionsInDB, validPermissions));\n\n if (unknownPermissions.length > 0) {\n await strapi.db\n .query('admin::api-token-permission')\n .deleteMany({ where: { action: { $in: unknownPermissions } } });\n }\n};\n\n/**\n * Ensures the creation of default API tokens during the app creation.\n *\n * Checks the database for existing users and API tokens:\n * - If there are no users and no API tokens, it creates two default API tokens:\n * 1. A \"Read Only\" API token with permissions for accessing resources.\n * 2. A \"Full Access\" API token with permissions for accessing and modifying resources.\n *\n * @sideEffects Creates new API tokens in the database if conditions are met.\n */\n\nconst createDefaultAPITokensIfNeeded = async () => {\n const userService = getService('user');\n const apiTokenService = getService('api-token-content-api');\n\n const usersCount = await userService.count();\n const apiTokenCount = await apiTokenService.countAll();\n\n if (usersCount === 0 && apiTokenCount === 0) {\n for (const token of constants.DEFAULT_API_TOKENS) {\n await apiTokenService.create(token);\n }\n }\n};\n\nexport default async ({ strapi }: { strapi: Core.Strapi }) => {\n // Get the merged token options (includes defaults merged with user config)\n const { options } = getTokenOptions();\n const legacyMaxRefreshFallback =\n expiresInToSeconds(options?.expiresIn) ?? DEFAULT_MAX_REFRESH_TOKEN_LIFESPAN;\n const legacyMaxSessionFallback =\n expiresInToSeconds(options?.expiresIn) ?? DEFAULT_MAX_SESSION_LIFESPAN;\n\n // Warn only when the user set legacy admin.auth.options.expiresIn. Merged JWT options always\n // include the default expiresIn ('30d'), so reading merged options alone is a false positive.\n const hasLegacyExpires = hasUserConfiguredAuthOptionsExpiresIn(\n strapi.config.get('admin.auth.options')\n );\n const hasNewMaxRefresh = strapi.config.get('admin.auth.sessions.maxRefreshTokenLifespan') != null;\n const hasNewMaxSession = strapi.config.get('admin.auth.sessions.maxSessionLifespan') != null;\n\n if (hasLegacyExpires && (!hasNewMaxRefresh || !hasNewMaxSession)) {\n strapi.log.warn(\n 'admin.auth.options.expiresIn is deprecated and will be removed in Strapi 6. Please configure admin.auth.sessions.maxRefreshTokenLifespan and admin.auth.sessions.maxSessionLifespan.'\n );\n }\n\n strapi.sessionManager.defineOrigin('admin', {\n jwtSecret: strapi.config.get('admin.auth.secret'),\n accessTokenLifespan: strapi.config.get('admin.auth.sessions.accessTokenLifespan', 30 * 60),\n maxRefreshTokenLifespan: strapi.config.get(\n 'admin.auth.sessions.maxRefreshTokenLifespan',\n legacyMaxRefreshFallback\n ),\n idleRefreshTokenLifespan: strapi.config.get(\n 'admin.auth.sessions.idleRefreshTokenLifespan',\n DEFAULT_IDLE_REFRESH_TOKEN_LIFESPAN\n ),\n maxSessionLifespan: strapi.config.get(\n 'admin.auth.sessions.maxSessionLifespan',\n legacyMaxSessionFallback\n ),\n idleSessionLifespan: strapi.config.get(\n 'admin.auth.sessions.idleSessionLifespan',\n DEFAULT_IDLE_SESSION_LIFESPAN\n ),\n algorithm: options?.algorithm,\n // Pass through all JWT options (includes privateKey, publicKey, and any other options)\n jwtOptions: options,\n });\n\n const isProduction = process.env.NODE_ENV === 'production';\n const adminCookieSecure = strapi.config.get('admin.auth.cookie.secure');\n if (isProduction && adminCookieSecure === false) {\n strapi.log.warn(\n 'Server is in production mode, but admin.auth.cookie.secure has been set to false. This is not recommended and will allow cookies to be sent over insecure connections.'\n );\n }\n\n await registerAdminConditions();\n await registerPermissionActions();\n registerModelHooks();\n\n const permissionService = getService('permission');\n const userService = getService('user');\n const roleService = getService('role');\n const apiTokenService = getService('api-token-content-api');\n const transferService = getService('transfer');\n const tokenService = getService('token');\n\n await roleService.createRolesIfNoneExist();\n await roleService.resetSuperAdminPermissions();\n await roleService.displayWarningIfNoSuperAdmin();\n\n await permissionService.cleanPermissionsInDatabase();\n\n await userService.displayWarningIfUsersDontHaveRole();\n\n await syncAuthSettings();\n await syncAPITokensPermissions();\n\n await getService('metrics').sendUpdateProjectInformation(strapi);\n getService('metrics').startCron(strapi);\n\n apiTokenService.checkSaltIsDefined();\n transferService.token.checkSaltIsDefined();\n tokenService.checkSecretIsDefined();\n\n await createDefaultAPITokensIfNeeded();\n};\n"],"names":["defaultAdminAuthSettings","providers","autoRegister","defaultRole","ssoLockedRoles","registerPermissionActions","getService","actionProvider","registerMany","adminActions","actions","registerAdminConditions","conditionProvider","adminConditions","conditions","registerModelHooks","sendDidChangeInterfaceLanguage","strapi","db","lifecycles","subscribe","models","afterCreate","afterDelete","beforeDelete","event","deleteTokensForUser","params","where","id","afterUpdate","data","preferedLanguage","roles","undefined","syncPermissionsForUser","result","users","query","findMany","select","state","affectedUserIds","map","u","userId","syncAuthSettings","adminStore","store","type","name","adminAuthSettings","get","key","newAuthSettings","merge","roleExists","exists","set","value","syncAPITokensPermissions","validPermissions","contentAPI","permissions","action","keys","permissionsInDB","async","pipe","unknownPermissions","uniq","difference","length","deleteMany","$in","createDefaultAPITokensIfNeeded","userService","apiTokenService","usersCount","count","apiTokenCount","countAll","token","constants","DEFAULT_API_TOKENS","create","options","getTokenOptions","legacyMaxRefreshFallback","expiresInToSeconds","expiresIn","DEFAULT_MAX_REFRESH_TOKEN_LIFESPAN","legacyMaxSessionFallback","DEFAULT_MAX_SESSION_LIFESPAN","hasLegacyExpires","hasUserConfiguredAuthOptionsExpiresIn","config","hasNewMaxRefresh","hasNewMaxSession","log","warn","sessionManager","defineOrigin","jwtSecret","accessTokenLifespan","maxRefreshTokenLifespan","idleRefreshTokenLifespan","DEFAULT_IDLE_REFRESH_TOKEN_LIFESPAN","maxSessionLifespan","idleSessionLifespan","DEFAULT_IDLE_SESSION_LIFESPAN","algorithm","jwtOptions","isProduction","process","env","NODE_ENV","adminCookieSecure","permissionService","roleService","transferService","tokenService","createRolesIfNoneExist","resetSuperAdminPermissions","displayWarningIfNoSuperAdmin","cleanPermissionsInDatabase","displayWarningIfUsersDontHaveRole","sendUpdateProjectInformation","startCron","checkSaltIsDefined","checkSecretIsDefined"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"bootstrap.js","sources":["../../../../server/src/bootstrap.ts"],"sourcesContent":["import { map, merge, difference } from 'lodash';\n\nimport type { Core } from '@strapi/types';\nimport { async } from '@strapi/utils';\nimport { getService } from './utils';\nimport {\n getTokenOptions,\n expiresInToSeconds,\n hasUserConfiguredAuthOptionsExpiresIn,\n} from './services/token';\nimport adminActions from './config/admin-actions';\nimport adminConditions from './config/admin-conditions';\nimport constants from './services/constants';\nimport {\n DEFAULT_MAX_REFRESH_TOKEN_LIFESPAN,\n DEFAULT_IDLE_REFRESH_TOKEN_LIFESPAN,\n DEFAULT_MAX_SESSION_LIFESPAN,\n DEFAULT_IDLE_SESSION_LIFESPAN,\n} from '../../shared/utils/session-auth';\n\nconst defaultAdminAuthSettings = {\n providers: {\n autoRegister: false,\n defaultRole: null,\n ssoLockedRoles: null,\n },\n};\n\nconst registerPermissionActions = async () => {\n await getService('permission').actionProvider.registerMany(adminActions.actions);\n};\n\nconst registerAdminConditions = async () => {\n await getService('permission').conditionProvider.registerMany(adminConditions.conditions);\n};\n\nconst registerModelHooks = () => {\n const { sendDidChangeInterfaceLanguage } = getService('metrics');\n\n strapi.db.lifecycles.subscribe({\n models: ['admin::user'],\n afterCreate: sendDidChangeInterfaceLanguage,\n afterDelete: sendDidChangeInterfaceLanguage,\n async beforeDelete(event) {\n // Delete all admin API tokens owned by this user before the user row is removed\n await getService('api-token-admin').deleteTokensForUser(event.params.where.id);\n },\n async afterUpdate(event) {\n if (event.params.data?.preferedLanguage) {\n sendDidChangeInterfaceLanguage();\n }\n if (event.params.data?.roles !== undefined) {\n // We re-sync token permissions for all owner users with their role when the user is updated\n await getService('api-token-admin').syncPermissionsForUser(event.result.id);\n }\n },\n });\n\n strapi.db.lifecycles.subscribe({\n models: ['admin::role'],\n // We re-sync token permissions for all owner users with this role when the role is deleted\n async beforeDelete(event) {\n const users = await strapi.db.query('admin::user').findMany({\n where: { roles: { id: event.params.where.id } },\n select: ['id'],\n });\n event.state.affectedUserIds = users.map((u: { id: unknown }) => u.id);\n },\n async afterDelete(event) {\n for (const userId of (event.state.affectedUserIds as unknown[]) ?? []) {\n await getService('api-token-admin').syncPermissionsForUser(userId as string | number);\n }\n },\n });\n};\n\nconst syncAuthSettings = async () => {\n const adminStore = await strapi.store({ type: 'core', name: 'admin' });\n const adminAuthSettings = await adminStore.get({ key: 'auth' });\n const newAuthSettings = merge({}, defaultAdminAuthSettings, adminAuthSettings);\n\n const roleExists = await getService('role').exists({\n id: newAuthSettings.providers.defaultRole,\n });\n\n // Reset the default SSO role if it has been deleted manually\n if (!roleExists) {\n newAuthSettings.providers.defaultRole = null;\n }\n\n await adminStore.set({ key: 'auth', value: newAuthSettings });\n};\n\nconst syncAPITokensPermissions = async () => {\n const validPermissions = strapi.contentAPI.permissions.providers.action.keys();\n const permissionsInDB = await async.pipe(\n strapi.db.query('admin::api-token-permission').findMany,\n (permissions) => map(permissions, 'action')\n )();\n\n const unknownPermissions = [...new Set(difference(permissionsInDB, validPermissions))];\n\n if (unknownPermissions.length > 0) {\n await strapi.db\n .query('admin::api-token-permission')\n .deleteMany({ where: { action: { $in: unknownPermissions } } });\n }\n};\n\n/**\n * Ensures the creation of default API tokens during the app creation.\n *\n * Checks the database for existing users and API tokens:\n * - If there are no users and no API tokens, it creates two default API tokens:\n * 1. A \"Read Only\" API token with permissions for accessing resources.\n * 2. A \"Full Access\" API token with permissions for accessing and modifying resources.\n *\n * @sideEffects Creates new API tokens in the database if conditions are met.\n */\n\nconst createDefaultAPITokensIfNeeded = async () => {\n const userService = getService('user');\n const apiTokenService = getService('api-token-content-api');\n\n const usersCount = await userService.count();\n const apiTokenCount = await apiTokenService.countAll();\n\n if (usersCount === 0 && apiTokenCount === 0) {\n for (const token of constants.DEFAULT_API_TOKENS) {\n await apiTokenService.create(token);\n }\n }\n};\n\nexport default async ({ strapi }: { strapi: Core.Strapi }) => {\n // Get the merged token options (includes defaults merged with user config)\n const { options } = getTokenOptions();\n const legacyMaxRefreshFallback =\n expiresInToSeconds(options?.expiresIn) ?? DEFAULT_MAX_REFRESH_TOKEN_LIFESPAN;\n const legacyMaxSessionFallback =\n expiresInToSeconds(options?.expiresIn) ?? DEFAULT_MAX_SESSION_LIFESPAN;\n\n // Warn only when the user set legacy admin.auth.options.expiresIn. Merged JWT options always\n // include the default expiresIn ('30d'), so reading merged options alone is a false positive.\n const hasLegacyExpires = hasUserConfiguredAuthOptionsExpiresIn(\n strapi.config.get('admin.auth.options')\n );\n const hasNewMaxRefresh = strapi.config.get('admin.auth.sessions.maxRefreshTokenLifespan') != null;\n const hasNewMaxSession = strapi.config.get('admin.auth.sessions.maxSessionLifespan') != null;\n\n if (hasLegacyExpires && (!hasNewMaxRefresh || !hasNewMaxSession)) {\n strapi.log.warn(\n 'admin.auth.options.expiresIn is deprecated and will be removed in Strapi 6. Please configure admin.auth.sessions.maxRefreshTokenLifespan and admin.auth.sessions.maxSessionLifespan.'\n );\n }\n\n strapi.sessionManager.defineOrigin('admin', {\n jwtSecret: strapi.config.get('admin.auth.secret'),\n accessTokenLifespan: strapi.config.get('admin.auth.sessions.accessTokenLifespan', 30 * 60),\n maxRefreshTokenLifespan: strapi.config.get(\n 'admin.auth.sessions.maxRefreshTokenLifespan',\n legacyMaxRefreshFallback\n ),\n idleRefreshTokenLifespan: strapi.config.get(\n 'admin.auth.sessions.idleRefreshTokenLifespan',\n DEFAULT_IDLE_REFRESH_TOKEN_LIFESPAN\n ),\n maxSessionLifespan: strapi.config.get(\n 'admin.auth.sessions.maxSessionLifespan',\n legacyMaxSessionFallback\n ),\n idleSessionLifespan: strapi.config.get(\n 'admin.auth.sessions.idleSessionLifespan',\n DEFAULT_IDLE_SESSION_LIFESPAN\n ),\n algorithm: options?.algorithm,\n // Pass through all JWT options (includes privateKey, publicKey, and any other options)\n jwtOptions: options,\n });\n\n const isProduction = process.env.NODE_ENV === 'production';\n const adminCookieSecure = strapi.config.get('admin.auth.cookie.secure');\n if (isProduction && adminCookieSecure === false) {\n strapi.log.warn(\n 'Server is in production mode, but admin.auth.cookie.secure has been set to false. This is not recommended and will allow cookies to be sent over insecure connections.'\n );\n }\n\n await registerAdminConditions();\n await registerPermissionActions();\n registerModelHooks();\n\n const permissionService = getService('permission');\n const userService = getService('user');\n const roleService = getService('role');\n const apiTokenService = getService('api-token-content-api');\n const transferService = getService('transfer');\n const tokenService = getService('token');\n\n await roleService.createRolesIfNoneExist();\n await roleService.resetSuperAdminPermissions();\n await roleService.displayWarningIfNoSuperAdmin();\n\n await permissionService.cleanPermissionsInDatabase();\n\n await userService.displayWarningIfUsersDontHaveRole();\n\n await syncAuthSettings();\n await syncAPITokensPermissions();\n\n await getService('metrics').sendUpdateProjectInformation(strapi);\n getService('metrics').startCron(strapi);\n\n apiTokenService.checkSaltIsDefined();\n transferService.token.checkSaltIsDefined();\n tokenService.checkSecretIsDefined();\n\n await createDefaultAPITokensIfNeeded();\n};\n"],"names":["defaultAdminAuthSettings","providers","autoRegister","defaultRole","ssoLockedRoles","registerPermissionActions","getService","actionProvider","registerMany","adminActions","actions","registerAdminConditions","conditionProvider","adminConditions","conditions","registerModelHooks","sendDidChangeInterfaceLanguage","strapi","db","lifecycles","subscribe","models","afterCreate","afterDelete","beforeDelete","event","deleteTokensForUser","params","where","id","afterUpdate","data","preferedLanguage","roles","undefined","syncPermissionsForUser","result","users","query","findMany","select","state","affectedUserIds","map","u","userId","syncAuthSettings","adminStore","store","type","name","adminAuthSettings","get","key","newAuthSettings","merge","roleExists","exists","set","value","syncAPITokensPermissions","validPermissions","contentAPI","permissions","action","keys","permissionsInDB","async","pipe","unknownPermissions","Set","difference","length","deleteMany","$in","createDefaultAPITokensIfNeeded","userService","apiTokenService","usersCount","count","apiTokenCount","countAll","token","constants","DEFAULT_API_TOKENS","create","options","getTokenOptions","legacyMaxRefreshFallback","expiresInToSeconds","expiresIn","DEFAULT_MAX_REFRESH_TOKEN_LIFESPAN","legacyMaxSessionFallback","DEFAULT_MAX_SESSION_LIFESPAN","hasLegacyExpires","hasUserConfiguredAuthOptionsExpiresIn","config","hasNewMaxRefresh","hasNewMaxSession","log","warn","sessionManager","defineOrigin","jwtSecret","accessTokenLifespan","maxRefreshTokenLifespan","idleRefreshTokenLifespan","DEFAULT_IDLE_REFRESH_TOKEN_LIFESPAN","maxSessionLifespan","idleSessionLifespan","DEFAULT_IDLE_SESSION_LIFESPAN","algorithm","jwtOptions","isProduction","process","env","NODE_ENV","adminCookieSecure","permissionService","roleService","transferService","tokenService","createRolesIfNoneExist","resetSuperAdminPermissions","displayWarningIfNoSuperAdmin","cleanPermissionsInDatabase","displayWarningIfUsersDontHaveRole","sendUpdateProjectInformation","startCron","checkSaltIsDefined","checkSecretIsDefined"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { merge, map,
|
|
1
|
+
import { merge, map, difference } from 'lodash';
|
|
2
2
|
import { async } from '@strapi/utils';
|
|
3
3
|
import { getService } from './utils/index.mjs';
|
|
4
4
|
import { getTokenOptions, expiresInToSeconds, hasUserConfiguredAuthOptionsExpiresIn } from './services/token.mjs';
|
|
@@ -75,7 +75,7 @@ const syncAuthSettings = async ()=>{
|
|
|
75
75
|
const adminAuthSettings = await adminStore.get({
|
|
76
76
|
key: 'auth'
|
|
77
77
|
});
|
|
78
|
-
const newAuthSettings = merge(defaultAdminAuthSettings, adminAuthSettings);
|
|
78
|
+
const newAuthSettings = merge({}, defaultAdminAuthSettings, adminAuthSettings);
|
|
79
79
|
const roleExists = await getService('role').exists({
|
|
80
80
|
id: newAuthSettings.providers.defaultRole
|
|
81
81
|
});
|
|
@@ -90,8 +90,10 @@ const syncAuthSettings = async ()=>{
|
|
|
90
90
|
};
|
|
91
91
|
const syncAPITokensPermissions = async ()=>{
|
|
92
92
|
const validPermissions = strapi.contentAPI.permissions.providers.action.keys();
|
|
93
|
-
const permissionsInDB = await async.pipe(strapi.db.query('admin::api-token-permission').findMany, map('action'))();
|
|
94
|
-
const unknownPermissions =
|
|
93
|
+
const permissionsInDB = await async.pipe(strapi.db.query('admin::api-token-permission').findMany, (permissions)=>map(permissions, 'action'))();
|
|
94
|
+
const unknownPermissions = [
|
|
95
|
+
...new Set(difference(permissionsInDB, validPermissions))
|
|
96
|
+
];
|
|
95
97
|
if (unknownPermissions.length > 0) {
|
|
96
98
|
await strapi.db.query('admin::api-token-permission').deleteMany({
|
|
97
99
|
where: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bootstrap.mjs","sources":["../../../../server/src/bootstrap.ts"],"sourcesContent":["import { merge, map, difference, uniq } from 'lodash/fp';\nimport type { Core } from '@strapi/types';\nimport { async } from '@strapi/utils';\nimport { getService } from './utils';\nimport {\n getTokenOptions,\n expiresInToSeconds,\n hasUserConfiguredAuthOptionsExpiresIn,\n} from './services/token';\nimport adminActions from './config/admin-actions';\nimport adminConditions from './config/admin-conditions';\nimport constants from './services/constants';\nimport {\n DEFAULT_MAX_REFRESH_TOKEN_LIFESPAN,\n DEFAULT_IDLE_REFRESH_TOKEN_LIFESPAN,\n DEFAULT_MAX_SESSION_LIFESPAN,\n DEFAULT_IDLE_SESSION_LIFESPAN,\n} from '../../shared/utils/session-auth';\n\nconst defaultAdminAuthSettings = {\n providers: {\n autoRegister: false,\n defaultRole: null,\n ssoLockedRoles: null,\n },\n};\n\nconst registerPermissionActions = async () => {\n await getService('permission').actionProvider.registerMany(adminActions.actions);\n};\n\nconst registerAdminConditions = async () => {\n await getService('permission').conditionProvider.registerMany(adminConditions.conditions);\n};\n\nconst registerModelHooks = () => {\n const { sendDidChangeInterfaceLanguage } = getService('metrics');\n\n strapi.db.lifecycles.subscribe({\n models: ['admin::user'],\n afterCreate: sendDidChangeInterfaceLanguage,\n afterDelete: sendDidChangeInterfaceLanguage,\n async beforeDelete(event) {\n // Delete all admin API tokens owned by this user before the user row is removed\n await getService('api-token-admin').deleteTokensForUser(event.params.where.id);\n },\n async afterUpdate(event) {\n if (event.params.data?.preferedLanguage) {\n sendDidChangeInterfaceLanguage();\n }\n if (event.params.data?.roles !== undefined) {\n // We re-sync token permissions for all owner users with their role when the user is updated\n await getService('api-token-admin').syncPermissionsForUser(event.result.id);\n }\n },\n });\n\n strapi.db.lifecycles.subscribe({\n models: ['admin::role'],\n // We re-sync token permissions for all owner users with this role when the role is deleted\n async beforeDelete(event) {\n const users = await strapi.db.query('admin::user').findMany({\n where: { roles: { id: event.params.where.id } },\n select: ['id'],\n });\n event.state.affectedUserIds = users.map((u: { id: unknown }) => u.id);\n },\n async afterDelete(event) {\n for (const userId of (event.state.affectedUserIds as unknown[]) ?? []) {\n await getService('api-token-admin').syncPermissionsForUser(userId as string | number);\n }\n },\n });\n};\n\nconst syncAuthSettings = async () => {\n const adminStore = await strapi.store({ type: 'core', name: 'admin' });\n const adminAuthSettings = await adminStore.get({ key: 'auth' });\n const newAuthSettings = merge(defaultAdminAuthSettings, adminAuthSettings);\n\n const roleExists = await getService('role').exists({\n id: newAuthSettings.providers.defaultRole,\n });\n\n // Reset the default SSO role if it has been deleted manually\n if (!roleExists) {\n newAuthSettings.providers.defaultRole = null;\n }\n\n await adminStore.set({ key: 'auth', value: newAuthSettings });\n};\n\nconst syncAPITokensPermissions = async () => {\n const validPermissions = strapi.contentAPI.permissions.providers.action.keys();\n const permissionsInDB = await async.pipe(\n strapi.db.query('admin::api-token-permission').findMany,\n map('action')\n )();\n\n const unknownPermissions = uniq(difference(permissionsInDB, validPermissions));\n\n if (unknownPermissions.length > 0) {\n await strapi.db\n .query('admin::api-token-permission')\n .deleteMany({ where: { action: { $in: unknownPermissions } } });\n }\n};\n\n/**\n * Ensures the creation of default API tokens during the app creation.\n *\n * Checks the database for existing users and API tokens:\n * - If there are no users and no API tokens, it creates two default API tokens:\n * 1. A \"Read Only\" API token with permissions for accessing resources.\n * 2. A \"Full Access\" API token with permissions for accessing and modifying resources.\n *\n * @sideEffects Creates new API tokens in the database if conditions are met.\n */\n\nconst createDefaultAPITokensIfNeeded = async () => {\n const userService = getService('user');\n const apiTokenService = getService('api-token-content-api');\n\n const usersCount = await userService.count();\n const apiTokenCount = await apiTokenService.countAll();\n\n if (usersCount === 0 && apiTokenCount === 0) {\n for (const token of constants.DEFAULT_API_TOKENS) {\n await apiTokenService.create(token);\n }\n }\n};\n\nexport default async ({ strapi }: { strapi: Core.Strapi }) => {\n // Get the merged token options (includes defaults merged with user config)\n const { options } = getTokenOptions();\n const legacyMaxRefreshFallback =\n expiresInToSeconds(options?.expiresIn) ?? DEFAULT_MAX_REFRESH_TOKEN_LIFESPAN;\n const legacyMaxSessionFallback =\n expiresInToSeconds(options?.expiresIn) ?? DEFAULT_MAX_SESSION_LIFESPAN;\n\n // Warn only when the user set legacy admin.auth.options.expiresIn. Merged JWT options always\n // include the default expiresIn ('30d'), so reading merged options alone is a false positive.\n const hasLegacyExpires = hasUserConfiguredAuthOptionsExpiresIn(\n strapi.config.get('admin.auth.options')\n );\n const hasNewMaxRefresh = strapi.config.get('admin.auth.sessions.maxRefreshTokenLifespan') != null;\n const hasNewMaxSession = strapi.config.get('admin.auth.sessions.maxSessionLifespan') != null;\n\n if (hasLegacyExpires && (!hasNewMaxRefresh || !hasNewMaxSession)) {\n strapi.log.warn(\n 'admin.auth.options.expiresIn is deprecated and will be removed in Strapi 6. Please configure admin.auth.sessions.maxRefreshTokenLifespan and admin.auth.sessions.maxSessionLifespan.'\n );\n }\n\n strapi.sessionManager.defineOrigin('admin', {\n jwtSecret: strapi.config.get('admin.auth.secret'),\n accessTokenLifespan: strapi.config.get('admin.auth.sessions.accessTokenLifespan', 30 * 60),\n maxRefreshTokenLifespan: strapi.config.get(\n 'admin.auth.sessions.maxRefreshTokenLifespan',\n legacyMaxRefreshFallback\n ),\n idleRefreshTokenLifespan: strapi.config.get(\n 'admin.auth.sessions.idleRefreshTokenLifespan',\n DEFAULT_IDLE_REFRESH_TOKEN_LIFESPAN\n ),\n maxSessionLifespan: strapi.config.get(\n 'admin.auth.sessions.maxSessionLifespan',\n legacyMaxSessionFallback\n ),\n idleSessionLifespan: strapi.config.get(\n 'admin.auth.sessions.idleSessionLifespan',\n DEFAULT_IDLE_SESSION_LIFESPAN\n ),\n algorithm: options?.algorithm,\n // Pass through all JWT options (includes privateKey, publicKey, and any other options)\n jwtOptions: options,\n });\n\n const isProduction = process.env.NODE_ENV === 'production';\n const adminCookieSecure = strapi.config.get('admin.auth.cookie.secure');\n if (isProduction && adminCookieSecure === false) {\n strapi.log.warn(\n 'Server is in production mode, but admin.auth.cookie.secure has been set to false. This is not recommended and will allow cookies to be sent over insecure connections.'\n );\n }\n\n await registerAdminConditions();\n await registerPermissionActions();\n registerModelHooks();\n\n const permissionService = getService('permission');\n const userService = getService('user');\n const roleService = getService('role');\n const apiTokenService = getService('api-token-content-api');\n const transferService = getService('transfer');\n const tokenService = getService('token');\n\n await roleService.createRolesIfNoneExist();\n await roleService.resetSuperAdminPermissions();\n await roleService.displayWarningIfNoSuperAdmin();\n\n await permissionService.cleanPermissionsInDatabase();\n\n await userService.displayWarningIfUsersDontHaveRole();\n\n await syncAuthSettings();\n await syncAPITokensPermissions();\n\n await getService('metrics').sendUpdateProjectInformation(strapi);\n getService('metrics').startCron(strapi);\n\n apiTokenService.checkSaltIsDefined();\n transferService.token.checkSaltIsDefined();\n tokenService.checkSecretIsDefined();\n\n await createDefaultAPITokensIfNeeded();\n};\n"],"names":["defaultAdminAuthSettings","providers","autoRegister","defaultRole","ssoLockedRoles","registerPermissionActions","getService","actionProvider","registerMany","adminActions","actions","registerAdminConditions","conditionProvider","adminConditions","conditions","registerModelHooks","sendDidChangeInterfaceLanguage","strapi","db","lifecycles","subscribe","models","afterCreate","afterDelete","beforeDelete","event","deleteTokensForUser","params","where","id","afterUpdate","data","preferedLanguage","roles","undefined","syncPermissionsForUser","result","users","query","findMany","select","state","affectedUserIds","map","u","userId","syncAuthSettings","adminStore","store","type","name","adminAuthSettings","get","key","newAuthSettings","merge","roleExists","exists","set","value","syncAPITokensPermissions","validPermissions","contentAPI","permissions","action","keys","permissionsInDB","async","pipe","unknownPermissions","uniq","difference","length","deleteMany","$in","createDefaultAPITokensIfNeeded","userService","apiTokenService","usersCount","count","apiTokenCount","countAll","token","constants","DEFAULT_API_TOKENS","create","options","getTokenOptions","legacyMaxRefreshFallback","expiresInToSeconds","expiresIn","DEFAULT_MAX_REFRESH_TOKEN_LIFESPAN","legacyMaxSessionFallback","DEFAULT_MAX_SESSION_LIFESPAN","hasLegacyExpires","hasUserConfiguredAuthOptionsExpiresIn","config","hasNewMaxRefresh","hasNewMaxSession","log","warn","sessionManager","defineOrigin","jwtSecret","accessTokenLifespan","maxRefreshTokenLifespan","idleRefreshTokenLifespan","DEFAULT_IDLE_REFRESH_TOKEN_LIFESPAN","maxSessionLifespan","idleSessionLifespan","DEFAULT_IDLE_SESSION_LIFESPAN","algorithm","jwtOptions","isProduction","process","env","NODE_ENV","adminCookieSecure","permissionService","roleService","transferService","tokenService","createRolesIfNoneExist","resetSuperAdminPermissions","displayWarningIfNoSuperAdmin","cleanPermissionsInDatabase","displayWarningIfUsersDontHaveRole","sendUpdateProjectInformation","startCron","checkSaltIsDefined","checkSecretIsDefined"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"bootstrap.mjs","sources":["../../../../server/src/bootstrap.ts"],"sourcesContent":["import { map, merge, difference } from 'lodash';\n\nimport type { Core } from '@strapi/types';\nimport { async } from '@strapi/utils';\nimport { getService } from './utils';\nimport {\n getTokenOptions,\n expiresInToSeconds,\n hasUserConfiguredAuthOptionsExpiresIn,\n} from './services/token';\nimport adminActions from './config/admin-actions';\nimport adminConditions from './config/admin-conditions';\nimport constants from './services/constants';\nimport {\n DEFAULT_MAX_REFRESH_TOKEN_LIFESPAN,\n DEFAULT_IDLE_REFRESH_TOKEN_LIFESPAN,\n DEFAULT_MAX_SESSION_LIFESPAN,\n DEFAULT_IDLE_SESSION_LIFESPAN,\n} from '../../shared/utils/session-auth';\n\nconst defaultAdminAuthSettings = {\n providers: {\n autoRegister: false,\n defaultRole: null,\n ssoLockedRoles: null,\n },\n};\n\nconst registerPermissionActions = async () => {\n await getService('permission').actionProvider.registerMany(adminActions.actions);\n};\n\nconst registerAdminConditions = async () => {\n await getService('permission').conditionProvider.registerMany(adminConditions.conditions);\n};\n\nconst registerModelHooks = () => {\n const { sendDidChangeInterfaceLanguage } = getService('metrics');\n\n strapi.db.lifecycles.subscribe({\n models: ['admin::user'],\n afterCreate: sendDidChangeInterfaceLanguage,\n afterDelete: sendDidChangeInterfaceLanguage,\n async beforeDelete(event) {\n // Delete all admin API tokens owned by this user before the user row is removed\n await getService('api-token-admin').deleteTokensForUser(event.params.where.id);\n },\n async afterUpdate(event) {\n if (event.params.data?.preferedLanguage) {\n sendDidChangeInterfaceLanguage();\n }\n if (event.params.data?.roles !== undefined) {\n // We re-sync token permissions for all owner users with their role when the user is updated\n await getService('api-token-admin').syncPermissionsForUser(event.result.id);\n }\n },\n });\n\n strapi.db.lifecycles.subscribe({\n models: ['admin::role'],\n // We re-sync token permissions for all owner users with this role when the role is deleted\n async beforeDelete(event) {\n const users = await strapi.db.query('admin::user').findMany({\n where: { roles: { id: event.params.where.id } },\n select: ['id'],\n });\n event.state.affectedUserIds = users.map((u: { id: unknown }) => u.id);\n },\n async afterDelete(event) {\n for (const userId of (event.state.affectedUserIds as unknown[]) ?? []) {\n await getService('api-token-admin').syncPermissionsForUser(userId as string | number);\n }\n },\n });\n};\n\nconst syncAuthSettings = async () => {\n const adminStore = await strapi.store({ type: 'core', name: 'admin' });\n const adminAuthSettings = await adminStore.get({ key: 'auth' });\n const newAuthSettings = merge({}, defaultAdminAuthSettings, adminAuthSettings);\n\n const roleExists = await getService('role').exists({\n id: newAuthSettings.providers.defaultRole,\n });\n\n // Reset the default SSO role if it has been deleted manually\n if (!roleExists) {\n newAuthSettings.providers.defaultRole = null;\n }\n\n await adminStore.set({ key: 'auth', value: newAuthSettings });\n};\n\nconst syncAPITokensPermissions = async () => {\n const validPermissions = strapi.contentAPI.permissions.providers.action.keys();\n const permissionsInDB = await async.pipe(\n strapi.db.query('admin::api-token-permission').findMany,\n (permissions) => map(permissions, 'action')\n )();\n\n const unknownPermissions = [...new Set(difference(permissionsInDB, validPermissions))];\n\n if (unknownPermissions.length > 0) {\n await strapi.db\n .query('admin::api-token-permission')\n .deleteMany({ where: { action: { $in: unknownPermissions } } });\n }\n};\n\n/**\n * Ensures the creation of default API tokens during the app creation.\n *\n * Checks the database for existing users and API tokens:\n * - If there are no users and no API tokens, it creates two default API tokens:\n * 1. A \"Read Only\" API token with permissions for accessing resources.\n * 2. A \"Full Access\" API token with permissions for accessing and modifying resources.\n *\n * @sideEffects Creates new API tokens in the database if conditions are met.\n */\n\nconst createDefaultAPITokensIfNeeded = async () => {\n const userService = getService('user');\n const apiTokenService = getService('api-token-content-api');\n\n const usersCount = await userService.count();\n const apiTokenCount = await apiTokenService.countAll();\n\n if (usersCount === 0 && apiTokenCount === 0) {\n for (const token of constants.DEFAULT_API_TOKENS) {\n await apiTokenService.create(token);\n }\n }\n};\n\nexport default async ({ strapi }: { strapi: Core.Strapi }) => {\n // Get the merged token options (includes defaults merged with user config)\n const { options } = getTokenOptions();\n const legacyMaxRefreshFallback =\n expiresInToSeconds(options?.expiresIn) ?? DEFAULT_MAX_REFRESH_TOKEN_LIFESPAN;\n const legacyMaxSessionFallback =\n expiresInToSeconds(options?.expiresIn) ?? DEFAULT_MAX_SESSION_LIFESPAN;\n\n // Warn only when the user set legacy admin.auth.options.expiresIn. Merged JWT options always\n // include the default expiresIn ('30d'), so reading merged options alone is a false positive.\n const hasLegacyExpires = hasUserConfiguredAuthOptionsExpiresIn(\n strapi.config.get('admin.auth.options')\n );\n const hasNewMaxRefresh = strapi.config.get('admin.auth.sessions.maxRefreshTokenLifespan') != null;\n const hasNewMaxSession = strapi.config.get('admin.auth.sessions.maxSessionLifespan') != null;\n\n if (hasLegacyExpires && (!hasNewMaxRefresh || !hasNewMaxSession)) {\n strapi.log.warn(\n 'admin.auth.options.expiresIn is deprecated and will be removed in Strapi 6. Please configure admin.auth.sessions.maxRefreshTokenLifespan and admin.auth.sessions.maxSessionLifespan.'\n );\n }\n\n strapi.sessionManager.defineOrigin('admin', {\n jwtSecret: strapi.config.get('admin.auth.secret'),\n accessTokenLifespan: strapi.config.get('admin.auth.sessions.accessTokenLifespan', 30 * 60),\n maxRefreshTokenLifespan: strapi.config.get(\n 'admin.auth.sessions.maxRefreshTokenLifespan',\n legacyMaxRefreshFallback\n ),\n idleRefreshTokenLifespan: strapi.config.get(\n 'admin.auth.sessions.idleRefreshTokenLifespan',\n DEFAULT_IDLE_REFRESH_TOKEN_LIFESPAN\n ),\n maxSessionLifespan: strapi.config.get(\n 'admin.auth.sessions.maxSessionLifespan',\n legacyMaxSessionFallback\n ),\n idleSessionLifespan: strapi.config.get(\n 'admin.auth.sessions.idleSessionLifespan',\n DEFAULT_IDLE_SESSION_LIFESPAN\n ),\n algorithm: options?.algorithm,\n // Pass through all JWT options (includes privateKey, publicKey, and any other options)\n jwtOptions: options,\n });\n\n const isProduction = process.env.NODE_ENV === 'production';\n const adminCookieSecure = strapi.config.get('admin.auth.cookie.secure');\n if (isProduction && adminCookieSecure === false) {\n strapi.log.warn(\n 'Server is in production mode, but admin.auth.cookie.secure has been set to false. This is not recommended and will allow cookies to be sent over insecure connections.'\n );\n }\n\n await registerAdminConditions();\n await registerPermissionActions();\n registerModelHooks();\n\n const permissionService = getService('permission');\n const userService = getService('user');\n const roleService = getService('role');\n const apiTokenService = getService('api-token-content-api');\n const transferService = getService('transfer');\n const tokenService = getService('token');\n\n await roleService.createRolesIfNoneExist();\n await roleService.resetSuperAdminPermissions();\n await roleService.displayWarningIfNoSuperAdmin();\n\n await permissionService.cleanPermissionsInDatabase();\n\n await userService.displayWarningIfUsersDontHaveRole();\n\n await syncAuthSettings();\n await syncAPITokensPermissions();\n\n await getService('metrics').sendUpdateProjectInformation(strapi);\n getService('metrics').startCron(strapi);\n\n apiTokenService.checkSaltIsDefined();\n transferService.token.checkSaltIsDefined();\n tokenService.checkSecretIsDefined();\n\n await createDefaultAPITokensIfNeeded();\n};\n"],"names":["defaultAdminAuthSettings","providers","autoRegister","defaultRole","ssoLockedRoles","registerPermissionActions","getService","actionProvider","registerMany","adminActions","actions","registerAdminConditions","conditionProvider","adminConditions","conditions","registerModelHooks","sendDidChangeInterfaceLanguage","strapi","db","lifecycles","subscribe","models","afterCreate","afterDelete","beforeDelete","event","deleteTokensForUser","params","where","id","afterUpdate","data","preferedLanguage","roles","undefined","syncPermissionsForUser","result","users","query","findMany","select","state","affectedUserIds","map","u","userId","syncAuthSettings","adminStore","store","type","name","adminAuthSettings","get","key","newAuthSettings","merge","roleExists","exists","set","value","syncAPITokensPermissions","validPermissions","contentAPI","permissions","action","keys","permissionsInDB","async","pipe","unknownPermissions","Set","difference","length","deleteMany","$in","createDefaultAPITokensIfNeeded","userService","apiTokenService","usersCount","count","apiTokenCount","countAll","token","constants","DEFAULT_API_TOKENS","create","options","getTokenOptions","legacyMaxRefreshFallback","expiresInToSeconds","expiresIn","DEFAULT_MAX_REFRESH_TOKEN_LIFESPAN","legacyMaxSessionFallback","DEFAULT_MAX_SESSION_LIFESPAN","hasLegacyExpires","hasUserConfiguredAuthOptionsExpiresIn","config","hasNewMaxRefresh","hasNewMaxSession","log","warn","sessionManager","defineOrigin","jwtSecret","accessTokenLifespan","maxRefreshTokenLifespan","idleRefreshTokenLifespan","DEFAULT_IDLE_REFRESH_TOKEN_LIFESPAN","maxSessionLifespan","idleSessionLifespan","DEFAULT_IDLE_SESSION_LIFESPAN","algorithm","jwtOptions","isProduction","process","env","NODE_ENV","adminCookieSecure","permissionService","roleService","transferService","tokenService","createRolesIfNoneExist","resetSuperAdminPermissions","displayWarningIfNoSuperAdmin","cleanPermissionsInDatabase","displayWarningIfUsersDontHaveRole","sendUpdateProjectInformation","startCron","checkSaltIsDefined","checkSecretIsDefined"],"mappings":"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"}
|
|
@@ -229,6 +229,13 @@ const actions = [
|
|
|
229
229
|
section: 'settings',
|
|
230
230
|
category: 'project'
|
|
231
231
|
},
|
|
232
|
+
{
|
|
233
|
+
uid: 'debug-dump.read',
|
|
234
|
+
displayName: 'Generate a support debug dump',
|
|
235
|
+
pluginName: 'admin',
|
|
236
|
+
section: 'settings',
|
|
237
|
+
category: 'debug and support'
|
|
238
|
+
},
|
|
232
239
|
{
|
|
233
240
|
uid: 'transfer.tokens.access',
|
|
234
241
|
displayName: 'Access the transfer tokens settings page',
|