@strapi/admin 5.29.0 → 5.30.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (375) hide show
  1. package/dist/admin/admin/src/StrapiApp.js.map +1 -1
  2. package/dist/admin/admin/src/StrapiApp.mjs.map +1 -1
  3. package/dist/admin/admin/src/components/ContentBox.js.map +1 -1
  4. package/dist/admin/admin/src/components/ContentBox.mjs.map +1 -1
  5. package/dist/admin/admin/src/components/DescriptionComponentRenderer.js.map +1 -1
  6. package/dist/admin/admin/src/components/DescriptionComponentRenderer.mjs.map +1 -1
  7. package/dist/admin/admin/src/components/Filters.js +1 -1
  8. package/dist/admin/admin/src/components/Filters.js.map +1 -1
  9. package/dist/admin/admin/src/components/Filters.mjs +1 -1
  10. package/dist/admin/admin/src/components/Filters.mjs.map +1 -1
  11. package/dist/admin/admin/src/components/Form.js +8 -3
  12. package/dist/admin/admin/src/components/Form.js.map +1 -1
  13. package/dist/admin/admin/src/components/Form.mjs +8 -3
  14. package/dist/admin/admin/src/components/Form.mjs.map +1 -1
  15. package/dist/admin/admin/src/components/FormInputs/Enumeration.js +1 -1
  16. package/dist/admin/admin/src/components/FormInputs/Enumeration.js.map +1 -1
  17. package/dist/admin/admin/src/components/FormInputs/Enumeration.mjs +1 -1
  18. package/dist/admin/admin/src/components/FormInputs/Enumeration.mjs.map +1 -1
  19. package/dist/admin/admin/src/components/FormInputs/Number.js +1 -1
  20. package/dist/admin/admin/src/components/FormInputs/Number.js.map +1 -1
  21. package/dist/admin/admin/src/components/FormInputs/Number.mjs +1 -1
  22. package/dist/admin/admin/src/components/FormInputs/Number.mjs.map +1 -1
  23. package/dist/admin/admin/src/components/FormInputs/Renderer.js.map +1 -1
  24. package/dist/admin/admin/src/components/FormInputs/Renderer.mjs.map +1 -1
  25. package/dist/admin/admin/src/components/FormInputs/String.js +2 -1
  26. package/dist/admin/admin/src/components/FormInputs/String.js.map +1 -1
  27. package/dist/admin/admin/src/components/FormInputs/String.mjs +2 -1
  28. package/dist/admin/admin/src/components/FormInputs/String.mjs.map +1 -1
  29. package/dist/admin/admin/src/components/FormInputs/Time.js.map +1 -1
  30. package/dist/admin/admin/src/components/FormInputs/Time.mjs.map +1 -1
  31. package/dist/admin/admin/src/components/GapDropZone.js.map +1 -1
  32. package/dist/admin/admin/src/components/GapDropZone.mjs.map +1 -1
  33. package/dist/admin/admin/src/components/GuidedTour/Overview.js.map +1 -1
  34. package/dist/admin/admin/src/components/GuidedTour/Overview.mjs.map +1 -1
  35. package/dist/admin/admin/src/components/GuidedTour/Steps/ContentTypeBuilderSteps.js.map +1 -1
  36. package/dist/admin/admin/src/components/GuidedTour/Steps/ContentTypeBuilderSteps.mjs.map +1 -1
  37. package/dist/admin/admin/src/components/GuidedTour/Steps/Step.js.map +1 -1
  38. package/dist/admin/admin/src/components/GuidedTour/Steps/Step.mjs.map +1 -1
  39. package/dist/admin/admin/src/components/Layouts/GridLayout.js.map +1 -1
  40. package/dist/admin/admin/src/components/Layouts/GridLayout.mjs.map +1 -1
  41. package/dist/admin/admin/src/components/Layouts/HeaderLayout.js +8 -4
  42. package/dist/admin/admin/src/components/Layouts/HeaderLayout.js.map +1 -1
  43. package/dist/admin/admin/src/components/Layouts/HeaderLayout.mjs +8 -4
  44. package/dist/admin/admin/src/components/Layouts/HeaderLayout.mjs.map +1 -1
  45. package/dist/admin/admin/src/components/NpsSurvey.js +5 -3
  46. package/dist/admin/admin/src/components/NpsSurvey.js.map +1 -1
  47. package/dist/admin/admin/src/components/NpsSurvey.mjs +5 -3
  48. package/dist/admin/admin/src/components/NpsSurvey.mjs.map +1 -1
  49. package/dist/admin/admin/src/components/PageHelpers.js.map +1 -1
  50. package/dist/admin/admin/src/components/PageHelpers.mjs.map +1 -1
  51. package/dist/admin/admin/src/components/PrivateRoute.js.map +1 -1
  52. package/dist/admin/admin/src/components/PrivateRoute.mjs.map +1 -1
  53. package/dist/admin/admin/src/components/RelativeTime.js.map +1 -1
  54. package/dist/admin/admin/src/components/RelativeTime.mjs.map +1 -1
  55. package/dist/admin/admin/src/components/ResizeIndicator.js.map +1 -1
  56. package/dist/admin/admin/src/components/ResizeIndicator.mjs.map +1 -1
  57. package/dist/admin/admin/src/components/Table.js +1 -1
  58. package/dist/admin/admin/src/components/Table.js.map +1 -1
  59. package/dist/admin/admin/src/components/Table.mjs +1 -1
  60. package/dist/admin/admin/src/components/Table.mjs.map +1 -1
  61. package/dist/admin/admin/src/components/Theme.js +34 -1
  62. package/dist/admin/admin/src/components/Theme.js.map +1 -1
  63. package/dist/admin/admin/src/components/Theme.mjs +34 -1
  64. package/dist/admin/admin/src/components/Theme.mjs.map +1 -1
  65. package/dist/admin/admin/src/components/Widgets.js.map +1 -1
  66. package/dist/admin/admin/src/components/Widgets.mjs.map +1 -1
  67. package/dist/admin/admin/src/core/apis/CustomFields.js.map +1 -1
  68. package/dist/admin/admin/src/core/apis/CustomFields.mjs.map +1 -1
  69. package/dist/admin/admin/src/core/apis/Plugin.js +0 -1
  70. package/dist/admin/admin/src/core/apis/Plugin.js.map +1 -1
  71. package/dist/admin/admin/src/core/apis/Plugin.mjs +0 -1
  72. package/dist/admin/admin/src/core/apis/Plugin.mjs.map +1 -1
  73. package/dist/admin/admin/src/core/apis/Widgets.js.map +1 -1
  74. package/dist/admin/admin/src/core/apis/Widgets.mjs.map +1 -1
  75. package/dist/admin/admin/src/core/apis/rbac.js.map +1 -1
  76. package/dist/admin/admin/src/core/apis/rbac.mjs.map +1 -1
  77. package/dist/admin/admin/src/core/apis/router.js.map +1 -1
  78. package/dist/admin/admin/src/core/apis/router.mjs.map +1 -1
  79. package/dist/admin/admin/src/features/BackButton.js.map +1 -1
  80. package/dist/admin/admin/src/features/BackButton.mjs.map +1 -1
  81. package/dist/admin/admin/src/features/Tracking.js.map +1 -1
  82. package/dist/admin/admin/src/features/Tracking.mjs.map +1 -1
  83. package/dist/admin/admin/src/features/Widgets.js.map +1 -1
  84. package/dist/admin/admin/src/features/Widgets.mjs.map +1 -1
  85. package/dist/admin/admin/src/hooks/usePersistentState.js.map +1 -1
  86. package/dist/admin/admin/src/hooks/usePersistentState.mjs.map +1 -1
  87. package/dist/admin/admin/src/hooks/useRBAC.js.map +1 -1
  88. package/dist/admin/admin/src/hooks/useRBAC.mjs.map +1 -1
  89. package/dist/admin/admin/src/pages/Auth/components/Login.js +1 -1
  90. package/dist/admin/admin/src/pages/Auth/components/Login.js.map +1 -1
  91. package/dist/admin/admin/src/pages/Auth/components/Login.mjs +1 -1
  92. package/dist/admin/admin/src/pages/Auth/components/Login.mjs.map +1 -1
  93. package/dist/admin/admin/src/pages/Auth/components/Register.js.map +1 -1
  94. package/dist/admin/admin/src/pages/Auth/components/Register.mjs.map +1 -1
  95. package/dist/admin/admin/src/pages/Home/HomePage.js.map +1 -1
  96. package/dist/admin/admin/src/pages/Home/HomePage.mjs.map +1 -1
  97. package/dist/admin/admin/src/pages/Marketplace/MarketplacePage.js +2 -2
  98. package/dist/admin/admin/src/pages/Marketplace/MarketplacePage.js.map +1 -1
  99. package/dist/admin/admin/src/pages/Marketplace/MarketplacePage.mjs +2 -2
  100. package/dist/admin/admin/src/pages/Marketplace/MarketplacePage.mjs.map +1 -1
  101. package/dist/admin/admin/src/pages/Marketplace/components/NpmPackageCard.js.map +1 -1
  102. package/dist/admin/admin/src/pages/Marketplace/components/NpmPackageCard.mjs.map +1 -1
  103. package/dist/admin/admin/src/pages/Marketplace/components/NpmPackagesFilters.js.map +1 -1
  104. package/dist/admin/admin/src/pages/Marketplace/components/NpmPackagesFilters.mjs.map +1 -1
  105. package/dist/admin/admin/src/pages/Marketplace/components/PageHeader.js.map +1 -1
  106. package/dist/admin/admin/src/pages/Marketplace/components/PageHeader.mjs.map +1 -1
  107. package/dist/admin/admin/src/pages/Marketplace/hooks/useMarketplaceData.js.map +1 -1
  108. package/dist/admin/admin/src/pages/Marketplace/hooks/useMarketplaceData.mjs.map +1 -1
  109. package/dist/admin/admin/src/pages/Settings/components/SettingsNav.js.map +1 -1
  110. package/dist/admin/admin/src/pages/Settings/components/SettingsNav.mjs.map +1 -1
  111. package/dist/admin/admin/src/pages/Settings/components/Tokens/FormHead.js +8 -1
  112. package/dist/admin/admin/src/pages/Settings/components/Tokens/FormHead.js.map +1 -1
  113. package/dist/admin/admin/src/pages/Settings/components/Tokens/FormHead.mjs +9 -2
  114. package/dist/admin/admin/src/pages/Settings/components/Tokens/FormHead.mjs.map +1 -1
  115. package/dist/admin/admin/src/pages/Settings/components/Tokens/LifeSpanInput.js.map +1 -1
  116. package/dist/admin/admin/src/pages/Settings/components/Tokens/LifeSpanInput.mjs.map +1 -1
  117. package/dist/admin/admin/src/pages/Settings/components/Tokens/Table.js.map +1 -1
  118. package/dist/admin/admin/src/pages/Settings/components/Tokens/Table.mjs.map +1 -1
  119. package/dist/admin/admin/src/pages/Settings/components/Tokens/TokenName.js +1 -0
  120. package/dist/admin/admin/src/pages/Settings/components/Tokens/TokenName.js.map +1 -1
  121. package/dist/admin/admin/src/pages/Settings/components/Tokens/TokenName.mjs +1 -0
  122. package/dist/admin/admin/src/pages/Settings/components/Tokens/TokenName.mjs.map +1 -1
  123. package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/EditView/EditViewPage.js.map +1 -1
  124. package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/EditView/EditViewPage.mjs.map +1 -1
  125. package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/EditView/components/CollapsableContentType.js.map +1 -1
  126. package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/EditView/components/CollapsableContentType.mjs.map +1 -1
  127. package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/EditView/utils/transformPermissionsData.js.map +1 -1
  128. package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/EditView/utils/transformPermissionsData.mjs.map +1 -1
  129. package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/ListView.js +2 -0
  130. package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/ListView.js.map +1 -1
  131. package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/ListView.mjs +2 -0
  132. package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/ListView.mjs.map +1 -1
  133. package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/ApplicationInfoPage.js.map +1 -1
  134. package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/ApplicationInfoPage.mjs.map +1 -1
  135. package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/components/LogoInput.js +1 -0
  136. package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/components/LogoInput.js.map +1 -1
  137. package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/components/LogoInput.mjs +1 -0
  138. package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/components/LogoInput.mjs.map +1 -1
  139. package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/utils/files.js.map +1 -1
  140. package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/utils/files.mjs.map +1 -1
  141. package/dist/admin/admin/src/pages/Settings/pages/InstalledPlugins.js.map +1 -1
  142. package/dist/admin/admin/src/pages/Settings/pages/InstalledPlugins.mjs.map +1 -1
  143. package/dist/admin/admin/src/pages/Settings/pages/Roles/CreatePage.js +10 -2
  144. package/dist/admin/admin/src/pages/Settings/pages/Roles/CreatePage.js.map +1 -1
  145. package/dist/admin/admin/src/pages/Settings/pages/Roles/CreatePage.mjs +10 -2
  146. package/dist/admin/admin/src/pages/Settings/pages/Roles/CreatePage.mjs.map +1 -1
  147. package/dist/admin/admin/src/pages/Settings/pages/Roles/EditPage.js +9 -2
  148. package/dist/admin/admin/src/pages/Settings/pages/Roles/EditPage.js.map +1 -1
  149. package/dist/admin/admin/src/pages/Settings/pages/Roles/EditPage.mjs +9 -2
  150. package/dist/admin/admin/src/pages/Settings/pages/Roles/EditPage.mjs.map +1 -1
  151. package/dist/admin/admin/src/pages/Settings/pages/Roles/ListPage.js.map +1 -1
  152. package/dist/admin/admin/src/pages/Settings/pages/Roles/ListPage.mjs.map +1 -1
  153. package/dist/admin/admin/src/pages/Settings/pages/Roles/components/CollapsePropertyMatrix.js.map +1 -1
  154. package/dist/admin/admin/src/pages/Settings/pages/Roles/components/CollapsePropertyMatrix.mjs.map +1 -1
  155. package/dist/admin/admin/src/pages/Settings/pages/Roles/components/ConditionsModal.js.map +1 -1
  156. package/dist/admin/admin/src/pages/Settings/pages/Roles/components/ConditionsModal.mjs.map +1 -1
  157. package/dist/admin/admin/src/pages/Settings/pages/Roles/components/ContentTypeCollapses.js.map +1 -1
  158. package/dist/admin/admin/src/pages/Settings/pages/Roles/components/ContentTypeCollapses.mjs.map +1 -1
  159. package/dist/admin/admin/src/pages/Settings/pages/Roles/components/GlobalActions.js.map +1 -1
  160. package/dist/admin/admin/src/pages/Settings/pages/Roles/components/GlobalActions.mjs.map +1 -1
  161. package/dist/admin/admin/src/pages/Settings/pages/Roles/components/Permissions.js.map +1 -1
  162. package/dist/admin/admin/src/pages/Settings/pages/Roles/components/Permissions.mjs.map +1 -1
  163. package/dist/admin/admin/src/pages/Settings/pages/Roles/components/PluginsAndSettings.js.map +1 -1
  164. package/dist/admin/admin/src/pages/Settings/pages/Roles/components/PluginsAndSettings.mjs.map +1 -1
  165. package/dist/admin/admin/src/pages/Settings/pages/Roles/components/RoleForm.js +2 -1
  166. package/dist/admin/admin/src/pages/Settings/pages/Roles/components/RoleForm.js.map +1 -1
  167. package/dist/admin/admin/src/pages/Settings/pages/Roles/components/RoleForm.mjs +2 -1
  168. package/dist/admin/admin/src/pages/Settings/pages/Roles/components/RoleForm.mjs.map +1 -1
  169. package/dist/admin/admin/src/pages/Settings/pages/Roles/utils/forms.js.map +1 -1
  170. package/dist/admin/admin/src/pages/Settings/pages/Roles/utils/forms.mjs.map +1 -1
  171. package/dist/admin/admin/src/pages/Settings/pages/Roles/utils/permissions.js.map +1 -1
  172. package/dist/admin/admin/src/pages/Settings/pages/Roles/utils/permissions.mjs.map +1 -1
  173. package/dist/admin/admin/src/pages/Settings/pages/TransferTokens/EditView.js.map +1 -1
  174. package/dist/admin/admin/src/pages/Settings/pages/TransferTokens/EditView.mjs.map +1 -1
  175. package/dist/admin/admin/src/pages/Settings/pages/TransferTokens/ListView.js +2 -0
  176. package/dist/admin/admin/src/pages/Settings/pages/TransferTokens/ListView.js.map +1 -1
  177. package/dist/admin/admin/src/pages/Settings/pages/TransferTokens/ListView.mjs +2 -0
  178. package/dist/admin/admin/src/pages/Settings/pages/TransferTokens/ListView.mjs.map +1 -1
  179. package/dist/admin/admin/src/pages/Settings/pages/Users/EditPage.js +9 -2
  180. package/dist/admin/admin/src/pages/Settings/pages/Users/EditPage.js.map +1 -1
  181. package/dist/admin/admin/src/pages/Settings/pages/Users/EditPage.mjs +9 -2
  182. package/dist/admin/admin/src/pages/Settings/pages/Users/EditPage.mjs.map +1 -1
  183. package/dist/admin/admin/src/pages/Settings/pages/Users/ListPage.js +3 -1
  184. package/dist/admin/admin/src/pages/Settings/pages/Users/ListPage.js.map +1 -1
  185. package/dist/admin/admin/src/pages/Settings/pages/Users/ListPage.mjs +3 -1
  186. package/dist/admin/admin/src/pages/Settings/pages/Users/ListPage.mjs.map +1 -1
  187. package/dist/admin/admin/src/pages/Settings/pages/Users/components/MagicLinkCE.js.map +1 -1
  188. package/dist/admin/admin/src/pages/Settings/pages/Users/components/MagicLinkCE.mjs.map +1 -1
  189. package/dist/admin/admin/src/pages/Settings/pages/Users/components/SelectRoles.js.map +1 -1
  190. package/dist/admin/admin/src/pages/Settings/pages/Users/components/SelectRoles.mjs.map +1 -1
  191. package/dist/admin/admin/src/pages/Settings/pages/Webhooks/EditPage.js.map +1 -1
  192. package/dist/admin/admin/src/pages/Settings/pages/Webhooks/EditPage.mjs.map +1 -1
  193. package/dist/admin/admin/src/pages/Settings/pages/Webhooks/ListPage.js.map +1 -1
  194. package/dist/admin/admin/src/pages/Settings/pages/Webhooks/ListPage.mjs.map +1 -1
  195. package/dist/admin/admin/src/pages/Settings/pages/Webhooks/components/HeadersInput.js +1 -1
  196. package/dist/admin/admin/src/pages/Settings/pages/Webhooks/components/HeadersInput.js.map +1 -1
  197. package/dist/admin/admin/src/pages/Settings/pages/Webhooks/components/HeadersInput.mjs +1 -1
  198. package/dist/admin/admin/src/pages/Settings/pages/Webhooks/components/HeadersInput.mjs.map +1 -1
  199. package/dist/admin/admin/src/pages/Settings/pages/Webhooks/components/WebhookForm.js +9 -2
  200. package/dist/admin/admin/src/pages/Settings/pages/Webhooks/components/WebhookForm.js.map +1 -1
  201. package/dist/admin/admin/src/pages/Settings/pages/Webhooks/components/WebhookForm.mjs +9 -2
  202. package/dist/admin/admin/src/pages/Settings/pages/Webhooks/components/WebhookForm.mjs.map +1 -1
  203. package/dist/admin/admin/src/pages/UseCasePage.js +1 -0
  204. package/dist/admin/admin/src/pages/UseCasePage.js.map +1 -1
  205. package/dist/admin/admin/src/pages/UseCasePage.mjs +1 -0
  206. package/dist/admin/admin/src/pages/UseCasePage.mjs.map +1 -1
  207. package/dist/admin/admin/src/services/api.js +2 -1
  208. package/dist/admin/admin/src/services/api.js.map +1 -1
  209. package/dist/admin/admin/src/services/api.mjs +2 -1
  210. package/dist/admin/admin/src/services/api.mjs.map +1 -1
  211. package/dist/admin/admin/src/services/apiTokens.js.map +1 -1
  212. package/dist/admin/admin/src/services/apiTokens.mjs.map +1 -1
  213. package/dist/admin/admin/src/services/transferTokens.js.map +1 -1
  214. package/dist/admin/admin/src/services/transferTokens.mjs.map +1 -1
  215. package/dist/admin/admin/src/services/users.js.map +1 -1
  216. package/dist/admin/admin/src/services/users.mjs.map +1 -1
  217. package/dist/admin/admin/src/services/webhooks.js.map +1 -1
  218. package/dist/admin/admin/src/services/webhooks.mjs.map +1 -1
  219. package/dist/admin/admin/src/translations/en.json.js +4 -0
  220. package/dist/admin/admin/src/translations/en.json.js.map +1 -1
  221. package/dist/admin/admin/src/translations/en.json.mjs +4 -0
  222. package/dist/admin/admin/src/translations/en.json.mjs.map +1 -1
  223. package/dist/admin/admin/src/utils/cookies.js.map +1 -1
  224. package/dist/admin/admin/src/utils/cookies.mjs.map +1 -1
  225. package/dist/admin/admin/src/utils/getFetchClient.js.map +1 -1
  226. package/dist/admin/admin/src/utils/getFetchClient.mjs.map +1 -1
  227. package/dist/admin/admin/src/utils/getPrefixedId.js.map +1 -1
  228. package/dist/admin/admin/src/utils/getPrefixedId.mjs.map +1 -1
  229. package/dist/admin/admin/src/utils/rulesEngine.js.map +1 -1
  230. package/dist/admin/admin/src/utils/rulesEngine.mjs.map +1 -1
  231. package/dist/admin/admin/src/utils/urls.js.map +1 -1
  232. package/dist/admin/admin/src/utils/urls.mjs.map +1 -1
  233. package/dist/admin/admin/src/utils/users.js.map +1 -1
  234. package/dist/admin/admin/src/utils/users.mjs.map +1 -1
  235. package/dist/admin/ee/admin/src/components/AuditLogs/Widgets.js.map +1 -1
  236. package/dist/admin/ee/admin/src/components/AuditLogs/Widgets.mjs.map +1 -1
  237. package/dist/admin/ee/admin/src/hooks/useLicenseLimitNotification.js.map +1 -1
  238. package/dist/admin/ee/admin/src/hooks/useLicenseLimitNotification.mjs.map +1 -1
  239. package/dist/admin/ee/admin/src/pages/AuthPage/components/SSOProviders.js.map +1 -1
  240. package/dist/admin/ee/admin/src/pages/AuthPage/components/SSOProviders.mjs.map +1 -1
  241. package/dist/admin/ee/admin/src/pages/AuthResponse.js.map +1 -1
  242. package/dist/admin/ee/admin/src/pages/AuthResponse.mjs.map +1 -1
  243. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/ApplicationInfoPage/components/AIUsage.js.map +1 -1
  244. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/ApplicationInfoPage/components/AIUsage.mjs.map +1 -1
  245. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/ListPage.js +3 -3
  246. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/ListPage.js.map +1 -1
  247. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/ListPage.mjs +3 -3
  248. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/ListPage.mjs.map +1 -1
  249. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/components/Modal.js.map +1 -1
  250. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/components/Modal.mjs.map +1 -1
  251. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/hooks/useFormatTimeStamp.js.map +1 -1
  252. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/hooks/useFormatTimeStamp.mjs.map +1 -1
  253. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/utils/getDisplayedFilters.js.map +1 -1
  254. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/utils/getDisplayedFilters.mjs.map +1 -1
  255. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/Users/components/MagicLinkEE.js.map +1 -1
  256. package/dist/admin/ee/admin/src/pages/SettingsPage/pages/Users/components/MagicLinkEE.mjs.map +1 -1
  257. package/dist/admin/ee/admin/src/services/ai.js +14 -1
  258. package/dist/admin/ee/admin/src/services/ai.js.map +1 -1
  259. package/dist/admin/ee/admin/src/services/ai.mjs +14 -2
  260. package/dist/admin/ee/admin/src/services/ai.mjs.map +1 -1
  261. package/dist/admin/ee/admin/src/services/auditLogs.js.map +1 -1
  262. package/dist/admin/ee/admin/src/services/auditLogs.mjs.map +1 -1
  263. package/dist/admin/ee.js +1 -0
  264. package/dist/admin/ee.js.map +1 -1
  265. package/dist/admin/ee.mjs +1 -1
  266. package/dist/admin/src/components/Form.d.ts +1 -1
  267. package/dist/admin/src/core/store/configure.d.ts +2 -2
  268. package/dist/admin/src/core/store/hooks.d.ts +2 -2
  269. package/dist/admin/src/ee.d.ts +1 -1
  270. package/dist/admin/src/hooks/useAdminRoles.d.ts +1 -1
  271. package/dist/admin/src/pages/Settings/pages/Webhooks/hooks/useWebhooks.d.ts +4 -4
  272. package/dist/admin/src/selectors.d.ts +2 -2
  273. package/dist/admin/src/services/admin.d.ts +6 -6
  274. package/dist/admin/src/services/api.d.ts +1 -1
  275. package/dist/admin/src/services/apiTokens.d.ts +1 -1
  276. package/dist/admin/src/services/auth.d.ts +13 -13
  277. package/dist/admin/src/services/contentApi.d.ts +1 -1
  278. package/dist/admin/src/services/contentManager.d.ts +1 -1
  279. package/dist/admin/src/services/homepage.d.ts +3 -3
  280. package/dist/admin/src/services/transferTokens.d.ts +1 -1
  281. package/dist/admin/src/services/users.d.ts +8 -8
  282. package/dist/admin/src/services/webhooks.d.ts +2 -2
  283. package/dist/admin/tests/utils.d.ts +1 -1
  284. package/dist/ee/admin/src/services/ai.d.ts +6 -3
  285. package/dist/ee/admin/src/services/auditLogs.d.ts +1 -1
  286. package/dist/ee/server/src/ai/containers/ai.d.ts +11 -0
  287. package/dist/ee/server/src/ai/containers/ai.d.ts.map +1 -0
  288. package/dist/ee/server/src/ai/controllers/ai.d.ts +1 -0
  289. package/dist/ee/server/src/ai/controllers/ai.d.ts.map +1 -1
  290. package/dist/ee/server/src/ai/routes/ai.d.ts.map +1 -1
  291. package/dist/ee/server/src/index.d.ts +1 -0
  292. package/dist/ee/server/src/index.d.ts.map +1 -1
  293. package/dist/server/ee/server/src/ai/containers/ai.js +18 -0
  294. package/dist/server/ee/server/src/ai/containers/ai.js.map +1 -0
  295. package/dist/server/ee/server/src/ai/containers/ai.mjs +16 -0
  296. package/dist/server/ee/server/src/ai/containers/ai.mjs.map +1 -0
  297. package/dist/server/ee/server/src/ai/controllers/ai.js +6 -0
  298. package/dist/server/ee/server/src/ai/controllers/ai.js.map +1 -1
  299. package/dist/server/ee/server/src/ai/controllers/ai.mjs +6 -0
  300. package/dist/server/ee/server/src/ai/controllers/ai.mjs.map +1 -1
  301. package/dist/server/ee/server/src/ai/routes/ai.js +11 -0
  302. package/dist/server/ee/server/src/ai/routes/ai.js.map +1 -1
  303. package/dist/server/ee/server/src/ai/routes/ai.mjs +11 -0
  304. package/dist/server/ee/server/src/ai/routes/ai.mjs.map +1 -1
  305. package/dist/server/ee/server/src/audit-logs/services/audit-logs.js.map +1 -1
  306. package/dist/server/ee/server/src/audit-logs/services/audit-logs.mjs.map +1 -1
  307. package/dist/server/ee/server/src/controllers/authentication-utils/constants.js.map +1 -1
  308. package/dist/server/ee/server/src/controllers/authentication-utils/constants.mjs.map +1 -1
  309. package/dist/server/ee/server/src/controllers/authentication-utils/utils.js.map +1 -1
  310. package/dist/server/ee/server/src/controllers/authentication-utils/utils.mjs.map +1 -1
  311. package/dist/server/ee/server/src/controllers/authentication.js.map +1 -1
  312. package/dist/server/ee/server/src/controllers/authentication.mjs.map +1 -1
  313. package/dist/server/ee/server/src/controllers/user.js.map +1 -1
  314. package/dist/server/ee/server/src/controllers/user.mjs.map +1 -1
  315. package/dist/server/ee/server/src/index.js +7 -0
  316. package/dist/server/ee/server/src/index.js.map +1 -1
  317. package/dist/server/ee/server/src/index.mjs +7 -0
  318. package/dist/server/ee/server/src/index.mjs.map +1 -1
  319. package/dist/server/ee/server/src/services/auth.js.map +1 -1
  320. package/dist/server/ee/server/src/services/auth.mjs.map +1 -1
  321. package/dist/server/ee/server/src/services/passport/sso.js.map +1 -1
  322. package/dist/server/ee/server/src/services/passport/sso.mjs.map +1 -1
  323. package/dist/server/ee/server/src/utils/index.js.map +1 -1
  324. package/dist/server/ee/server/src/utils/index.mjs.map +1 -1
  325. package/dist/server/server/src/controllers/transfer/index.js.map +1 -1
  326. package/dist/server/server/src/controllers/transfer/index.mjs.map +1 -1
  327. package/dist/server/server/src/controllers/user.js +10 -0
  328. package/dist/server/server/src/controllers/user.js.map +1 -1
  329. package/dist/server/server/src/controllers/user.mjs +10 -0
  330. package/dist/server/server/src/controllers/user.mjs.map +1 -1
  331. package/dist/server/server/src/domain/action/index.js.map +1 -1
  332. package/dist/server/server/src/domain/action/index.mjs.map +1 -1
  333. package/dist/server/server/src/domain/condition/index.js.map +1 -1
  334. package/dist/server/server/src/domain/condition/index.mjs.map +1 -1
  335. package/dist/server/server/src/domain/permission/index.js.map +1 -1
  336. package/dist/server/server/src/domain/permission/index.mjs.map +1 -1
  337. package/dist/server/server/src/middlewares/rateLimit.js.map +1 -1
  338. package/dist/server/server/src/middlewares/rateLimit.mjs.map +1 -1
  339. package/dist/server/server/src/routes/serve-admin-panel.js.map +1 -1
  340. package/dist/server/server/src/routes/serve-admin-panel.mjs.map +1 -1
  341. package/dist/server/server/src/services/api-token.js.map +1 -1
  342. package/dist/server/server/src/services/api-token.mjs.map +1 -1
  343. package/dist/server/server/src/services/auth.js.map +1 -1
  344. package/dist/server/server/src/services/auth.mjs.map +1 -1
  345. package/dist/server/server/src/services/content-type.js.map +1 -1
  346. package/dist/server/server/src/services/content-type.mjs.map +1 -1
  347. package/dist/server/server/src/services/encryption.js.map +1 -1
  348. package/dist/server/server/src/services/encryption.mjs.map +1 -1
  349. package/dist/server/server/src/services/homepage.js.map +1 -1
  350. package/dist/server/server/src/services/homepage.mjs.map +1 -1
  351. package/dist/server/server/src/services/permission/permissions-manager/sanitize.js.map +1 -1
  352. package/dist/server/server/src/services/permission/permissions-manager/sanitize.mjs.map +1 -1
  353. package/dist/server/server/src/services/permission/permissions-manager/validate.js.map +1 -1
  354. package/dist/server/server/src/services/permission/permissions-manager/validate.mjs.map +1 -1
  355. package/dist/server/server/src/services/role.js.map +1 -1
  356. package/dist/server/server/src/services/role.mjs.map +1 -1
  357. package/dist/server/server/src/services/transfer/token.js.map +1 -1
  358. package/dist/server/server/src/services/transfer/token.mjs.map +1 -1
  359. package/dist/server/server/src/services/user.js +30 -0
  360. package/dist/server/server/src/services/user.js.map +1 -1
  361. package/dist/server/server/src/services/user.mjs +30 -0
  362. package/dist/server/server/src/services/user.mjs.map +1 -1
  363. package/dist/server/server/src/utils/index.js.map +1 -1
  364. package/dist/server/server/src/utils/index.mjs.map +1 -1
  365. package/dist/server/server/src/validation/action-provider.js.map +1 -1
  366. package/dist/server/server/src/validation/action-provider.mjs.map +1 -1
  367. package/dist/server/server/src/validation/common-functions/check-fields-are-correctly-nested.js.map +1 -1
  368. package/dist/server/server/src/validation/common-functions/check-fields-are-correctly-nested.mjs.map +1 -1
  369. package/dist/server/server/src/validation/common-validators.js.map +1 -1
  370. package/dist/server/server/src/validation/common-validators.mjs.map +1 -1
  371. package/dist/server/src/controllers/user.d.ts.map +1 -1
  372. package/dist/server/src/services/user.d.ts.map +1 -1
  373. package/dist/shared/contracts/ai.d.ts +16 -0
  374. package/dist/shared/contracts/ai.d.ts.map +1 -1
  375. package/package.json +7 -7
@@ -1 +1 @@
1
- {"version":3,"file":"serve-admin-panel.mjs","sources":["../../../../../server/src/routes/serve-admin-panel.ts"],"sourcesContent":["import type { Context, Next } from 'koa';\nimport { resolve, join, extname, basename } from 'path';\nimport fse from 'fs-extra';\nimport koaStatic from 'koa-static';\nimport type { Core } from '@strapi/types';\n\nconst registerAdminPanelRoute = ({ strapi }: { strapi: Core.Strapi }) => {\n let buildDir = resolve(strapi.dirs.dist.root, 'build');\n\n if (!fse.pathExistsSync(buildDir)) {\n buildDir = resolve(__dirname, '../../build');\n }\n\n const serveAdminMiddleware = async (ctx: Context, next: Next) => {\n await next();\n\n if (ctx.method !== 'HEAD' && ctx.method !== 'GET') {\n return;\n }\n\n if (ctx.body != null || ctx.status !== 404) {\n return;\n }\n\n ctx.type = 'html';\n ctx.body = fse.createReadStream(join(buildDir, 'index.html'));\n };\n\n strapi.server.routes([\n {\n method: 'GET',\n path: `${strapi.config.admin.path}/:path*`,\n handler: [\n serveAdminMiddleware,\n serveStatic(buildDir, {\n maxage: 31536000,\n defer: false,\n index: 'index.html',\n setHeaders(res: any, path: any) {\n const ext = extname(path);\n // publicly cache static files to avoid unnecessary network & disk access\n if (ext !== '.html') {\n res.setHeader('cache-control', 'public, max-age=31536000, immutable');\n }\n },\n }),\n ],\n config: { auth: false },\n },\n ]);\n};\n\n// serveStatic is not supposed to be used to serve a folder that have sub-folders\nconst serveStatic = (filesDir: any, koaStaticOptions = {}) => {\n const serve = koaStatic(filesDir, koaStaticOptions);\n\n return async (ctx: Context, next: Next) => {\n const prev = ctx.path;\n const newPath = basename(ctx.path);\n\n ctx.path = newPath;\n await serve(ctx, async () => {\n ctx.path = prev;\n await next();\n ctx.path = newPath;\n });\n ctx.path = prev;\n };\n};\n\nexport default registerAdminPanelRoute;\n"],"names":["registerAdminPanelRoute","strapi","buildDir","resolve","dirs","dist","root","fse","pathExistsSync","__dirname","serveAdminMiddleware","ctx","next","method","body","status","type","createReadStream","join","server","routes","path","config","admin","handler","serveStatic","maxage","defer","index","setHeaders","res","ext","extname","setHeader","auth","filesDir","koaStaticOptions","serve","koaStatic","prev","newPath","basename"],"mappings":";;;;AAMA,MAAMA,uBAA0B,GAAA,CAAC,EAAEC,MAAM,EAA2B,GAAA;IAClE,IAAIC,QAAAA,GAAWC,QAAQF,MAAOG,CAAAA,IAAI,CAACC,IAAI,CAACC,IAAI,EAAE,OAAA,CAAA;AAE9C,IAAA,IAAI,CAACC,GAAAA,CAAIC,cAAc,CAACN,QAAW,CAAA,EAAA;AACjCA,QAAAA,QAAAA,GAAWC,QAAQM,SAAW,EAAA,aAAA,CAAA;AAChC;IAEA,MAAMC,oBAAAA,GAAuB,OAAOC,GAAcC,EAAAA,IAAAA,GAAAA;QAChD,MAAMA,IAAAA,EAAAA;AAEN,QAAA,IAAID,IAAIE,MAAM,KAAK,UAAUF,GAAIE,CAAAA,MAAM,KAAK,KAAO,EAAA;AACjD,YAAA;AACF;AAEA,QAAA,IAAIF,IAAIG,IAAI,IAAI,QAAQH,GAAII,CAAAA,MAAM,KAAK,GAAK,EAAA;AAC1C,YAAA;AACF;AAEAJ,QAAAA,GAAAA,CAAIK,IAAI,GAAG,MAAA;AACXL,QAAAA,GAAAA,CAAIG,IAAI,GAAGP,GAAAA,CAAIU,gBAAgB,CAACC,KAAKhB,QAAU,EAAA,YAAA,CAAA,CAAA;AACjD,KAAA;IAEAD,MAAOkB,CAAAA,MAAM,CAACC,MAAM,CAAC;AACnB,QAAA;YACEP,MAAQ,EAAA,KAAA;YACRQ,IAAM,EAAA,CAAC,EAAEpB,MAAAA,CAAOqB,MAAM,CAACC,KAAK,CAACF,IAAI,CAAC,OAAO,CAAC;YAC1CG,OAAS,EAAA;AACPd,gBAAAA,oBAAAA;AACAe,gBAAAA,WAAAA,CAAYvB,QAAU,EAAA;oBACpBwB,MAAQ,EAAA,QAAA;oBACRC,KAAO,EAAA,KAAA;oBACPC,KAAO,EAAA,YAAA;oBACPC,UAAWC,CAAAA,CAAAA,GAAQ,EAAET,IAAS,EAAA;AAC5B,wBAAA,MAAMU,MAAMC,OAAQX,CAAAA,IAAAA,CAAAA;;AAEpB,wBAAA,IAAIU,QAAQ,OAAS,EAAA;4BACnBD,GAAIG,CAAAA,SAAS,CAAC,eAAiB,EAAA,qCAAA,CAAA;AACjC;AACF;AACF,iBAAA;AACD,aAAA;YACDX,MAAQ,EAAA;gBAAEY,IAAM,EAAA;AAAM;AACxB;AACD,KAAA,CAAA;AACH;AAEA;AACA,MAAMT,WAAc,GAAA,CAACU,QAAeC,EAAAA,gBAAAA,GAAmB,EAAE,GAAA;IACvD,MAAMC,KAAAA,GAAQC,UAAUH,QAAUC,EAAAA,gBAAAA,CAAAA;AAElC,IAAA,OAAO,OAAOzB,GAAcC,EAAAA,IAAAA,GAAAA;QAC1B,MAAM2B,IAAAA,GAAO5B,IAAIU,IAAI;QACrB,MAAMmB,OAAAA,GAAUC,QAAS9B,CAAAA,GAAAA,CAAIU,IAAI,CAAA;AAEjCV,QAAAA,GAAAA,CAAIU,IAAI,GAAGmB,OAAAA;AACX,QAAA,MAAMH,MAAM1B,GAAK,EAAA,UAAA;AACfA,YAAAA,GAAAA,CAAIU,IAAI,GAAGkB,IAAAA;YACX,MAAM3B,IAAAA,EAAAA;AACND,YAAAA,GAAAA,CAAIU,IAAI,GAAGmB,OAAAA;AACb,SAAA,CAAA;AACA7B,QAAAA,GAAAA,CAAIU,IAAI,GAAGkB,IAAAA;AACb,KAAA;AACF,CAAA;;;;"}
1
+ {"version":3,"file":"serve-admin-panel.mjs","sources":["../../../../../server/src/routes/serve-admin-panel.ts"],"sourcesContent":["import type { Context, Next } from 'koa';\nimport { resolve, join, extname, basename } from 'path';\nimport fse from 'fs-extra';\nimport koaStatic from 'koa-static';\nimport type { Core } from '@strapi/types';\n\nconst registerAdminPanelRoute = ({ strapi }: { strapi: Core.Strapi }) => {\n let buildDir = resolve(strapi.dirs.dist.root, 'build');\n\n if (!fse.pathExistsSync(buildDir)) {\n buildDir = resolve(__dirname, '../../build');\n }\n\n const serveAdminMiddleware = async (ctx: Context, next: Next) => {\n await next();\n\n if (ctx.method !== 'HEAD' && ctx.method !== 'GET') {\n return;\n }\n\n if (ctx.body != null || ctx.status !== 404) {\n return;\n }\n\n ctx.type = 'html';\n ctx.body = fse.createReadStream(join(buildDir, 'index.html'));\n };\n\n strapi.server.routes([\n {\n method: 'GET',\n path: `${strapi.config.admin.path}/:path*`,\n handler: [\n serveAdminMiddleware,\n serveStatic(buildDir, {\n maxage: 31536000,\n defer: false,\n index: 'index.html',\n setHeaders(res: any, path: any) {\n const ext = extname(path);\n // publicly cache static files to avoid unnecessary network & disk access\n if (ext !== '.html') {\n res.setHeader('cache-control', 'public, max-age=31536000, immutable');\n }\n },\n }),\n ],\n config: { auth: false },\n },\n ]);\n};\n\n// serveStatic is not supposed to be used to serve a folder that have sub-folders\nconst serveStatic = (filesDir: any, koaStaticOptions = {}) => {\n const serve = koaStatic(filesDir, koaStaticOptions);\n\n return async (ctx: Context, next: Next) => {\n const prev = ctx.path;\n const newPath = basename(ctx.path);\n\n ctx.path = newPath;\n await serve(ctx, async () => {\n ctx.path = prev;\n await next();\n ctx.path = newPath;\n });\n ctx.path = prev;\n };\n};\n\nexport default registerAdminPanelRoute;\n"],"names":["registerAdminPanelRoute","strapi","buildDir","resolve","dirs","dist","root","fse","pathExistsSync","__dirname","serveAdminMiddleware","ctx","next","method","body","status","type","createReadStream","join","server","routes","path","config","admin","handler","serveStatic","maxage","defer","index","setHeaders","res","ext","extname","setHeader","auth","filesDir","koaStaticOptions","serve","koaStatic","prev","newPath","basename"],"mappings":";;;;AAMA,MAAMA,uBAA0B,GAAA,CAAC,EAAEC,MAAM,EAA2B,GAAA;IAClE,IAAIC,QAAAA,GAAWC,QAAQF,MAAOG,CAAAA,IAAI,CAACC,IAAI,CAACC,IAAI,EAAE,OAAA,CAAA;AAE9C,IAAA,IAAI,CAACC,GAAAA,CAAIC,cAAc,CAACN,QAAW,CAAA,EAAA;AACjCA,QAAAA,QAAAA,GAAWC,QAAQM,SAAW,EAAA,aAAA,CAAA;AAChC;IAEA,MAAMC,oBAAAA,GAAuB,OAAOC,GAAcC,EAAAA,IAAAA,GAAAA;QAChD,MAAMA,IAAAA,EAAAA;AAEN,QAAA,IAAID,IAAIE,MAAM,KAAK,UAAUF,GAAIE,CAAAA,MAAM,KAAK,KAAO,EAAA;AACjD,YAAA;AACF;AAEA,QAAA,IAAIF,IAAIG,IAAI,IAAI,QAAQH,GAAII,CAAAA,MAAM,KAAK,GAAK,EAAA;AAC1C,YAAA;AACF;AAEAJ,QAAAA,GAAAA,CAAIK,IAAI,GAAG,MAAA;AACXL,QAAAA,GAAAA,CAAIG,IAAI,GAAGP,GAAAA,CAAIU,gBAAgB,CAACC,KAAKhB,QAAU,EAAA,YAAA,CAAA,CAAA;AACjD,KAAA;IAEAD,MAAOkB,CAAAA,MAAM,CAACC,MAAM,CAAC;AACnB,QAAA;YACEP,MAAQ,EAAA,KAAA;YACRQ,IAAM,EAAA,CAAA,EAAGpB,OAAOqB,MAAM,CAACC,KAAK,CAACF,IAAI,CAAC,OAAO,CAAC;YAC1CG,OAAS,EAAA;AACPd,gBAAAA,oBAAAA;AACAe,gBAAAA,WAAAA,CAAYvB,QAAU,EAAA;oBACpBwB,MAAQ,EAAA,QAAA;oBACRC,KAAO,EAAA,KAAA;oBACPC,KAAO,EAAA,YAAA;oBACPC,UAAWC,CAAAA,CAAAA,GAAQ,EAAET,IAAS,EAAA;AAC5B,wBAAA,MAAMU,MAAMC,OAAQX,CAAAA,IAAAA,CAAAA;;AAEpB,wBAAA,IAAIU,QAAQ,OAAS,EAAA;4BACnBD,GAAIG,CAAAA,SAAS,CAAC,eAAiB,EAAA,qCAAA,CAAA;AACjC;AACF;AACF,iBAAA;AACD,aAAA;YACDX,MAAQ,EAAA;gBAAEY,IAAM,EAAA;AAAM;AACxB;AACD,KAAA,CAAA;AACH;AAEA;AACA,MAAMT,WAAc,GAAA,CAACU,QAAeC,EAAAA,gBAAAA,GAAmB,EAAE,GAAA;IACvD,MAAMC,KAAAA,GAAQC,UAAUH,QAAUC,EAAAA,gBAAAA,CAAAA;AAElC,IAAA,OAAO,OAAOzB,GAAcC,EAAAA,IAAAA,GAAAA;QAC1B,MAAM2B,IAAAA,GAAO5B,IAAIU,IAAI;QACrB,MAAMmB,OAAAA,GAAUC,QAAS9B,CAAAA,GAAAA,CAAIU,IAAI,CAAA;AAEjCV,QAAAA,GAAAA,CAAIU,IAAI,GAAGmB,OAAAA;AACX,QAAA,MAAMH,MAAM1B,GAAK,EAAA,UAAA;AACfA,YAAAA,GAAAA,CAAIU,IAAI,GAAGkB,IAAAA;YACX,MAAM3B,IAAAA,EAAAA;AACND,YAAAA,GAAAA,CAAIU,IAAI,GAAGmB,OAAAA;AACb,SAAA,CAAA;AACA7B,QAAAA,GAAAA,CAAIU,IAAI,GAAGkB,IAAAA;AACb,KAAA;AACF,CAAA;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"api-token.js","sources":["../../../../../server/src/services/api-token.ts"],"sourcesContent":["import crypto from 'crypto';\nimport { omit, difference, isNil, isEmpty, map, isArray, uniq, isNumber } from 'lodash/fp';\nimport { errors } from '@strapi/utils';\nimport type { Update, ApiToken, ApiTokenBody } from '../../../shared/contracts/api-token';\nimport constants from './constants';\nimport { getService } from '../utils';\n\nconst { ValidationError, NotFoundError } = errors;\n\ntype ApiTokenPermission = {\n id: number | `${number}`;\n action: string;\n token: DBApiToken | number;\n};\n\ntype DBApiToken = ApiToken & {\n permissions: (number | ApiTokenPermission)[];\n};\n\nconst SELECT_FIELDS = [\n 'id',\n 'name',\n 'description',\n 'lastUsedAt',\n 'type',\n 'lifespan',\n 'expiresAt',\n 'createdAt',\n 'updatedAt',\n];\n\nconst POPULATE_FIELDS = ['permissions'];\n\n// TODO: we need to ensure the permissions are actually valid registered permissions!\n\n/**\n * Assert that a token's permissions attribute is valid for its type\n */\nconst assertCustomTokenPermissionsValidity = (\n type: ApiTokenBody['type'],\n permissions: ApiTokenBody['permissions']\n) => {\n // Ensure non-custom tokens doesn't have permissions\n if (type !== constants.API_TOKEN_TYPE.CUSTOM && !isEmpty(permissions)) {\n throw new ValidationError('Non-custom tokens should not reference permissions');\n }\n\n // Custom type tokens should always have permissions attached to them\n if (type === constants.API_TOKEN_TYPE.CUSTOM && !isArray(permissions)) {\n throw new ValidationError('Missing permissions attribute for custom token');\n }\n\n // Permissions provided for a custom type token should be valid/registered permissions UID\n if (type === constants.API_TOKEN_TYPE.CUSTOM) {\n const validPermissions = strapi.contentAPI.permissions.providers.action.keys();\n const invalidPermissions = difference(permissions, validPermissions) as string[];\n\n if (!isEmpty(invalidPermissions)) {\n throw new ValidationError(`Unknown permissions provided: ${invalidPermissions.join(', ')}`);\n }\n }\n};\n\n/**\n * Check if a token's lifespan is valid\n */\nconst isValidLifespan = (lifespan: unknown) => {\n if (isNil(lifespan)) {\n return true;\n }\n\n if (!isNumber(lifespan) || !Object.values(constants.API_TOKEN_LIFESPANS).includes(lifespan)) {\n return false;\n }\n\n return true;\n};\n\n/**\n * Assert that a token's lifespan is valid\n */\nconst assertValidLifespan = (lifespan: unknown) => {\n if (!isValidLifespan(lifespan)) {\n throw new ValidationError(\n `lifespan must be one of the following values:\n ${Object.values(constants.API_TOKEN_LIFESPANS).join(', ')}`\n );\n }\n};\n\n/**\n * Flatten a token's database permissions objects to an array of strings\n */\nconst flattenTokenPermissions = (token: DBApiToken): ApiToken => {\n if (!token) {\n return token;\n }\n\n return {\n ...token,\n permissions: isArray(token.permissions) ? map('action', token.permissions) : token.permissions,\n };\n};\n\ntype WhereParams = {\n id?: string | number;\n name?: string;\n lastUsedAt?: number;\n description?: string;\n accessKey?: string;\n};\n\n/**\n * Get a token\n */\nconst getBy = async (whereParams: WhereParams = {}): Promise<ApiToken | null> => {\n if (Object.keys(whereParams).length === 0) {\n return null;\n }\n\n const token = await strapi.db.query('admin::api-token').findOne({\n select: [...SELECT_FIELDS, 'encryptedKey'],\n populate: POPULATE_FIELDS,\n where: whereParams,\n });\n\n if (!token) {\n return token;\n }\n\n const { encryptedKey, ...rest } = token;\n\n if (!encryptedKey) {\n return flattenTokenPermissions(rest);\n }\n\n const accessKey = getService('encryption').decrypt(encryptedKey);\n\n return flattenTokenPermissions({\n ...rest,\n accessKey,\n });\n};\n\n/**\n * Check if token exists\n */\nconst exists = async (whereParams: WhereParams = {}): Promise<boolean> => {\n const apiToken = await getBy(whereParams);\n\n return !!apiToken;\n};\n\n/**\n * Return a secure sha512 hash of an accessKey\n */\nconst hash = (accessKey: string) => {\n return crypto\n .createHmac('sha512', strapi.config.get('admin.apiToken.salt'))\n .update(accessKey)\n .digest('hex');\n};\n\nconst getExpirationFields = (lifespan: ApiTokenBody['lifespan']) => {\n // it must be nil or a finite number >= 0\n const isValidNumber = isNumber(lifespan) && Number.isFinite(lifespan) && lifespan > 0;\n if (!isValidNumber && !isNil(lifespan)) {\n throw new ValidationError('lifespan must be a positive number or null');\n }\n\n return {\n lifespan: lifespan || null,\n expiresAt: lifespan ? Date.now() + lifespan : null,\n };\n};\n\n/**\n * Create a token and its permissions\n */\nconst create = async (attributes: ApiTokenBody): Promise<ApiToken> => {\n const encryptionService = getService('encryption');\n const accessKey = crypto.randomBytes(128).toString('hex');\n const encryptedKey = encryptionService.encrypt(accessKey);\n\n assertCustomTokenPermissionsValidity(attributes.type, attributes.permissions);\n assertValidLifespan(attributes.lifespan);\n\n // Create the token\n const apiToken: ApiToken = await strapi.db.query('admin::api-token').create({\n select: SELECT_FIELDS,\n populate: POPULATE_FIELDS,\n data: {\n ...omit('permissions', attributes),\n accessKey: hash(accessKey),\n encryptedKey,\n ...getExpirationFields(attributes.lifespan),\n },\n });\n\n const result: ApiToken = { ...apiToken, accessKey };\n\n // If this is a custom type token, create and the related permissions\n if (attributes.type === constants.API_TOKEN_TYPE.CUSTOM) {\n // TODO: createMany doesn't seem to create relation properly, implement a better way rather than a ton of queries\n // const permissionsCount = await strapi.db.query('admin::api-token-permission').createMany({\n // populate: POPULATE_FIELDS,\n // data: attributes.permissions.map(action => ({ action, token: apiToken })),\n // });\n await Promise.all(\n uniq(attributes.permissions).map((action) =>\n strapi.db.query('admin::api-token-permission').create({\n data: { action, token: apiToken },\n })\n )\n );\n\n const currentPermissions = await strapi.db\n .query('admin::api-token')\n .load(apiToken, 'permissions');\n\n if (currentPermissions) {\n Object.assign(result, { permissions: map('action', currentPermissions) });\n }\n }\n\n return result;\n};\n\nconst regenerate = async (id: string | number): Promise<ApiToken> => {\n const accessKey = crypto.randomBytes(128).toString('hex');\n const encryptionService = getService('encryption');\n const encryptedKey = encryptionService.encrypt(accessKey);\n\n const apiToken: ApiToken = await strapi.db.query('admin::api-token').update({\n select: ['id', 'accessKey'],\n where: { id },\n data: {\n accessKey: hash(accessKey),\n encryptedKey,\n },\n });\n\n if (!apiToken) {\n throw new NotFoundError('The provided token id does not exist');\n }\n\n return {\n ...apiToken,\n accessKey,\n };\n};\n\nconst checkSaltIsDefined = () => {\n if (!strapi.config.get('admin.apiToken.salt')) {\n // TODO V5: stop reading API_TOKEN_SALT\n if (process.env.API_TOKEN_SALT) {\n process.emitWarning(`[deprecated] In future versions, Strapi will stop reading directly from the environment variable API_TOKEN_SALT. Please set apiToken.salt in config/admin.js instead.\nFor security reasons, keep storing the secret in an environment variable and use env() to read it in config/admin.js (ex: \\`apiToken: { salt: env('API_TOKEN_SALT') }\\`). See https://docs.strapi.io/developer-docs/latest/setup-deployment-guides/configurations/optional/environment.html#configuration-using-environment-variables.`);\n\n strapi.config.set('admin.apiToken.salt', process.env.API_TOKEN_SALT);\n } else {\n throw new Error(\n `Missing apiToken.salt. Please set apiToken.salt in config/admin.js (ex: you can generate one using Node with \\`crypto.randomBytes(16).toString('base64')\\`).\nFor security reasons, prefer storing the secret in an environment variable and read it in config/admin.js. See https://docs.strapi.io/developer-docs/latest/setup-deployment-guides/configurations/optional/environment.html#configuration-using-environment-variables.`\n );\n }\n }\n};\n\n/**\n * Return a list of all tokens and their permissions\n */\nconst list = async (): Promise<Array<ApiToken>> => {\n const tokens: Array<DBApiToken> = await strapi.db.query('admin::api-token').findMany({\n select: SELECT_FIELDS,\n populate: POPULATE_FIELDS,\n orderBy: { name: 'ASC' },\n });\n\n if (!tokens) {\n return tokens;\n }\n\n return tokens.map((token) => flattenTokenPermissions(token));\n};\n\n/**\n * Revoke (delete) a token\n */\nconst revoke = async (id: string | number): Promise<ApiToken> => {\n return strapi.db\n .query('admin::api-token')\n .delete({ select: SELECT_FIELDS, populate: POPULATE_FIELDS, where: { id } });\n};\n\n/**\n * Retrieve a token by id\n */\nconst getById = async (id: string | number) => {\n return getBy({ id });\n};\n\n/**\n * Retrieve a token by name\n */\nconst getByName = async (name: string) => {\n return getBy({ name });\n};\n\n/**\n * Update a token and its permissions\n */\nconst update = async (\n id: string | number,\n attributes: Update.Request['body']\n): Promise<ApiToken> => {\n // retrieve token without permissions\n const originalToken: DBApiToken = await strapi.db\n .query('admin::api-token')\n .findOne({ where: { id } });\n\n if (!originalToken) {\n throw new NotFoundError('Token not found');\n }\n\n const changingTypeToCustom =\n attributes.type === constants.API_TOKEN_TYPE.CUSTOM &&\n originalToken.type !== constants.API_TOKEN_TYPE.CUSTOM;\n\n // if we're updating the permissions on any token type, or changing from non-custom to custom, ensure they're still valid\n // if neither type nor permissions are changing, we don't need to validate again or else we can't allow partial update\n if (attributes.permissions || changingTypeToCustom) {\n assertCustomTokenPermissionsValidity(\n attributes.type || originalToken.type,\n attributes.permissions || originalToken.permissions\n );\n }\n\n assertValidLifespan(attributes.lifespan);\n\n const updatedToken: ApiToken = await strapi.db.query('admin::api-token').update({\n select: SELECT_FIELDS,\n where: { id },\n data: omit('permissions', attributes),\n });\n\n // custom tokens need to have their permissions updated as well\n if (updatedToken.type === constants.API_TOKEN_TYPE.CUSTOM && attributes.permissions) {\n const currentPermissionsResult = await strapi.db\n .query('admin::api-token')\n .load(updatedToken, 'permissions');\n\n const currentPermissions = map('action', currentPermissionsResult || []);\n const newPermissions = uniq(attributes.permissions);\n\n const actionsToDelete = difference(currentPermissions, newPermissions);\n const actionsToAdd = difference(newPermissions, currentPermissions);\n\n // TODO: improve efficiency here\n // method using a loop -- works but very inefficient\n await Promise.all(\n actionsToDelete.map((action) =>\n strapi.db.query('admin::api-token-permission').delete({\n where: { action, token: id },\n })\n )\n );\n\n // TODO: improve efficiency here\n // using a loop -- works but very inefficient\n await Promise.all(\n actionsToAdd.map((action) =>\n strapi.db.query('admin::api-token-permission').create({\n data: { action, token: id },\n })\n )\n );\n }\n // if type is not custom, make sure any old permissions get removed\n else if (updatedToken.type !== constants.API_TOKEN_TYPE.CUSTOM) {\n await strapi.db.query('admin::api-token-permission').delete({\n where: { token: id },\n });\n }\n\n // retrieve permissions\n const permissionsFromDb = await strapi.db\n .query('admin::api-token')\n .load(updatedToken, 'permissions');\n\n return {\n ...updatedToken,\n permissions: permissionsFromDb ? permissionsFromDb.map((p: any) => p.action) : undefined,\n };\n};\n\nconst count = async (where = {}): Promise<number> => {\n return strapi.db.query('admin::api-token').count({ where });\n};\n\nexport {\n create,\n count,\n regenerate,\n exists,\n checkSaltIsDefined,\n hash,\n list,\n revoke,\n getById,\n update,\n getByName,\n getBy,\n};\n"],"names":["ValidationError","NotFoundError","errors","SELECT_FIELDS","POPULATE_FIELDS","assertCustomTokenPermissionsValidity","type","permissions","constants","API_TOKEN_TYPE","CUSTOM","isEmpty","isArray","validPermissions","strapi","contentAPI","providers","action","keys","invalidPermissions","difference","join","isValidLifespan","lifespan","isNil","isNumber","Object","values","API_TOKEN_LIFESPANS","includes","assertValidLifespan","flattenTokenPermissions","token","map","getBy","whereParams","length","db","query","findOne","select","populate","where","encryptedKey","rest","accessKey","getService","decrypt","exists","apiToken","hash","crypto","createHmac","config","get","update","digest","getExpirationFields","isValidNumber","Number","isFinite","expiresAt","Date","now","create","attributes","encryptionService","randomBytes","toString","encrypt","data","omit","result","Promise","all","uniq","currentPermissions","load","assign","regenerate","id","checkSaltIsDefined","process","env","API_TOKEN_SALT","emitWarning","set","Error","list","tokens","findMany","orderBy","name","revoke","delete","getById","getByName","originalToken","changingTypeToCustom","updatedToken","currentPermissionsResult","newPermissions","actionsToDelete","actionsToAdd","permissionsFromDb","p","undefined","count"],"mappings":"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"}
1
+ {"version":3,"file":"api-token.js","sources":["../../../../../server/src/services/api-token.ts"],"sourcesContent":["import crypto from 'crypto';\nimport { omit, difference, isNil, isEmpty, map, isArray, uniq, isNumber } from 'lodash/fp';\nimport { errors } from '@strapi/utils';\nimport type { Update, ApiToken, ApiTokenBody } from '../../../shared/contracts/api-token';\nimport constants from './constants';\nimport { getService } from '../utils';\n\nconst { ValidationError, NotFoundError } = errors;\n\ntype ApiTokenPermission = {\n id: number | `${number}`;\n action: string;\n token: DBApiToken | number;\n};\n\ntype DBApiToken = ApiToken & {\n permissions: (number | ApiTokenPermission)[];\n};\n\nconst SELECT_FIELDS = [\n 'id',\n 'name',\n 'description',\n 'lastUsedAt',\n 'type',\n 'lifespan',\n 'expiresAt',\n 'createdAt',\n 'updatedAt',\n];\n\nconst POPULATE_FIELDS = ['permissions'];\n\n// TODO: we need to ensure the permissions are actually valid registered permissions!\n\n/**\n * Assert that a token's permissions attribute is valid for its type\n */\nconst assertCustomTokenPermissionsValidity = (\n type: ApiTokenBody['type'],\n permissions: ApiTokenBody['permissions']\n) => {\n // Ensure non-custom tokens doesn't have permissions\n if (type !== constants.API_TOKEN_TYPE.CUSTOM && !isEmpty(permissions)) {\n throw new ValidationError('Non-custom tokens should not reference permissions');\n }\n\n // Custom type tokens should always have permissions attached to them\n if (type === constants.API_TOKEN_TYPE.CUSTOM && !isArray(permissions)) {\n throw new ValidationError('Missing permissions attribute for custom token');\n }\n\n // Permissions provided for a custom type token should be valid/registered permissions UID\n if (type === constants.API_TOKEN_TYPE.CUSTOM) {\n const validPermissions = strapi.contentAPI.permissions.providers.action.keys();\n const invalidPermissions = difference(permissions, validPermissions) as string[];\n\n if (!isEmpty(invalidPermissions)) {\n throw new ValidationError(`Unknown permissions provided: ${invalidPermissions.join(', ')}`);\n }\n }\n};\n\n/**\n * Check if a token's lifespan is valid\n */\nconst isValidLifespan = (lifespan: unknown) => {\n if (isNil(lifespan)) {\n return true;\n }\n\n if (!isNumber(lifespan) || !Object.values(constants.API_TOKEN_LIFESPANS).includes(lifespan)) {\n return false;\n }\n\n return true;\n};\n\n/**\n * Assert that a token's lifespan is valid\n */\nconst assertValidLifespan = (lifespan: unknown) => {\n if (!isValidLifespan(lifespan)) {\n throw new ValidationError(\n `lifespan must be one of the following values:\n ${Object.values(constants.API_TOKEN_LIFESPANS).join(', ')}`\n );\n }\n};\n\n/**\n * Flatten a token's database permissions objects to an array of strings\n */\nconst flattenTokenPermissions = (token: DBApiToken): ApiToken => {\n if (!token) {\n return token;\n }\n\n return {\n ...token,\n permissions: isArray(token.permissions) ? map('action', token.permissions) : token.permissions,\n };\n};\n\ntype WhereParams = {\n id?: string | number;\n name?: string;\n lastUsedAt?: number;\n description?: string;\n accessKey?: string;\n};\n\n/**\n * Get a token\n */\nconst getBy = async (whereParams: WhereParams = {}): Promise<ApiToken | null> => {\n if (Object.keys(whereParams).length === 0) {\n return null;\n }\n\n const token = await strapi.db.query('admin::api-token').findOne({\n select: [...SELECT_FIELDS, 'encryptedKey'],\n populate: POPULATE_FIELDS,\n where: whereParams,\n });\n\n if (!token) {\n return token;\n }\n\n const { encryptedKey, ...rest } = token;\n\n if (!encryptedKey) {\n return flattenTokenPermissions(rest);\n }\n\n const accessKey = getService('encryption').decrypt(encryptedKey);\n\n return flattenTokenPermissions({\n ...rest,\n accessKey,\n });\n};\n\n/**\n * Check if token exists\n */\nconst exists = async (whereParams: WhereParams = {}): Promise<boolean> => {\n const apiToken = await getBy(whereParams);\n\n return !!apiToken;\n};\n\n/**\n * Return a secure sha512 hash of an accessKey\n */\nconst hash = (accessKey: string) => {\n return crypto\n .createHmac('sha512', strapi.config.get('admin.apiToken.salt'))\n .update(accessKey)\n .digest('hex');\n};\n\nconst getExpirationFields = (lifespan: ApiTokenBody['lifespan']) => {\n // it must be nil or a finite number >= 0\n const isValidNumber = isNumber(lifespan) && Number.isFinite(lifespan) && lifespan > 0;\n if (!isValidNumber && !isNil(lifespan)) {\n throw new ValidationError('lifespan must be a positive number or null');\n }\n\n return {\n lifespan: lifespan || null,\n expiresAt: lifespan ? Date.now() + lifespan : null,\n };\n};\n\n/**\n * Create a token and its permissions\n */\nconst create = async (attributes: ApiTokenBody): Promise<ApiToken> => {\n const encryptionService = getService('encryption');\n const accessKey = crypto.randomBytes(128).toString('hex');\n const encryptedKey = encryptionService.encrypt(accessKey);\n\n assertCustomTokenPermissionsValidity(attributes.type, attributes.permissions);\n assertValidLifespan(attributes.lifespan);\n\n // Create the token\n const apiToken: ApiToken = await strapi.db.query('admin::api-token').create({\n select: SELECT_FIELDS,\n populate: POPULATE_FIELDS,\n data: {\n ...omit('permissions', attributes),\n accessKey: hash(accessKey),\n encryptedKey,\n ...getExpirationFields(attributes.lifespan),\n },\n });\n\n const result: ApiToken = { ...apiToken, accessKey };\n\n // If this is a custom type token, create and the related permissions\n if (attributes.type === constants.API_TOKEN_TYPE.CUSTOM) {\n // TODO: createMany doesn't seem to create relation properly, implement a better way rather than a ton of queries\n // const permissionsCount = await strapi.db.query('admin::api-token-permission').createMany({\n // populate: POPULATE_FIELDS,\n // data: attributes.permissions.map(action => ({ action, token: apiToken })),\n // });\n await Promise.all(\n uniq(attributes.permissions).map((action) =>\n strapi.db.query('admin::api-token-permission').create({\n data: { action, token: apiToken },\n })\n )\n );\n\n const currentPermissions = await strapi.db\n .query('admin::api-token')\n .load(apiToken, 'permissions');\n\n if (currentPermissions) {\n Object.assign(result, { permissions: map('action', currentPermissions) });\n }\n }\n\n return result;\n};\n\nconst regenerate = async (id: string | number): Promise<ApiToken> => {\n const accessKey = crypto.randomBytes(128).toString('hex');\n const encryptionService = getService('encryption');\n const encryptedKey = encryptionService.encrypt(accessKey);\n\n const apiToken: ApiToken = await strapi.db.query('admin::api-token').update({\n select: ['id', 'accessKey'],\n where: { id },\n data: {\n accessKey: hash(accessKey),\n encryptedKey,\n },\n });\n\n if (!apiToken) {\n throw new NotFoundError('The provided token id does not exist');\n }\n\n return {\n ...apiToken,\n accessKey,\n };\n};\n\nconst checkSaltIsDefined = () => {\n if (!strapi.config.get('admin.apiToken.salt')) {\n // TODO V5: stop reading API_TOKEN_SALT\n if (process.env.API_TOKEN_SALT) {\n process.emitWarning(`[deprecated] In future versions, Strapi will stop reading directly from the environment variable API_TOKEN_SALT. Please set apiToken.salt in config/admin.js instead.\nFor security reasons, keep storing the secret in an environment variable and use env() to read it in config/admin.js (ex: \\`apiToken: { salt: env('API_TOKEN_SALT') }\\`). See https://docs.strapi.io/developer-docs/latest/setup-deployment-guides/configurations/optional/environment.html#configuration-using-environment-variables.`);\n\n strapi.config.set('admin.apiToken.salt', process.env.API_TOKEN_SALT);\n } else {\n throw new Error(\n `Missing apiToken.salt. Please set apiToken.salt in config/admin.js (ex: you can generate one using Node with \\`crypto.randomBytes(16).toString('base64')\\`).\nFor security reasons, prefer storing the secret in an environment variable and read it in config/admin.js. See https://docs.strapi.io/developer-docs/latest/setup-deployment-guides/configurations/optional/environment.html#configuration-using-environment-variables.`\n );\n }\n }\n};\n\n/**\n * Return a list of all tokens and their permissions\n */\nconst list = async (): Promise<Array<ApiToken>> => {\n const tokens: Array<DBApiToken> = await strapi.db.query('admin::api-token').findMany({\n select: SELECT_FIELDS,\n populate: POPULATE_FIELDS,\n orderBy: { name: 'ASC' },\n });\n\n if (!tokens) {\n return tokens;\n }\n\n return tokens.map((token) => flattenTokenPermissions(token));\n};\n\n/**\n * Revoke (delete) a token\n */\nconst revoke = async (id: string | number): Promise<ApiToken> => {\n return strapi.db\n .query('admin::api-token')\n .delete({ select: SELECT_FIELDS, populate: POPULATE_FIELDS, where: { id } });\n};\n\n/**\n * Retrieve a token by id\n */\nconst getById = async (id: string | number) => {\n return getBy({ id });\n};\n\n/**\n * Retrieve a token by name\n */\nconst getByName = async (name: string) => {\n return getBy({ name });\n};\n\n/**\n * Update a token and its permissions\n */\nconst update = async (\n id: string | number,\n attributes: Update.Request['body']\n): Promise<ApiToken> => {\n // retrieve token without permissions\n const originalToken: DBApiToken = await strapi.db\n .query('admin::api-token')\n .findOne({ where: { id } });\n\n if (!originalToken) {\n throw new NotFoundError('Token not found');\n }\n\n const changingTypeToCustom =\n attributes.type === constants.API_TOKEN_TYPE.CUSTOM &&\n originalToken.type !== constants.API_TOKEN_TYPE.CUSTOM;\n\n // if we're updating the permissions on any token type, or changing from non-custom to custom, ensure they're still valid\n // if neither type nor permissions are changing, we don't need to validate again or else we can't allow partial update\n if (attributes.permissions || changingTypeToCustom) {\n assertCustomTokenPermissionsValidity(\n attributes.type || originalToken.type,\n attributes.permissions || originalToken.permissions\n );\n }\n\n assertValidLifespan(attributes.lifespan);\n\n const updatedToken: ApiToken = await strapi.db.query('admin::api-token').update({\n select: SELECT_FIELDS,\n where: { id },\n data: omit('permissions', attributes),\n });\n\n // custom tokens need to have their permissions updated as well\n if (updatedToken.type === constants.API_TOKEN_TYPE.CUSTOM && attributes.permissions) {\n const currentPermissionsResult = await strapi.db\n .query('admin::api-token')\n .load(updatedToken, 'permissions');\n\n const currentPermissions = map('action', currentPermissionsResult || []);\n const newPermissions = uniq(attributes.permissions);\n\n const actionsToDelete = difference(currentPermissions, newPermissions);\n const actionsToAdd = difference(newPermissions, currentPermissions);\n\n // TODO: improve efficiency here\n // method using a loop -- works but very inefficient\n await Promise.all(\n actionsToDelete.map((action) =>\n strapi.db.query('admin::api-token-permission').delete({\n where: { action, token: id },\n })\n )\n );\n\n // TODO: improve efficiency here\n // using a loop -- works but very inefficient\n await Promise.all(\n actionsToAdd.map((action) =>\n strapi.db.query('admin::api-token-permission').create({\n data: { action, token: id },\n })\n )\n );\n }\n // if type is not custom, make sure any old permissions get removed\n else if (updatedToken.type !== constants.API_TOKEN_TYPE.CUSTOM) {\n await strapi.db.query('admin::api-token-permission').delete({\n where: { token: id },\n });\n }\n\n // retrieve permissions\n const permissionsFromDb = await strapi.db\n .query('admin::api-token')\n .load(updatedToken, 'permissions');\n\n return {\n ...updatedToken,\n permissions: permissionsFromDb ? permissionsFromDb.map((p: any) => p.action) : undefined,\n };\n};\n\nconst count = async (where = {}): Promise<number> => {\n return strapi.db.query('admin::api-token').count({ where });\n};\n\nexport {\n create,\n count,\n regenerate,\n exists,\n checkSaltIsDefined,\n hash,\n list,\n revoke,\n getById,\n update,\n getByName,\n getBy,\n};\n"],"names":["ValidationError","NotFoundError","errors","SELECT_FIELDS","POPULATE_FIELDS","assertCustomTokenPermissionsValidity","type","permissions","constants","API_TOKEN_TYPE","CUSTOM","isEmpty","isArray","validPermissions","strapi","contentAPI","providers","action","keys","invalidPermissions","difference","join","isValidLifespan","lifespan","isNil","isNumber","Object","values","API_TOKEN_LIFESPANS","includes","assertValidLifespan","flattenTokenPermissions","token","map","getBy","whereParams","length","db","query","findOne","select","populate","where","encryptedKey","rest","accessKey","getService","decrypt","exists","apiToken","hash","crypto","createHmac","config","get","update","digest","getExpirationFields","isValidNumber","Number","isFinite","expiresAt","Date","now","create","attributes","encryptionService","randomBytes","toString","encrypt","data","omit","result","Promise","all","uniq","currentPermissions","load","assign","regenerate","id","checkSaltIsDefined","process","env","API_TOKEN_SALT","emitWarning","set","Error","list","tokens","findMany","orderBy","name","revoke","delete","getById","getByName","originalToken","changingTypeToCustom","updatedToken","currentPermissionsResult","newPermissions","actionsToDelete","actionsToAdd","permissionsFromDb","p","undefined","count"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"api-token.mjs","sources":["../../../../../server/src/services/api-token.ts"],"sourcesContent":["import crypto from 'crypto';\nimport { omit, difference, isNil, isEmpty, map, isArray, uniq, isNumber } from 'lodash/fp';\nimport { errors } from '@strapi/utils';\nimport type { Update, ApiToken, ApiTokenBody } from '../../../shared/contracts/api-token';\nimport constants from './constants';\nimport { getService } from '../utils';\n\nconst { ValidationError, NotFoundError } = errors;\n\ntype ApiTokenPermission = {\n id: number | `${number}`;\n action: string;\n token: DBApiToken | number;\n};\n\ntype DBApiToken = ApiToken & {\n permissions: (number | ApiTokenPermission)[];\n};\n\nconst SELECT_FIELDS = [\n 'id',\n 'name',\n 'description',\n 'lastUsedAt',\n 'type',\n 'lifespan',\n 'expiresAt',\n 'createdAt',\n 'updatedAt',\n];\n\nconst POPULATE_FIELDS = ['permissions'];\n\n// TODO: we need to ensure the permissions are actually valid registered permissions!\n\n/**\n * Assert that a token's permissions attribute is valid for its type\n */\nconst assertCustomTokenPermissionsValidity = (\n type: ApiTokenBody['type'],\n permissions: ApiTokenBody['permissions']\n) => {\n // Ensure non-custom tokens doesn't have permissions\n if (type !== constants.API_TOKEN_TYPE.CUSTOM && !isEmpty(permissions)) {\n throw new ValidationError('Non-custom tokens should not reference permissions');\n }\n\n // Custom type tokens should always have permissions attached to them\n if (type === constants.API_TOKEN_TYPE.CUSTOM && !isArray(permissions)) {\n throw new ValidationError('Missing permissions attribute for custom token');\n }\n\n // Permissions provided for a custom type token should be valid/registered permissions UID\n if (type === constants.API_TOKEN_TYPE.CUSTOM) {\n const validPermissions = strapi.contentAPI.permissions.providers.action.keys();\n const invalidPermissions = difference(permissions, validPermissions) as string[];\n\n if (!isEmpty(invalidPermissions)) {\n throw new ValidationError(`Unknown permissions provided: ${invalidPermissions.join(', ')}`);\n }\n }\n};\n\n/**\n * Check if a token's lifespan is valid\n */\nconst isValidLifespan = (lifespan: unknown) => {\n if (isNil(lifespan)) {\n return true;\n }\n\n if (!isNumber(lifespan) || !Object.values(constants.API_TOKEN_LIFESPANS).includes(lifespan)) {\n return false;\n }\n\n return true;\n};\n\n/**\n * Assert that a token's lifespan is valid\n */\nconst assertValidLifespan = (lifespan: unknown) => {\n if (!isValidLifespan(lifespan)) {\n throw new ValidationError(\n `lifespan must be one of the following values:\n ${Object.values(constants.API_TOKEN_LIFESPANS).join(', ')}`\n );\n }\n};\n\n/**\n * Flatten a token's database permissions objects to an array of strings\n */\nconst flattenTokenPermissions = (token: DBApiToken): ApiToken => {\n if (!token) {\n return token;\n }\n\n return {\n ...token,\n permissions: isArray(token.permissions) ? map('action', token.permissions) : token.permissions,\n };\n};\n\ntype WhereParams = {\n id?: string | number;\n name?: string;\n lastUsedAt?: number;\n description?: string;\n accessKey?: string;\n};\n\n/**\n * Get a token\n */\nconst getBy = async (whereParams: WhereParams = {}): Promise<ApiToken | null> => {\n if (Object.keys(whereParams).length === 0) {\n return null;\n }\n\n const token = await strapi.db.query('admin::api-token').findOne({\n select: [...SELECT_FIELDS, 'encryptedKey'],\n populate: POPULATE_FIELDS,\n where: whereParams,\n });\n\n if (!token) {\n return token;\n }\n\n const { encryptedKey, ...rest } = token;\n\n if (!encryptedKey) {\n return flattenTokenPermissions(rest);\n }\n\n const accessKey = getService('encryption').decrypt(encryptedKey);\n\n return flattenTokenPermissions({\n ...rest,\n accessKey,\n });\n};\n\n/**\n * Check if token exists\n */\nconst exists = async (whereParams: WhereParams = {}): Promise<boolean> => {\n const apiToken = await getBy(whereParams);\n\n return !!apiToken;\n};\n\n/**\n * Return a secure sha512 hash of an accessKey\n */\nconst hash = (accessKey: string) => {\n return crypto\n .createHmac('sha512', strapi.config.get('admin.apiToken.salt'))\n .update(accessKey)\n .digest('hex');\n};\n\nconst getExpirationFields = (lifespan: ApiTokenBody['lifespan']) => {\n // it must be nil or a finite number >= 0\n const isValidNumber = isNumber(lifespan) && Number.isFinite(lifespan) && lifespan > 0;\n if (!isValidNumber && !isNil(lifespan)) {\n throw new ValidationError('lifespan must be a positive number or null');\n }\n\n return {\n lifespan: lifespan || null,\n expiresAt: lifespan ? Date.now() + lifespan : null,\n };\n};\n\n/**\n * Create a token and its permissions\n */\nconst create = async (attributes: ApiTokenBody): Promise<ApiToken> => {\n const encryptionService = getService('encryption');\n const accessKey = crypto.randomBytes(128).toString('hex');\n const encryptedKey = encryptionService.encrypt(accessKey);\n\n assertCustomTokenPermissionsValidity(attributes.type, attributes.permissions);\n assertValidLifespan(attributes.lifespan);\n\n // Create the token\n const apiToken: ApiToken = await strapi.db.query('admin::api-token').create({\n select: SELECT_FIELDS,\n populate: POPULATE_FIELDS,\n data: {\n ...omit('permissions', attributes),\n accessKey: hash(accessKey),\n encryptedKey,\n ...getExpirationFields(attributes.lifespan),\n },\n });\n\n const result: ApiToken = { ...apiToken, accessKey };\n\n // If this is a custom type token, create and the related permissions\n if (attributes.type === constants.API_TOKEN_TYPE.CUSTOM) {\n // TODO: createMany doesn't seem to create relation properly, implement a better way rather than a ton of queries\n // const permissionsCount = await strapi.db.query('admin::api-token-permission').createMany({\n // populate: POPULATE_FIELDS,\n // data: attributes.permissions.map(action => ({ action, token: apiToken })),\n // });\n await Promise.all(\n uniq(attributes.permissions).map((action) =>\n strapi.db.query('admin::api-token-permission').create({\n data: { action, token: apiToken },\n })\n )\n );\n\n const currentPermissions = await strapi.db\n .query('admin::api-token')\n .load(apiToken, 'permissions');\n\n if (currentPermissions) {\n Object.assign(result, { permissions: map('action', currentPermissions) });\n }\n }\n\n return result;\n};\n\nconst regenerate = async (id: string | number): Promise<ApiToken> => {\n const accessKey = crypto.randomBytes(128).toString('hex');\n const encryptionService = getService('encryption');\n const encryptedKey = encryptionService.encrypt(accessKey);\n\n const apiToken: ApiToken = await strapi.db.query('admin::api-token').update({\n select: ['id', 'accessKey'],\n where: { id },\n data: {\n accessKey: hash(accessKey),\n encryptedKey,\n },\n });\n\n if (!apiToken) {\n throw new NotFoundError('The provided token id does not exist');\n }\n\n return {\n ...apiToken,\n accessKey,\n };\n};\n\nconst checkSaltIsDefined = () => {\n if (!strapi.config.get('admin.apiToken.salt')) {\n // TODO V5: stop reading API_TOKEN_SALT\n if (process.env.API_TOKEN_SALT) {\n process.emitWarning(`[deprecated] In future versions, Strapi will stop reading directly from the environment variable API_TOKEN_SALT. Please set apiToken.salt in config/admin.js instead.\nFor security reasons, keep storing the secret in an environment variable and use env() to read it in config/admin.js (ex: \\`apiToken: { salt: env('API_TOKEN_SALT') }\\`). See https://docs.strapi.io/developer-docs/latest/setup-deployment-guides/configurations/optional/environment.html#configuration-using-environment-variables.`);\n\n strapi.config.set('admin.apiToken.salt', process.env.API_TOKEN_SALT);\n } else {\n throw new Error(\n `Missing apiToken.salt. Please set apiToken.salt in config/admin.js (ex: you can generate one using Node with \\`crypto.randomBytes(16).toString('base64')\\`).\nFor security reasons, prefer storing the secret in an environment variable and read it in config/admin.js. See https://docs.strapi.io/developer-docs/latest/setup-deployment-guides/configurations/optional/environment.html#configuration-using-environment-variables.`\n );\n }\n }\n};\n\n/**\n * Return a list of all tokens and their permissions\n */\nconst list = async (): Promise<Array<ApiToken>> => {\n const tokens: Array<DBApiToken> = await strapi.db.query('admin::api-token').findMany({\n select: SELECT_FIELDS,\n populate: POPULATE_FIELDS,\n orderBy: { name: 'ASC' },\n });\n\n if (!tokens) {\n return tokens;\n }\n\n return tokens.map((token) => flattenTokenPermissions(token));\n};\n\n/**\n * Revoke (delete) a token\n */\nconst revoke = async (id: string | number): Promise<ApiToken> => {\n return strapi.db\n .query('admin::api-token')\n .delete({ select: SELECT_FIELDS, populate: POPULATE_FIELDS, where: { id } });\n};\n\n/**\n * Retrieve a token by id\n */\nconst getById = async (id: string | number) => {\n return getBy({ id });\n};\n\n/**\n * Retrieve a token by name\n */\nconst getByName = async (name: string) => {\n return getBy({ name });\n};\n\n/**\n * Update a token and its permissions\n */\nconst update = async (\n id: string | number,\n attributes: Update.Request['body']\n): Promise<ApiToken> => {\n // retrieve token without permissions\n const originalToken: DBApiToken = await strapi.db\n .query('admin::api-token')\n .findOne({ where: { id } });\n\n if (!originalToken) {\n throw new NotFoundError('Token not found');\n }\n\n const changingTypeToCustom =\n attributes.type === constants.API_TOKEN_TYPE.CUSTOM &&\n originalToken.type !== constants.API_TOKEN_TYPE.CUSTOM;\n\n // if we're updating the permissions on any token type, or changing from non-custom to custom, ensure they're still valid\n // if neither type nor permissions are changing, we don't need to validate again or else we can't allow partial update\n if (attributes.permissions || changingTypeToCustom) {\n assertCustomTokenPermissionsValidity(\n attributes.type || originalToken.type,\n attributes.permissions || originalToken.permissions\n );\n }\n\n assertValidLifespan(attributes.lifespan);\n\n const updatedToken: ApiToken = await strapi.db.query('admin::api-token').update({\n select: SELECT_FIELDS,\n where: { id },\n data: omit('permissions', attributes),\n });\n\n // custom tokens need to have their permissions updated as well\n if (updatedToken.type === constants.API_TOKEN_TYPE.CUSTOM && attributes.permissions) {\n const currentPermissionsResult = await strapi.db\n .query('admin::api-token')\n .load(updatedToken, 'permissions');\n\n const currentPermissions = map('action', currentPermissionsResult || []);\n const newPermissions = uniq(attributes.permissions);\n\n const actionsToDelete = difference(currentPermissions, newPermissions);\n const actionsToAdd = difference(newPermissions, currentPermissions);\n\n // TODO: improve efficiency here\n // method using a loop -- works but very inefficient\n await Promise.all(\n actionsToDelete.map((action) =>\n strapi.db.query('admin::api-token-permission').delete({\n where: { action, token: id },\n })\n )\n );\n\n // TODO: improve efficiency here\n // using a loop -- works but very inefficient\n await Promise.all(\n actionsToAdd.map((action) =>\n strapi.db.query('admin::api-token-permission').create({\n data: { action, token: id },\n })\n )\n );\n }\n // if type is not custom, make sure any old permissions get removed\n else if (updatedToken.type !== constants.API_TOKEN_TYPE.CUSTOM) {\n await strapi.db.query('admin::api-token-permission').delete({\n where: { token: id },\n });\n }\n\n // retrieve permissions\n const permissionsFromDb = await strapi.db\n .query('admin::api-token')\n .load(updatedToken, 'permissions');\n\n return {\n ...updatedToken,\n permissions: permissionsFromDb ? permissionsFromDb.map((p: any) => p.action) : undefined,\n };\n};\n\nconst count = async (where = {}): Promise<number> => {\n return strapi.db.query('admin::api-token').count({ where });\n};\n\nexport {\n create,\n count,\n regenerate,\n exists,\n checkSaltIsDefined,\n hash,\n list,\n revoke,\n getById,\n update,\n getByName,\n getBy,\n};\n"],"names":["ValidationError","NotFoundError","errors","SELECT_FIELDS","POPULATE_FIELDS","assertCustomTokenPermissionsValidity","type","permissions","constants","API_TOKEN_TYPE","CUSTOM","isEmpty","isArray","validPermissions","strapi","contentAPI","providers","action","keys","invalidPermissions","difference","join","isValidLifespan","lifespan","isNil","isNumber","Object","values","API_TOKEN_LIFESPANS","includes","assertValidLifespan","flattenTokenPermissions","token","map","getBy","whereParams","length","db","query","findOne","select","populate","where","encryptedKey","rest","accessKey","getService","decrypt","exists","apiToken","hash","crypto","createHmac","config","get","update","digest","getExpirationFields","isValidNumber","Number","isFinite","expiresAt","Date","now","create","attributes","encryptionService","randomBytes","toString","encrypt","data","omit","result","Promise","all","uniq","currentPermissions","load","assign","regenerate","id","checkSaltIsDefined","process","env","API_TOKEN_SALT","emitWarning","set","Error","list","tokens","findMany","orderBy","name","revoke","delete","getById","getByName","originalToken","changingTypeToCustom","updatedToken","currentPermissionsResult","newPermissions","actionsToDelete","actionsToAdd","permissionsFromDb","p","undefined","count"],"mappings":"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"}
1
+ {"version":3,"file":"api-token.mjs","sources":["../../../../../server/src/services/api-token.ts"],"sourcesContent":["import crypto from 'crypto';\nimport { omit, difference, isNil, isEmpty, map, isArray, uniq, isNumber } from 'lodash/fp';\nimport { errors } from '@strapi/utils';\nimport type { Update, ApiToken, ApiTokenBody } from '../../../shared/contracts/api-token';\nimport constants from './constants';\nimport { getService } from '../utils';\n\nconst { ValidationError, NotFoundError } = errors;\n\ntype ApiTokenPermission = {\n id: number | `${number}`;\n action: string;\n token: DBApiToken | number;\n};\n\ntype DBApiToken = ApiToken & {\n permissions: (number | ApiTokenPermission)[];\n};\n\nconst SELECT_FIELDS = [\n 'id',\n 'name',\n 'description',\n 'lastUsedAt',\n 'type',\n 'lifespan',\n 'expiresAt',\n 'createdAt',\n 'updatedAt',\n];\n\nconst POPULATE_FIELDS = ['permissions'];\n\n// TODO: we need to ensure the permissions are actually valid registered permissions!\n\n/**\n * Assert that a token's permissions attribute is valid for its type\n */\nconst assertCustomTokenPermissionsValidity = (\n type: ApiTokenBody['type'],\n permissions: ApiTokenBody['permissions']\n) => {\n // Ensure non-custom tokens doesn't have permissions\n if (type !== constants.API_TOKEN_TYPE.CUSTOM && !isEmpty(permissions)) {\n throw new ValidationError('Non-custom tokens should not reference permissions');\n }\n\n // Custom type tokens should always have permissions attached to them\n if (type === constants.API_TOKEN_TYPE.CUSTOM && !isArray(permissions)) {\n throw new ValidationError('Missing permissions attribute for custom token');\n }\n\n // Permissions provided for a custom type token should be valid/registered permissions UID\n if (type === constants.API_TOKEN_TYPE.CUSTOM) {\n const validPermissions = strapi.contentAPI.permissions.providers.action.keys();\n const invalidPermissions = difference(permissions, validPermissions) as string[];\n\n if (!isEmpty(invalidPermissions)) {\n throw new ValidationError(`Unknown permissions provided: ${invalidPermissions.join(', ')}`);\n }\n }\n};\n\n/**\n * Check if a token's lifespan is valid\n */\nconst isValidLifespan = (lifespan: unknown) => {\n if (isNil(lifespan)) {\n return true;\n }\n\n if (!isNumber(lifespan) || !Object.values(constants.API_TOKEN_LIFESPANS).includes(lifespan)) {\n return false;\n }\n\n return true;\n};\n\n/**\n * Assert that a token's lifespan is valid\n */\nconst assertValidLifespan = (lifespan: unknown) => {\n if (!isValidLifespan(lifespan)) {\n throw new ValidationError(\n `lifespan must be one of the following values:\n ${Object.values(constants.API_TOKEN_LIFESPANS).join(', ')}`\n );\n }\n};\n\n/**\n * Flatten a token's database permissions objects to an array of strings\n */\nconst flattenTokenPermissions = (token: DBApiToken): ApiToken => {\n if (!token) {\n return token;\n }\n\n return {\n ...token,\n permissions: isArray(token.permissions) ? map('action', token.permissions) : token.permissions,\n };\n};\n\ntype WhereParams = {\n id?: string | number;\n name?: string;\n lastUsedAt?: number;\n description?: string;\n accessKey?: string;\n};\n\n/**\n * Get a token\n */\nconst getBy = async (whereParams: WhereParams = {}): Promise<ApiToken | null> => {\n if (Object.keys(whereParams).length === 0) {\n return null;\n }\n\n const token = await strapi.db.query('admin::api-token').findOne({\n select: [...SELECT_FIELDS, 'encryptedKey'],\n populate: POPULATE_FIELDS,\n where: whereParams,\n });\n\n if (!token) {\n return token;\n }\n\n const { encryptedKey, ...rest } = token;\n\n if (!encryptedKey) {\n return flattenTokenPermissions(rest);\n }\n\n const accessKey = getService('encryption').decrypt(encryptedKey);\n\n return flattenTokenPermissions({\n ...rest,\n accessKey,\n });\n};\n\n/**\n * Check if token exists\n */\nconst exists = async (whereParams: WhereParams = {}): Promise<boolean> => {\n const apiToken = await getBy(whereParams);\n\n return !!apiToken;\n};\n\n/**\n * Return a secure sha512 hash of an accessKey\n */\nconst hash = (accessKey: string) => {\n return crypto\n .createHmac('sha512', strapi.config.get('admin.apiToken.salt'))\n .update(accessKey)\n .digest('hex');\n};\n\nconst getExpirationFields = (lifespan: ApiTokenBody['lifespan']) => {\n // it must be nil or a finite number >= 0\n const isValidNumber = isNumber(lifespan) && Number.isFinite(lifespan) && lifespan > 0;\n if (!isValidNumber && !isNil(lifespan)) {\n throw new ValidationError('lifespan must be a positive number or null');\n }\n\n return {\n lifespan: lifespan || null,\n expiresAt: lifespan ? Date.now() + lifespan : null,\n };\n};\n\n/**\n * Create a token and its permissions\n */\nconst create = async (attributes: ApiTokenBody): Promise<ApiToken> => {\n const encryptionService = getService('encryption');\n const accessKey = crypto.randomBytes(128).toString('hex');\n const encryptedKey = encryptionService.encrypt(accessKey);\n\n assertCustomTokenPermissionsValidity(attributes.type, attributes.permissions);\n assertValidLifespan(attributes.lifespan);\n\n // Create the token\n const apiToken: ApiToken = await strapi.db.query('admin::api-token').create({\n select: SELECT_FIELDS,\n populate: POPULATE_FIELDS,\n data: {\n ...omit('permissions', attributes),\n accessKey: hash(accessKey),\n encryptedKey,\n ...getExpirationFields(attributes.lifespan),\n },\n });\n\n const result: ApiToken = { ...apiToken, accessKey };\n\n // If this is a custom type token, create and the related permissions\n if (attributes.type === constants.API_TOKEN_TYPE.CUSTOM) {\n // TODO: createMany doesn't seem to create relation properly, implement a better way rather than a ton of queries\n // const permissionsCount = await strapi.db.query('admin::api-token-permission').createMany({\n // populate: POPULATE_FIELDS,\n // data: attributes.permissions.map(action => ({ action, token: apiToken })),\n // });\n await Promise.all(\n uniq(attributes.permissions).map((action) =>\n strapi.db.query('admin::api-token-permission').create({\n data: { action, token: apiToken },\n })\n )\n );\n\n const currentPermissions = await strapi.db\n .query('admin::api-token')\n .load(apiToken, 'permissions');\n\n if (currentPermissions) {\n Object.assign(result, { permissions: map('action', currentPermissions) });\n }\n }\n\n return result;\n};\n\nconst regenerate = async (id: string | number): Promise<ApiToken> => {\n const accessKey = crypto.randomBytes(128).toString('hex');\n const encryptionService = getService('encryption');\n const encryptedKey = encryptionService.encrypt(accessKey);\n\n const apiToken: ApiToken = await strapi.db.query('admin::api-token').update({\n select: ['id', 'accessKey'],\n where: { id },\n data: {\n accessKey: hash(accessKey),\n encryptedKey,\n },\n });\n\n if (!apiToken) {\n throw new NotFoundError('The provided token id does not exist');\n }\n\n return {\n ...apiToken,\n accessKey,\n };\n};\n\nconst checkSaltIsDefined = () => {\n if (!strapi.config.get('admin.apiToken.salt')) {\n // TODO V5: stop reading API_TOKEN_SALT\n if (process.env.API_TOKEN_SALT) {\n process.emitWarning(`[deprecated] In future versions, Strapi will stop reading directly from the environment variable API_TOKEN_SALT. Please set apiToken.salt in config/admin.js instead.\nFor security reasons, keep storing the secret in an environment variable and use env() to read it in config/admin.js (ex: \\`apiToken: { salt: env('API_TOKEN_SALT') }\\`). See https://docs.strapi.io/developer-docs/latest/setup-deployment-guides/configurations/optional/environment.html#configuration-using-environment-variables.`);\n\n strapi.config.set('admin.apiToken.salt', process.env.API_TOKEN_SALT);\n } else {\n throw new Error(\n `Missing apiToken.salt. Please set apiToken.salt in config/admin.js (ex: you can generate one using Node with \\`crypto.randomBytes(16).toString('base64')\\`).\nFor security reasons, prefer storing the secret in an environment variable and read it in config/admin.js. See https://docs.strapi.io/developer-docs/latest/setup-deployment-guides/configurations/optional/environment.html#configuration-using-environment-variables.`\n );\n }\n }\n};\n\n/**\n * Return a list of all tokens and their permissions\n */\nconst list = async (): Promise<Array<ApiToken>> => {\n const tokens: Array<DBApiToken> = await strapi.db.query('admin::api-token').findMany({\n select: SELECT_FIELDS,\n populate: POPULATE_FIELDS,\n orderBy: { name: 'ASC' },\n });\n\n if (!tokens) {\n return tokens;\n }\n\n return tokens.map((token) => flattenTokenPermissions(token));\n};\n\n/**\n * Revoke (delete) a token\n */\nconst revoke = async (id: string | number): Promise<ApiToken> => {\n return strapi.db\n .query('admin::api-token')\n .delete({ select: SELECT_FIELDS, populate: POPULATE_FIELDS, where: { id } });\n};\n\n/**\n * Retrieve a token by id\n */\nconst getById = async (id: string | number) => {\n return getBy({ id });\n};\n\n/**\n * Retrieve a token by name\n */\nconst getByName = async (name: string) => {\n return getBy({ name });\n};\n\n/**\n * Update a token and its permissions\n */\nconst update = async (\n id: string | number,\n attributes: Update.Request['body']\n): Promise<ApiToken> => {\n // retrieve token without permissions\n const originalToken: DBApiToken = await strapi.db\n .query('admin::api-token')\n .findOne({ where: { id } });\n\n if (!originalToken) {\n throw new NotFoundError('Token not found');\n }\n\n const changingTypeToCustom =\n attributes.type === constants.API_TOKEN_TYPE.CUSTOM &&\n originalToken.type !== constants.API_TOKEN_TYPE.CUSTOM;\n\n // if we're updating the permissions on any token type, or changing from non-custom to custom, ensure they're still valid\n // if neither type nor permissions are changing, we don't need to validate again or else we can't allow partial update\n if (attributes.permissions || changingTypeToCustom) {\n assertCustomTokenPermissionsValidity(\n attributes.type || originalToken.type,\n attributes.permissions || originalToken.permissions\n );\n }\n\n assertValidLifespan(attributes.lifespan);\n\n const updatedToken: ApiToken = await strapi.db.query('admin::api-token').update({\n select: SELECT_FIELDS,\n where: { id },\n data: omit('permissions', attributes),\n });\n\n // custom tokens need to have their permissions updated as well\n if (updatedToken.type === constants.API_TOKEN_TYPE.CUSTOM && attributes.permissions) {\n const currentPermissionsResult = await strapi.db\n .query('admin::api-token')\n .load(updatedToken, 'permissions');\n\n const currentPermissions = map('action', currentPermissionsResult || []);\n const newPermissions = uniq(attributes.permissions);\n\n const actionsToDelete = difference(currentPermissions, newPermissions);\n const actionsToAdd = difference(newPermissions, currentPermissions);\n\n // TODO: improve efficiency here\n // method using a loop -- works but very inefficient\n await Promise.all(\n actionsToDelete.map((action) =>\n strapi.db.query('admin::api-token-permission').delete({\n where: { action, token: id },\n })\n )\n );\n\n // TODO: improve efficiency here\n // using a loop -- works but very inefficient\n await Promise.all(\n actionsToAdd.map((action) =>\n strapi.db.query('admin::api-token-permission').create({\n data: { action, token: id },\n })\n )\n );\n }\n // if type is not custom, make sure any old permissions get removed\n else if (updatedToken.type !== constants.API_TOKEN_TYPE.CUSTOM) {\n await strapi.db.query('admin::api-token-permission').delete({\n where: { token: id },\n });\n }\n\n // retrieve permissions\n const permissionsFromDb = await strapi.db\n .query('admin::api-token')\n .load(updatedToken, 'permissions');\n\n return {\n ...updatedToken,\n permissions: permissionsFromDb ? permissionsFromDb.map((p: any) => p.action) : undefined,\n };\n};\n\nconst count = async (where = {}): Promise<number> => {\n return strapi.db.query('admin::api-token').count({ where });\n};\n\nexport {\n create,\n count,\n regenerate,\n exists,\n checkSaltIsDefined,\n hash,\n list,\n revoke,\n getById,\n update,\n getByName,\n getBy,\n};\n"],"names":["ValidationError","NotFoundError","errors","SELECT_FIELDS","POPULATE_FIELDS","assertCustomTokenPermissionsValidity","type","permissions","constants","API_TOKEN_TYPE","CUSTOM","isEmpty","isArray","validPermissions","strapi","contentAPI","providers","action","keys","invalidPermissions","difference","join","isValidLifespan","lifespan","isNil","isNumber","Object","values","API_TOKEN_LIFESPANS","includes","assertValidLifespan","flattenTokenPermissions","token","map","getBy","whereParams","length","db","query","findOne","select","populate","where","encryptedKey","rest","accessKey","getService","decrypt","exists","apiToken","hash","crypto","createHmac","config","get","update","digest","getExpirationFields","isValidNumber","Number","isFinite","expiresAt","Date","now","create","attributes","encryptionService","randomBytes","toString","encrypt","data","omit","result","Promise","all","uniq","currentPermissions","load","assign","regenerate","id","checkSaltIsDefined","process","env","API_TOKEN_SALT","emitWarning","set","Error","list","tokens","findMany","orderBy","name","revoke","delete","getById","getByName","originalToken","changingTypeToCustom","updatedToken","currentPermissionsResult","newPermissions","actionsToDelete","actionsToAdd","permissionsFromDb","p","undefined","count"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"auth.js","sources":["../../../../../server/src/services/auth.ts"],"sourcesContent":["import bcrypt from 'bcryptjs';\nimport _ from 'lodash';\nimport { errors } from '@strapi/utils';\nimport { getService } from '../utils';\nimport type { AdminUser } from '../../../shared/contracts/shared';\nimport '@strapi/types';\n\nconst { ApplicationError } = errors;\n\n/**\n * hashes a password\n * @param password - password to hash\n * @returns hashed password\n */\nconst hashPassword = (password: string) => bcrypt.hash(password, 10);\n\n/**\n * Validate a password\n * @param password\n * @param hash\n * @returns {Promise<boolean>} is the password valid\n */\nconst validatePassword = (password: string, hash: string) => bcrypt.compare(password, hash);\n\n/**\n * Check login credentials\n * @param email the users email address\n * @param password the users password\n */\nconst checkCredentials = async ({ email, password }: { email: string; password: string }) => {\n const user: AdminUser = await strapi.db.query('admin::user').findOne({ where: { email } });\n\n if (!user || !user.password) {\n return [null, false, { message: 'Invalid credentials' }];\n }\n\n const isValid = await validatePassword(password, user.password);\n\n if (!isValid) {\n return [null, false, { message: 'Invalid credentials' }];\n }\n\n if (!(user.isActive === true)) {\n return [null, false, { message: 'User not active' }];\n }\n\n return [null, user];\n};\n\n/**\n * Send an email to the user if it exists or do nothing\n * @param email user email for which to reset the password\n */\nconst forgotPassword = async ({ email } = {} as { email: string }) => {\n const user: AdminUser = await strapi.db\n .query('admin::user')\n .findOne({ where: { email, isActive: true } });\n if (!user) {\n return;\n }\n\n const resetPasswordToken = getService('token').createToken();\n await getService('user').updateById(user.id, { resetPasswordToken });\n\n // Send an email to the admin.\n const url = `${strapi.config.get(\n 'admin.absoluteUrl'\n )}/auth/reset-password?code=${resetPasswordToken}`;\n\n return strapi\n .plugin('email')\n .service('email')\n .sendTemplatedEmail(\n {\n to: user.email,\n from: strapi.config.get('admin.forgotPassword.from'),\n replyTo: strapi.config.get('admin.forgotPassword.replyTo'),\n },\n strapi.config.get('admin.forgotPassword.emailTemplate'),\n {\n url,\n user: _.pick(user, ['email', 'firstname', 'lastname', 'username']),\n }\n )\n .catch((err: unknown) => {\n // log error server side but do not disclose it to the user to avoid leaking informations\n strapi.log.error(err);\n });\n};\n\n/**\n * Reset a user password\n * @param resetPasswordToken token generated to request a password reset\n * @param password new user password\n */\nconst resetPassword = async (\n { resetPasswordToken, password } = {} as { resetPasswordToken: string; password: string }\n) => {\n const matchingUser: AdminUser | undefined = await strapi.db\n .query('admin::user')\n .findOne({ where: { resetPasswordToken, isActive: true } });\n\n if (!matchingUser) {\n throw new ApplicationError();\n }\n\n return getService('user').updateById(matchingUser.id, {\n password,\n resetPasswordToken: null,\n });\n};\n\nexport default { checkCredentials, validatePassword, hashPassword, forgotPassword, resetPassword };\n"],"names":["ApplicationError","errors","hashPassword","password","bcrypt","hash","validatePassword","compare","checkCredentials","email","user","strapi","db","query","findOne","where","message","isValid","isActive","forgotPassword","resetPasswordToken","getService","createToken","updateById","id","url","config","get","plugin","service","sendTemplatedEmail","to","from","replyTo","_","pick","catch","err","log","error","resetPassword","matchingUser"],"mappings":"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"}
1
+ {"version":3,"file":"auth.js","sources":["../../../../../server/src/services/auth.ts"],"sourcesContent":["import bcrypt from 'bcryptjs';\nimport _ from 'lodash';\nimport { errors } from '@strapi/utils';\nimport { getService } from '../utils';\nimport type { AdminUser } from '../../../shared/contracts/shared';\nimport '@strapi/types';\n\nconst { ApplicationError } = errors;\n\n/**\n * hashes a password\n * @param password - password to hash\n * @returns hashed password\n */\nconst hashPassword = (password: string) => bcrypt.hash(password, 10);\n\n/**\n * Validate a password\n * @param password\n * @param hash\n * @returns {Promise<boolean>} is the password valid\n */\nconst validatePassword = (password: string, hash: string) => bcrypt.compare(password, hash);\n\n/**\n * Check login credentials\n * @param email the users email address\n * @param password the users password\n */\nconst checkCredentials = async ({ email, password }: { email: string; password: string }) => {\n const user: AdminUser = await strapi.db.query('admin::user').findOne({ where: { email } });\n\n if (!user || !user.password) {\n return [null, false, { message: 'Invalid credentials' }];\n }\n\n const isValid = await validatePassword(password, user.password);\n\n if (!isValid) {\n return [null, false, { message: 'Invalid credentials' }];\n }\n\n if (!(user.isActive === true)) {\n return [null, false, { message: 'User not active' }];\n }\n\n return [null, user];\n};\n\n/**\n * Send an email to the user if it exists or do nothing\n * @param email user email for which to reset the password\n */\nconst forgotPassword = async ({ email } = {} as { email: string }) => {\n const user: AdminUser = await strapi.db\n .query('admin::user')\n .findOne({ where: { email, isActive: true } });\n if (!user) {\n return;\n }\n\n const resetPasswordToken = getService('token').createToken();\n await getService('user').updateById(user.id, { resetPasswordToken });\n\n // Send an email to the admin.\n const url = `${strapi.config.get(\n 'admin.absoluteUrl'\n )}/auth/reset-password?code=${resetPasswordToken}`;\n\n return strapi\n .plugin('email')\n .service('email')\n .sendTemplatedEmail(\n {\n to: user.email,\n from: strapi.config.get('admin.forgotPassword.from'),\n replyTo: strapi.config.get('admin.forgotPassword.replyTo'),\n },\n strapi.config.get('admin.forgotPassword.emailTemplate'),\n {\n url,\n user: _.pick(user, ['email', 'firstname', 'lastname', 'username']),\n }\n )\n .catch((err: unknown) => {\n // log error server side but do not disclose it to the user to avoid leaking informations\n strapi.log.error(err);\n });\n};\n\n/**\n * Reset a user password\n * @param resetPasswordToken token generated to request a password reset\n * @param password new user password\n */\nconst resetPassword = async (\n { resetPasswordToken, password } = {} as { resetPasswordToken: string; password: string }\n) => {\n const matchingUser: AdminUser | undefined = await strapi.db\n .query('admin::user')\n .findOne({ where: { resetPasswordToken, isActive: true } });\n\n if (!matchingUser) {\n throw new ApplicationError();\n }\n\n return getService('user').updateById(matchingUser.id, {\n password,\n resetPasswordToken: null,\n });\n};\n\nexport default { checkCredentials, validatePassword, hashPassword, forgotPassword, resetPassword };\n"],"names":["ApplicationError","errors","hashPassword","password","bcrypt","hash","validatePassword","compare","checkCredentials","email","user","strapi","db","query","findOne","where","message","isValid","isActive","forgotPassword","resetPasswordToken","getService","createToken","updateById","id","url","config","get","plugin","service","sendTemplatedEmail","to","from","replyTo","_","pick","catch","err","log","error","resetPassword","matchingUser"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"auth.mjs","sources":["../../../../../server/src/services/auth.ts"],"sourcesContent":["import bcrypt from 'bcryptjs';\nimport _ from 'lodash';\nimport { errors } from '@strapi/utils';\nimport { getService } from '../utils';\nimport type { AdminUser } from '../../../shared/contracts/shared';\nimport '@strapi/types';\n\nconst { ApplicationError } = errors;\n\n/**\n * hashes a password\n * @param password - password to hash\n * @returns hashed password\n */\nconst hashPassword = (password: string) => bcrypt.hash(password, 10);\n\n/**\n * Validate a password\n * @param password\n * @param hash\n * @returns {Promise<boolean>} is the password valid\n */\nconst validatePassword = (password: string, hash: string) => bcrypt.compare(password, hash);\n\n/**\n * Check login credentials\n * @param email the users email address\n * @param password the users password\n */\nconst checkCredentials = async ({ email, password }: { email: string; password: string }) => {\n const user: AdminUser = await strapi.db.query('admin::user').findOne({ where: { email } });\n\n if (!user || !user.password) {\n return [null, false, { message: 'Invalid credentials' }];\n }\n\n const isValid = await validatePassword(password, user.password);\n\n if (!isValid) {\n return [null, false, { message: 'Invalid credentials' }];\n }\n\n if (!(user.isActive === true)) {\n return [null, false, { message: 'User not active' }];\n }\n\n return [null, user];\n};\n\n/**\n * Send an email to the user if it exists or do nothing\n * @param email user email for which to reset the password\n */\nconst forgotPassword = async ({ email } = {} as { email: string }) => {\n const user: AdminUser = await strapi.db\n .query('admin::user')\n .findOne({ where: { email, isActive: true } });\n if (!user) {\n return;\n }\n\n const resetPasswordToken = getService('token').createToken();\n await getService('user').updateById(user.id, { resetPasswordToken });\n\n // Send an email to the admin.\n const url = `${strapi.config.get(\n 'admin.absoluteUrl'\n )}/auth/reset-password?code=${resetPasswordToken}`;\n\n return strapi\n .plugin('email')\n .service('email')\n .sendTemplatedEmail(\n {\n to: user.email,\n from: strapi.config.get('admin.forgotPassword.from'),\n replyTo: strapi.config.get('admin.forgotPassword.replyTo'),\n },\n strapi.config.get('admin.forgotPassword.emailTemplate'),\n {\n url,\n user: _.pick(user, ['email', 'firstname', 'lastname', 'username']),\n }\n )\n .catch((err: unknown) => {\n // log error server side but do not disclose it to the user to avoid leaking informations\n strapi.log.error(err);\n });\n};\n\n/**\n * Reset a user password\n * @param resetPasswordToken token generated to request a password reset\n * @param password new user password\n */\nconst resetPassword = async (\n { resetPasswordToken, password } = {} as { resetPasswordToken: string; password: string }\n) => {\n const matchingUser: AdminUser | undefined = await strapi.db\n .query('admin::user')\n .findOne({ where: { resetPasswordToken, isActive: true } });\n\n if (!matchingUser) {\n throw new ApplicationError();\n }\n\n return getService('user').updateById(matchingUser.id, {\n password,\n resetPasswordToken: null,\n });\n};\n\nexport default { checkCredentials, validatePassword, hashPassword, forgotPassword, resetPassword };\n"],"names":["ApplicationError","errors","hashPassword","password","bcrypt","hash","validatePassword","compare","checkCredentials","email","user","strapi","db","query","findOne","where","message","isValid","isActive","forgotPassword","resetPasswordToken","getService","createToken","updateById","id","url","config","get","plugin","service","sendTemplatedEmail","to","from","replyTo","_","pick","catch","err","log","error","resetPassword","matchingUser"],"mappings":";;;;;;AAOA,MAAM,EAAEA,gBAAgB,EAAE,GAAGC,MAAAA;AAE7B;;;;AAIC,IACD,MAAMC,YAAe,GAAA,CAACC,WAAqBC,MAAOC,CAAAA,IAAI,CAACF,QAAU,EAAA,EAAA,CAAA;AAEjE;;;;;IAMA,MAAMG,mBAAmB,CAACH,QAAAA,EAAkBE,OAAiBD,MAAOG,CAAAA,OAAO,CAACJ,QAAUE,EAAAA,IAAAA,CAAAA;AAEtF;;;;AAIC,IACD,MAAMG,gBAAmB,GAAA,OAAO,EAAEC,KAAK,EAAEN,QAAQ,EAAuC,GAAA;IACtF,MAAMO,IAAAA,GAAkB,MAAMC,MAAOC,CAAAA,EAAE,CAACC,KAAK,CAAC,aAAeC,CAAAA,CAAAA,OAAO,CAAC;QAAEC,KAAO,EAAA;AAAEN,YAAAA;AAAM;AAAE,KAAA,CAAA;AAExF,IAAA,IAAI,CAACC,IAAAA,IAAQ,CAACA,IAAAA,CAAKP,QAAQ,EAAE;QAC3B,OAAO;AAAC,YAAA,IAAA;AAAM,YAAA,KAAA;AAAO,YAAA;gBAAEa,OAAS,EAAA;AAAsB;AAAE,SAAA;AAC1D;AAEA,IAAA,MAAMC,OAAU,GAAA,MAAMX,gBAAiBH,CAAAA,QAAAA,EAAUO,KAAKP,QAAQ,CAAA;AAE9D,IAAA,IAAI,CAACc,OAAS,EAAA;QACZ,OAAO;AAAC,YAAA,IAAA;AAAM,YAAA,KAAA;AAAO,YAAA;gBAAED,OAAS,EAAA;AAAsB;AAAE,SAAA;AAC1D;AAEA,IAAA,IAAI,EAAEN,IAAAA,CAAKQ,QAAQ,KAAK,IAAG,CAAI,EAAA;QAC7B,OAAO;AAAC,YAAA,IAAA;AAAM,YAAA,KAAA;AAAO,YAAA;gBAAEF,OAAS,EAAA;AAAkB;AAAE,SAAA;AACtD;IAEA,OAAO;AAAC,QAAA,IAAA;AAAMN,QAAAA;AAAK,KAAA;AACrB,CAAA;AAEA;;;IAIA,MAAMS,iBAAiB,OAAO,EAAEV,KAAK,EAAE,GAAG,EAAuB,GAAA;IAC/D,MAAMC,IAAAA,GAAkB,MAAMC,MAAOC,CAAAA,EAAE,CACpCC,KAAK,CAAC,aACNC,CAAAA,CAAAA,OAAO,CAAC;QAAEC,KAAO,EAAA;AAAEN,YAAAA,KAAAA;YAAOS,QAAU,EAAA;AAAK;AAAE,KAAA,CAAA;AAC9C,IAAA,IAAI,CAACR,IAAM,EAAA;AACT,QAAA;AACF;IAEA,MAAMU,kBAAAA,GAAqBC,UAAW,CAAA,OAAA,CAAA,CAASC,WAAW,EAAA;AAC1D,IAAA,MAAMD,WAAW,MAAQE,CAAAA,CAAAA,UAAU,CAACb,IAAAA,CAAKc,EAAE,EAAE;AAAEJ,QAAAA;AAAmB,KAAA,CAAA;;AAGlE,IAAA,MAAMK,GAAM,GAAA,CAAC,EAAEd,MAAAA,CAAOe,MAAM,CAACC,GAAG,CAC9B,mBACA,CAAA,CAAA,0BAA0B,EAAEP,kBAAAA,CAAmB,CAAC;IAElD,OAAOT,MAAAA,CACJiB,MAAM,CAAC,OAAA,CAAA,CACPC,OAAO,CAAC,OAAA,CAAA,CACRC,kBAAkB,CACjB;AACEC,QAAAA,EAAAA,EAAIrB,KAAKD,KAAK;AACduB,QAAAA,IAAAA,EAAMrB,MAAOe,CAAAA,MAAM,CAACC,GAAG,CAAC,2BAAA,CAAA;AACxBM,QAAAA,OAAAA,EAAStB,MAAOe,CAAAA,MAAM,CAACC,GAAG,CAAC,8BAAA;AAC7B,KAAA,EACAhB,MAAOe,CAAAA,MAAM,CAACC,GAAG,CAAC,oCAClB,CAAA,EAAA;AACEF,QAAAA,GAAAA;QACAf,IAAMwB,EAAAA,UAAAA,CAAEC,IAAI,CAACzB,IAAM,EAAA;AAAC,YAAA,OAAA;AAAS,YAAA,WAAA;AAAa,YAAA,UAAA;AAAY,YAAA;AAAW,SAAA;KAGpE0B,CAAAA,CAAAA,KAAK,CAAC,CAACC,GAAAA,GAAAA;;QAEN1B,MAAO2B,CAAAA,GAAG,CAACC,KAAK,CAACF,GAAAA,CAAAA;AACnB,KAAA,CAAA;AACJ,CAAA;AAEA;;;;IAKA,MAAMG,aAAgB,GAAA,OACpB,EAAEpB,kBAAkB,EAAEjB,QAAQ,EAAE,GAAG,EAAsD,GAAA;IAEzF,MAAMsC,YAAAA,GAAsC,MAAM9B,MAAOC,CAAAA,EAAE,CACxDC,KAAK,CAAC,aACNC,CAAAA,CAAAA,OAAO,CAAC;QAAEC,KAAO,EAAA;AAAEK,YAAAA,kBAAAA;YAAoBF,QAAU,EAAA;AAAK;AAAE,KAAA,CAAA;AAE3D,IAAA,IAAI,CAACuB,YAAc,EAAA;AACjB,QAAA,MAAM,IAAIzC,gBAAAA,EAAAA;AACZ;AAEA,IAAA,OAAOqB,WAAW,MAAQE,CAAAA,CAAAA,UAAU,CAACkB,YAAAA,CAAajB,EAAE,EAAE;AACpDrB,QAAAA,QAAAA;QACAiB,kBAAoB,EAAA;AACtB,KAAA,CAAA;AACF,CAAA;AAEA,WAAe;AAAEZ,IAAAA,gBAAAA;AAAkBF,IAAAA,gBAAAA;AAAkBJ,IAAAA,YAAAA;AAAciB,IAAAA,cAAAA;AAAgBqB,IAAAA;AAAc,CAAE;;;;"}
1
+ {"version":3,"file":"auth.mjs","sources":["../../../../../server/src/services/auth.ts"],"sourcesContent":["import bcrypt from 'bcryptjs';\nimport _ from 'lodash';\nimport { errors } from '@strapi/utils';\nimport { getService } from '../utils';\nimport type { AdminUser } from '../../../shared/contracts/shared';\nimport '@strapi/types';\n\nconst { ApplicationError } = errors;\n\n/**\n * hashes a password\n * @param password - password to hash\n * @returns hashed password\n */\nconst hashPassword = (password: string) => bcrypt.hash(password, 10);\n\n/**\n * Validate a password\n * @param password\n * @param hash\n * @returns {Promise<boolean>} is the password valid\n */\nconst validatePassword = (password: string, hash: string) => bcrypt.compare(password, hash);\n\n/**\n * Check login credentials\n * @param email the users email address\n * @param password the users password\n */\nconst checkCredentials = async ({ email, password }: { email: string; password: string }) => {\n const user: AdminUser = await strapi.db.query('admin::user').findOne({ where: { email } });\n\n if (!user || !user.password) {\n return [null, false, { message: 'Invalid credentials' }];\n }\n\n const isValid = await validatePassword(password, user.password);\n\n if (!isValid) {\n return [null, false, { message: 'Invalid credentials' }];\n }\n\n if (!(user.isActive === true)) {\n return [null, false, { message: 'User not active' }];\n }\n\n return [null, user];\n};\n\n/**\n * Send an email to the user if it exists or do nothing\n * @param email user email for which to reset the password\n */\nconst forgotPassword = async ({ email } = {} as { email: string }) => {\n const user: AdminUser = await strapi.db\n .query('admin::user')\n .findOne({ where: { email, isActive: true } });\n if (!user) {\n return;\n }\n\n const resetPasswordToken = getService('token').createToken();\n await getService('user').updateById(user.id, { resetPasswordToken });\n\n // Send an email to the admin.\n const url = `${strapi.config.get(\n 'admin.absoluteUrl'\n )}/auth/reset-password?code=${resetPasswordToken}`;\n\n return strapi\n .plugin('email')\n .service('email')\n .sendTemplatedEmail(\n {\n to: user.email,\n from: strapi.config.get('admin.forgotPassword.from'),\n replyTo: strapi.config.get('admin.forgotPassword.replyTo'),\n },\n strapi.config.get('admin.forgotPassword.emailTemplate'),\n {\n url,\n user: _.pick(user, ['email', 'firstname', 'lastname', 'username']),\n }\n )\n .catch((err: unknown) => {\n // log error server side but do not disclose it to the user to avoid leaking informations\n strapi.log.error(err);\n });\n};\n\n/**\n * Reset a user password\n * @param resetPasswordToken token generated to request a password reset\n * @param password new user password\n */\nconst resetPassword = async (\n { resetPasswordToken, password } = {} as { resetPasswordToken: string; password: string }\n) => {\n const matchingUser: AdminUser | undefined = await strapi.db\n .query('admin::user')\n .findOne({ where: { resetPasswordToken, isActive: true } });\n\n if (!matchingUser) {\n throw new ApplicationError();\n }\n\n return getService('user').updateById(matchingUser.id, {\n password,\n resetPasswordToken: null,\n });\n};\n\nexport default { checkCredentials, validatePassword, hashPassword, forgotPassword, resetPassword };\n"],"names":["ApplicationError","errors","hashPassword","password","bcrypt","hash","validatePassword","compare","checkCredentials","email","user","strapi","db","query","findOne","where","message","isValid","isActive","forgotPassword","resetPasswordToken","getService","createToken","updateById","id","url","config","get","plugin","service","sendTemplatedEmail","to","from","replyTo","_","pick","catch","err","log","error","resetPassword","matchingUser"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"content-type.js","sources":["../../../../../server/src/services/content-type.ts"],"sourcesContent":["import _ from 'lodash';\nimport { uniq, startsWith } from 'lodash/fp';\nimport { contentTypes as contentTypesUtils } from '@strapi/utils';\nimport type { Modules, Struct } from '@strapi/types';\nimport { getService } from '../utils';\nimport actionDomain from '../domain/action';\nimport permissionDomain from '../domain/permission';\n\ninterface FieldOptions {\n prefix?: string; // prefix to add to the path\n nestingLevel?: number; // level of nesting to achieve\n requiredOnly?: boolean; // only returns required nestedFields\n existingFields?: string[]; // fields that are already selected, meaning that some sub-fields may be required\n restrictedSubjects?: string[]; // subjectsId to ignore\n components?: {\n // components where components attributes can be found\n [key: string]: any;\n };\n}\n\n/**\n * Creates an array of paths to the fields and nested fields, without path nodes\n */\nconst getNestedFields = (\n model: Struct.ContentTypeSchema,\n {\n prefix = '',\n nestingLevel = 15,\n components = {},\n requiredOnly = false,\n existingFields = [],\n }: FieldOptions\n): string[] => {\n if (nestingLevel === 0) {\n return prefix ? [prefix] : [];\n }\n\n const nonAuthorizableFields = contentTypesUtils.getNonVisibleAttributes(model);\n\n return _.reduce(\n model.attributes,\n (fields: any, attr: any, key: any) => {\n if (nonAuthorizableFields.includes(key)) return fields;\n\n const fieldPath = prefix ? `${prefix}.${key}` : key;\n const shouldBeIncluded = !requiredOnly || attr.required === true;\n const insideExistingFields = existingFields && existingFields.some(startsWith(fieldPath));\n\n if (attr.type === 'component') {\n if (shouldBeIncluded || insideExistingFields) {\n const compoFields = getNestedFields(components[attr.component], {\n nestingLevel: nestingLevel - 1,\n prefix: fieldPath,\n components,\n requiredOnly,\n existingFields,\n });\n\n if (compoFields.length === 0 && shouldBeIncluded) {\n return fields.concat(fieldPath);\n }\n\n return fields.concat(compoFields);\n }\n return fields;\n }\n\n if (shouldBeIncluded) {\n return fields.concat(fieldPath);\n }\n\n return fields;\n },\n []\n );\n};\n\n/**\n * Creates an array of paths to the fields and nested fields, with path nodes\n */\nconst getNestedFieldsWithIntermediate = (\n model: Struct.ContentTypeSchema,\n { prefix = '', nestingLevel = 15, components = {} }: FieldOptions\n): string[] => {\n if (nestingLevel === 0) {\n return [];\n }\n\n const nonAuthorizableFields = contentTypesUtils.getNonVisibleAttributes(model);\n\n return _.reduce(\n model.attributes,\n (fields: any, attr: any, key: any) => {\n if (nonAuthorizableFields.includes(key)) return fields;\n\n const fieldPath = prefix ? `${prefix}.${key}` : key;\n fields.push(fieldPath);\n\n if (attr.type === 'component') {\n const compoFields = getNestedFieldsWithIntermediate(components[attr.component], {\n nestingLevel: nestingLevel - 1,\n prefix: fieldPath,\n components,\n });\n\n fields.push(...compoFields);\n }\n\n return fields;\n },\n []\n );\n};\n\n/**\n * Creates an array of permissions with the \"properties.fields\" attribute filled\n */\nconst getPermissionsWithNestedFields = (\n actions: any[],\n { nestingLevel, restrictedSubjects = [] }: FieldOptions = {}\n): Modules.Permissions.PermissionRule[] => {\n return actions.reduce((permissions, action) => {\n const validSubjects = action.subjects.filter(\n (subject: any) => !restrictedSubjects.includes(subject)\n );\n\n // Create a Permission for each subject (content-type uid) within the action\n for (const subject of validSubjects) {\n const fields = actionDomain.appliesToProperty('fields', action)\n ? getNestedFields(strapi.contentTypes[subject], {\n components: strapi.components,\n nestingLevel,\n })\n : undefined;\n\n const permission = permissionDomain.create({\n action: action.actionId,\n subject,\n properties: { fields },\n });\n\n permissions.push(permission);\n }\n\n return permissions;\n }, []);\n};\n\n/**\n * Cleans permissions' fields (add required ones, remove the non-existing ones)\n */\nconst cleanPermissionFields = (\n permissions: Modules.Permissions.PermissionRule[]\n): Modules.Permissions.PermissionRule[] => {\n const { actionProvider } = getService('permission');\n\n return permissions.map((permission: any) => {\n const {\n action: actionId,\n subject,\n properties: { fields },\n } = permission;\n\n const action = actionProvider.get(actionId) as any;\n\n // todo see if it's possible to check property on action + subject (async)\n if (!actionDomain.appliesToProperty('fields', action)) {\n return permissionDomain.deleteProperty('fields', permission);\n }\n\n if (!subject || !strapi.contentTypes[subject]) {\n return permission;\n }\n\n const possibleFields = getNestedFieldsWithIntermediate(strapi.contentTypes[subject], {\n components: strapi.components,\n });\n\n const currentFields: string[] = fields || [];\n\n const validUserFields: string[] = uniq(\n possibleFields.filter((pf) =>\n currentFields.some((cf) => pf === cf || startsWith(`${cf}.`, pf))\n )\n );\n\n // A field is considered \"not nested\" if no other valid user field starts with this field's path followed by a dot.\n // This helps to remove redundant parent paths when a more specific child path is already included.\n // For example, if 'component.title' is present, 'component' would be filtered out by this condition.\n const isNotNestedField = (field: string) =>\n !validUserFields.some(\n (validUserField: string) =>\n validUserField !== field && startsWith(`${field}.`, validUserField)\n );\n\n // Filter out fields that are parent paths of other included fields.\n const newFields = validUserFields.filter(isNotNestedField);\n\n return permissionDomain.setProperty('fields', newFields, permission);\n }, []);\n};\n\nexport {\n getNestedFields,\n getPermissionsWithNestedFields,\n cleanPermissionFields,\n getNestedFieldsWithIntermediate,\n};\n"],"names":["getNestedFields","model","prefix","nestingLevel","components","requiredOnly","existingFields","nonAuthorizableFields","contentTypesUtils","getNonVisibleAttributes","_","reduce","attributes","fields","attr","key","includes","fieldPath","shouldBeIncluded","required","insideExistingFields","some","startsWith","type","compoFields","component","length","concat","getNestedFieldsWithIntermediate","push","getPermissionsWithNestedFields","actions","restrictedSubjects","permissions","action","validSubjects","subjects","filter","subject","actionDomain","appliesToProperty","strapi","contentTypes","undefined","permission","permissionDomain","create","actionId","properties","cleanPermissionFields","actionProvider","getService","map","get","deleteProperty","possibleFields","currentFields","validUserFields","uniq","pf","cf","isNotNestedField","field","validUserField","newFields","setProperty"],"mappings":"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"}
1
+ {"version":3,"file":"content-type.js","sources":["../../../../../server/src/services/content-type.ts"],"sourcesContent":["import _ from 'lodash';\nimport { uniq, startsWith } from 'lodash/fp';\nimport { contentTypes as contentTypesUtils } from '@strapi/utils';\nimport type { Modules, Struct } from '@strapi/types';\nimport { getService } from '../utils';\nimport actionDomain from '../domain/action';\nimport permissionDomain from '../domain/permission';\n\ninterface FieldOptions {\n prefix?: string; // prefix to add to the path\n nestingLevel?: number; // level of nesting to achieve\n requiredOnly?: boolean; // only returns required nestedFields\n existingFields?: string[]; // fields that are already selected, meaning that some sub-fields may be required\n restrictedSubjects?: string[]; // subjectsId to ignore\n components?: {\n // components where components attributes can be found\n [key: string]: any;\n };\n}\n\n/**\n * Creates an array of paths to the fields and nested fields, without path nodes\n */\nconst getNestedFields = (\n model: Struct.ContentTypeSchema,\n {\n prefix = '',\n nestingLevel = 15,\n components = {},\n requiredOnly = false,\n existingFields = [],\n }: FieldOptions\n): string[] => {\n if (nestingLevel === 0) {\n return prefix ? [prefix] : [];\n }\n\n const nonAuthorizableFields = contentTypesUtils.getNonVisibleAttributes(model);\n\n return _.reduce(\n model.attributes,\n (fields: any, attr: any, key: any) => {\n if (nonAuthorizableFields.includes(key)) return fields;\n\n const fieldPath = prefix ? `${prefix}.${key}` : key;\n const shouldBeIncluded = !requiredOnly || attr.required === true;\n const insideExistingFields = existingFields && existingFields.some(startsWith(fieldPath));\n\n if (attr.type === 'component') {\n if (shouldBeIncluded || insideExistingFields) {\n const compoFields = getNestedFields(components[attr.component], {\n nestingLevel: nestingLevel - 1,\n prefix: fieldPath,\n components,\n requiredOnly,\n existingFields,\n });\n\n if (compoFields.length === 0 && shouldBeIncluded) {\n return fields.concat(fieldPath);\n }\n\n return fields.concat(compoFields);\n }\n return fields;\n }\n\n if (shouldBeIncluded) {\n return fields.concat(fieldPath);\n }\n\n return fields;\n },\n []\n );\n};\n\n/**\n * Creates an array of paths to the fields and nested fields, with path nodes\n */\nconst getNestedFieldsWithIntermediate = (\n model: Struct.ContentTypeSchema,\n { prefix = '', nestingLevel = 15, components = {} }: FieldOptions\n): string[] => {\n if (nestingLevel === 0) {\n return [];\n }\n\n const nonAuthorizableFields = contentTypesUtils.getNonVisibleAttributes(model);\n\n return _.reduce(\n model.attributes,\n (fields: any, attr: any, key: any) => {\n if (nonAuthorizableFields.includes(key)) return fields;\n\n const fieldPath = prefix ? `${prefix}.${key}` : key;\n fields.push(fieldPath);\n\n if (attr.type === 'component') {\n const compoFields = getNestedFieldsWithIntermediate(components[attr.component], {\n nestingLevel: nestingLevel - 1,\n prefix: fieldPath,\n components,\n });\n\n fields.push(...compoFields);\n }\n\n return fields;\n },\n []\n );\n};\n\n/**\n * Creates an array of permissions with the \"properties.fields\" attribute filled\n */\nconst getPermissionsWithNestedFields = (\n actions: any[],\n { nestingLevel, restrictedSubjects = [] }: FieldOptions = {}\n): Modules.Permissions.PermissionRule[] => {\n return actions.reduce((permissions, action) => {\n const validSubjects = action.subjects.filter(\n (subject: any) => !restrictedSubjects.includes(subject)\n );\n\n // Create a Permission for each subject (content-type uid) within the action\n for (const subject of validSubjects) {\n const fields = actionDomain.appliesToProperty('fields', action)\n ? getNestedFields(strapi.contentTypes[subject], {\n components: strapi.components,\n nestingLevel,\n })\n : undefined;\n\n const permission = permissionDomain.create({\n action: action.actionId,\n subject,\n properties: { fields },\n });\n\n permissions.push(permission);\n }\n\n return permissions;\n }, []);\n};\n\n/**\n * Cleans permissions' fields (add required ones, remove the non-existing ones)\n */\nconst cleanPermissionFields = (\n permissions: Modules.Permissions.PermissionRule[]\n): Modules.Permissions.PermissionRule[] => {\n const { actionProvider } = getService('permission');\n\n return permissions.map((permission: any) => {\n const {\n action: actionId,\n subject,\n properties: { fields },\n } = permission;\n\n const action = actionProvider.get(actionId) as any;\n\n // todo see if it's possible to check property on action + subject (async)\n if (!actionDomain.appliesToProperty('fields', action)) {\n return permissionDomain.deleteProperty('fields', permission);\n }\n\n if (!subject || !strapi.contentTypes[subject]) {\n return permission;\n }\n\n const possibleFields = getNestedFieldsWithIntermediate(strapi.contentTypes[subject], {\n components: strapi.components,\n });\n\n const currentFields: string[] = fields || [];\n\n const validUserFields: string[] = uniq(\n possibleFields.filter((pf) =>\n currentFields.some((cf) => pf === cf || startsWith(`${cf}.`, pf))\n )\n );\n\n // A field is considered \"not nested\" if no other valid user field starts with this field's path followed by a dot.\n // This helps to remove redundant parent paths when a more specific child path is already included.\n // For example, if 'component.title' is present, 'component' would be filtered out by this condition.\n const isNotNestedField = (field: string) =>\n !validUserFields.some(\n (validUserField: string) =>\n validUserField !== field && startsWith(`${field}.`, validUserField)\n );\n\n // Filter out fields that are parent paths of other included fields.\n const newFields = validUserFields.filter(isNotNestedField);\n\n return permissionDomain.setProperty('fields', newFields, permission);\n }, []);\n};\n\nexport {\n getNestedFields,\n getPermissionsWithNestedFields,\n cleanPermissionFields,\n getNestedFieldsWithIntermediate,\n};\n"],"names":["getNestedFields","model","prefix","nestingLevel","components","requiredOnly","existingFields","nonAuthorizableFields","contentTypesUtils","getNonVisibleAttributes","_","reduce","attributes","fields","attr","key","includes","fieldPath","shouldBeIncluded","required","insideExistingFields","some","startsWith","type","compoFields","component","length","concat","getNestedFieldsWithIntermediate","push","getPermissionsWithNestedFields","actions","restrictedSubjects","permissions","action","validSubjects","subjects","filter","subject","actionDomain","appliesToProperty","strapi","contentTypes","undefined","permission","permissionDomain","create","actionId","properties","cleanPermissionFields","actionProvider","getService","map","get","deleteProperty","possibleFields","currentFields","validUserFields","uniq","pf","cf","isNotNestedField","field","validUserField","newFields","setProperty"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"content-type.mjs","sources":["../../../../../server/src/services/content-type.ts"],"sourcesContent":["import _ from 'lodash';\nimport { uniq, startsWith } from 'lodash/fp';\nimport { contentTypes as contentTypesUtils } from '@strapi/utils';\nimport type { Modules, Struct } from '@strapi/types';\nimport { getService } from '../utils';\nimport actionDomain from '../domain/action';\nimport permissionDomain from '../domain/permission';\n\ninterface FieldOptions {\n prefix?: string; // prefix to add to the path\n nestingLevel?: number; // level of nesting to achieve\n requiredOnly?: boolean; // only returns required nestedFields\n existingFields?: string[]; // fields that are already selected, meaning that some sub-fields may be required\n restrictedSubjects?: string[]; // subjectsId to ignore\n components?: {\n // components where components attributes can be found\n [key: string]: any;\n };\n}\n\n/**\n * Creates an array of paths to the fields and nested fields, without path nodes\n */\nconst getNestedFields = (\n model: Struct.ContentTypeSchema,\n {\n prefix = '',\n nestingLevel = 15,\n components = {},\n requiredOnly = false,\n existingFields = [],\n }: FieldOptions\n): string[] => {\n if (nestingLevel === 0) {\n return prefix ? [prefix] : [];\n }\n\n const nonAuthorizableFields = contentTypesUtils.getNonVisibleAttributes(model);\n\n return _.reduce(\n model.attributes,\n (fields: any, attr: any, key: any) => {\n if (nonAuthorizableFields.includes(key)) return fields;\n\n const fieldPath = prefix ? `${prefix}.${key}` : key;\n const shouldBeIncluded = !requiredOnly || attr.required === true;\n const insideExistingFields = existingFields && existingFields.some(startsWith(fieldPath));\n\n if (attr.type === 'component') {\n if (shouldBeIncluded || insideExistingFields) {\n const compoFields = getNestedFields(components[attr.component], {\n nestingLevel: nestingLevel - 1,\n prefix: fieldPath,\n components,\n requiredOnly,\n existingFields,\n });\n\n if (compoFields.length === 0 && shouldBeIncluded) {\n return fields.concat(fieldPath);\n }\n\n return fields.concat(compoFields);\n }\n return fields;\n }\n\n if (shouldBeIncluded) {\n return fields.concat(fieldPath);\n }\n\n return fields;\n },\n []\n );\n};\n\n/**\n * Creates an array of paths to the fields and nested fields, with path nodes\n */\nconst getNestedFieldsWithIntermediate = (\n model: Struct.ContentTypeSchema,\n { prefix = '', nestingLevel = 15, components = {} }: FieldOptions\n): string[] => {\n if (nestingLevel === 0) {\n return [];\n }\n\n const nonAuthorizableFields = contentTypesUtils.getNonVisibleAttributes(model);\n\n return _.reduce(\n model.attributes,\n (fields: any, attr: any, key: any) => {\n if (nonAuthorizableFields.includes(key)) return fields;\n\n const fieldPath = prefix ? `${prefix}.${key}` : key;\n fields.push(fieldPath);\n\n if (attr.type === 'component') {\n const compoFields = getNestedFieldsWithIntermediate(components[attr.component], {\n nestingLevel: nestingLevel - 1,\n prefix: fieldPath,\n components,\n });\n\n fields.push(...compoFields);\n }\n\n return fields;\n },\n []\n );\n};\n\n/**\n * Creates an array of permissions with the \"properties.fields\" attribute filled\n */\nconst getPermissionsWithNestedFields = (\n actions: any[],\n { nestingLevel, restrictedSubjects = [] }: FieldOptions = {}\n): Modules.Permissions.PermissionRule[] => {\n return actions.reduce((permissions, action) => {\n const validSubjects = action.subjects.filter(\n (subject: any) => !restrictedSubjects.includes(subject)\n );\n\n // Create a Permission for each subject (content-type uid) within the action\n for (const subject of validSubjects) {\n const fields = actionDomain.appliesToProperty('fields', action)\n ? getNestedFields(strapi.contentTypes[subject], {\n components: strapi.components,\n nestingLevel,\n })\n : undefined;\n\n const permission = permissionDomain.create({\n action: action.actionId,\n subject,\n properties: { fields },\n });\n\n permissions.push(permission);\n }\n\n return permissions;\n }, []);\n};\n\n/**\n * Cleans permissions' fields (add required ones, remove the non-existing ones)\n */\nconst cleanPermissionFields = (\n permissions: Modules.Permissions.PermissionRule[]\n): Modules.Permissions.PermissionRule[] => {\n const { actionProvider } = getService('permission');\n\n return permissions.map((permission: any) => {\n const {\n action: actionId,\n subject,\n properties: { fields },\n } = permission;\n\n const action = actionProvider.get(actionId) as any;\n\n // todo see if it's possible to check property on action + subject (async)\n if (!actionDomain.appliesToProperty('fields', action)) {\n return permissionDomain.deleteProperty('fields', permission);\n }\n\n if (!subject || !strapi.contentTypes[subject]) {\n return permission;\n }\n\n const possibleFields = getNestedFieldsWithIntermediate(strapi.contentTypes[subject], {\n components: strapi.components,\n });\n\n const currentFields: string[] = fields || [];\n\n const validUserFields: string[] = uniq(\n possibleFields.filter((pf) =>\n currentFields.some((cf) => pf === cf || startsWith(`${cf}.`, pf))\n )\n );\n\n // A field is considered \"not nested\" if no other valid user field starts with this field's path followed by a dot.\n // This helps to remove redundant parent paths when a more specific child path is already included.\n // For example, if 'component.title' is present, 'component' would be filtered out by this condition.\n const isNotNestedField = (field: string) =>\n !validUserFields.some(\n (validUserField: string) =>\n validUserField !== field && startsWith(`${field}.`, validUserField)\n );\n\n // Filter out fields that are parent paths of other included fields.\n const newFields = validUserFields.filter(isNotNestedField);\n\n return permissionDomain.setProperty('fields', newFields, permission);\n }, []);\n};\n\nexport {\n getNestedFields,\n getPermissionsWithNestedFields,\n cleanPermissionFields,\n getNestedFieldsWithIntermediate,\n};\n"],"names":["getNestedFields","model","prefix","nestingLevel","components","requiredOnly","existingFields","nonAuthorizableFields","contentTypesUtils","getNonVisibleAttributes","_","reduce","attributes","fields","attr","key","includes","fieldPath","shouldBeIncluded","required","insideExistingFields","some","startsWith","type","compoFields","component","length","concat","getNestedFieldsWithIntermediate","push","getPermissionsWithNestedFields","actions","restrictedSubjects","permissions","action","validSubjects","subjects","filter","subject","actionDomain","appliesToProperty","strapi","contentTypes","undefined","permission","permissionDomain","create","actionId","properties","cleanPermissionFields","actionProvider","getService","map","get","deleteProperty","possibleFields","currentFields","validUserFields","uniq","pf","cf","isNotNestedField","field","validUserField","newFields","setProperty"],"mappings":"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"}
1
+ {"version":3,"file":"content-type.mjs","sources":["../../../../../server/src/services/content-type.ts"],"sourcesContent":["import _ from 'lodash';\nimport { uniq, startsWith } from 'lodash/fp';\nimport { contentTypes as contentTypesUtils } from '@strapi/utils';\nimport type { Modules, Struct } from '@strapi/types';\nimport { getService } from '../utils';\nimport actionDomain from '../domain/action';\nimport permissionDomain from '../domain/permission';\n\ninterface FieldOptions {\n prefix?: string; // prefix to add to the path\n nestingLevel?: number; // level of nesting to achieve\n requiredOnly?: boolean; // only returns required nestedFields\n existingFields?: string[]; // fields that are already selected, meaning that some sub-fields may be required\n restrictedSubjects?: string[]; // subjectsId to ignore\n components?: {\n // components where components attributes can be found\n [key: string]: any;\n };\n}\n\n/**\n * Creates an array of paths to the fields and nested fields, without path nodes\n */\nconst getNestedFields = (\n model: Struct.ContentTypeSchema,\n {\n prefix = '',\n nestingLevel = 15,\n components = {},\n requiredOnly = false,\n existingFields = [],\n }: FieldOptions\n): string[] => {\n if (nestingLevel === 0) {\n return prefix ? [prefix] : [];\n }\n\n const nonAuthorizableFields = contentTypesUtils.getNonVisibleAttributes(model);\n\n return _.reduce(\n model.attributes,\n (fields: any, attr: any, key: any) => {\n if (nonAuthorizableFields.includes(key)) return fields;\n\n const fieldPath = prefix ? `${prefix}.${key}` : key;\n const shouldBeIncluded = !requiredOnly || attr.required === true;\n const insideExistingFields = existingFields && existingFields.some(startsWith(fieldPath));\n\n if (attr.type === 'component') {\n if (shouldBeIncluded || insideExistingFields) {\n const compoFields = getNestedFields(components[attr.component], {\n nestingLevel: nestingLevel - 1,\n prefix: fieldPath,\n components,\n requiredOnly,\n existingFields,\n });\n\n if (compoFields.length === 0 && shouldBeIncluded) {\n return fields.concat(fieldPath);\n }\n\n return fields.concat(compoFields);\n }\n return fields;\n }\n\n if (shouldBeIncluded) {\n return fields.concat(fieldPath);\n }\n\n return fields;\n },\n []\n );\n};\n\n/**\n * Creates an array of paths to the fields and nested fields, with path nodes\n */\nconst getNestedFieldsWithIntermediate = (\n model: Struct.ContentTypeSchema,\n { prefix = '', nestingLevel = 15, components = {} }: FieldOptions\n): string[] => {\n if (nestingLevel === 0) {\n return [];\n }\n\n const nonAuthorizableFields = contentTypesUtils.getNonVisibleAttributes(model);\n\n return _.reduce(\n model.attributes,\n (fields: any, attr: any, key: any) => {\n if (nonAuthorizableFields.includes(key)) return fields;\n\n const fieldPath = prefix ? `${prefix}.${key}` : key;\n fields.push(fieldPath);\n\n if (attr.type === 'component') {\n const compoFields = getNestedFieldsWithIntermediate(components[attr.component], {\n nestingLevel: nestingLevel - 1,\n prefix: fieldPath,\n components,\n });\n\n fields.push(...compoFields);\n }\n\n return fields;\n },\n []\n );\n};\n\n/**\n * Creates an array of permissions with the \"properties.fields\" attribute filled\n */\nconst getPermissionsWithNestedFields = (\n actions: any[],\n { nestingLevel, restrictedSubjects = [] }: FieldOptions = {}\n): Modules.Permissions.PermissionRule[] => {\n return actions.reduce((permissions, action) => {\n const validSubjects = action.subjects.filter(\n (subject: any) => !restrictedSubjects.includes(subject)\n );\n\n // Create a Permission for each subject (content-type uid) within the action\n for (const subject of validSubjects) {\n const fields = actionDomain.appliesToProperty('fields', action)\n ? getNestedFields(strapi.contentTypes[subject], {\n components: strapi.components,\n nestingLevel,\n })\n : undefined;\n\n const permission = permissionDomain.create({\n action: action.actionId,\n subject,\n properties: { fields },\n });\n\n permissions.push(permission);\n }\n\n return permissions;\n }, []);\n};\n\n/**\n * Cleans permissions' fields (add required ones, remove the non-existing ones)\n */\nconst cleanPermissionFields = (\n permissions: Modules.Permissions.PermissionRule[]\n): Modules.Permissions.PermissionRule[] => {\n const { actionProvider } = getService('permission');\n\n return permissions.map((permission: any) => {\n const {\n action: actionId,\n subject,\n properties: { fields },\n } = permission;\n\n const action = actionProvider.get(actionId) as any;\n\n // todo see if it's possible to check property on action + subject (async)\n if (!actionDomain.appliesToProperty('fields', action)) {\n return permissionDomain.deleteProperty('fields', permission);\n }\n\n if (!subject || !strapi.contentTypes[subject]) {\n return permission;\n }\n\n const possibleFields = getNestedFieldsWithIntermediate(strapi.contentTypes[subject], {\n components: strapi.components,\n });\n\n const currentFields: string[] = fields || [];\n\n const validUserFields: string[] = uniq(\n possibleFields.filter((pf) =>\n currentFields.some((cf) => pf === cf || startsWith(`${cf}.`, pf))\n )\n );\n\n // A field is considered \"not nested\" if no other valid user field starts with this field's path followed by a dot.\n // This helps to remove redundant parent paths when a more specific child path is already included.\n // For example, if 'component.title' is present, 'component' would be filtered out by this condition.\n const isNotNestedField = (field: string) =>\n !validUserFields.some(\n (validUserField: string) =>\n validUserField !== field && startsWith(`${field}.`, validUserField)\n );\n\n // Filter out fields that are parent paths of other included fields.\n const newFields = validUserFields.filter(isNotNestedField);\n\n return permissionDomain.setProperty('fields', newFields, permission);\n }, []);\n};\n\nexport {\n getNestedFields,\n getPermissionsWithNestedFields,\n cleanPermissionFields,\n getNestedFieldsWithIntermediate,\n};\n"],"names":["getNestedFields","model","prefix","nestingLevel","components","requiredOnly","existingFields","nonAuthorizableFields","contentTypesUtils","getNonVisibleAttributes","_","reduce","attributes","fields","attr","key","includes","fieldPath","shouldBeIncluded","required","insideExistingFields","some","startsWith","type","compoFields","component","length","concat","getNestedFieldsWithIntermediate","push","getPermissionsWithNestedFields","actions","restrictedSubjects","permissions","action","validSubjects","subjects","filter","subject","actionDomain","appliesToProperty","strapi","contentTypes","undefined","permission","permissionDomain","create","actionId","properties","cleanPermissionFields","actionProvider","getService","map","get","deleteProperty","possibleFields","currentFields","validUserFields","uniq","pf","cf","isNotNestedField","field","validUserField","newFields","setProperty"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"encryption.js","sources":["../../../../../server/src/services/encryption.ts"],"sourcesContent":["import crypto from 'crypto';\n\nconst IV_LENGTH = 16; // 16 bytes for AES-GCM IV\nconst ENCRYPTION_VERSION = 'v1';\n\nconst getHashedKey = (): Buffer | null => {\n const rawKey: string = strapi.config.get('admin.secrets.encryptionKey');\n if (!rawKey) {\n strapi.log.warn('Encryption key is missing from config');\n return null;\n }\n\n return crypto.createHash('sha256').update(rawKey).digest(); // Always 32 bytes\n};\n\n/**\n * Encrypts a value string using AES-256-GCM.\n * Returns a string prefixed with the encryption version and includes IV, encrypted content, and auth tag (all hex-encoded).\n */\nconst encrypt = (value: string) => {\n const key = getHashedKey();\n if (!key) return null;\n\n const iv = crypto.randomBytes(IV_LENGTH);\n const cipher = crypto.createCipheriv('aes-256-gcm', key, iv);\n\n let encrypted = cipher.update(value, 'utf8', 'hex');\n encrypted += cipher.final('hex');\n\n const authTag = cipher.getAuthTag();\n\n return `${ENCRYPTION_VERSION}:${iv.toString('hex')}:${encrypted}:${authTag.toString('hex')}`;\n};\n\n/**\n * Decrypts a value encrypted by encrypt().\n * Supports versioned formats like v1:iv:encrypted:authTag\n */\nconst decrypt = (encryptedValue: string) => {\n const [version, ...rest] = encryptedValue.split(':');\n\n if (version !== ENCRYPTION_VERSION) {\n throw new Error(`Unsupported encryption version: ${version}`);\n }\n\n const [ivHex, encryptedHex, tagHex] = rest;\n if (!ivHex || !encryptedHex || !tagHex) {\n throw new Error('Invalid encrypted value format');\n }\n\n const key = getHashedKey();\n if (!key) return null;\n\n const iv = Buffer.from(ivHex, 'hex');\n const encryptedText = Buffer.from(encryptedHex, 'hex');\n const authTag = Buffer.from(tagHex, 'hex');\n\n try {\n const decipher = crypto.createDecipheriv('aes-256-gcm', key, iv);\n decipher.setAuthTag(authTag);\n\n let decrypted = decipher.update(encryptedText, undefined, 'utf8');\n decrypted += decipher.final('utf8');\n\n return decrypted;\n } catch (err) {\n strapi.log.warn(\n '[decrypt] Unable to decrypt value — encryption key may have changed or data is corrupted.'\n );\n return null;\n }\n};\n\nexport default {\n encrypt,\n decrypt,\n};\n"],"names":["IV_LENGTH","ENCRYPTION_VERSION","getHashedKey","rawKey","strapi","config","get","log","warn","crypto","createHash","update","digest","encrypt","value","key","iv","randomBytes","cipher","createCipheriv","encrypted","final","authTag","getAuthTag","toString","decrypt","encryptedValue","version","rest","split","Error","ivHex","encryptedHex","tagHex","Buffer","from","encryptedText","decipher","createDecipheriv","setAuthTag","decrypted","undefined","err"],"mappings":"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"}
1
+ {"version":3,"file":"encryption.js","sources":["../../../../../server/src/services/encryption.ts"],"sourcesContent":["import crypto from 'crypto';\n\nconst IV_LENGTH = 16; // 16 bytes for AES-GCM IV\nconst ENCRYPTION_VERSION = 'v1';\n\nconst getHashedKey = (): Buffer | null => {\n const rawKey: string = strapi.config.get('admin.secrets.encryptionKey');\n if (!rawKey) {\n strapi.log.warn('Encryption key is missing from config');\n return null;\n }\n\n return crypto.createHash('sha256').update(rawKey).digest(); // Always 32 bytes\n};\n\n/**\n * Encrypts a value string using AES-256-GCM.\n * Returns a string prefixed with the encryption version and includes IV, encrypted content, and auth tag (all hex-encoded).\n */\nconst encrypt = (value: string) => {\n const key = getHashedKey();\n if (!key) return null;\n\n const iv = crypto.randomBytes(IV_LENGTH);\n const cipher = crypto.createCipheriv('aes-256-gcm', key, iv);\n\n let encrypted = cipher.update(value, 'utf8', 'hex');\n encrypted += cipher.final('hex');\n\n const authTag = cipher.getAuthTag();\n\n return `${ENCRYPTION_VERSION}:${iv.toString('hex')}:${encrypted}:${authTag.toString('hex')}`;\n};\n\n/**\n * Decrypts a value encrypted by encrypt().\n * Supports versioned formats like v1:iv:encrypted:authTag\n */\nconst decrypt = (encryptedValue: string) => {\n const [version, ...rest] = encryptedValue.split(':');\n\n if (version !== ENCRYPTION_VERSION) {\n throw new Error(`Unsupported encryption version: ${version}`);\n }\n\n const [ivHex, encryptedHex, tagHex] = rest;\n if (!ivHex || !encryptedHex || !tagHex) {\n throw new Error('Invalid encrypted value format');\n }\n\n const key = getHashedKey();\n if (!key) return null;\n\n const iv = Buffer.from(ivHex, 'hex');\n const encryptedText = Buffer.from(encryptedHex, 'hex');\n const authTag = Buffer.from(tagHex, 'hex');\n\n try {\n const decipher = crypto.createDecipheriv('aes-256-gcm', key, iv);\n decipher.setAuthTag(authTag);\n\n let decrypted = decipher.update(encryptedText, undefined, 'utf8');\n decrypted += decipher.final('utf8');\n\n return decrypted;\n } catch (err) {\n strapi.log.warn(\n '[decrypt] Unable to decrypt value — encryption key may have changed or data is corrupted.'\n );\n return null;\n }\n};\n\nexport default {\n encrypt,\n decrypt,\n};\n"],"names":["IV_LENGTH","ENCRYPTION_VERSION","getHashedKey","rawKey","strapi","config","get","log","warn","crypto","createHash","update","digest","encrypt","value","key","iv","randomBytes","cipher","createCipheriv","encrypted","final","authTag","getAuthTag","toString","decrypt","encryptedValue","version","rest","split","Error","ivHex","encryptedHex","tagHex","Buffer","from","encryptedText","decipher","createDecipheriv","setAuthTag","decrypted","undefined","err"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"encryption.mjs","sources":["../../../../../server/src/services/encryption.ts"],"sourcesContent":["import crypto from 'crypto';\n\nconst IV_LENGTH = 16; // 16 bytes for AES-GCM IV\nconst ENCRYPTION_VERSION = 'v1';\n\nconst getHashedKey = (): Buffer | null => {\n const rawKey: string = strapi.config.get('admin.secrets.encryptionKey');\n if (!rawKey) {\n strapi.log.warn('Encryption key is missing from config');\n return null;\n }\n\n return crypto.createHash('sha256').update(rawKey).digest(); // Always 32 bytes\n};\n\n/**\n * Encrypts a value string using AES-256-GCM.\n * Returns a string prefixed with the encryption version and includes IV, encrypted content, and auth tag (all hex-encoded).\n */\nconst encrypt = (value: string) => {\n const key = getHashedKey();\n if (!key) return null;\n\n const iv = crypto.randomBytes(IV_LENGTH);\n const cipher = crypto.createCipheriv('aes-256-gcm', key, iv);\n\n let encrypted = cipher.update(value, 'utf8', 'hex');\n encrypted += cipher.final('hex');\n\n const authTag = cipher.getAuthTag();\n\n return `${ENCRYPTION_VERSION}:${iv.toString('hex')}:${encrypted}:${authTag.toString('hex')}`;\n};\n\n/**\n * Decrypts a value encrypted by encrypt().\n * Supports versioned formats like v1:iv:encrypted:authTag\n */\nconst decrypt = (encryptedValue: string) => {\n const [version, ...rest] = encryptedValue.split(':');\n\n if (version !== ENCRYPTION_VERSION) {\n throw new Error(`Unsupported encryption version: ${version}`);\n }\n\n const [ivHex, encryptedHex, tagHex] = rest;\n if (!ivHex || !encryptedHex || !tagHex) {\n throw new Error('Invalid encrypted value format');\n }\n\n const key = getHashedKey();\n if (!key) return null;\n\n const iv = Buffer.from(ivHex, 'hex');\n const encryptedText = Buffer.from(encryptedHex, 'hex');\n const authTag = Buffer.from(tagHex, 'hex');\n\n try {\n const decipher = crypto.createDecipheriv('aes-256-gcm', key, iv);\n decipher.setAuthTag(authTag);\n\n let decrypted = decipher.update(encryptedText, undefined, 'utf8');\n decrypted += decipher.final('utf8');\n\n return decrypted;\n } catch (err) {\n strapi.log.warn(\n '[decrypt] Unable to decrypt value — encryption key may have changed or data is corrupted.'\n );\n return null;\n }\n};\n\nexport default {\n encrypt,\n decrypt,\n};\n"],"names":["IV_LENGTH","ENCRYPTION_VERSION","getHashedKey","rawKey","strapi","config","get","log","warn","crypto","createHash","update","digest","encrypt","value","key","iv","randomBytes","cipher","createCipheriv","encrypted","final","authTag","getAuthTag","toString","decrypt","encryptedValue","version","rest","split","Error","ivHex","encryptedHex","tagHex","Buffer","from","encryptedText","decipher","createDecipheriv","setAuthTag","decrypted","undefined","err"],"mappings":"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"}
1
+ {"version":3,"file":"encryption.mjs","sources":["../../../../../server/src/services/encryption.ts"],"sourcesContent":["import crypto from 'crypto';\n\nconst IV_LENGTH = 16; // 16 bytes for AES-GCM IV\nconst ENCRYPTION_VERSION = 'v1';\n\nconst getHashedKey = (): Buffer | null => {\n const rawKey: string = strapi.config.get('admin.secrets.encryptionKey');\n if (!rawKey) {\n strapi.log.warn('Encryption key is missing from config');\n return null;\n }\n\n return crypto.createHash('sha256').update(rawKey).digest(); // Always 32 bytes\n};\n\n/**\n * Encrypts a value string using AES-256-GCM.\n * Returns a string prefixed with the encryption version and includes IV, encrypted content, and auth tag (all hex-encoded).\n */\nconst encrypt = (value: string) => {\n const key = getHashedKey();\n if (!key) return null;\n\n const iv = crypto.randomBytes(IV_LENGTH);\n const cipher = crypto.createCipheriv('aes-256-gcm', key, iv);\n\n let encrypted = cipher.update(value, 'utf8', 'hex');\n encrypted += cipher.final('hex');\n\n const authTag = cipher.getAuthTag();\n\n return `${ENCRYPTION_VERSION}:${iv.toString('hex')}:${encrypted}:${authTag.toString('hex')}`;\n};\n\n/**\n * Decrypts a value encrypted by encrypt().\n * Supports versioned formats like v1:iv:encrypted:authTag\n */\nconst decrypt = (encryptedValue: string) => {\n const [version, ...rest] = encryptedValue.split(':');\n\n if (version !== ENCRYPTION_VERSION) {\n throw new Error(`Unsupported encryption version: ${version}`);\n }\n\n const [ivHex, encryptedHex, tagHex] = rest;\n if (!ivHex || !encryptedHex || !tagHex) {\n throw new Error('Invalid encrypted value format');\n }\n\n const key = getHashedKey();\n if (!key) return null;\n\n const iv = Buffer.from(ivHex, 'hex');\n const encryptedText = Buffer.from(encryptedHex, 'hex');\n const authTag = Buffer.from(tagHex, 'hex');\n\n try {\n const decipher = crypto.createDecipheriv('aes-256-gcm', key, iv);\n decipher.setAuthTag(authTag);\n\n let decrypted = decipher.update(encryptedText, undefined, 'utf8');\n decrypted += decipher.final('utf8');\n\n return decrypted;\n } catch (err) {\n strapi.log.warn(\n '[decrypt] Unable to decrypt value — encryption key may have changed or data is corrupted.'\n );\n return null;\n }\n};\n\nexport default {\n encrypt,\n decrypt,\n};\n"],"names":["IV_LENGTH","ENCRYPTION_VERSION","getHashedKey","rawKey","strapi","config","get","log","warn","crypto","createHash","update","digest","encrypt","value","key","iv","randomBytes","cipher","createCipheriv","encrypted","final","authTag","getAuthTag","toString","decrypt","encryptedValue","version","rest","split","Error","ivHex","encryptedHex","tagHex","Buffer","from","encryptedText","decipher","createDecipheriv","setAuthTag","decrypted","undefined","err"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"homepage.js","sources":["../../../../../server/src/services/homepage.ts"],"sourcesContent":["import { Core } from '@strapi/types';\nimport { getService } from '../utils';\nimport {\n HomepageLayout,\n HomepageLayoutSchema,\n HomepageLayoutWrite,\n HomepageLayoutWriteSchema,\n} from '../controllers/validation/schema';\n\nconst DEFAULT_WIDTH = 6 as const;\nconst keyFor = (userId: number) => `homepage-layout:${userId}`;\n\nconst isContentTypeVisible = (model: any) =>\n model?.pluginOptions?.['content-type-builder']?.visible !== false;\n\nexport const homepageService = ({ strapi }: { strapi: Core.Strapi }) => {\n const adminStore = strapi.store({ type: 'core', name: 'admin' });\n const getKeyStatistics = async () => {\n const contentTypes = Object.entries(strapi.contentTypes).filter(([, contentType]) => {\n return isContentTypeVisible(contentType);\n });\n\n const countApiTokens = await getService('api-token').count();\n const countAdmins = await getService('user').count();\n const countLocales = (await strapi.plugin('i18n')?.service('locales')?.count()) ?? null;\n const countsAssets = await strapi.db.query('plugin::upload.file').count();\n const countWebhooks = await strapi.db.query('strapi::webhook').count();\n\n const componentCategories = new Set(\n Object.values(strapi.components).map((component) => component.category)\n );\n const components = Array.from(componentCategories);\n\n return {\n assets: countsAssets,\n contentTypes: contentTypes.length,\n components: components.length,\n locales: countLocales,\n admins: countAdmins,\n webhooks: countWebhooks,\n apiTokens: countApiTokens,\n };\n };\n\n const getHomepageLayout = async (userId: number): Promise<HomepageLayout | null> => {\n const key = keyFor(userId);\n const value = await adminStore.get({ key });\n if (!value) {\n // nothing saved yet\n return null;\n }\n\n return HomepageLayoutSchema.parse(value);\n };\n\n const updateHomepageLayout = async (userId: number, input: unknown): Promise<HomepageLayout> => {\n const write: HomepageLayoutWrite = HomepageLayoutWriteSchema.parse(input);\n\n const key = keyFor(userId);\n\n const currentRaw = await adminStore.get({ key });\n const current: HomepageLayout | null = currentRaw\n ? HomepageLayoutSchema.parse(currentRaw)\n : null;\n\n const widgetsNext = write.widgets ?? current?.widgets ?? [];\n\n // Normalize widths (fill defaults where missing)\n const normalizedWidgets = widgetsNext.map((w) => {\n const prev = current?.widgets.find((cw) => cw.uid === w.uid);\n return {\n uid: w.uid,\n width: w.width ?? prev?.width ?? DEFAULT_WIDTH,\n };\n });\n\n const next: HomepageLayout = {\n version: write.version ?? 1,\n widgets: normalizedWidgets,\n updatedAt: write.updatedAt ?? new Date().toISOString(),\n };\n\n await adminStore.set({ key, value: next });\n return next;\n };\n return {\n getKeyStatistics,\n getHomepageLayout,\n updateHomepageLayout,\n };\n};\n"],"names":["DEFAULT_WIDTH","keyFor","userId","isContentTypeVisible","model","pluginOptions","visible","homepageService","strapi","adminStore","store","type","name","getKeyStatistics","contentTypes","Object","entries","filter","contentType","countApiTokens","getService","count","countAdmins","countLocales","plugin","service","countsAssets","db","query","countWebhooks","componentCategories","Set","values","components","map","component","category","Array","from","assets","length","locales","admins","webhooks","apiTokens","getHomepageLayout","key","value","get","HomepageLayoutSchema","parse","updateHomepageLayout","input","write","HomepageLayoutWriteSchema","currentRaw","current","widgetsNext","widgets","normalizedWidgets","w","prev","find","cw","uid","width","next","version","updatedAt","Date","toISOString","set"],"mappings":"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"}
1
+ {"version":3,"file":"homepage.js","sources":["../../../../../server/src/services/homepage.ts"],"sourcesContent":["import { Core } from '@strapi/types';\nimport { getService } from '../utils';\nimport {\n HomepageLayout,\n HomepageLayoutSchema,\n HomepageLayoutWrite,\n HomepageLayoutWriteSchema,\n} from '../controllers/validation/schema';\n\nconst DEFAULT_WIDTH = 6 as const;\nconst keyFor = (userId: number) => `homepage-layout:${userId}`;\n\nconst isContentTypeVisible = (model: any) =>\n model?.pluginOptions?.['content-type-builder']?.visible !== false;\n\nexport const homepageService = ({ strapi }: { strapi: Core.Strapi }) => {\n const adminStore = strapi.store({ type: 'core', name: 'admin' });\n const getKeyStatistics = async () => {\n const contentTypes = Object.entries(strapi.contentTypes).filter(([, contentType]) => {\n return isContentTypeVisible(contentType);\n });\n\n const countApiTokens = await getService('api-token').count();\n const countAdmins = await getService('user').count();\n const countLocales = (await strapi.plugin('i18n')?.service('locales')?.count()) ?? null;\n const countsAssets = await strapi.db.query('plugin::upload.file').count();\n const countWebhooks = await strapi.db.query('strapi::webhook').count();\n\n const componentCategories = new Set(\n Object.values(strapi.components).map((component) => component.category)\n );\n const components = Array.from(componentCategories);\n\n return {\n assets: countsAssets,\n contentTypes: contentTypes.length,\n components: components.length,\n locales: countLocales,\n admins: countAdmins,\n webhooks: countWebhooks,\n apiTokens: countApiTokens,\n };\n };\n\n const getHomepageLayout = async (userId: number): Promise<HomepageLayout | null> => {\n const key = keyFor(userId);\n const value = await adminStore.get({ key });\n if (!value) {\n // nothing saved yet\n return null;\n }\n\n return HomepageLayoutSchema.parse(value);\n };\n\n const updateHomepageLayout = async (userId: number, input: unknown): Promise<HomepageLayout> => {\n const write: HomepageLayoutWrite = HomepageLayoutWriteSchema.parse(input);\n\n const key = keyFor(userId);\n\n const currentRaw = await adminStore.get({ key });\n const current: HomepageLayout | null = currentRaw\n ? HomepageLayoutSchema.parse(currentRaw)\n : null;\n\n const widgetsNext = write.widgets ?? current?.widgets ?? [];\n\n // Normalize widths (fill defaults where missing)\n const normalizedWidgets = widgetsNext.map((w) => {\n const prev = current?.widgets.find((cw) => cw.uid === w.uid);\n return {\n uid: w.uid,\n width: w.width ?? prev?.width ?? DEFAULT_WIDTH,\n };\n });\n\n const next: HomepageLayout = {\n version: write.version ?? 1,\n widgets: normalizedWidgets,\n updatedAt: write.updatedAt ?? new Date().toISOString(),\n };\n\n await adminStore.set({ key, value: next });\n return next;\n };\n return {\n getKeyStatistics,\n getHomepageLayout,\n updateHomepageLayout,\n };\n};\n"],"names":["DEFAULT_WIDTH","keyFor","userId","isContentTypeVisible","model","pluginOptions","visible","homepageService","strapi","adminStore","store","type","name","getKeyStatistics","contentTypes","Object","entries","filter","contentType","countApiTokens","getService","count","countAdmins","countLocales","plugin","service","countsAssets","db","query","countWebhooks","componentCategories","Set","values","components","map","component","category","Array","from","assets","length","locales","admins","webhooks","apiTokens","getHomepageLayout","key","value","get","HomepageLayoutSchema","parse","updateHomepageLayout","input","write","HomepageLayoutWriteSchema","currentRaw","current","widgetsNext","widgets","normalizedWidgets","w","prev","find","cw","uid","width","next","version","updatedAt","Date","toISOString","set"],"mappings":"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"}