@strapi/admin 4.5.0-alpha.0 → 4.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (317) hide show
  1. package/admin/src/StrapiApp.js +21 -18
  2. package/admin/src/assets/images/hot-air-balloon.png +0 -0
  3. package/admin/src/assets/images/icon_offline-cloud.svg +3 -3
  4. package/admin/src/assets/images/logo-strapi-2022.svg +7 -0
  5. package/admin/src/assets/images/upgrade-details.png +0 -0
  6. package/admin/src/components/Providers/index.js +14 -10
  7. package/admin/src/content-manager/components/CollectionTypeFormWrapper/index.js +24 -0
  8. package/admin/src/content-manager/components/DynamicTable/CellContent/CellValue.js +1 -1
  9. package/admin/src/content-manager/components/DynamicTable/CellContent/RelationMultiple/index.js +5 -4
  10. package/admin/src/content-manager/components/DynamicTable/CellContent/index.js +10 -0
  11. package/admin/src/content-manager/components/DynamicTable/TableRows/index.js +20 -15
  12. package/admin/src/content-manager/components/DynamicTable/index.js +21 -4
  13. package/admin/src/content-manager/components/DynamicZone/components/Component/index.js +19 -9
  14. package/admin/src/content-manager/components/DynamicZone/index.js +6 -2
  15. package/admin/src/content-manager/components/EditViewDataManagerProvider/index.js +153 -63
  16. package/admin/src/content-manager/components/EditViewDataManagerProvider/reducer.js +180 -132
  17. package/admin/src/content-manager/components/EditViewDataManagerProvider/utils/cleanData.js +70 -16
  18. package/admin/src/content-manager/components/EditViewDataManagerProvider/utils/findLeafByPathAndReplace.js +52 -0
  19. package/admin/src/content-manager/components/EditViewDataManagerProvider/utils/index.js +2 -0
  20. package/admin/src/content-manager/components/EditViewDataManagerProvider/utils/recursivelyFindPathsBasedOnCondition.js +72 -0
  21. package/admin/src/content-manager/components/FieldComponent/index.js +9 -2
  22. package/admin/src/content-manager/components/FieldTypeIcon/index.js +31 -1
  23. package/admin/src/content-manager/components/Inputs/index.js +36 -14
  24. package/admin/src/content-manager/components/NonRepeatableComponent/index.js +2 -0
  25. package/admin/src/content-manager/components/PreviewWysiwyg/index.js +1 -1
  26. package/admin/src/content-manager/components/RelationInput/RelationInput.js +163 -96
  27. package/admin/src/content-manager/components/RelationInput/components/RelationItem.js +2 -2
  28. package/admin/src/content-manager/components/RelationInput/constants.js +1 -1
  29. package/admin/src/content-manager/components/RelationInputDataManager/RelationInputDataManager.js +116 -73
  30. package/admin/src/content-manager/components/RelationInputDataManager/utils/diffRelations.js +24 -0
  31. package/admin/src/content-manager/components/RelationInputDataManager/utils/index.js +3 -1
  32. package/admin/src/content-manager/components/RelationInputDataManager/utils/normalizeRelations.js +17 -31
  33. package/admin/src/content-manager/components/RelationInputDataManager/utils/normalizeSearchResults.js +16 -0
  34. package/admin/src/content-manager/components/RelationInputDataManager/utils/select.js +35 -11
  35. package/admin/src/content-manager/components/RepeatableComponent/DraggedItem/index.js +5 -0
  36. package/admin/src/content-manager/components/RepeatableComponent/index.js +4 -3
  37. package/admin/src/content-manager/components/SingleTypeFormWrapper/index.js +23 -0
  38. package/admin/src/content-manager/hooks/__test__/usePrev.test.js +26 -0
  39. package/admin/src/content-manager/hooks/index.js +1 -0
  40. package/admin/src/content-manager/hooks/useFetchContentTypeLayout/utils/formatLayouts.js +19 -48
  41. package/admin/src/content-manager/hooks/usePrev.js +14 -0
  42. package/admin/src/content-manager/hooks/useRelation/useRelation.js +116 -15
  43. package/admin/src/content-manager/pages/App/reducer.js +3 -0
  44. package/admin/src/content-manager/pages/EditSettingsView/components/FormModal.js +7 -2
  45. package/admin/src/content-manager/pages/EditSettingsView/index.js +2 -1
  46. package/admin/src/content-manager/pages/EditView/Header/index.js +118 -50
  47. package/admin/src/content-manager/pages/EditView/Header/utils/select.js +4 -0
  48. package/admin/src/content-manager/pages/EditView/index.js +102 -93
  49. package/admin/src/content-manager/pages/ListSettingsView/components/DraggableCard.js +3 -3
  50. package/admin/src/content-manager/pages/ListSettingsView/components/Settings.js +2 -2
  51. package/admin/src/content-manager/pages/ListSettingsView/components/SortDisplayedFields.js +1 -1
  52. package/admin/src/content-manager/pages/ListView/index.js +24 -15
  53. package/admin/src/content-manager/pages/ListView/utils/buildQueryString.js +14 -2
  54. package/admin/src/contexts/ApiTokenPermissions/index.js +24 -0
  55. package/admin/src/core/apis/CustomFields.js +79 -0
  56. package/admin/src/core/apis/index.js +1 -0
  57. package/admin/src/core/store/configureStore.js +17 -2
  58. package/admin/src/favicon.png +0 -0
  59. package/admin/src/hooks/index.js +1 -0
  60. package/admin/src/hooks/useFetchMarketplacePlugins/index.js +2 -2
  61. package/admin/src/hooks/useFetchMarketplacePlugins/utils/api.js +4 -2
  62. package/admin/src/hooks/useFetchMarketplaceProviders/index.js +3 -3
  63. package/admin/src/hooks/useFetchMarketplaceProviders/utils/api.js +5 -3
  64. package/admin/src/hooks/useRegenerate/index.js +34 -0
  65. package/admin/src/index.js +1 -0
  66. package/admin/src/pages/App/index.js +1 -1
  67. package/admin/src/pages/HomePage/SocialLinks.js +1 -1
  68. package/admin/src/pages/HomePage/assets/corner-ornament.svg +48 -0
  69. package/admin/src/pages/HomePage/index.js +3 -2
  70. package/admin/src/pages/MarketplacePage/components/NpmPackageCard/CardButton.js +110 -0
  71. package/admin/src/pages/MarketplacePage/components/NpmPackageCard/InstallPluginButton.js +32 -21
  72. package/admin/src/pages/MarketplacePage/components/NpmPackageCard/PackageStats.js +79 -0
  73. package/admin/src/pages/MarketplacePage/components/NpmPackageCard/index.js +28 -11
  74. package/admin/src/pages/MarketplacePage/components/NpmPackagesFilters/FilterSelect.js +41 -0
  75. package/admin/src/pages/MarketplacePage/components/NpmPackagesFilters/FiltersPopover.js +96 -0
  76. package/admin/src/pages/MarketplacePage/components/NpmPackagesFilters/index.js +106 -0
  77. package/admin/src/pages/MarketplacePage/components/NpmPackagesGrid/index.js +4 -0
  78. package/admin/src/pages/MarketplacePage/components/SortSelect/index.js +70 -0
  79. package/admin/src/pages/MarketplacePage/index.js +68 -8
  80. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/ActionBoundRoutes/index.js +56 -0
  81. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/BoundRoute/getMethodColor.js +41 -0
  82. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/BoundRoute/index.js +72 -0
  83. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/CollapsableContentType/CheckBoxWrapper.js +30 -0
  84. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/CollapsableContentType/index.js +150 -0
  85. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/ContenTypesSection/index.js +37 -0
  86. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/FormApiTokenContainer/index.js +255 -0
  87. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/FormBody/index.js +78 -0
  88. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/FormHead/index.js +89 -0
  89. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/Permissions/index.js +40 -0
  90. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/Regenerate/index.js +68 -0
  91. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/index.js +216 -197
  92. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/init.js +13 -0
  93. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/reducer.js +72 -0
  94. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/utils/getDateOfExpiration.js +16 -0
  95. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/utils/index.js +5 -0
  96. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/utils/schema.js +2 -1
  97. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/utils/transformPermissionsData.js +36 -0
  98. package/admin/src/pages/SettingsPage/pages/ApiTokens/ListView/DynamicTable/DefaultButton/index.js +63 -0
  99. package/admin/src/pages/SettingsPage/pages/ApiTokens/ListView/DynamicTable/DeleteButton/index.js +1 -0
  100. package/admin/src/pages/SettingsPage/pages/ApiTokens/ListView/DynamicTable/ReadButton/index.js +19 -0
  101. package/admin/src/pages/SettingsPage/pages/ApiTokens/ListView/DynamicTable/UpdateButton/index.js +3 -36
  102. package/admin/src/pages/SettingsPage/pages/ApiTokens/ListView/DynamicTable/index.js +13 -11
  103. package/admin/src/pages/SettingsPage/pages/ApiTokens/ListView/index.js +3 -2
  104. package/admin/src/pages/SettingsPage/pages/ApiTokens/ListView/utils/tableHeaders.js +8 -8
  105. package/admin/src/pages/SettingsPage/pages/ApiTokens/ProtectedEditView/index.js +1 -1
  106. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/ConditionsModal/ActionRow/index.js +7 -38
  107. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/ConditionsModal/ActionRow/utils/options.js +31 -0
  108. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/ConditionsModal/index.js +32 -43
  109. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/ContentTypeCollapse/Collapse/index.js +1 -1
  110. package/admin/src/pages/SettingsPage/pages/Roles/ListPage/components/RoleRow/index.js +3 -1
  111. package/admin/src/pages/SettingsPage/pages/Roles/ListPage/index.js +2 -1
  112. package/admin/src/pages/SettingsPage/pages/Users/ListPage/ModalForm/index.js +2 -2
  113. package/admin/src/pages/SettingsPage/pages/Webhooks/EditView/components/EventInput/index.js +2 -2
  114. package/admin/src/permissions/defaultPermissions.js +2 -6
  115. package/admin/src/translations/ca.json +4 -2
  116. package/admin/src/translations/de.json +5 -2
  117. package/admin/src/translations/dk.json +4 -1
  118. package/admin/src/translations/en.json +38 -3
  119. package/admin/src/translations/es.json +157 -158
  120. package/admin/src/translations/fr.json +4 -1
  121. package/admin/src/translations/gu.json +608 -606
  122. package/admin/src/translations/he.json +1 -1
  123. package/admin/src/translations/hi.json +689 -687
  124. package/admin/src/translations/hu.json +3 -1
  125. package/admin/src/translations/id.json +3 -1
  126. package/admin/src/translations/it.json +3 -1
  127. package/admin/src/translations/ja.json +3 -1
  128. package/admin/src/translations/ko.json +3 -1
  129. package/admin/src/translations/ml.json +689 -687
  130. package/admin/src/translations/nl.json +4 -1
  131. package/admin/src/translations/no.json +1 -1
  132. package/admin/src/translations/pl.json +3 -1
  133. package/admin/src/translations/pt-BR.json +4 -1
  134. package/admin/src/translations/ru.json +489 -491
  135. package/admin/src/translations/sa.json +86 -83
  136. package/admin/src/translations/sk.json +4 -1
  137. package/admin/src/translations/sv.json +4 -1
  138. package/admin/src/translations/th.json +1 -1
  139. package/admin/src/translations/zh-Hans.json +5 -2
  140. package/admin/src/translations/zh.json +4 -1
  141. package/build/1856.172d5fa0.chunk.js +174 -0
  142. package/build/2077.058590f4.chunk.js +206 -0
  143. package/build/2912.2c42c07b.chunk.js +259 -0
  144. package/build/4318.5e670740.chunk.js +30 -0
  145. package/build/4715.22747b59.chunk.js +387 -0
  146. package/build/{4800.d09f1225.chunk.js → 4800.a6935af6.chunk.js} +1 -1
  147. package/build/4982.1b75ddb1.chunk.js +325 -0
  148. package/build/617f9c948fa79e6d73bd.png +0 -0
  149. package/build/6d21938306785f176538.png +0 -0
  150. package/build/70674f63fc3904c20de0.svg +7 -0
  151. package/build/7379.d246dd38.chunk.js +1 -0
  152. package/build/7692.a36fb2c2.chunk.js +470 -0
  153. package/build/7841.c50e9509.chunk.js +259 -0
  154. package/build/7866.ba215f99.chunk.js +505 -0
  155. package/build/7e9af4fb7e723fcebf1f.svg +48 -0
  156. package/build/8380.e53e7207.chunk.js +299 -0
  157. package/build/8549.832ed79d.chunk.js +159 -0
  158. package/build/8738.0fe8a61e.chunk.js +463 -0
  159. package/build/{9066.08049eb1.chunk.js → 9066.eaf76ff3.chunk.js} +5 -5
  160. package/build/{9166.037339e0.chunk.js → 9166.90876521.chunk.js} +16 -15
  161. package/build/{9420.43a86e7c.chunk.js → 9420.5292d1d2.chunk.js} +38 -37
  162. package/build/9649.468667d9.chunk.js +199 -0
  163. package/build/9d5d788027e86620c234.svg +5 -0
  164. package/build/{Admin-authenticatedApp.e39f36c9.chunk.js → Admin-authenticatedApp.c4f68103.chunk.js} +3 -3
  165. package/build/{Admin_homePage.118926e0.chunk.js → Admin_homePage.26d32e30.chunk.js} +6 -5
  166. package/build/Admin_marketplace.32375885.chunk.js +22 -0
  167. package/build/{Admin_profilePage.9d50ac44.chunk.js → Admin_profilePage.da32abbc.chunk.js} +1 -1
  168. package/build/Admin_settingsPage.bf2234e1.chunk.js +178 -0
  169. package/build/admin-app.9049056c.chunk.js +112 -0
  170. package/build/admin-edit-roles-page.69d9fcb2.chunk.js +1 -0
  171. package/build/{admin-users.97a08630.chunk.js → admin-users.d71f198a.chunk.js} +3 -3
  172. package/build/api-tokens-create-page.93dd0689.chunk.js +1 -0
  173. package/build/api-tokens-edit-page.b0adac81.chunk.js +1 -0
  174. package/build/api-tokens-list-page.bb36535f.chunk.js +16 -0
  175. package/build/ca-json.07ae0f2c.chunk.js +1 -0
  176. package/build/content-manager.ff998bed.chunk.js +1204 -0
  177. package/build/content-type-builder-list-view.5b3cd768.chunk.js +194 -0
  178. package/build/content-type-builder-translation-en-json.f985c9c4.chunk.js +1 -0
  179. package/build/content-type-builder-translation-sv-json.6deff030.chunk.js +1 -0
  180. package/build/content-type-builder.16af63a6.chunk.js +145 -0
  181. package/build/de-json.6b3e1894.chunk.js +1 -0
  182. package/build/dk-json.144c6a8e.chunk.js +1 -0
  183. package/build/{email-settings-page.64037147.chunk.js → email-settings-page.c3469093.chunk.js} +6 -6
  184. package/build/en-json.4a269f6b.chunk.js +1 -0
  185. package/build/es-json.6d123a82.chunk.js +1 -0
  186. package/build/fr-json.28ab54cb.chunk.js +1 -0
  187. package/build/gu-json.9a50ea64.chunk.js +1 -0
  188. package/build/he-json.72f18790.chunk.js +1 -0
  189. package/build/hi-json.0301b7ba.chunk.js +1 -0
  190. package/build/hu-json.c4b641bb.chunk.js +1 -0
  191. package/build/{i18n-settings-page.0b73785d.chunk.js → i18n-settings-page.46d894ff.chunk.js} +5 -5
  192. package/build/id-json.86035797.chunk.js +1 -0
  193. package/build/index.html +1 -1
  194. package/build/it-json.bbdc8993.chunk.js +1 -0
  195. package/build/ja-json.1c9eeeec.chunk.js +1 -0
  196. package/build/ko-json.e1f66398.chunk.js +1 -0
  197. package/build/main.91328e7a.js +9381 -0
  198. package/build/ml-json.963c889f.chunk.js +1 -0
  199. package/build/nl-json.2b8cc3a0.chunk.js +1 -0
  200. package/build/no-json.a58c28bd.chunk.js +1 -0
  201. package/build/pl-json.249626b3.chunk.js +1 -0
  202. package/build/pt-BR-json.7852f808.chunk.js +1 -0
  203. package/build/ru-json.d7cfc2ff.chunk.js +1 -0
  204. package/build/runtime~main.c9c319c0.js +2 -0
  205. package/build/sa-json.44e95991.chunk.js +1 -0
  206. package/build/sk-json.7ba4b330.chunk.js +1 -0
  207. package/build/sso-settings-page.9ceb0140.chunk.js +1 -0
  208. package/build/sv-json.8e5a7911.chunk.js +1 -0
  209. package/build/th-json.a67309b1.chunk.js +1 -0
  210. package/build/{upload-settings.80ff0974.chunk.js → upload-settings.53b690f3.chunk.js} +5 -5
  211. package/build/{upload-translation-en-json.004a86c1.chunk.js → upload-translation-en-json.86da7b0a.chunk.js} +1 -1
  212. package/build/{users-advanced-settings-page.a02f4806.chunk.js → users-advanced-settings-page.3f4ee86e.chunk.js} +5 -5
  213. package/build/{webhook-edit-page.d2ea3351.chunk.js → webhook-edit-page.dc9442ce.chunk.js} +2 -2
  214. package/build/webhook-list-page.02191138.chunk.js +134 -0
  215. package/build/zh-Hans-json.21617c24.chunk.js +1 -0
  216. package/build/zh-json.608aaf24.chunk.js +1 -0
  217. package/ee/admin/pages/SettingsPage/pages/Roles/ListPage/index.js +3 -2
  218. package/ee/server/controllers/user.js +5 -3
  219. package/env.js +1 -0
  220. package/package.json +13 -11
  221. package/scripts/build.js +11 -0
  222. package/server/bootstrap.js +19 -1
  223. package/server/config/admin-actions.js +20 -0
  224. package/server/content-types/api-token-permission.js +36 -0
  225. package/server/content-types/api-token.js +25 -1
  226. package/server/content-types/index.js +1 -0
  227. package/server/controllers/admin.js +3 -0
  228. package/server/controllers/api-token.js +24 -1
  229. package/server/controllers/content-api.js +15 -0
  230. package/server/controllers/index.js +1 -0
  231. package/server/controllers/user.js +3 -2
  232. package/server/routes/api-tokens.js +11 -0
  233. package/server/routes/content-api.js +20 -0
  234. package/server/routes/index.js +2 -0
  235. package/server/services/api-token.js +309 -29
  236. package/server/services/constants.js +10 -0
  237. package/server/services/permission/engine.js +36 -226
  238. package/server/services/permission.js +4 -1
  239. package/server/strategies/admin.js +7 -1
  240. package/server/strategies/api-token.js +72 -11
  241. package/server/validation/api-tokens.js +12 -2
  242. package/utils/create-plugins-exclude-path.js +40 -0
  243. package/utils/get-custom-app-config-file.js +5 -0
  244. package/webpack.alias.js +0 -13
  245. package/webpack.config.js +4 -1
  246. package/admin/src/assets/images/banner_strapi-rocket.png +0 -0
  247. package/admin/src/assets/images/big-logo-home.png +0 -0
  248. package/admin/src/assets/images/homepage-logo.png +0 -0
  249. package/admin/src/assets/images/icon_made-by-strapi.svg +0 -5
  250. package/admin/src/assets/images/logo_strapi_auth.png +0 -0
  251. package/admin/src/assets/images/logo_strapi_auth_v4.png +0 -0
  252. package/admin/src/assets/images/logo_strapi_menu.png +0 -0
  253. package/admin/src/assets/images/oops.png +0 -0
  254. package/admin/src/content-manager/components/State/index.js +0 -37
  255. package/admin/src/favicon.ico +0 -0
  256. package/build/15026a3d58aeb2828134.png +0 -0
  257. package/build/1856.47226450.chunk.js +0 -173
  258. package/build/2077.c935ee42.chunk.js +0 -205
  259. package/build/2912.a015078a.chunk.js +0 -258
  260. package/build/4715.58cd558f.chunk.js +0 -387
  261. package/build/4982.05eda880.chunk.js +0 -324
  262. package/build/7098.40dcd7bf.chunk.js +0 -1
  263. package/build/7841.91f793dc.chunk.js +0 -258
  264. package/build/7866.1201afbd.chunk.js +0 -504
  265. package/build/8380.8789ff76.chunk.js +0 -284
  266. package/build/8549.133c4473.chunk.js +0 -158
  267. package/build/8851.e4ac62f2.chunk.js +0 -158
  268. package/build/90f49a385afb000fb1d4.svg +0 -5
  269. package/build/9311.7cc03f29.chunk.js +0 -508
  270. package/build/Admin_marketplace.82c0570b.chunk.js +0 -11
  271. package/build/Admin_settingsPage.98a711e5.chunk.js +0 -178
  272. package/build/a6b842e0b6d2b61135d1.svg +0 -5
  273. package/build/admin-app.4f7618a9.chunk.js +0 -112
  274. package/build/admin-edit-roles-page.554ba3fa.chunk.js +0 -1
  275. package/build/api-tokens-create-page.4c262d6e.chunk.js +0 -1
  276. package/build/api-tokens-edit-page.10a9d368.chunk.js +0 -1
  277. package/build/api-tokens-list-page.442c9f3c.chunk.js +0 -15
  278. package/build/b997a22a2e0b87ef1fa2.ico +0 -0
  279. package/build/bd81ba6c07827282255d.png +0 -0
  280. package/build/c3de6118ef47086ad05c.png +0 -0
  281. package/build/ca-json.a16899ae.chunk.js +0 -1
  282. package/build/content-manager.7d57c9d1.chunk.js +0 -1200
  283. package/build/content-type-builder-list-view.8cc534e0.chunk.js +0 -194
  284. package/build/content-type-builder-translation-en-json.201bfb78.chunk.js +0 -1
  285. package/build/content-type-builder.684df7a4.chunk.js +0 -142
  286. package/build/de-json.aa6026b3.chunk.js +0 -1
  287. package/build/dk-json.fac2bcfb.chunk.js +0 -1
  288. package/build/en-json.0c69c7d7.chunk.js +0 -1
  289. package/build/es-json.d672e181.chunk.js +0 -1
  290. package/build/fb376b132d18bf4522ca.png +0 -0
  291. package/build/fde9b1ad0670d29a2516.png +0 -0
  292. package/build/fr-json.71a16175.chunk.js +0 -1
  293. package/build/gu-json.ca345cd1.chunk.js +0 -1
  294. package/build/he-json.3b825d80.chunk.js +0 -1
  295. package/build/hi-json.50c7e6d4.chunk.js +0 -1
  296. package/build/hu-json.e0521dcc.chunk.js +0 -1
  297. package/build/id-json.4b1ff8d6.chunk.js +0 -1
  298. package/build/it-json.86bac220.chunk.js +0 -1
  299. package/build/ja-json.4e44e36b.chunk.js +0 -1
  300. package/build/ko-json.1003756e.chunk.js +0 -1
  301. package/build/main.b47db1a3.js +0 -9337
  302. package/build/ml-json.c7774425.chunk.js +0 -1
  303. package/build/nl-json.f58ea235.chunk.js +0 -1
  304. package/build/no-json.40386397.chunk.js +0 -1
  305. package/build/pl-json.fed96aba.chunk.js +0 -1
  306. package/build/pt-BR-json.073799ab.chunk.js +0 -1
  307. package/build/ru-json.7ad2cbbf.chunk.js +0 -1
  308. package/build/runtime~main.feeac6d3.js +0 -2
  309. package/build/sa-json.f0f704f0.chunk.js +0 -1
  310. package/build/sk-json.a848961b.chunk.js +0 -1
  311. package/build/sso-settings-page.445184e0.chunk.js +0 -1
  312. package/build/sv-json.b038acbe.chunk.js +0 -1
  313. package/build/th-json.72e8de3d.chunk.js +0 -1
  314. package/build/webhook-list-page.2775a683.chunk.js +0 -134
  315. package/build/zh-Hans-json.03d2bda1.chunk.js +0 -1
  316. package/build/zh-json.3d0cc664.chunk.js +0 -1
  317. package/server/services/permission/engine-hooks.js +0 -82
@@ -1,107 +1,36 @@
1
1
  'use strict';
2
2
 
3
- const {
4
- curry,
5
- map,
6
- filter,
7
- propEq,
8
- isFunction,
9
- isBoolean,
10
- isArray,
11
- isNil,
12
- isEmpty,
13
- isObject,
14
- prop,
15
- merge,
16
- pick,
17
- difference,
18
- cloneDeep,
19
- } = require('lodash/fp');
20
- const { AbilityBuilder, Ability } = require('@casl/ability');
21
- const sift = require('sift');
3
+ const { curry, isArray, isEmpty, difference } = require('lodash/fp');
4
+ const permissions = require('@strapi/permissions');
5
+
22
6
  const permissionDomain = require('../../domain/permission/index');
23
7
  const { getService } = require('../../utils');
24
- const {
25
- createEngineHooks,
26
- createWillEvaluateContext,
27
- createWillRegisterContext,
28
- } = require('./engine-hooks');
29
-
30
- const allowedOperations = [
31
- '$or',
32
- '$and',
33
- '$eq',
34
- '$ne',
35
- '$in',
36
- '$nin',
37
- '$lt',
38
- '$lte',
39
- '$gt',
40
- '$gte',
41
- '$exists',
42
- '$elemMatch',
43
- ];
44
- const operations = pick(allowedOperations, sift);
45
-
46
- const conditionsMatcher = (conditions) => {
47
- return sift.createQueryTester(conditions, { operations });
48
- };
49
-
50
- module.exports = (conditionProvider) => {
51
- const state = {
52
- hooks: createEngineHooks(),
53
- };
54
-
55
- return {
56
- hooks: state.hooks,
57
-
58
- /**
59
- * Generate an ability based on the given user (using associated roles & permissions)
60
- * @param user
61
- * @param options
62
- * @returns {Promise<Ability>}
63
- */
64
- async generateUserAbility(user, options) {
65
- const permissions = await getService('permission').findUserPermissions(user);
66
- const abilityCreator = this.generateAbilityCreatorFor(user);
67
8
 
68
- return abilityCreator(permissions, options);
69
- },
9
+ module.exports = (params) => {
10
+ const { providers } = params;
70
11
 
12
+ const engine = permissions.engine
13
+ .new({ providers })
71
14
  /**
72
- * Create an ability factory for a specific user
73
- * @param user
74
- * @returns {function(*, *): Promise<Ability>}
15
+ * Validate the permission's action exists in the action registry
75
16
  */
76
- generateAbilityCreatorFor(user) {
77
- return async (permissions, options) => {
78
- const { can, build } = new AbilityBuilder(Ability);
79
-
80
- for (const permission of permissions) {
81
- const registerFn = this.createRegisterFunction(can, permission, user);
82
-
83
- await this.evaluate({ permission, user, options, registerFn });
84
- }
85
-
86
- return build({ conditionsMatcher });
87
- };
88
- },
89
-
90
- /**
91
- * Validate, invalidate and transform the permission attributes
92
- * @param {Permission} permission
93
- * @returns {null|Permission}
94
- */
95
- formatPermission(permission) {
96
- const { actionProvider } = getService('permission');
97
-
98
- const action = actionProvider.get(permission.action);
17
+ .on('before-format::validate.permission', ({ permission }) => {
18
+ const action = providers.action.get(permission.action);
99
19
 
100
20
  // If the action isn't registered into the action provider, then ignore the permission
101
21
  if (!action) {
102
- return null;
22
+ strapi.log.debug(
23
+ `Unknown action "${permission.action}" supplied when registering a new permission in engine`
24
+ );
25
+ return false;
103
26
  }
27
+ })
104
28
 
29
+ /**
30
+ * Remove invalid properties from the permission based on the action (applyToProperties)
31
+ */
32
+ .on('format.permission', (permission) => {
33
+ const action = providers.action.get(permission.action);
105
34
  const properties = permission.properties || {};
106
35
 
107
36
  // Only keep the properties allowed by the action (action.applyToProperties)
@@ -116,153 +45,34 @@ module.exports = (conditionProvider) => {
116
45
  permission
117
46
  );
118
47
 
119
- // If the `fields` property is an empty array, then ignore the permission
120
- const { fields } = properties;
121
-
122
- if (isArray(fields) && isEmpty(fields)) {
123
- return null;
124
- }
125
-
126
48
  return permissionWithSanitizedProperties;
127
- },
128
-
129
- /**
130
- * Update the permission components through various processing
131
- * @param {Permission} permission
132
- * @returns {Promise<void>}
133
- */
134
- async applyPermissionProcessors(permission) {
135
- const context = createWillEvaluateContext(permission);
136
-
137
- // 1. Trigger willEvaluatePermission hook and await transformation operated on the permission
138
- await state.hooks.willEvaluatePermission.call(context);
139
- },
49
+ })
140
50
 
141
51
  /**
142
- * Register new rules using `registerFn` based on valid permission's conditions
143
- * @param options {object}
144
- * @param options.permission {object}
145
- * @param options.user {object}
146
- * @param options.options {object | undefined}
147
- * @param options.registerFn {Function}
148
- * @returns {Promise<void>}
52
+ * Ignore the permission if the fields property is an empty array (access to no field)
149
53
  */
150
- async evaluate(options) {
151
- const { user, registerFn, options: conditionOptions } = options;
152
-
153
- // Assert options.permission validity and format it
154
- const permission = this.formatPermission(options.permission);
155
-
156
- // If options.permission is invalid, then ignore the permission
157
- if (permission === null) {
158
- return;
159
- }
160
-
161
- await this.applyPermissionProcessors(permission);
162
-
163
- // Extract the up-to-date components from the permission
164
- const { action, subject, properties = {}, conditions } = permission;
165
-
166
- // Register the permission if there is no condition
167
- if (isEmpty(conditions)) {
168
- return registerFn({ action, subject, fields: properties.fields });
169
- }
170
-
171
- /** Set of functions used to resolve + evaluate conditions & register the permission if allowed */
172
-
173
- // 1. Replace each condition name by its associated value
174
- const resolveConditions = map(conditionProvider.get);
175
-
176
- // 2. Filter conditions, only keep those whose handler is a function
177
- const filterValidConditions = filter((condition) => isFunction(condition.handler));
178
-
179
- // 3. Evaluate the conditions handler and returns an object
180
- // containing both the original condition and its result
181
- const evaluateConditions = (conditions) => {
182
- return Promise.all(
183
- conditions.map(async (condition) => ({
184
- condition,
185
- result: await condition.handler(
186
- user,
187
- merge(conditionOptions, { permission: cloneDeep(permission) })
188
- ),
189
- }))
190
- );
191
- };
192
-
193
- // 4. Only keeps booleans or objects as condition's result
194
- const filterValidResults = filter(({ result }) => isBoolean(result) || isObject(result));
195
-
196
- /**/
197
-
198
- const evaluatedConditions = await Promise.resolve(conditions)
199
- .then(resolveConditions)
200
- .then(filterValidConditions)
201
- .then(evaluateConditions)
202
- .then(filterValidResults);
54
+ .on('after-format::validate.permission', ({ permission }) => {
55
+ const { fields } = permission.properties;
203
56
 
204
- // Utils
205
- const resultPropEq = propEq('result');
206
- const pickResults = map(prop('result'));
207
-
208
- if (evaluatedConditions.every(resultPropEq(false))) {
209
- return;
210
- }
211
-
212
- // If there is no condition or if one of them return true, register the permission as is
213
- if (isEmpty(evaluatedConditions) || evaluatedConditions.some(resultPropEq(true))) {
214
- return registerFn({ action, subject, fields: properties.fields });
215
- }
216
-
217
- const results = pickResults(evaluatedConditions).filter(isObject);
218
-
219
- if (isEmpty(results)) {
220
- return registerFn({ action, subject, fields: properties.fields });
57
+ if (isArray(fields) && isEmpty(fields)) {
58
+ return false;
221
59
  }
60
+ });
222
61
 
223
- // Register the permission
224
- return registerFn({
225
- action,
226
- subject,
227
- fields: properties.fields,
228
- condition: { $and: [{ $or: results }] },
229
- });
62
+ return {
63
+ get hooks() {
64
+ return engine.hooks;
230
65
  },
231
66
 
232
67
  /**
233
- * Encapsulate a register function with custom params to fit `evaluatePermission`'s syntax
234
- * @param can
235
- * @param {Permission} permission
236
- * @param {object} user
237
- * @returns {function}
68
+ * Generate an ability based on the given user (using associated roles & permissions)
69
+ * @param user
70
+ * @returns {Promise<Ability>}
238
71
  */
239
- createRegisterFunction(can, permission, user) {
240
- const registerToCasl = (caslPermission) => {
241
- const { action, subject, fields, condition } = caslPermission;
242
-
243
- can(
244
- action,
245
- isNil(subject) ? 'all' : subject,
246
- fields,
247
- isObject(condition) ? condition : undefined
248
- );
249
- };
250
-
251
- const runWillRegisterHook = async (caslPermission) => {
252
- const hookContext = createWillRegisterContext(caslPermission, {
253
- permission,
254
- user,
255
- });
256
-
257
- await state.hooks.willRegisterPermission.call(hookContext);
258
-
259
- return caslPermission;
260
- };
72
+ async generateUserAbility(user) {
73
+ const permissions = await getService('permission').findUserPermissions(user);
261
74
 
262
- return async (caslPermission) => {
263
- await runWillRegisterHook(caslPermission);
264
- registerToCasl(caslPermission);
265
- };
75
+ return engine.generateAbility(permissions, user);
266
76
  },
267
77
 
268
78
  /**
@@ -10,11 +10,14 @@ const permissionQueries = require('./permission/queries');
10
10
 
11
11
  const actionProvider = createActionProvider();
12
12
  const conditionProvider = createConditionProvider();
13
- const engine = createPermissionEngine(conditionProvider);
14
13
  const sectionsBuilder = createSectionsBuilder();
15
14
 
16
15
  const sanitizePermission = domain.sanitizePermissionFields;
17
16
 
17
+ const engine = createPermissionEngine({
18
+ providers: { action: actionProvider, condition: conditionProvider },
19
+ });
20
+
18
21
  module.exports = {
19
22
  // Queries / Actions
20
23
  ...permissionQueries,
@@ -33,10 +33,16 @@ const authenticate = async (ctx) => {
33
33
 
34
34
  const userAbility = await getService('permission').engine.generateUserAbility(user);
35
35
 
36
+ // TODO: use the ability from ctx.state.auth instead of
37
+ // ctx.state.userAbility, and remove the assign below
36
38
  ctx.state.userAbility = userAbility;
37
39
  ctx.state.user = user;
38
40
 
39
- return { authenticated: true, credentials: user };
41
+ return {
42
+ authenticated: true,
43
+ credentials: user,
44
+ ability: userAbility,
45
+ };
40
46
  };
41
47
 
42
48
  /** @type {import('.').AuthStrategy} */
@@ -1,5 +1,6 @@
1
1
  'use strict';
2
2
 
3
+ const { castArray, isNil } = require('lodash/fp');
3
4
  const { UnauthorizedError, ForbiddenError } = require('@strapi/utils').errors;
4
5
  const constants = require('../services/constants');
5
6
  const { getService } = require('../utils');
@@ -20,7 +21,10 @@ const extractToken = (ctx) => {
20
21
  return null;
21
22
  };
22
23
 
23
- /** @type {import('.').AuthenticateFunction} */
24
+ /**
25
+ * Authenticate the validity of the token
26
+ *
27
+ * @type {import('.').AuthenticateFunction} */
24
28
  const authenticate = async (ctx) => {
25
29
  const apiTokenService = getService('api-token');
26
30
  const token = extractToken(ctx);
@@ -33,33 +37,90 @@ const authenticate = async (ctx) => {
33
37
  accessKey: apiTokenService.hash(token),
34
38
  });
35
39
 
40
+ // token not found
36
41
  if (!apiToken) {
37
42
  return { authenticated: false };
38
43
  }
39
44
 
45
+ const currentDate = new Date();
46
+
47
+ if (!isNil(apiToken.expiresAt)) {
48
+ const expirationDate = new Date(apiToken.expiresAt);
49
+ // token has expired
50
+ if (expirationDate < currentDate) {
51
+ return { authenticated: false, error: new UnauthorizedError('Token expired') };
52
+ }
53
+ }
54
+
55
+ // update lastUsedAt
56
+ await strapi.query('admin::api-token').update({
57
+ where: { id: apiToken.id },
58
+ data: { lastUsedAt: currentDate },
59
+ });
60
+
61
+ if (apiToken.type === constants.API_TOKEN_TYPE.CUSTOM) {
62
+ const ability = await strapi.contentAPI.permissions.engine.generateAbility(
63
+ apiToken.permissions.map((action) => ({ action }))
64
+ );
65
+
66
+ return { authenticated: true, ability, credentials: apiToken };
67
+ }
68
+
40
69
  return { authenticated: true, credentials: apiToken };
41
70
  };
42
71
 
43
- /** @type {import('.').VerifyFunction} */
72
+ /**
73
+ * Verify the token has the required abilities for the requested scope
74
+ *
75
+ * @type {import('.').VerifyFunction} */
44
76
  const verify = (auth, config) => {
45
- const { credentials: apiToken } = auth;
77
+ const { credentials: apiToken, ability } = auth;
46
78
 
47
79
  if (!apiToken) {
48
- throw new UnauthorizedError();
80
+ throw new UnauthorizedError('Token not found');
81
+ }
82
+
83
+ const currentDate = new Date();
84
+
85
+ if (!isNil(apiToken.expiresAt)) {
86
+ const expirationDate = new Date(apiToken.expiresAt);
87
+ // token has expired
88
+ if (expirationDate < currentDate) {
89
+ throw new UnauthorizedError('Token expired');
90
+ }
49
91
  }
50
92
 
93
+ // Full access
51
94
  if (apiToken.type === constants.API_TOKEN_TYPE.FULL_ACCESS) {
52
95
  return;
53
96
  }
54
97
 
55
- /**
56
- * If you don't have `full-access` you can only access `find` and `findOne`
57
- * scopes. If the route has no scope, then you can't get access to it.
58
- */
98
+ // Read only
99
+ if (apiToken.type === constants.API_TOKEN_TYPE.READ_ONLY) {
100
+ /**
101
+ * If you don't have `full-access` you can only access `find` and `findOne`
102
+ * scopes. If the route has no scope, then you can't get access to it.
103
+ */
104
+ const scopes = castArray(config.scope);
59
105
 
60
- const scopes = Array.isArray(config.scope) ? config.scope : [config.scope];
61
- if (config.scope && scopes.every(isReadScope)) {
62
- return;
106
+ if (config.scope && scopes.every(isReadScope)) {
107
+ return;
108
+ }
109
+ }
110
+
111
+ // Custom
112
+ else if (apiToken.type === constants.API_TOKEN_TYPE.CUSTOM) {
113
+ if (!ability) {
114
+ throw new ForbiddenError();
115
+ }
116
+
117
+ const scopes = castArray(config.scope);
118
+
119
+ const isAllowed = scopes.every((scope) => ability.can(scope));
120
+
121
+ if (isAllowed) {
122
+ return;
123
+ }
63
124
  }
64
125
 
65
126
  throw new ForbiddenError();
@@ -9,8 +9,16 @@ const apiTokenCreationSchema = yup
9
9
  name: yup.string().min(1).required(),
10
10
  description: yup.string().optional(),
11
11
  type: yup.string().oneOf(Object.values(constants.API_TOKEN_TYPE)).required(),
12
+ permissions: yup.array().of(yup.string()).nullable(),
13
+ lifespan: yup
14
+ .number()
15
+ .integer()
16
+ .min(1)
17
+ .oneOf(Object.values(constants.API_TOKEN_LIFESPANS))
18
+ .nullable(),
12
19
  })
13
- .noUnknown();
20
+ .noUnknown()
21
+ .strict();
14
22
 
15
23
  const apiTokenUpdateSchema = yup
16
24
  .object()
@@ -18,8 +26,10 @@ const apiTokenUpdateSchema = yup
18
26
  name: yup.string().min(1).notNull(),
19
27
  description: yup.string().nullable(),
20
28
  type: yup.string().oneOf(Object.values(constants.API_TOKEN_TYPE)).notNull(),
29
+ permissions: yup.array().of(yup.string()).nullable(),
21
30
  })
22
- .noUnknown();
31
+ .noUnknown()
32
+ .strict();
23
33
 
24
34
  module.exports = {
25
35
  validateApiTokenCreationInput: validateYupSchema(apiTokenCreationSchema),
@@ -0,0 +1,40 @@
1
+ 'use strict';
2
+
3
+ const { sep, join } = require('path');
4
+
5
+ const NODE_MODULES = 'node_modules';
6
+ /**
7
+ * @param {string[]} pluginsPath – an array of paths to the plugins from the user's directory
8
+ * @returns {RegExp} a regex that will exclude _all_ node_modules except for the plugins in the pluginsPath array.
9
+ */
10
+ const createPluginsExcludePath = (pluginsPath = []) => {
11
+ /**
12
+ * converts the full path to just the plugin path
13
+ * e.g. `/Users/username/strapi/node_modules/@scope/plugin-name`
14
+ * to `@scope/plugin-name`
15
+ */
16
+ const tsxPlugins = pluginsPath.reduce((acc, curr) => {
17
+ const dirPaths = curr.split(sep);
18
+
19
+ const nodeModulePathIndex = dirPaths.findIndex((val) => val === NODE_MODULES);
20
+
21
+ if (nodeModulePathIndex > 0) {
22
+ const pluginNodeModulePath = dirPaths.slice(nodeModulePathIndex + 1);
23
+ return [...acc, join(...pluginNodeModulePath)];
24
+ }
25
+
26
+ return acc;
27
+ }, []);
28
+
29
+ /**
30
+ * If there aren't any plugins in the node_modules array, just return the node_modules regex
31
+ * without complicating it.
32
+ */
33
+ if (tsxPlugins.length === 0) {
34
+ return /node_modules/;
35
+ }
36
+
37
+ return new RegExp(`${NODE_MODULES}/(?!(${tsxPlugins.join('|')}))`);
38
+ };
39
+
40
+ module.exports = createPluginsExcludePath;
@@ -11,6 +11,11 @@ const { isUsingTypeScript } = require('@strapi/typescript-utils');
11
11
  */
12
12
  const getCustomAppConfigFile = async (dir) => {
13
13
  const adminSrcPath = join(dir, 'src', 'admin');
14
+
15
+ if (!fse.pathExistsSync(adminSrcPath)) {
16
+ return undefined;
17
+ }
18
+
14
19
  const useTypeScript = await isUsingTypeScript(adminSrcPath, 'tsconfig.json');
15
20
 
16
21
  const files = await fse.readdir(adminSrcPath);
package/webpack.alias.js CHANGED
@@ -37,21 +37,8 @@ const aliasExactMatch = [
37
37
  'yup',
38
38
  ];
39
39
 
40
- const alias = [
41
- 'react-select/animated',
42
- 'react-select/async',
43
- 'react-select/async-creatable',
44
- 'react-select/base',
45
- 'react-select/creatable',
46
- ];
47
-
48
40
  // See https://webpack.js.org/configuration/resolve/
49
41
  module.exports = {
50
- ...alias.reduce((acc, name) => {
51
- acc[name] = require.resolve(name);
52
- return acc;
53
- }, {}),
54
-
55
42
  ...aliasExactMatch.reduce((acc, name) => {
56
43
  acc[`${name}$`] = require.resolve(name);
57
44
  return acc;
package/webpack.config.js CHANGED
@@ -13,6 +13,7 @@ const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin'
13
13
 
14
14
  const alias = require('./webpack.alias');
15
15
  const getClientEnvironment = require('./env');
16
+ const createPluginsExcludePath = require('./utils/create-plugins-exclude-path');
16
17
 
17
18
  const EE_REGEX = /from.* ['"]ee_else_ce\//;
18
19
 
@@ -49,6 +50,8 @@ module.exports = ({
49
50
  ]
50
51
  : [];
51
52
 
53
+ const excludeRegex = createPluginsExcludePath(pluginsPath);
54
+
52
55
  return {
53
56
  mode: isProduction ? 'production' : 'development',
54
57
  bail: !!isProduction,
@@ -82,7 +85,7 @@ module.exports = ({
82
85
  test: /\.tsx?$/,
83
86
  loader: require.resolve('esbuild-loader'),
84
87
  include: [cacheDir, ...pluginsPath],
85
- exclude: /node_modules/,
88
+ exclude: excludeRegex,
86
89
  options: {
87
90
  loader: 'tsx',
88
91
  target: 'es2015',
@@ -1,5 +0,0 @@
1
- <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
2
- <rect x="3" y="3" width="18" height="18" rx="4" fill="#4945FF"/>
3
- <path fill-rule="evenodd" clip-rule="evenodd" d="M15.8075 7.625H9.03058V11.1792H12.2533C12.4977 11.1792 12.6958 11.3773 12.6958 11.6216V14.8444H16.25V8.06746C16.25 7.82309 16.0519 7.625 15.8075 7.625Z" fill="white"/>
4
- <path opacity="0.4" fill-rule="evenodd" clip-rule="evenodd" d="M9.0308 7.625V11.1792H6.01073C5.81364 11.1792 5.71494 10.9409 5.8543 10.8015L9.0308 7.625ZM13.0735 18.0209C12.9342 18.1603 12.6959 18.0616 12.6959 17.8645V14.8444H16.25L13.0735 18.0209ZM12.4746 11.1792H9.03058V14.4019C9.03058 14.6463 9.22868 14.8444 9.47304 14.8444H12.6958V11.4004C12.6958 11.2782 12.5968 11.1792 12.4746 11.1792Z" fill="#DAD9FF"/>
5
- </svg>
Binary file
@@ -1,37 +0,0 @@
1
- import React from 'react';
2
- import PropTypes from 'prop-types';
3
- import { useIntl } from 'react-intl';
4
- import { Typography } from '@strapi/design-system/Typography';
5
- import { Box } from '@strapi/design-system/Box';
6
- import { getTrad } from '../../utils';
7
-
8
- const State = ({ isPublished }) => {
9
- const { formatMessage } = useIntl();
10
- const content = formatMessage({
11
- id: getTrad(`containers.List.${isPublished ? 'published' : 'draft'}`),
12
- });
13
- const background = isPublished ? 'success100' : 'secondary100';
14
- const textColor = isPublished ? 'success700' : 'secondary700';
15
-
16
- return (
17
- <Box
18
- background={background}
19
- hasRadius
20
- paddingTop={1}
21
- paddingBottom={1}
22
- paddingLeft={2}
23
- paddingRight={2}
24
- style={{ width: 'fit-content' }}
25
- >
26
- <Typography fontWeight="bold" textColor={textColor}>
27
- {content}
28
- </Typography>
29
- </Box>
30
- );
31
- };
32
-
33
- State.propTypes = {
34
- isPublished: PropTypes.bool.isRequired,
35
- };
36
-
37
- export default State;
Binary file
Binary file