@strapi/admin 4.12.0 → 4.12.2

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 (190) hide show
  1. package/admin/src/components/LeftMenu/index.js +1 -1
  2. package/admin/src/components/PluginsInitializer/index.js +23 -0
  3. package/admin/src/content-manager/components/CollectionTypeFormWrapper/index.js +9 -14
  4. package/admin/src/content-manager/components/EditViewDataManagerProvider/utils/cleanData.js +1 -1
  5. package/admin/src/content-manager/components/InputUID/index.js +2 -3
  6. package/admin/src/content-manager/components/RelationInput/RelationInput.js +1 -1
  7. package/admin/src/content-manager/components/RelationInputDataManager/utils/getRelationLink.js +1 -3
  8. package/admin/src/content-manager/components/RelationInputDataManager/utils/select.js +4 -6
  9. package/admin/src/content-manager/components/SingleTypeFormWrapper/index.js +7 -9
  10. package/admin/src/content-manager/pages/App/utils/getContentTypeLinks.js +1 -3
  11. package/admin/src/content-manager/pages/EditSettingsView/index.js +31 -18
  12. package/admin/src/content-manager/pages/ListSettingsView/components/EditFieldForm.js +1 -3
  13. package/admin/src/content-manager/pages/ListSettingsView/components/Settings.js +1 -3
  14. package/admin/src/content-manager/pages/ListSettingsView/components/SortDisplayedFields.js +14 -32
  15. package/admin/src/content-manager/pages/ListSettingsView/index.js +50 -40
  16. package/admin/src/content-manager/pages/ListView/components/BulkActionButtons/SelectedEntriesModal/index.js +7 -2
  17. package/admin/src/content-manager/pages/ListView/components/CellContent/RelationMultiple/index.js +2 -2
  18. package/admin/src/content-manager/pages/ListView/index.js +10 -4
  19. package/admin/src/content-manager/sharedReducers/crudReducer/reducer.js +1 -1
  20. package/admin/src/content-manager/utils/checkIfAttributeIsDisplayable.js +2 -4
  21. package/admin/src/content-manager/utils/index.js +0 -1
  22. package/admin/src/hooks/index.js +0 -3
  23. package/admin/src/hooks/useAdminRolePermissions/__mocks__/index.js +5 -0
  24. package/admin/src/hooks/useAdminRolePermissions/index.js +34 -0
  25. package/admin/src/hooks/useAdminRoles/__mocks__/index.js +5 -0
  26. package/admin/src/hooks/useAdminRoles/index.js +40 -0
  27. package/admin/src/pages/AuthPage/components/Register/index.js +4 -0
  28. package/admin/src/pages/AuthPage/constants.js +2 -2
  29. package/admin/src/pages/InstalledPluginsPage/Plugins.js +2 -2
  30. package/admin/src/pages/InstalledPluginsPage/hooks/usePlugins/index.js +29 -0
  31. package/admin/src/pages/MarketplacePage/hooks/useFetchMarketplacePlugins/index.js +44 -0
  32. package/admin/src/pages/MarketplacePage/hooks/useFetchMarketplaceProviders/index.js +44 -0
  33. package/admin/src/pages/MarketplacePage/utils/useMarketplaceData.js +2 -2
  34. package/admin/src/pages/SettingsPage/pages/Roles/CreatePage/index.js +24 -9
  35. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/RoleForm/index.js +1 -0
  36. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/index.js +34 -20
  37. package/admin/src/pages/SettingsPage/pages/Roles/ListPage/index.js +31 -84
  38. package/admin/src/pages/SettingsPage/pages/Roles/hooks/useAdminRolePermissionLayout/index.js +23 -0
  39. package/admin/src/translations/ar.json +9 -3
  40. package/admin/src/translations/ca.json +8 -2
  41. package/admin/src/translations/de.json +8 -2
  42. package/admin/src/translations/dk.json +8 -2
  43. package/admin/src/translations/en.json +9 -3
  44. package/admin/src/translations/es.json +9 -3
  45. package/admin/src/translations/eu.json +8 -2
  46. package/admin/src/translations/fr.json +9 -2
  47. package/admin/src/translations/gu.json +8 -2
  48. package/admin/src/translations/hi.json +9 -3
  49. package/admin/src/translations/hu.json +9 -3
  50. package/admin/src/translations/ja.json +12 -6
  51. package/admin/src/translations/ko.json +12 -6
  52. package/admin/src/translations/ml.json +8 -2
  53. package/admin/src/translations/nl.json +8 -2
  54. package/admin/src/translations/pl.json +8 -2
  55. package/admin/src/translations/pt-BR.json +8 -2
  56. package/admin/src/translations/ru.json +8 -2
  57. package/admin/src/translations/sa.json +9 -3
  58. package/admin/src/translations/sk.json +8 -2
  59. package/admin/src/translations/sv.json +7 -2
  60. package/admin/src/translations/tr.json +8 -2
  61. package/admin/src/translations/zh-Hans.json +8 -2
  62. package/admin/src/translations/zh.json +8 -2
  63. package/admin/src/utils/index.js +0 -1
  64. package/build/1049.f76cb14b.chunk.js +1 -0
  65. package/build/1386.879bcd90.chunk.js +7 -0
  66. package/build/{2225.15d1df72.chunk.js → 2225.c6244756.chunk.js} +1 -1
  67. package/build/2379.f1641312.chunk.js +1 -0
  68. package/build/2395.46f8d0c1.chunk.js +26 -0
  69. package/build/2801.5cef5ec8.chunk.js +1 -0
  70. package/build/{3483.e2ee2547.chunk.js → 3483.03c24f96.chunk.js} +1 -1
  71. package/build/3929.5632f24d.chunk.js +114 -0
  72. package/build/4546.cfafae68.chunk.js +1 -0
  73. package/build/6691.4985ef22.chunk.js +105 -0
  74. package/build/7464.3e64a1d5.chunk.js +1 -0
  75. package/build/8276.10a3f883.chunk.js +26 -0
  76. package/build/{9806.aa25371d.chunk.js → 9806.3392505e.chunk.js} +2 -2
  77. package/build/{Admin-authenticatedApp.376233ff.chunk.js → Admin-authenticatedApp.3c585a0d.chunk.js} +3 -3
  78. package/build/{Admin_marketplace.f0b87fce.chunk.js → Admin_marketplace.dde9c148.chunk.js} +6 -6
  79. package/build/Admin_pluginsPage.bbe79434.chunk.js +6 -0
  80. package/build/{Admin_profilePage.a968035f.chunk.js → Admin_profilePage.192edc52.chunk.js} +1 -1
  81. package/build/{Admin_settingsPage.8c600d1a.chunk.js → Admin_settingsPage.97cb9d41.chunk.js} +1 -1
  82. package/build/admin-app.91898385.chunk.js +36 -0
  83. package/build/admin-edit-roles-page.6d567273.chunk.js +267 -0
  84. package/build/{admin-edit-users.67704088.chunk.js → admin-edit-users.79eeb125.chunk.js} +1 -1
  85. package/build/admin-roles-list.23ddff26.chunk.js +22 -0
  86. package/build/{admin-users.3279ffb0.chunk.js → admin-users.123aa08e.chunk.js} +1 -1
  87. package/build/ar-json.74e40bc7.chunk.js +1 -0
  88. package/build/{ca-json.a53c10b6.chunk.js → ca-json.fc6001d3.chunk.js} +1 -1
  89. package/build/content-manager.2af15f57.chunk.js +1099 -0
  90. package/build/{de-json.b3be02c7.chunk.js → de-json.e72545cf.chunk.js} +1 -1
  91. package/build/dk-json.e77140ef.chunk.js +1 -0
  92. package/build/{en-json.e34140fc.chunk.js → en-json.08c05fcf.chunk.js} +1 -1
  93. package/build/es-json.b1f2284b.chunk.js +1 -0
  94. package/build/{eu-json.633025f0.chunk.js → eu-json.63d0a898.chunk.js} +1 -1
  95. package/build/{fr-json.aa8839d2.chunk.js → fr-json.33c6428b.chunk.js} +1 -1
  96. package/build/{gu-json.5bd62812.chunk.js → gu-json.7efe8cc2.chunk.js} +1 -1
  97. package/build/{hi-json.9104eb78.chunk.js → hi-json.0d633692.chunk.js} +1 -1
  98. package/build/{hu-json.9f4aae42.chunk.js → hu-json.c74b6a1e.chunk.js} +1 -1
  99. package/build/index.html +1 -1
  100. package/build/{ja-json.91286391.chunk.js → ja-json.e1959a1c.chunk.js} +1 -1
  101. package/build/{ko-json.fcf3ec4b.chunk.js → ko-json.ce5d6d94.chunk.js} +1 -1
  102. package/build/main.f13fc96c.js +2856 -0
  103. package/build/{ml-json.557aa14c.chunk.js → ml-json.940d7ace.chunk.js} +1 -1
  104. package/build/{nl-json.b2b16eea.chunk.js → nl-json.fe38f0fb.chunk.js} +1 -1
  105. package/build/{pl-json.f094a417.chunk.js → pl-json.d55e8e78.chunk.js} +1 -1
  106. package/build/{pt-BR-json.dec7fb01.chunk.js → pt-BR-json.ae0a0d2e.chunk.js} +1 -1
  107. package/build/review-workflows-settings-create-view.cb08cfa2.chunk.js +1 -0
  108. package/build/review-workflows-settings-edit-view.3c7cbe63.chunk.js +1 -0
  109. package/build/review-workflows-settings-list-view.1611dc1f.chunk.js +56 -0
  110. package/build/{ru-json.8193d8c4.chunk.js → ru-json.1c976644.chunk.js} +1 -1
  111. package/build/{runtime~main.58ec8df6.js → runtime~main.2902859a.js} +1 -1
  112. package/build/{sa-json.a56836f1.chunk.js → sa-json.2c03ef4e.chunk.js} +1 -1
  113. package/build/sk-json.b41847e8.chunk.js +1 -0
  114. package/build/sso-settings-page.12b6d8ae.chunk.js +1 -0
  115. package/build/{sv-json.fd0e86c6.chunk.js → sv-json.568cb7ae.chunk.js} +1 -1
  116. package/build/{tr-json.56c32cf6.chunk.js → tr-json.c9f22432.chunk.js} +1 -1
  117. package/build/upload-settings.7f93d4c0.chunk.js +14 -0
  118. package/build/upload.37488080.chunk.js +58 -0
  119. package/build/users-advanced-settings-page.f0760eb8.chunk.js +9 -0
  120. package/build/users-email-settings-page.ff4b32f3.chunk.js +9 -0
  121. package/build/users-providers-settings-page.48de0306.chunk.js +14 -0
  122. package/build/users-roles-settings-page.3f9f063e.chunk.js +30 -0
  123. package/build/{zh-Hans-json.36d81cdc.chunk.js → zh-Hans-json.937b395b.chunk.js} +1 -1
  124. package/build/{zh-json.1cc86ff0.chunk.js → zh-json.bfc2e036.chunk.js} +1 -1
  125. package/ee/admin/hooks/useAuthProviders/index.js +1 -3
  126. package/ee/admin/pages/AuthResponse/index.js +1 -3
  127. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/Stages/Stage/Stage.js +35 -32
  128. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/pages/CreateView/CreateView.js +1 -7
  129. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/pages/EditView/EditView.js +16 -14
  130. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/pages/ListView/ListView.js +32 -31
  131. package/ee/admin/pages/SettingsPage/pages/SingleSignOn/index.js +16 -26
  132. package/ee/server/config/admin-actions.js +6 -6
  133. package/ee/server/services/review-workflows/entity-service-decorator.js +4 -3
  134. package/index.js +2 -0
  135. package/package.json +16 -16
  136. package/scripts/build.js +1 -0
  137. package/server/controllers/role.js +9 -1
  138. package/server/middlewares/rateLimit.js +6 -2
  139. package/server/services/role.js +3 -2
  140. package/server/services/transfer/token.js +27 -4
  141. package/server/validation/authentication/register.js +2 -2
  142. package/webpack.config.js +2 -1
  143. package/admin/src/content-manager/components/SingleTypeFormWrapper/utils/getRequestUrl.js +0 -5
  144. package/admin/src/content-manager/components/SingleTypeFormWrapper/utils/index.js +0 -2
  145. package/admin/src/content-manager/pages/EditSettingsView/utils/api.js +0 -16
  146. package/admin/src/content-manager/pages/ListSettingsView/init.js +0 -9
  147. package/admin/src/content-manager/utils/getRequestUrl.js +0 -4
  148. package/admin/src/hooks/marketplace/useFetchMarketplacePlugins/index.js +0 -44
  149. package/admin/src/hooks/marketplace/useFetchMarketplaceProviders/index.js +0 -44
  150. package/admin/src/hooks/useFetchEnabledPlugins/index.js +0 -24
  151. package/admin/src/hooks/useFetchEnabledPlugins/utils/api.js +0 -10
  152. package/admin/src/hooks/useFetchPermissionsLayout/index.js +0 -42
  153. package/admin/src/hooks/useFetchPermissionsLayout/reducer.js +0 -35
  154. package/admin/src/hooks/useFetchRole/index.js +0 -68
  155. package/admin/src/hooks/useFetchRole/reducer.js +0 -33
  156. package/admin/src/hooks/useRolesList/index.js +0 -58
  157. package/admin/src/hooks/useRolesList/init.js +0 -5
  158. package/admin/src/hooks/useRolesList/reducer.js +0 -31
  159. package/admin/src/utils/getRequestUrl.js +0 -3
  160. package/build/1049.758a01f5.chunk.js +0 -1
  161. package/build/1386.762d6eb8.chunk.js +0 -7
  162. package/build/2379.0ca87a89.chunk.js +0 -1
  163. package/build/2395.df7a044a.chunk.js +0 -26
  164. package/build/2801.b1140c9b.chunk.js +0 -1
  165. package/build/4546.ff9fdf30.chunk.js +0 -1
  166. package/build/6691.f880a0b6.chunk.js +0 -105
  167. package/build/7065.ec811562.chunk.js +0 -114
  168. package/build/7464.8a6c1e6c.chunk.js +0 -1
  169. package/build/8276.6c7b8e6e.chunk.js +0 -26
  170. package/build/Admin_pluginsPage.8728ff6e.chunk.js +0 -6
  171. package/build/admin-app.1c3f7fd6.chunk.js +0 -36
  172. package/build/admin-edit-roles-page.a49b9f4f.chunk.js +0 -267
  173. package/build/admin-roles-list.0c129e98.chunk.js +0 -23
  174. package/build/ar-json.f530bc3f.chunk.js +0 -1
  175. package/build/content-manager.e9205db1.chunk.js +0 -1103
  176. package/build/dk-json.842aa391.chunk.js +0 -1
  177. package/build/es-json.f57b5335.chunk.js +0 -1
  178. package/build/main.1e3b0985.js +0 -2856
  179. package/build/review-workflows-settings-create-view.05758184.chunk.js +0 -1
  180. package/build/review-workflows-settings-edit-view.c33f7c58.chunk.js +0 -1
  181. package/build/review-workflows-settings-list-view.f055e1be.chunk.js +0 -56
  182. package/build/sk-json.bf2f057a.chunk.js +0 -1
  183. package/build/sso-settings-page.7c9b2fd9.chunk.js +0 -1
  184. package/build/upload-settings.cac210a0.chunk.js +0 -14
  185. package/build/upload.cbfeefa5.chunk.js +0 -58
  186. package/build/users-advanced-settings-page.18379a56.chunk.js +0 -9
  187. package/build/users-email-settings-page.a87978e5.chunk.js +0 -9
  188. package/build/users-providers-settings-page.8876c1ee.chunk.js +0 -14
  189. package/build/users-roles-settings-page.0431f48c.chunk.js +0 -30
  190. /package/admin/src/{hooks/marketplace → pages/MarketplacePage}/constants.js +0 -0
@@ -169,38 +169,39 @@ export function ReviewWorkflowsListView() {
169
169
  <>
170
170
  <Layout.Header
171
171
  primaryAction={
172
- <LinkButton
173
- disabled={!canCreate}
174
- startIcon={<Plus />}
175
- size="S"
176
- to="/settings/review-workflows/create"
177
- onClick={(event) => {
178
- /**
179
- * If the current license has a workflow limit:
180
- * check if the total count of workflows exceeds that limit. If so,
181
- * prevent the navigation and show the limits overlay.
182
- *
183
- * If the current license does not have a limit (e.g. offline license):
184
- * allow the user to navigate to the create-view. In case they exceed the
185
- * current hard-limit of 200 they will see an error thrown by the API.
186
- */
172
+ canCreate && (
173
+ <LinkButton
174
+ startIcon={<Plus />}
175
+ size="S"
176
+ to="/settings/review-workflows/create"
177
+ onClick={(event) => {
178
+ /**
179
+ * If the current license has a workflow limit:
180
+ * check if the total count of workflows exceeds that limit. If so,
181
+ * prevent the navigation and show the limits overlay.
182
+ *
183
+ * If the current license does not have a limit (e.g. offline license):
184
+ * allow the user to navigate to the create-view. In case they exceed the
185
+ * current hard-limit of 200 they will see an error thrown by the API.
186
+ */
187
187
 
188
- if (
189
- limits?.[CHARGEBEE_WORKFLOW_ENTITLEMENT_NAME] &&
190
- meta?.workflowCount >= parseInt(limits[CHARGEBEE_WORKFLOW_ENTITLEMENT_NAME], 10)
191
- ) {
192
- event.preventDefault();
193
- setShowLimitModal(true);
194
- } else {
195
- trackUsage('willCreateWorkflow');
196
- }
197
- }}
198
- >
199
- {formatMessage({
200
- id: 'Settings.review-workflows.list.page.create',
201
- defaultMessage: 'Create new workflow',
202
- })}
203
- </LinkButton>
188
+ if (
189
+ limits?.[CHARGEBEE_WORKFLOW_ENTITLEMENT_NAME] &&
190
+ meta?.workflowCount >= parseInt(limits[CHARGEBEE_WORKFLOW_ENTITLEMENT_NAME], 10)
191
+ ) {
192
+ event.preventDefault();
193
+ setShowLimitModal(true);
194
+ } else {
195
+ trackUsage('willCreateWorkflow');
196
+ }
197
+ }}
198
+ >
199
+ {formatMessage({
200
+ id: 'Settings.review-workflows.list.page.create',
201
+ defaultMessage: 'Create new workflow',
202
+ })}
203
+ </LinkButton>
204
+ )
204
205
  }
205
206
  subtitle={formatMessage({
206
207
  id: 'Settings.review-workflows.list.page.subtitle',
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import * as React from 'react';
2
2
 
3
3
  import {
4
4
  Button,
@@ -28,18 +28,20 @@ import isEqual from 'lodash/isEqual';
28
28
  import { useIntl } from 'react-intl';
29
29
  import { useSelector } from 'react-redux';
30
30
 
31
- import { useRolesList, useSettingsForm } from '../../../../../../admin/src/hooks';
31
+ import { useSettingsForm } from '../../../../../../admin/src/hooks';
32
+ import { useAdminRoles } from '../../../../../../admin/src/hooks/useAdminRoles';
32
33
  import { selectAdminPermissions } from '../../../../../../admin/src/pages/App/selectors';
33
- import { getRequestUrl } from '../../../../../../admin/src/utils';
34
34
 
35
35
  import schema from './utils/schema';
36
36
 
37
37
  export const SingleSignOn = () => {
38
+ useFocusWhenNavigate();
39
+
38
40
  const { formatMessage } = useIntl();
39
41
  const permissions = useSelector(selectAdminPermissions);
40
42
 
41
43
  const {
42
- isLoading: isLoadingForPermissions,
44
+ isLoading: isLoadingPermissions,
43
45
  allowedActions: { canUpdate, canReadRoles },
44
46
  } = useRBAC({
45
47
  ...permissions.settings.sso,
@@ -47,44 +49,32 @@ export const SingleSignOn = () => {
47
49
  });
48
50
 
49
51
  const [
50
- { formErrors, initialData, isLoading, modifiedData, showHeaderButtonLoader },
51
- // eslint-disable-next-line no-unused-vars
52
- dispatch,
52
+ { formErrors, initialData, isLoading: isLoadingForm, modifiedData, showHeaderButtonLoader },
53
+ ,
53
54
  { handleChange, handleSubmit },
54
- ] = useSettingsForm(getRequestUrl('providers/options'), schema, () => {}, [
55
+ ] = useSettingsForm('/admin/providers/options', schema, () => {}, [
55
56
  'autoRegister',
56
57
  'defaultRole',
57
58
  'ssoLockedRoles',
58
59
  ]);
59
- const { roles } = useRolesList(canReadRoles);
60
-
61
- useFocusWhenNavigate();
62
60
 
63
- const showLoader = isLoadingForPermissions || isLoading;
61
+ const { roles, isLoading: isLoadingRoles } = useAdminRoles(undefined, {
62
+ enabled: canReadRoles,
63
+ });
64
64
 
65
+ const isLoading = isLoadingPermissions || isLoadingRoles || isLoadingForm;
65
66
  // TODO: focus() first error field, but it looks like that requires refactoring from useSettingsForm to Formik
66
67
 
67
- const isHeaderButtonDisabled = isEqual(initialData, modifiedData);
68
-
69
68
  return (
70
69
  <Layout>
71
70
  <SettingsPageTitle name="SSO" />
72
71
  <Main tabIndex={-1}>
73
- <form
74
- onSubmit={(e) => {
75
- if (isHeaderButtonDisabled) {
76
- e.preventDefault();
77
-
78
- return;
79
- }
80
- handleSubmit(e);
81
- }}
82
- >
72
+ <form onSubmit={handleSubmit}>
83
73
  <HeaderLayout
84
74
  primaryAction={
85
75
  <Button
86
76
  data-testid="save-button"
87
- disabled={isHeaderButtonDisabled}
77
+ disabled={isEqual(initialData, modifiedData)}
88
78
  loading={showHeaderButtonLoader}
89
79
  startIcon={<Check />}
90
80
  type="submit"
@@ -103,7 +93,7 @@ export const SingleSignOn = () => {
103
93
  })}
104
94
  />
105
95
  <ContentLayout>
106
- {showLoader ? (
96
+ {isLoading ? (
107
97
  <LoadingIndicatorPage />
108
98
  ) : (
109
99
  <Flex
@@ -39,24 +39,24 @@ module.exports = {
39
39
  subCategory: 'options',
40
40
  },
41
41
  {
42
- uid: 'review-workflows.update',
43
- displayName: 'Update',
42
+ uid: 'review-workflows.read',
43
+ displayName: 'Read',
44
44
  pluginName: 'admin',
45
45
  section: 'settings',
46
46
  category: 'review workflows',
47
47
  subCategory: 'options',
48
48
  },
49
49
  {
50
- uid: 'review-workflows.delete',
51
- displayName: 'Delete',
50
+ uid: 'review-workflows.update',
51
+ displayName: 'Update',
52
52
  pluginName: 'admin',
53
53
  section: 'settings',
54
54
  category: 'review workflows',
55
55
  subCategory: 'options',
56
56
  },
57
57
  {
58
- uid: 'review-workflows.read',
59
- displayName: 'Read',
58
+ uid: 'review-workflows.delete',
59
+ displayName: 'Delete',
60
60
  pluginName: 'admin',
61
61
  section: 'settings',
62
62
  category: 'review workflows',
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- const { isNil, isNull } = require('lodash/fp');
3
+ const { isNil } = require('lodash/fp');
4
4
  const { ENTITY_STAGE_ATTRIBUTE } = require('../../constants/workflows');
5
5
  const { WORKFLOW_UPDATE_STAGE } = require('../../constants/webhookEvents');
6
6
  const { getService } = require('../../utils');
@@ -56,7 +56,7 @@ const decorator = (service) => ({
56
56
  async update(uid, entityId, opts = {}) {
57
57
  // Prevents the stage from being set to null
58
58
  const data = { ...opts.data };
59
- if (isNull(data[ENTITY_STAGE_ATTRIBUTE])) {
59
+ if (isNil(data[ENTITY_STAGE_ATTRIBUTE])) {
60
60
  delete data[ENTITY_STAGE_ATTRIBUTE];
61
61
  return service.update.call(this, uid, entityId, { ...opts, data });
62
62
  }
@@ -66,7 +66,8 @@ const decorator = (service) => ({
66
66
  const updatedEntity = await service.update.call(this, uid, entityId, { ...opts, data });
67
67
  const updatedStage = updatedEntity[ENTITY_STAGE_ATTRIBUTE];
68
68
 
69
- if (previousStage?.id && previousStage.id !== updatedStage.id) {
69
+ // Stage might be null if field is not populated
70
+ if (updatedStage && previousStage?.id && previousStage.id !== updatedStage.id) {
70
71
  const model = strapi.getModel(uid);
71
72
 
72
73
  strapi.eventHub.emit(WORKFLOW_UPDATE_STAGE, {
package/index.js CHANGED
@@ -31,6 +31,7 @@ async function build({ appDir, buildDestDir, env, forceBuild, optimize, options,
31
31
  const dest = path.resolve(buildDestDir, 'build');
32
32
 
33
33
  const pluginsPath = Object.keys(plugins).map((pluginName) => plugins[pluginName].pathToPlugin);
34
+ const enforceSourceMaps = process.env.STRAPI_ENFORCE_SOURCEMAPS === 'true' ?? false;
34
35
 
35
36
  // Either use the tsconfig file from the generated app or the one inside the .cache folder
36
37
  // so we can develop plugins in TS while being in a JS app
@@ -42,6 +43,7 @@ async function build({ appDir, buildDestDir, env, forceBuild, optimize, options,
42
43
  appDir,
43
44
  cacheDir,
44
45
  dest,
46
+ enforceSourceMaps,
45
47
  entry,
46
48
  env,
47
49
  optimize,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@strapi/admin",
3
- "version": "4.12.0",
3
+ "version": "4.12.2",
4
4
  "description": "Strapi Admin",
5
5
  "repository": {
6
6
  "type": "git",
@@ -42,31 +42,31 @@
42
42
  "dependencies": {
43
43
  "@casl/ability": "^5.4.3",
44
44
  "@pmmmwh/react-refresh-webpack-plugin": "0.5.10",
45
- "@strapi/data-transfer": "4.12.0",
45
+ "@strapi/data-transfer": "4.12.2",
46
46
  "@strapi/design-system": "1.8.2",
47
- "@strapi/helper-plugin": "4.12.0",
47
+ "@strapi/helper-plugin": "4.12.2",
48
48
  "@strapi/icons": "1.8.2",
49
- "@strapi/permissions": "4.12.0",
50
- "@strapi/provider-audit-logs-local": "4.12.0",
51
- "@strapi/typescript-utils": "4.12.0",
52
- "@strapi/utils": "4.12.0",
49
+ "@strapi/permissions": "4.12.2",
50
+ "@strapi/provider-audit-logs-local": "4.12.2",
51
+ "@strapi/typescript-utils": "4.12.2",
52
+ "@strapi/utils": "4.12.2",
53
53
  "axios": "1.4.0",
54
54
  "bcryptjs": "2.4.3",
55
55
  "browserslist": "^4.17.3",
56
56
  "browserslist-to-esbuild": "1.2.0",
57
57
  "chalk": "^4.1.2",
58
- "chokidar": "^3.5.1",
58
+ "chokidar": "3.5.3",
59
59
  "codemirror5": "npm:codemirror@^5.65.11",
60
60
  "cross-env": "^7.0.3",
61
61
  "css-loader": "^6.8.1",
62
62
  "date-fns": "2.30.0",
63
- "dotenv": "8.5.1",
63
+ "dotenv": "14.2.0",
64
64
  "esbuild-loader": "^2.21.0",
65
- "execa": "^1.0.0",
65
+ "execa": "5.1.1",
66
66
  "fast-deep-equal": "3.1.3",
67
67
  "find-root": "1.1.0",
68
68
  "fork-ts-checker-webpack-plugin": "7.3.0",
69
- "formik": "^2.4.0",
69
+ "formik": "2.4.0",
70
70
  "fractional-indexing": "3.2.0",
71
71
  "fs-extra": "10.0.0",
72
72
  "highlight.js": "^10.4.1",
@@ -114,10 +114,10 @@
114
114
  "react-select": "5.7.0",
115
115
  "react-window": "1.8.8",
116
116
  "redux": "^4.2.1",
117
- "reselect": "^4.1.7",
117
+ "reselect": "4.1.7",
118
118
  "rimraf": "3.0.2",
119
119
  "sanitize-html": "2.11.0",
120
- "semver": "7.5.2",
120
+ "semver": "7.5.4",
121
121
  "sift": "16.0.1",
122
122
  "style-loader": "3.3.1",
123
123
  "styled-components": "5.3.3",
@@ -126,7 +126,7 @@
126
126
  "webpack-cli": "^5.1.0",
127
127
  "webpack-dev-server": "^4.15.0",
128
128
  "webpackbar": "^5.0.2",
129
- "yup": "^0.32.9"
129
+ "yup": "0.32.9"
130
130
  },
131
131
  "devDependencies": {
132
132
  "@testing-library/dom": "9.2.0",
@@ -142,7 +142,7 @@
142
142
  "@strapi/strapi": "^4.3.4"
143
143
  },
144
144
  "engines": {
145
- "node": ">=14.19.1 <=18.x.x",
145
+ "node": ">=16.0.0 <=20.x.x",
146
146
  "npm": ">=6.0.0"
147
147
  },
148
148
  "nx": {
@@ -154,5 +154,5 @@
154
154
  }
155
155
  }
156
156
  },
157
- "gitHead": "7f8109a1a736c1d997fbb445469b3b59550c7aeb"
157
+ "gitHead": "b5a0cb4020ee9b170243e458decd5b1babf474e3"
158
158
  }
package/scripts/build.js CHANGED
@@ -54,6 +54,7 @@ const buildAdmin = async () => {
54
54
  telemetryDisabled: process.env.STRAPI_TELEMETRY_DISABLED === 'true' ?? false,
55
55
  },
56
56
  tsConfigFilePath,
57
+ enforceSourceMaps: process.env.STRAPI_ENFORCE_SOURCEMAPS === 'true' ?? false,
57
58
  };
58
59
 
59
60
  const config =
@@ -49,7 +49,15 @@ module.exports = {
49
49
  * @param {KoaContext} ctx - koa context
50
50
  */
51
51
  async findAll(ctx) {
52
- const roles = await getService('role').findAllWithUsersCount();
52
+ const { query } = ctx.request;
53
+
54
+ const permissionsManager = getService('permission').createPermissionsManager({
55
+ ability: ctx.state.userAbility,
56
+ model: 'admin::role',
57
+ });
58
+ const sanitizedQuery = await permissionsManager.sanitizeQuery(query);
59
+
60
+ const roles = await getService('role').findAllWithUsersCount(sanitizedQuery);
53
61
 
54
62
  ctx.body = {
55
63
  data: roles,
@@ -1,7 +1,8 @@
1
1
  'use strict';
2
2
 
3
+ const path = require('path');
3
4
  const utils = require('@strapi/utils');
4
- const { has, toLower } = require('lodash/fp');
5
+ const { isString, has, toLower } = require('lodash/fp');
5
6
 
6
7
  const { RateLimitError } = utils.errors;
7
8
 
@@ -24,11 +25,14 @@ module.exports =
24
25
  const rateLimit = require('koa2-ratelimit').RateLimit;
25
26
 
26
27
  const userEmail = toLower(ctx.request.body.email) || 'unknownEmail';
28
+ const requestPath = isString(ctx.request.path)
29
+ ? toLower(path.normalize(ctx.request.path)).replace(/\/$/, '')
30
+ : 'invalidPath';
27
31
 
28
32
  const loadConfig = {
29
33
  interval: { min: 5 },
30
34
  max: 5,
31
- prefixKey: `${userEmail}:${ctx.request.path}:${ctx.request.ip}`,
35
+ prefixKey: `${userEmail}:${requestPath}:${ctx.request.ip}`,
32
36
  handler() {
33
37
  throw new RateLimitError();
34
38
  },
@@ -110,8 +110,9 @@ const find = (params = {}, populate) => {
110
110
  * Find all roles in database
111
111
  * @returns {Promise<array>}
112
112
  */
113
- const findAllWithUsersCount = async (populate) => {
114
- const roles = await strapi.query('admin::role').findMany({ populate });
113
+ const findAllWithUsersCount = async (params) => {
114
+ const roles = await strapi.entityService.findMany('admin::role', params);
115
+
115
116
  for (const role of roles) {
116
117
  role.usersCount = await getUsersCount(role.id);
117
118
  }
@@ -1,7 +1,8 @@
1
1
  'use strict';
2
2
 
3
- const { map, isArray, omit, uniq, isNil, difference, isEmpty } = require('lodash/fp');
4
3
  const crypto = require('crypto');
4
+ const assert = require('assert');
5
+ const { map, isArray, omit, uniq, isNil, difference, isEmpty } = require('lodash/fp');
5
6
 
6
7
  const {
7
8
  errors: { ValidationError, NotFoundError },
@@ -65,6 +66,24 @@ const list = async () => {
65
66
  return tokens.map((token) => flattenTokenPermissions(token));
66
67
  };
67
68
 
69
+ /**
70
+ * Create a random token's access key
71
+ * @returns {string}
72
+ */
73
+ const generateRandomAccessKey = () => crypto.randomBytes(128).toString('hex');
74
+
75
+ /**
76
+ * Validate the given access key's format and returns it if valid
77
+ * @param {string} accessKey
78
+ * @return {string}
79
+ */
80
+ const validateAccessKey = (accessKey) => {
81
+ assert(typeof accessKey === 'string', 'Access key needs to be a string');
82
+ assert(accessKey.length >= 15, 'Access key needs to have at least 15 characters');
83
+
84
+ return accessKey;
85
+ };
86
+
68
87
  /**
69
88
  * Create a token and its permissions
70
89
  *
@@ -73,11 +92,16 @@ const list = async () => {
73
92
  * @param {string} attributes.description
74
93
  * @param {number} attributes.lifespan
75
94
  * @param {string[]} attributes.permissions
95
+ * @param {string} [attributes.accessKey]
76
96
  *
77
97
  * @returns {Promise<TransferToken>}
78
98
  */
79
99
  const create = async (attributes) => {
80
- const accessKey = crypto.randomBytes(128).toString('hex');
100
+ const accessKey =
101
+ 'accessKey' in attributes ? validateAccessKey(attributes.accessKey) : generateRandomAccessKey();
102
+
103
+ // Make sure the access key isn't picked up directly from the attributes for the next steps
104
+ delete attributes.accessKey;
81
105
 
82
106
  assertTokenPermissionsValidity(attributes);
83
107
  assertValidLifespan(attributes);
@@ -380,8 +404,7 @@ const flattenTokenPermissions = (token) => {
380
404
 
381
405
  /**
382
406
  * Assert that a token's permissions are valid
383
- *
384
- * @param {TransferToken} token
407
+ * @param {object} attributes
385
408
  */
386
409
  const assertTokenPermissionsValidity = (attributes) => {
387
410
  const permissionService = strapi.admin.services.transfer.permission;
@@ -11,7 +11,7 @@ const registrationSchema = yup
11
11
  .object()
12
12
  .shape({
13
13
  firstname: validators.firstname.required(),
14
- lastname: validators.lastname,
14
+ lastname: validators.lastname.nullable(),
15
15
  password: validators.password.required(),
16
16
  })
17
17
  .required()
@@ -32,7 +32,7 @@ const adminRegistrationSchema = yup
32
32
  .shape({
33
33
  email: validators.email.required(),
34
34
  firstname: validators.firstname.required(),
35
- lastname: validators.lastname,
35
+ lastname: validators.lastname.nullable(),
36
36
  password: validators.password.required(),
37
37
  })
38
38
  .required()
package/webpack.config.js CHANGED
@@ -28,6 +28,7 @@ module.exports = ({
28
28
  features: [],
29
29
  },
30
30
  tsConfigFilePath,
31
+ enforceSourceMaps,
31
32
  }) => {
32
33
  const isProduction = env === 'production';
33
34
 
@@ -54,7 +55,7 @@ module.exports = ({
54
55
  return {
55
56
  mode: isProduction ? 'production' : 'development',
56
57
  bail: !!isProduction,
57
- devtool: isProduction ? false : 'eval-source-map',
58
+ devtool: isProduction && !enforceSourceMaps ? false : 'source-map',
58
59
  experiments: {
59
60
  topLevelAwait: true,
60
61
  },
@@ -1,5 +0,0 @@
1
- import { getRequestUrl } from '../../../utils';
2
-
3
- const requestURL = (path) => getRequestUrl(`single-types/${path}`);
4
-
5
- export default requestURL;
@@ -1,2 +0,0 @@
1
- // eslint-disable-next-line import/prefer-default-export
2
- export { default as getRequestUrl } from './getRequestUrl';
@@ -1,16 +0,0 @@
1
- import { getFetchClient } from '@strapi/helper-plugin';
2
-
3
- import { getRequestUrl } from '../../../utils';
4
-
5
- const putCMSettingsEV = (body, slug, isContentTypeView) => {
6
- const { put } = getFetchClient();
7
-
8
- return put(
9
- getRequestUrl(
10
- isContentTypeView ? `content-types/${slug}/configuration` : `components/${slug}/configuration`
11
- ),
12
- body
13
- );
14
- };
15
-
16
- export default putCMSettingsEV;
@@ -1,9 +0,0 @@
1
- const init = (initialState, layout) => {
2
- return {
3
- ...initialState,
4
- initialData: layout,
5
- modifiedData: layout,
6
- };
7
- };
8
-
9
- export default init;
@@ -1,4 +0,0 @@
1
- // FIXME when back-end ready
2
- const getRequestUrl = (path) => `/content-manager/${path}`;
3
-
4
- export default getRequestUrl;
@@ -1,44 +0,0 @@
1
- import { useNotification } from '@strapi/helper-plugin';
2
- import qs from 'qs';
3
- import { useQuery } from 'react-query';
4
-
5
- import { MARKETPLACE_API_URL } from '../constants';
6
-
7
- const fetchMarketplacePlugins = async (params = {}) => {
8
- try {
9
- const queryString = qs.stringify(qs.parse(params));
10
- const res = await fetch(`${MARKETPLACE_API_URL}/plugins?${queryString}`);
11
-
12
- if (!res.ok) {
13
- throw new Error('Failed to fetch marketplace plugins.');
14
- }
15
-
16
- const data = await res.json();
17
-
18
- return data;
19
- } catch (error) {
20
- console.error(error);
21
- }
22
-
23
- return null;
24
- };
25
-
26
- const useFetchMarketplacePlugins = (notifyLoad, params) => {
27
- const toggleNotification = useNotification();
28
-
29
- return useQuery(['list-marketplace-plugins', params], () => fetchMarketplacePlugins(params), {
30
- onSuccess() {
31
- if (notifyLoad) {
32
- notifyLoad();
33
- }
34
- },
35
- onError() {
36
- toggleNotification({
37
- type: 'warning',
38
- message: { id: 'notification.error', defaultMessage: 'An error occured' },
39
- });
40
- },
41
- });
42
- };
43
-
44
- export default useFetchMarketplacePlugins;
@@ -1,44 +0,0 @@
1
- import { useNotification } from '@strapi/helper-plugin';
2
- import qs from 'qs';
3
- import { useQuery } from 'react-query';
4
-
5
- import { MARKETPLACE_API_URL } from '../constants';
6
-
7
- const fetchMarketplaceProviders = async (params = {}) => {
8
- try {
9
- const queryString = qs.stringify(qs.parse(params));
10
- const res = await fetch(`${MARKETPLACE_API_URL}/providers?${queryString}`);
11
-
12
- if (!res.ok) {
13
- throw new Error('Failed to fetch marketplace providers.');
14
- }
15
-
16
- const data = await res.json();
17
-
18
- return data;
19
- } catch (error) {
20
- console.error(error);
21
- }
22
-
23
- return null;
24
- };
25
-
26
- const useFetchMarketplaceProviders = (notifyLoad, params) => {
27
- const toggleNotification = useNotification();
28
-
29
- return useQuery(['list-marketplace-providers', params], () => fetchMarketplaceProviders(params), {
30
- onSuccess() {
31
- if (notifyLoad) {
32
- notifyLoad();
33
- }
34
- },
35
- onError() {
36
- toggleNotification({
37
- type: 'warning',
38
- message: { id: 'notification.error', defaultMessage: 'An error occured' },
39
- });
40
- },
41
- });
42
- };
43
-
44
- export default useFetchMarketplaceProviders;
@@ -1,24 +0,0 @@
1
- import { useNotification } from '@strapi/helper-plugin';
2
- import { useQuery } from 'react-query';
3
-
4
- import { fetchEnabledPlugins } from './utils/api';
5
-
6
- const useFetchEnabledPlugins = (notifyLoad) => {
7
- const toggleNotification = useNotification();
8
-
9
- return useQuery('list-enabled-plugins', () => fetchEnabledPlugins(), {
10
- onSuccess() {
11
- if (notifyLoad) {
12
- notifyLoad();
13
- }
14
- },
15
- onError() {
16
- toggleNotification({
17
- type: 'warning',
18
- message: { id: 'notification.error', defaultMessage: 'An error occured' },
19
- });
20
- },
21
- });
22
- };
23
-
24
- export default useFetchEnabledPlugins;
@@ -1,10 +0,0 @@
1
- import { getFetchClient } from '@strapi/helper-plugin';
2
-
3
- const fetchEnabledPlugins = async () => {
4
- const { get } = getFetchClient();
5
- const { data } = await get('/admin/plugins');
6
-
7
- return data;
8
- };
9
-
10
- export { fetchEnabledPlugins };