@strapi/admin 4.7.0-beta.0 → 4.9.0-alpha.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 (257) hide show
  1. package/admin/src/content-manager/components/CollectionTypeFormWrapper/index.js +6 -14
  2. package/admin/src/content-manager/components/DynamicTable/CellContent/RelationMultiple/index.js +1 -1
  3. package/admin/src/content-manager/components/DynamicZone/components/DynamicComponent.js +2 -0
  4. package/admin/src/content-manager/components/EditViewDataManagerProvider/reducer.js +39 -9
  5. package/admin/src/content-manager/components/EditViewDataManagerProvider/utils/cleanData.js +9 -15
  6. package/admin/src/content-manager/components/SingleTypeFormWrapper/index.js +4 -12
  7. package/admin/src/content-manager/pages/EditView/DeleteLink/index.js +6 -8
  8. package/admin/src/content-manager/pages/ListView/index.js +6 -11
  9. package/admin/src/hooks/useRegenerate/index.js +2 -2
  10. package/admin/src/hooks/useSettingsMenu/utils/defaultGlobalLinks.js +0 -7
  11. package/admin/src/index.js +1 -0
  12. package/admin/src/pages/SettingsPage/components/SettingsNav/index.js +15 -2
  13. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/CollapsableContentType/index.js +3 -5
  14. package/admin/src/pages/SettingsPage/{components/Tokens/TokenBox → pages/ApiTokens/EditView/components/ContentBox}/index.js +17 -17
  15. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/FormApiTokenContainer/index.js +142 -52
  16. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/FormBody/index.js +78 -0
  17. package/admin/src/pages/SettingsPage/{components/Tokens → pages/ApiTokens/EditView/components}/FormHead/index.js +19 -36
  18. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/Regenerate/index.js +1 -5
  19. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/index.js +14 -37
  20. package/admin/src/pages/SettingsPage/{components/Tokens/Table → pages/ApiTokens/ListView/DynamicTable}/DefaultButton/index.js +1 -1
  21. package/admin/src/pages/SettingsPage/{components/Tokens/Table → pages/ApiTokens/ListView/DynamicTable}/DeleteButton/index.js +1 -1
  22. package/admin/src/pages/SettingsPage/{components/Tokens/Table → pages/ApiTokens/ListView/DynamicTable}/ReadButton/index.js +0 -0
  23. package/admin/src/pages/SettingsPage/{components/Tokens/Table → pages/ApiTokens/ListView/DynamicTable}/UpdateButton/index.js +0 -0
  24. package/admin/src/pages/SettingsPage/pages/ApiTokens/ListView/DynamicTable/index.js +112 -0
  25. package/admin/src/pages/SettingsPage/pages/ApiTokens/ListView/index.js +13 -5
  26. package/admin/src/pages/SettingsPage/pages/Users/components/MagicLink/MagicLinkWrapper.js +3 -20
  27. package/admin/src/pages/SettingsPage/utils/defaultRoutes.js +0 -33
  28. package/admin/src/permissions/defaultPermissions.js +2 -23
  29. package/admin/src/translations/ar.json +4 -4
  30. package/admin/src/translations/ca.json +4 -4
  31. package/admin/src/translations/cs.json +4 -4
  32. package/admin/src/translations/de.json +4 -4
  33. package/admin/src/translations/dk.json +4 -4
  34. package/admin/src/translations/en.json +9 -17
  35. package/admin/src/translations/es.json +4 -4
  36. package/admin/src/translations/eu.json +4 -4
  37. package/admin/src/translations/fr.json +4 -4
  38. package/admin/src/translations/gu.json +4 -4
  39. package/admin/src/translations/he.json +4 -4
  40. package/admin/src/translations/hi.json +4 -4
  41. package/admin/src/translations/hu.json +4 -4
  42. package/admin/src/translations/id.json +4 -4
  43. package/admin/src/translations/it.json +4 -4
  44. package/admin/src/translations/ja.json +4 -4
  45. package/admin/src/translations/ko.json +4 -4
  46. package/admin/src/translations/ml.json +4 -4
  47. package/admin/src/translations/ms.json +4 -4
  48. package/admin/src/translations/nl.json +4 -4
  49. package/admin/src/translations/no.json +4 -4
  50. package/admin/src/translations/pl.json +4 -4
  51. package/admin/src/translations/pt-BR.json +4 -4
  52. package/admin/src/translations/pt.json +4 -4
  53. package/admin/src/translations/ru.json +785 -789
  54. package/admin/src/translations/sa.json +4 -4
  55. package/admin/src/translations/sk.json +4 -4
  56. package/admin/src/translations/sv.json +4 -4
  57. package/admin/src/translations/th.json +4 -4
  58. package/admin/src/translations/tr.json +4 -4
  59. package/admin/src/translations/uk.json +4 -4
  60. package/admin/src/translations/vi.json +4 -4
  61. package/admin/src/translations/zh-Hans.json +4 -4
  62. package/admin/src/translations/zh.json +4 -4
  63. package/build/1683.d59d0f23.chunk.js +268 -0
  64. package/build/{4855.bd092921.chunk.js → 2223.1bfea951.chunk.js} +88 -88
  65. package/build/2743.646a1015.chunk.js +45 -0
  66. package/build/3075.3ee481f1.chunk.js +108 -0
  67. package/build/3632.2e378cf8.chunk.js +138 -0
  68. package/build/4318.cd55ce02.chunk.js +30 -0
  69. package/build/8633.00ccd382.chunk.js +1 -0
  70. package/build/9707.b36ed71e.chunk.js +96 -0
  71. package/build/{Admin-authenticatedApp.f29f6021.chunk.js → Admin-authenticatedApp.a73577e1.chunk.js} +2 -2
  72. package/build/{Admin_InternalErrorPage.157152a8.chunk.js → Admin_InternalErrorPage.178ddb90.chunk.js} +1 -1
  73. package/build/{Admin_homePage.b1730882.chunk.js → Admin_homePage.c2f5f27d.chunk.js} +2 -2
  74. package/build/{Admin_marketplace.ea0316c2.chunk.js → Admin_marketplace.1df49c42.chunk.js} +1 -1
  75. package/build/{Admin_pluginsPage.5c24f963.chunk.js → Admin_pluginsPage.8d824408.chunk.js} +2 -2
  76. package/build/{Admin_profilePage.59af1978.chunk.js → Admin_profilePage.cb667bc5.chunk.js} +2 -2
  77. package/build/Admin_settingsPage.f90615fb.chunk.js +178 -0
  78. package/build/{Upload_ConfigureTheView.3f2b6e6a.chunk.js → Upload_ConfigureTheView.d306009d.chunk.js} +1 -1
  79. package/build/admin-app.06f07029.chunk.js +112 -0
  80. package/build/admin-edit-roles-page.35199b9d.chunk.js +1 -0
  81. package/build/admin-edit-users.9e48b00d.chunk.js +10 -0
  82. package/build/admin-users.cf7b4151.chunk.js +11 -0
  83. package/build/{api-tokens-create-page.0db3aec1.chunk.js → api-tokens-create-page.a31c7fba.chunk.js} +1 -1
  84. package/build/{api-tokens-edit-page.671e0e26.chunk.js → api-tokens-edit-page.64fef287.chunk.js} +1 -1
  85. package/build/api-tokens-list-page.e600ad3e.chunk.js +16 -0
  86. package/build/ar-json.39e54aba.chunk.js +1 -0
  87. package/build/{audit-logs-settings-page.c3dce30d.chunk.js → audit-logs-settings-page.d4da4579.chunk.js} +1 -1
  88. package/build/{ca-json.f6a0f472.chunk.js → ca-json.4d999055.chunk.js} +1 -1
  89. package/build/content-manager.255c3a59.chunk.js +1139 -0
  90. package/build/{content-type-builder-list-view.79e84b36.chunk.js → content-type-builder-list-view.8d7a3d68.chunk.js} +5 -5
  91. package/build/content-type-builder.3c8558a5.chunk.js +126 -0
  92. package/build/cs-json.4b44411c.chunk.js +1 -0
  93. package/build/{de-json.30e1f35b.chunk.js → de-json.866f8a28.chunk.js} +1 -1
  94. package/build/{dk-json.e6d9ffa4.chunk.js → dk-json.10f7b1d1.chunk.js} +1 -1
  95. package/build/email-settings-page.b19f2eb2.chunk.js +10 -0
  96. package/build/en-json.1997583c.chunk.js +1 -0
  97. package/build/es-json.ea15c957.chunk.js +1 -0
  98. package/build/{eu-json.fceecd8b.chunk.js → eu-json.3bc24d60.chunk.js} +1 -1
  99. package/build/{fr-json.78545ef8.chunk.js → fr-json.e88fbdfd.chunk.js} +1 -1
  100. package/build/{gu-json.676518f2.chunk.js → gu-json.94f0d242.chunk.js} +1 -1
  101. package/build/{he-json.ad22e8cc.chunk.js → he-json.f0de8cdb.chunk.js} +1 -1
  102. package/build/{hi-json.19b51c09.chunk.js → hi-json.df3a7be2.chunk.js} +1 -1
  103. package/build/{hu-json.f947088f.chunk.js → hu-json.680e6eef.chunk.js} +1 -1
  104. package/build/{i18n-settings-page.b8d8753e.chunk.js → i18n-settings-page.a6b49eac.chunk.js} +1 -1
  105. package/build/{id-json.504daa84.chunk.js → id-json.e0d83d41.chunk.js} +1 -1
  106. package/build/index.html +1 -1
  107. package/build/{it-json.2fd90f4d.chunk.js → it-json.8be59205.chunk.js} +1 -1
  108. package/build/{ja-json.c9f12d0b.chunk.js → ja-json.97ee41ba.chunk.js} +1 -1
  109. package/build/{ko-json.ef463065.chunk.js → ko-json.4cbbf4f2.chunk.js} +1 -1
  110. package/build/main.7f308c20.js +4322 -0
  111. package/build/{ml-json.490f666c.chunk.js → ml-json.e3747091.chunk.js} +1 -1
  112. package/build/ms-json.0eddffd9.chunk.js +1 -0
  113. package/build/{nl-json.c416295a.chunk.js → nl-json.371a15ee.chunk.js} +1 -1
  114. package/build/{no-json.1a2258ba.chunk.js → no-json.9b3cd181.chunk.js} +1 -1
  115. package/build/{pl-json.8cf0c871.chunk.js → pl-json.e535cbce.chunk.js} +1 -1
  116. package/build/{pt-BR-json.51fab8d0.chunk.js → pt-BR-json.e5fafa46.chunk.js} +1 -1
  117. package/build/pt-json.ee554a41.chunk.js +1 -0
  118. package/build/review-workflows-settings.7b4be1b0.chunk.js +63 -0
  119. package/build/{ru-json.aa5cd123.chunk.js → ru-json.866f0ff1.chunk.js} +1 -1
  120. package/build/runtime~main.bf374148.js +2 -0
  121. package/build/{sa-json.f3fa5407.chunk.js → sa-json.7efeb257.chunk.js} +1 -1
  122. package/build/{sk-json.9ec60d9f.chunk.js → sk-json.7bbeb0af.chunk.js} +1 -1
  123. package/build/{sso-settings-page.b85ad080.chunk.js → sso-settings-page.ad2143dd.chunk.js} +1 -1
  124. package/build/{sv-json.c6b0c237.chunk.js → sv-json.dc40951f.chunk.js} +1 -1
  125. package/build/{th-json.6e68155c.chunk.js → th-json.f664b96d.chunk.js} +1 -1
  126. package/build/{tr-json.9f41dc08.chunk.js → tr-json.b79eae31.chunk.js} +1 -1
  127. package/build/uk-json.b7e38370.chunk.js +1 -0
  128. package/build/upload-settings.eb1a7908.chunk.js +84 -0
  129. package/build/upload.700e2c84.chunk.js +33 -0
  130. package/build/{users-advanced-settings-page.fce9908e.chunk.js → users-advanced-settings-page.aae212f2.chunk.js} +1 -1
  131. package/build/{users-email-settings-page.343d0ad2.chunk.js → users-email-settings-page.8a9b0da1.chunk.js} +1 -1
  132. package/build/{users-providers-settings-page.e5a9a3f1.chunk.js → users-providers-settings-page.e6be909d.chunk.js} +10 -10
  133. package/build/{users-roles-settings-page.66312f31.chunk.js → users-roles-settings-page.97d06a80.chunk.js} +3 -3
  134. package/build/vi-json.ee4c5537.chunk.js +1 -0
  135. package/build/webhook-edit-page.9eb0f789.chunk.js +75 -0
  136. package/build/webhook-list-page.66082323.chunk.js +42 -0
  137. package/build/{zh-Hans-json.9c0eac99.chunk.js → zh-Hans-json.30a18940.chunk.js} +1 -1
  138. package/build/{zh-json.f88f563d.chunk.js → zh-json.49d84433.chunk.js} +1 -1
  139. package/ee/admin/hooks/useSettingsMenu/utils/customAdminLinks.js +12 -12
  140. package/ee/admin/hooks/useSettingsMenu/utils/customGlobalLinks.js +21 -13
  141. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/ReviewWorkflows.js +137 -0
  142. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/actions/index.js +42 -0
  143. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/AddStage/AddStage.js +87 -0
  144. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/AddStage/index.js +1 -0
  145. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/Stages/Stage/Stage.js +90 -0
  146. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/Stages/Stage/index.js +1 -0
  147. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/Stages/Stages.js +77 -0
  148. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/Stages/index.js +1 -0
  149. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/constants.js +6 -0
  150. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/hooks/useReviewWorkflows.js +63 -0
  151. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/index.js +3 -0
  152. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/reducer/index.js +102 -0
  153. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/utils/getWorkflowValidationSchema.js +25 -0
  154. package/ee/admin/pages/SettingsPage/utils/customRoutes.js +16 -2
  155. package/ee/admin/permissions/customPermissions.js +7 -0
  156. package/ee/server/bootstrap.js +7 -1
  157. package/ee/server/config/admin-actions.js +10 -0
  158. package/ee/server/constants/default-stages.json +14 -0
  159. package/ee/server/constants/default-workflow.json +1 -0
  160. package/ee/server/constants/workflows.js +7 -0
  161. package/ee/server/content-types/index.js +9 -0
  162. package/ee/server/content-types/workflow/index.js +34 -0
  163. package/ee/server/content-types/workflow-stage/index.js +36 -0
  164. package/ee/server/controllers/index.js +2 -0
  165. package/ee/server/controllers/workflows/index.js +36 -0
  166. package/ee/server/controllers/workflows/stages/index.js +57 -0
  167. package/ee/server/index.js +1 -0
  168. package/ee/server/routes/index.js +87 -0
  169. package/ee/server/services/index.js +3 -0
  170. package/ee/server/services/review-workflows/review-workflows.js +54 -0
  171. package/ee/server/services/review-workflows/stages.js +133 -0
  172. package/ee/server/services/review-workflows/workflows.js +25 -0
  173. package/ee/server/utils/index.js +8 -0
  174. package/ee/server/utils/test.js +11 -0
  175. package/ee/server/validation/review-workflows.js +17 -0
  176. package/package.json +13 -13
  177. package/server/bootstrap.js +0 -2
  178. package/server/config/admin-actions.js +0 -64
  179. package/server/content-types/index.js +0 -2
  180. package/server/controllers/admin.js +0 -55
  181. package/server/controllers/api-token.js +5 -4
  182. package/server/controllers/index.js +0 -1
  183. package/server/register.js +9 -2
  184. package/server/routes/admin.js +0 -28
  185. package/server/routes/index.js +0 -2
  186. package/server/services/api-token.js +3 -2
  187. package/server/services/constants.js +0 -6
  188. package/server/services/index.js +0 -1
  189. package/server/strategies/api-token.js +2 -4
  190. package/server/strategies/index.js +0 -1
  191. package/server/utils/index.d.ts +0 -2
  192. package/server/validation/api-tokens.js +6 -1
  193. package/webpack.config.js +0 -3
  194. package/admin/src/pages/SettingsPage/components/Tokens/FormiTokenContainer/LifeSpanInput.js +0 -96
  195. package/admin/src/pages/SettingsPage/components/Tokens/LifeSpanInput/index.js +0 -98
  196. package/admin/src/pages/SettingsPage/components/Tokens/Regenerate/index.js +0 -73
  197. package/admin/src/pages/SettingsPage/components/Tokens/Table/index.js +0 -135
  198. package/admin/src/pages/SettingsPage/components/Tokens/TokenDescription/index.js +0 -51
  199. package/admin/src/pages/SettingsPage/components/Tokens/TokenName/index.js +0 -46
  200. package/admin/src/pages/SettingsPage/components/Tokens/TokenTypeSelect/index.js +0 -69
  201. package/admin/src/pages/SettingsPage/pages/TransferTokens/EditView/components/FormTransferTokenContainer/index.js +0 -105
  202. package/admin/src/pages/SettingsPage/pages/TransferTokens/EditView/components/LoadingView/index.js +0 -50
  203. package/admin/src/pages/SettingsPage/pages/TransferTokens/EditView/index.js +0 -201
  204. package/admin/src/pages/SettingsPage/pages/TransferTokens/EditView/utils/getDateOfExpiration.js +0 -16
  205. package/admin/src/pages/SettingsPage/pages/TransferTokens/EditView/utils/index.js +0 -4
  206. package/admin/src/pages/SettingsPage/pages/TransferTokens/EditView/utils/schema.js +0 -10
  207. package/admin/src/pages/SettingsPage/pages/TransferTokens/ListView/index.js +0 -182
  208. package/admin/src/pages/SettingsPage/pages/TransferTokens/ListView/utils/tableHeaders.js +0 -48
  209. package/admin/src/pages/SettingsPage/pages/TransferTokens/ProtectedCreateView/index.js +0 -14
  210. package/admin/src/pages/SettingsPage/pages/TransferTokens/ProtectedEditView/index.js +0 -14
  211. package/admin/src/pages/SettingsPage/pages/TransferTokens/ProtectedListView/index.js +0 -12
  212. package/build/1683.c8aa7b7c.chunk.js +0 -268
  213. package/build/2743.6d1632f9.chunk.js +0 -45
  214. package/build/3075.dc3894fe.chunk.js +0 -108
  215. package/build/3632.0317b618.chunk.js +0 -138
  216. package/build/4649.15cc0afe.chunk.js +0 -30
  217. package/build/7259.aa68d808.chunk.js +0 -1
  218. package/build/7407.883fb1f5.chunk.js +0 -1
  219. package/build/9707.7290fd92.chunk.js +0 -96
  220. package/build/Admin_settingsPage.178dc6e3.chunk.js +0 -178
  221. package/build/admin-app.77a50e1f.chunk.js +0 -112
  222. package/build/admin-edit-roles-page.446b69dc.chunk.js +0 -1
  223. package/build/admin-edit-users.2ed69bfd.chunk.js +0 -10
  224. package/build/admin-users.fc003b10.chunk.js +0 -11
  225. package/build/api-tokens-list-page.7387102c.chunk.js +0 -16
  226. package/build/ar-json.932794f7.chunk.js +0 -1
  227. package/build/content-manager.42b24d46.chunk.js +0 -1139
  228. package/build/content-type-builder.855db321.chunk.js +0 -126
  229. package/build/cs-json.79879fb6.chunk.js +0 -1
  230. package/build/email-settings-page.d1fcc7a3.chunk.js +0 -10
  231. package/build/en-json.b0748970.chunk.js +0 -1
  232. package/build/es-json.e275481d.chunk.js +0 -1
  233. package/build/main.1022ed01.js +0 -4393
  234. package/build/ms-json.db87d8d3.chunk.js +0 -1
  235. package/build/pt-json.62927d1e.chunk.js +0 -1
  236. package/build/runtime~main.84941a97.js +0 -2
  237. package/build/transfer-tokens-create-page.16e23791.chunk.js +0 -1
  238. package/build/transfer-tokens-edit-page.3886c973.chunk.js +0 -1
  239. package/build/transfer-tokens-list-page.e8010a89.chunk.js +0 -16
  240. package/build/uk-json.b2fcd567.chunk.js +0 -1
  241. package/build/upload-settings.ef64bbf9.chunk.js +0 -84
  242. package/build/upload.c5730dfa.chunk.js +0 -33
  243. package/build/vi-json.f08d7d03.chunk.js +0 -1
  244. package/build/webhook-edit-page.73e51e64.chunk.js +0 -75
  245. package/build/webhook-list-page.1134f130.chunk.js +0 -42
  246. package/server/content-types/transfer-token-permission.js +0 -36
  247. package/server/content-types/transfer-token.js +0 -66
  248. package/server/controllers/transfer/index.js +0 -13
  249. package/server/controllers/transfer/runner.js +0 -24
  250. package/server/controllers/transfer/token.js +0 -131
  251. package/server/routes/transfer.js +0 -95
  252. package/server/services/transfer/index.js +0 -6
  253. package/server/services/transfer/permission.js +0 -22
  254. package/server/services/transfer/token.js +0 -409
  255. package/server/strategies/data-transfer.js +0 -107
  256. package/server/validation/transfer/index.js +0 -5
  257. package/server/validation/transfer/token.js +0 -34
@@ -1,22 +0,0 @@
1
- 'use strict';
2
-
3
- const permissions = require('@strapi/permissions');
4
- const { providerFactory } = require('@strapi/utils');
5
-
6
- const DEFAULT_TRANSFER_ACTIONS = ['push'];
7
-
8
- const providers = {
9
- action: providerFactory(),
10
- condition: providerFactory(),
11
- };
12
-
13
- DEFAULT_TRANSFER_ACTIONS.forEach((action) => {
14
- providers.action.register(action, { action });
15
- });
16
-
17
- const engine = permissions.engine.new({ providers });
18
-
19
- module.exports = {
20
- engine,
21
- providers,
22
- };
@@ -1,409 +0,0 @@
1
- 'use strict';
2
-
3
- const { map, isArray, omit, uniq, isNil, difference, isEmpty } = require('lodash/fp');
4
- const crypto = require('crypto');
5
-
6
- const {
7
- errors: { ValidationError, NotFoundError },
8
- } = require('@strapi/utils');
9
-
10
- const constants = require('../constants');
11
-
12
- const TRANSFER_TOKEN_UID = 'admin::transfer-token';
13
- const TRANSFER_TOKEN_PERMISSION_UID = 'admin::transfer-token-permission';
14
-
15
- /**
16
- * @typedef TransferToken
17
- *
18
- * @property {number|string} id
19
- * @property {string} name
20
- * @property {string} description
21
- * @property {string} accessKey
22
- * @property {number} lastUsedAt
23
- * @property {number} lifespan
24
- * @property {number} expiresAt
25
- * @property {(number[]|TransferTokenPermission[])} permissions
26
- */
27
-
28
- /**
29
- * @typedef TransferTokenPermission
30
- *
31
- * @property {number|string} id
32
- * @property {string} action
33
- * @property {TransferToken|number} token
34
- */
35
-
36
- /** @constant {Array<string>} */
37
- const SELECT_FIELDS = [
38
- 'id',
39
- 'name',
40
- 'description',
41
- 'lastUsedAt',
42
- 'lifespan',
43
- 'expiresAt',
44
- 'createdAt',
45
- 'updatedAt',
46
- ];
47
-
48
- /** @constant {Array<string>} */
49
- const POPULATE_FIELDS = ['permissions'];
50
-
51
- /**
52
- * Return a list of all tokens and their permissions
53
- *
54
- * @returns {Promise<Omit<TransferToken, 'accessKey'>[]>}
55
- */
56
- const list = async () => {
57
- const tokens = await strapi.query(TRANSFER_TOKEN_UID).findMany({
58
- select: SELECT_FIELDS,
59
- populate: POPULATE_FIELDS,
60
- orderBy: { name: 'ASC' },
61
- });
62
-
63
- if (!tokens) return tokens;
64
- return tokens.map((token) => flattenTokenPermissions(token));
65
- };
66
-
67
- /**
68
- * Create a token and its permissions
69
- *
70
- * @param {Object} attributes
71
- * @param {string} attributes.name
72
- * @param {string} attributes.description
73
- * @param {number} attributes.lifespan
74
- * @param {string[]} attributes.permissions
75
- *
76
- * @returns {Promise<TransferToken>}
77
- */
78
- const create = async (attributes) => {
79
- const accessKey = crypto.randomBytes(128).toString('hex');
80
-
81
- assertTokenPermissionsValidity(attributes);
82
- assertValidLifespan(attributes);
83
-
84
- const result = await strapi.db.transaction(async () => {
85
- const transferToken = await strapi.query(TRANSFER_TOKEN_UID).create({
86
- select: SELECT_FIELDS,
87
- populate: POPULATE_FIELDS,
88
- data: {
89
- ...omit('permissions', attributes),
90
- accessKey: hash(accessKey),
91
- ...getExpirationFields(attributes.lifespan),
92
- },
93
- });
94
-
95
- await Promise.all(
96
- uniq(attributes.permissions).map((action) =>
97
- strapi
98
- .query(TRANSFER_TOKEN_PERMISSION_UID)
99
- .create({ data: { action, token: transferToken } })
100
- )
101
- );
102
-
103
- const currentPermissions = await strapi.entityService.load(
104
- TRANSFER_TOKEN_UID,
105
- transferToken,
106
- 'permissions'
107
- );
108
-
109
- if (currentPermissions) {
110
- Object.assign(transferToken, { permissions: map('action', currentPermissions) });
111
- }
112
-
113
- return transferToken;
114
- });
115
-
116
- return { ...result, accessKey };
117
- };
118
-
119
- /**
120
- * Update a token and its permissions
121
- *
122
- * @param {string|number} id
123
- * @param {Object} attributes
124
- * @param {string} attributes.name
125
- * @param {number} attributes.lastUsedAt
126
- * @param {string[]} attributes.permissions
127
- * @param {string} attributes.description
128
- *
129
- * @returns {Promise<Omit<TransferToken, 'accessKey'>>}
130
- */
131
- const update = async (id, attributes) => {
132
- // retrieve token without permissions
133
- const originalToken = await strapi.query(TRANSFER_TOKEN_UID).findOne({ where: { id } });
134
-
135
- if (!originalToken) {
136
- throw new NotFoundError('Token not found');
137
- }
138
-
139
- assertTokenPermissionsValidity(attributes);
140
- assertValidLifespan(attributes);
141
-
142
- return strapi.db.transaction(async () => {
143
- const updatedToken = await strapi.query(TRANSFER_TOKEN_UID).update({
144
- select: SELECT_FIELDS,
145
- where: { id },
146
- data: {
147
- ...omit('permissions', attributes),
148
- },
149
- });
150
-
151
- const currentPermissionsResult = await strapi.entityService.load(
152
- TRANSFER_TOKEN_UID,
153
- updatedToken,
154
- 'permissions'
155
- );
156
-
157
- const currentPermissions = map('action', currentPermissionsResult || []);
158
- const newPermissions = uniq(attributes.permissions);
159
-
160
- const actionsToDelete = difference(currentPermissions, newPermissions);
161
- const actionsToAdd = difference(newPermissions, currentPermissions);
162
-
163
- // TODO: improve efficiency here
164
- // method using a loop -- works but very inefficient
165
- await Promise.all(
166
- actionsToDelete.map((action) =>
167
- strapi.query(TRANSFER_TOKEN_PERMISSION_UID).delete({
168
- where: { action, token: id },
169
- })
170
- )
171
- );
172
-
173
- // TODO: improve efficiency here
174
- // using a loop -- works but very inefficient
175
- await Promise.all(
176
- actionsToAdd.map((action) =>
177
- strapi.query(TRANSFER_TOKEN_PERMISSION_UID).create({
178
- data: { action, token: id },
179
- })
180
- )
181
- );
182
-
183
- // retrieve permissions
184
- const permissionsFromDb = await strapi.entityService.load(
185
- TRANSFER_TOKEN_UID,
186
- updatedToken,
187
- 'permissions'
188
- );
189
-
190
- return {
191
- ...updatedToken,
192
- permissions: permissionsFromDb ? permissionsFromDb.map((p) => p.action) : undefined,
193
- };
194
- });
195
- };
196
-
197
- /**
198
- * Revoke (delete) a token
199
- *
200
- * @param {string|number} id
201
- *
202
- * @returns {Promise<Omit<TransferToken, 'accessKey'>>}
203
- */
204
- const revoke = async (id) => {
205
- return strapi.db.transaction(async () =>
206
- strapi
207
- .query(TRANSFER_TOKEN_UID)
208
- .delete({ select: SELECT_FIELDS, populate: POPULATE_FIELDS, where: { id } })
209
- );
210
- };
211
-
212
- /**
213
- * Get a token
214
- *
215
- * @param {Object} whereParams
216
- * @param {string|number} whereParams.id
217
- * @param {string} whereParams.name
218
- * @param {number} whereParams.lastUsedAt
219
- * @param {string} whereParams.description
220
- * @param {string} whereParams.accessKey
221
- *
222
- * @returns {Promise<Omit<TransferToken, 'accessKey'> | null>}
223
- */
224
- const getBy = async (whereParams = {}) => {
225
- if (Object.keys(whereParams).length === 0) {
226
- return null;
227
- }
228
-
229
- const token = await strapi
230
- .query(TRANSFER_TOKEN_UID)
231
- .findOne({ select: SELECT_FIELDS, populate: POPULATE_FIELDS, where: whereParams });
232
-
233
- if (!token) return token;
234
- return flattenTokenPermissions(token);
235
- };
236
-
237
- /**
238
- * Retrieve a token by id
239
- *
240
- * @param {string|number} id
241
- *
242
- * @returns {Promise<Omit<TransferToken, 'accessKey'>>}
243
- */
244
- const getById = async (id) => {
245
- return getBy({ id });
246
- };
247
-
248
- /**
249
- * Retrieve a token by name
250
- *
251
- * @param {string} name
252
- *
253
- * ^@returns {Promise<Omit<TransferToken, 'accessKey'>>}
254
- */
255
- const getByName = async (name) => {
256
- return getBy({ name });
257
- };
258
-
259
- /**
260
- * Check if token exists
261
- *
262
- * @param {Object} whereParams
263
- * @param {string|number} whereParams.id
264
- * @param {string} whereParams.name
265
- * @param {number} whereParams.lastUsedAt
266
- * @param {string} whereParams.description
267
- * @param {string} whereParams.accessKey
268
- *
269
- * @returns {Promise<boolean>}
270
- */
271
- const exists = async (whereParams = {}) => {
272
- const transferToken = await getBy(whereParams);
273
-
274
- return !!transferToken;
275
- };
276
-
277
- /**
278
- * @param {string|number} id
279
- *
280
- * @returns {Promise<TransferToken>}
281
- */
282
- const regenerate = async (id) => {
283
- const accessKey = crypto.randomBytes(128).toString('hex');
284
- const transferToken = await strapi.db.transaction(async () =>
285
- strapi.query(TRANSFER_TOKEN_UID).update({
286
- select: ['id', 'accessKey'],
287
- where: { id },
288
- data: {
289
- accessKey: hash(accessKey),
290
- },
291
- })
292
- );
293
-
294
- if (!transferToken) {
295
- throw new NotFoundError('The provided token id does not exist');
296
- }
297
-
298
- return {
299
- ...transferToken,
300
- accessKey,
301
- };
302
- };
303
-
304
- /**
305
- * @param {number} lifespan
306
- *
307
- * @returns { { lifespan: null | number, expiresAt: null | number } }
308
- */
309
- const getExpirationFields = (lifespan) => {
310
- // it must be nil or a finite number >= 0
311
- const isValidNumber = Number.isFinite(lifespan) && lifespan > 0;
312
- if (!isValidNumber && !isNil(lifespan)) {
313
- throw new ValidationError('lifespan must be a positive number or null');
314
- }
315
-
316
- return {
317
- lifespan: lifespan || null,
318
- expiresAt: lifespan ? Date.now() + lifespan : null,
319
- };
320
- };
321
-
322
- /**
323
- * Return a secure sha512 hash of an accessKey
324
- *
325
- * @param {string} accessKey
326
- *
327
- * @returns {string}
328
- */
329
- const hash = (accessKey) => {
330
- return crypto
331
- .createHmac('sha512', strapi.config.get('admin.transfer.token.salt'))
332
- .update(accessKey)
333
- .digest('hex');
334
- };
335
-
336
- /**
337
- * @returns {void}
338
- */
339
- const checkSaltIsDefined = () => {
340
- if (!strapi.config.get('admin.transfer.token.salt')) {
341
- throw new Error(
342
- `Missing transfer.token.salt. Please set transfer.token.salt in config/admin.js (ex: you can generate one using Node with \`crypto.randomBytes(16).toString('base64')\`).
343
- For 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.`
344
- );
345
- }
346
- };
347
-
348
- /**
349
- * Flatten a token's database permissions objects to an array of strings
350
- *
351
- * @param {TransferToken} token
352
- *
353
- * @returns {TransferToken}
354
- */
355
- const flattenTokenPermissions = (token) => {
356
- if (!token) return token;
357
-
358
- return {
359
- ...token,
360
- permissions: isArray(token.permissions) ? map('action', token.permissions) : token.permissions,
361
- };
362
- };
363
-
364
- /**
365
- * Assert that a token's permissions are valid
366
- *
367
- * @param {TransferToken} token
368
- */
369
- const assertTokenPermissionsValidity = (attributes) => {
370
- const permissionService = strapi.admin.services.transfer.permission;
371
- const validPermissions = permissionService.providers.action.keys();
372
- const invalidPermissions = difference(attributes.permissions, validPermissions);
373
-
374
- if (!isEmpty(invalidPermissions)) {
375
- throw new ValidationError(`Unknown permissions provided: ${invalidPermissions.join(', ')}`);
376
- }
377
- };
378
-
379
- /**
380
- * Assert that a token's lifespan is valid
381
- *
382
- * @param {TransferToken} token
383
- */
384
- const assertValidLifespan = ({ lifespan }) => {
385
- if (isNil(lifespan)) {
386
- return;
387
- }
388
-
389
- if (!Object.values(constants.TRANSFER_TOKEN_LIFESPANS).includes(lifespan)) {
390
- throw new ValidationError(
391
- `lifespan must be one of the following values:
392
- ${Object.values(constants.TRANSFER_TOKEN_LIFESPANS).join(', ')}`
393
- );
394
- }
395
- };
396
-
397
- module.exports = {
398
- create,
399
- list,
400
- exists,
401
- getBy,
402
- getById,
403
- getByName,
404
- update,
405
- revoke,
406
- regenerate,
407
- hash,
408
- checkSaltIsDefined,
409
- };
@@ -1,107 +0,0 @@
1
- 'use strict';
2
-
3
- const { UnauthorizedError, ForbiddenError } = require('@strapi/utils/lib/errors');
4
- const { castArray, isNil } = require('lodash/fp');
5
-
6
- const { getService } = require('../utils');
7
-
8
- const extractToken = (ctx) => {
9
- if (ctx.request && ctx.request.header && ctx.request.header.authorization) {
10
- const parts = ctx.request.header.authorization.split(/\s+/);
11
-
12
- if (parts[0].toLowerCase() !== 'bearer' || parts.length !== 2) {
13
- return null;
14
- }
15
-
16
- return parts[1];
17
- }
18
-
19
- return null;
20
- };
21
-
22
- /**
23
- * Authenticate the validity of the token
24
- *
25
- * @type {import('.').AuthenticateFunction}
26
- */
27
- const authenticate = async (ctx) => {
28
- const { token: tokenService } = getService('transfer');
29
- const token = extractToken(ctx);
30
-
31
- if (!token) {
32
- return { authenticated: false };
33
- }
34
-
35
- const transferToken = await tokenService.getBy({ accessKey: tokenService.hash(token) });
36
-
37
- // Check if the token exists
38
- if (!transferToken) {
39
- return { authenticated: false };
40
- }
41
-
42
- // Check if the token has expired
43
- const currentDate = new Date();
44
-
45
- if (!isNil(transferToken.expiresAt)) {
46
- const expirationDate = new Date(transferToken.expiresAt);
47
-
48
- if (expirationDate < currentDate) {
49
- return { authenticated: false, error: new UnauthorizedError('Token expired') };
50
- }
51
- }
52
-
53
- // Update token metadata
54
- await strapi.query('admin::transfer-token').update({
55
- where: { id: transferToken.id },
56
- data: { lastUsedAt: currentDate },
57
- });
58
-
59
- // Generate an ability based on the token permissions
60
- const ability = await getService('transfer').permission.engine.generateAbility(
61
- transferToken.permissions.map((action) => ({ action }))
62
- );
63
-
64
- return { authenticated: true, ability, credentials: transferToken };
65
- };
66
-
67
- /**
68
- * Verify the token has the required abilities for the requested scope
69
- *
70
- * @type {import('.').VerifyFunction}
71
- */
72
- const verify = async (auth, config = {}) => {
73
- const { credentials: transferToken, ability } = auth;
74
-
75
- if (!transferToken) {
76
- throw new UnauthorizedError('Token not found');
77
- }
78
-
79
- const currentDate = new Date();
80
-
81
- if (!isNil(transferToken.expiresAt)) {
82
- const expirationDate = new Date(transferToken.expiresAt);
83
- // token has expired
84
- if (expirationDate < currentDate) {
85
- throw new UnauthorizedError('Token expired');
86
- }
87
- }
88
-
89
- if (!ability) {
90
- throw new ForbiddenError();
91
- }
92
-
93
- const scopes = castArray(config.scope ?? []);
94
-
95
- const isAllowed = scopes.every((scope) => ability.can(scope));
96
-
97
- if (!isAllowed) {
98
- throw new ForbiddenError();
99
- }
100
- };
101
-
102
- /** @type {import('.').AuthStrategy} */
103
- module.exports = {
104
- name: 'data-transfer',
105
- authenticate,
106
- verify,
107
- };
@@ -1,5 +0,0 @@
1
- 'use strict';
2
-
3
- module.exports = {
4
- token: require('./token'),
5
- };
@@ -1,34 +0,0 @@
1
- 'use strict';
2
-
3
- const { yup, validateYupSchema } = require('@strapi/utils');
4
- const constants = require('../../services/constants');
5
-
6
- const transferTokenCreationSchema = yup
7
- .object()
8
- .shape({
9
- name: yup.string().min(1).required(),
10
- description: yup.string().optional(),
11
- permissions: yup.array().of(yup.string()).nullable(),
12
- lifespan: yup
13
- .number()
14
- .min(1)
15
- .oneOf(Object.values(constants.TRANSFER_TOKEN_LIFESPANS))
16
- .nullable(),
17
- })
18
- .noUnknown()
19
- .strict();
20
-
21
- const transferTokenUpdateSchema = yup
22
- .object()
23
- .shape({
24
- name: yup.string().min(1).notNull(),
25
- description: yup.string().nullable(),
26
- permissions: yup.array().of(yup.string()).nullable(),
27
- })
28
- .noUnknown()
29
- .strict();
30
-
31
- module.exports = {
32
- validateTransferTokenCreationInput: validateYupSchema(transferTokenCreationSchema),
33
- validateTransferTokenUpdateInput: validateYupSchema(transferTokenUpdateSchema),
34
- };