@strapi/plugin-users-permissions 0.0.0-next.de5394e73076ccf7aca1e28dc68894e3c43f8b91 → 0.0.0-next.e037a7b2d1f48b7bd8bcd0d9400ca0f9ded8a982

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 (41) hide show
  1. package/admin/src/components/Permissions/index.js +2 -4
  2. package/admin/src/{permissions.js → constants.js} +1 -3
  3. package/admin/src/index.js +12 -13
  4. package/admin/src/pages/AdvancedSettings/index.js +48 -35
  5. package/admin/src/pages/EmailTemplates/index.js +66 -55
  6. package/admin/src/pages/Providers/index.js +66 -64
  7. package/admin/src/{hooks → pages/Roles/hooks}/usePlugins.js +15 -8
  8. package/admin/src/pages/Roles/index.js +12 -9
  9. package/admin/src/pages/Roles/pages/CreatePage.js +190 -0
  10. package/admin/src/pages/Roles/pages/EditPage.js +211 -0
  11. package/admin/src/pages/Roles/{ListPage → pages/ListPage}/components/TableBody.js +44 -14
  12. package/admin/src/pages/Roles/{ListPage → pages/ListPage}/index.js +31 -32
  13. package/admin/src/pages/Roles/{ListPage → pages/ListPage}/utils/api.js +2 -4
  14. package/admin/src/translations/zh-Hans.json +80 -80
  15. package/admin/src/utils/index.js +0 -1
  16. package/documentation/content-api.yaml +1 -1
  17. package/jest.config.front.js +1 -1
  18. package/package.json +10 -10
  19. package/server/bootstrap/index.js +35 -0
  20. package/server/controllers/auth.js +46 -13
  21. package/server/controllers/user.js +12 -1
  22. package/server/middlewares/rateLimit.js +41 -21
  23. package/admin/src/hooks/index.js +0 -5
  24. package/admin/src/hooks/useFetchRole/index.js +0 -67
  25. package/admin/src/hooks/useFetchRole/reducer.js +0 -31
  26. package/admin/src/hooks/useForm/index.js +0 -70
  27. package/admin/src/hooks/useForm/reducer.js +0 -40
  28. package/admin/src/hooks/useRolesList/index.js +0 -65
  29. package/admin/src/hooks/useRolesList/init.js +0 -5
  30. package/admin/src/hooks/useRolesList/reducer.js +0 -31
  31. package/admin/src/pages/AdvancedSettings/utils/api.js +0 -18
  32. package/admin/src/pages/EmailTemplates/utils/api.js +0 -18
  33. package/admin/src/pages/Providers/reducer.js +0 -54
  34. package/admin/src/pages/Providers/utils/api.js +0 -26
  35. package/admin/src/pages/Providers/utils/createProvidersArray.js +0 -21
  36. package/admin/src/pages/Roles/CreatePage.js +0 -185
  37. package/admin/src/pages/Roles/EditPage.js +0 -197
  38. package/admin/src/pages/Roles/ProtectedCreatePage.js +0 -15
  39. package/admin/src/pages/Roles/ProtectedEditPage.js +0 -15
  40. package/admin/src/pages/Roles/ProtectedListPage.js +0 -17
  41. package/admin/src/utils/getRequestURL.js +0 -5
@@ -1,6 +1,6 @@
1
1
  import React, { useReducer } from 'react';
2
2
 
3
- import { Accordion, AccordionContent, AccordionToggle, Box, Flex } from '@strapi/design-system';
3
+ import { Accordion, AccordionContent, AccordionToggle, Flex } from '@strapi/design-system';
4
4
  import { useIntl } from 'react-intl';
5
5
 
6
6
  import { useUsersPermissions } from '../../contexts/UsersPermissionsContext';
@@ -44,9 +44,7 @@ const Permissions = () => {
44
44
  variant={index % 2 ? 'primary' : 'secondary'}
45
45
  />
46
46
  <AccordionContent>
47
- <Box>
48
- <PermissionRow permissions={modifiedData[collapse.name]} name={collapse.name} />
49
- </Box>
47
+ <PermissionRow permissions={modifiedData[collapse.name]} name={collapse.name} />
50
48
  </AccordionContent>
51
49
  </Accordion>
52
50
  ))}
@@ -1,4 +1,4 @@
1
- const pluginPermissions = {
1
+ export const PERMISSIONS = {
2
2
  // Roles
3
3
  accessRoles: [
4
4
  { action: 'plugin::users-permissions.roles.create', subject: null },
@@ -27,5 +27,3 @@ const pluginPermissions = {
27
27
  readProviders: [{ action: 'plugin::users-permissions.providers.read', subject: null }],
28
28
  updateProviders: [{ action: 'plugin::users-permissions.providers.update', subject: null }],
29
29
  };
30
-
31
- export default pluginPermissions;
@@ -8,8 +8,7 @@ import { prefixPluginTranslations } from '@strapi/helper-plugin';
8
8
 
9
9
  import pluginPkg from '../../package.json';
10
10
 
11
- import pluginPermissions from './permissions';
12
- import pluginId from './pluginId';
11
+ import { PERMISSIONS } from './constants';
13
12
  import getTrad from './utils/getTrad';
14
13
 
15
14
  const name = pluginPkg.strapi.name;
@@ -19,7 +18,7 @@ export default {
19
18
  // Create the plugin's settings section
20
19
  app.createSettingSection(
21
20
  {
22
- id: pluginId,
21
+ id: 'users-permissions',
23
22
  intlLabel: {
24
23
  id: getTrad('Settings.section-label'),
25
24
  defaultMessage: 'Users & Permissions plugin',
@@ -32,7 +31,7 @@ export default {
32
31
  defaultMessage: 'Roles',
33
32
  },
34
33
  id: 'roles',
35
- to: `/settings/${pluginId}/roles`,
34
+ to: `/settings/users-permissions/roles`,
36
35
  async Component() {
37
36
  const component = await import(
38
37
  /* webpackChunkName: "users-roles-settings-page" */ './pages/Roles'
@@ -40,7 +39,7 @@ export default {
40
39
 
41
40
  return component;
42
41
  },
43
- permissions: pluginPermissions.accessRoles,
42
+ permissions: PERMISSIONS.accessRoles,
44
43
  },
45
44
  {
46
45
  intlLabel: {
@@ -48,7 +47,7 @@ export default {
48
47
  defaultMessage: 'Providers',
49
48
  },
50
49
  id: 'providers',
51
- to: `/settings/${pluginId}/providers`,
50
+ to: `/settings/users-permissions/providers`,
52
51
  async Component() {
53
52
  const component = await import(
54
53
  /* webpackChunkName: "users-providers-settings-page" */ './pages/Providers'
@@ -56,7 +55,7 @@ export default {
56
55
 
57
56
  return component;
58
57
  },
59
- permissions: pluginPermissions.readProviders,
58
+ permissions: PERMISSIONS.readProviders,
60
59
  },
61
60
  {
62
61
  intlLabel: {
@@ -64,7 +63,7 @@ export default {
64
63
  defaultMessage: 'Email templates',
65
64
  },
66
65
  id: 'email-templates',
67
- to: `/settings/${pluginId}/email-templates`,
66
+ to: `/settings/users-permissions/email-templates`,
68
67
  async Component() {
69
68
  const component = await import(
70
69
  /* webpackChunkName: "users-email-settings-page" */ './pages/EmailTemplates'
@@ -72,7 +71,7 @@ export default {
72
71
 
73
72
  return component;
74
73
  },
75
- permissions: pluginPermissions.readEmailTemplates,
74
+ permissions: PERMISSIONS.readEmailTemplates,
76
75
  },
77
76
  {
78
77
  intlLabel: {
@@ -80,7 +79,7 @@ export default {
80
79
  defaultMessage: 'Advanced Settings',
81
80
  },
82
81
  id: 'advanced-settings',
83
- to: `/settings/${pluginId}/advanced-settings`,
82
+ to: `/settings/users-permissions/advanced-settings`,
84
83
  async Component() {
85
84
  const component = await import(
86
85
  /* webpackChunkName: "users-advanced-settings-page" */ './pages/AdvancedSettings'
@@ -88,13 +87,13 @@ export default {
88
87
 
89
88
  return component;
90
89
  },
91
- permissions: pluginPermissions.readAdvancedSettings,
90
+ permissions: PERMISSIONS.readAdvancedSettings,
92
91
  },
93
92
  ]
94
93
  );
95
94
 
96
95
  app.registerPlugin({
97
- id: pluginId,
96
+ id: 'users-permissions',
98
97
  name,
99
98
  });
100
99
  },
@@ -107,7 +106,7 @@ export default {
107
106
  )
108
107
  .then(({ default: data }) => {
109
108
  return {
110
- data: prefixPluginTranslations(data, pluginId),
109
+ data: prefixPluginTranslations(data, 'users-permissions'),
111
110
  locale,
112
111
  };
113
112
  })
@@ -1,4 +1,4 @@
1
- import React, { useMemo } from 'react';
1
+ import React from 'react';
2
2
 
3
3
  import {
4
4
  Box,
@@ -20,6 +20,8 @@ import {
20
20
  GenericInput,
21
21
  LoadingIndicatorPage,
22
22
  SettingsPageTitle,
23
+ useAPIErrorHandler,
24
+ useFetchClient,
23
25
  useFocusWhenNavigate,
24
26
  useNotification,
25
27
  useOverlayBlocker,
@@ -30,15 +32,14 @@ import { Formik } from 'formik';
30
32
  import { useIntl } from 'react-intl';
31
33
  import { useMutation, useQuery, useQueryClient } from 'react-query';
32
34
 
33
- import pluginPermissions from '../../permissions';
35
+ import { PERMISSIONS } from '../../constants';
34
36
  import { getTrad } from '../../utils';
35
37
 
36
- import { fetchData, putAdvancedSettings } from './utils/api';
37
38
  import layout from './utils/layout';
38
39
  import schema from './utils/schema';
39
40
 
40
41
  const ProtectedAdvancedSettingsPage = () => (
41
- <CheckPagePermissions permissions={pluginPermissions.readAdvancedSettings}>
42
+ <CheckPagePermissions permissions={PERMISSIONS.readAdvancedSettings}>
42
43
  <AdvancedSettingsPage />
43
44
  </CheckPagePermissions>
44
45
  );
@@ -49,39 +50,47 @@ const AdvancedSettingsPage = () => {
49
50
  const { lockApp, unlockApp } = useOverlayBlocker();
50
51
  const { notifyStatus } = useNotifyAT();
51
52
  const queryClient = useQueryClient();
53
+ const { get, put } = useFetchClient();
54
+ const { formatAPIError } = useAPIErrorHandler();
55
+
52
56
  useFocusWhenNavigate();
53
57
 
54
- const updatePermissions = useMemo(
55
- () => ({ update: pluginPermissions.updateAdvancedSettings }),
56
- []
57
- );
58
58
  const {
59
59
  isLoading: isLoadingForPermissions,
60
60
  allowedActions: { canUpdate },
61
- } = useRBAC(updatePermissions);
62
-
63
- const { status: isLoadingData, data } = useQuery('advanced', () => fetchData(), {
64
- onSuccess() {
65
- notifyStatus(
66
- formatMessage({
67
- id: getTrad('Form.advancedSettings.data.loaded'),
68
- defaultMessage: 'Advanced settings data has been loaded',
69
- })
70
- );
71
- },
72
- onError() {
73
- toggleNotification({
74
- type: 'warning',
75
- message: { id: getTrad('notification.error'), defaultMessage: 'An error occured' },
76
- });
61
+ } = useRBAC({ update: PERMISSIONS.updateAdvancedSettings });
62
+
63
+ const { isLoading: isLoadingData, data } = useQuery(
64
+ ['users-permissions', 'advanced'],
65
+ async () => {
66
+ const { data } = await get('/users-permissions/advanced');
67
+
68
+ return data;
77
69
  },
78
- });
70
+ {
71
+ onSuccess() {
72
+ notifyStatus(
73
+ formatMessage({
74
+ id: getTrad('Form.advancedSettings.data.loaded'),
75
+ defaultMessage: 'Advanced settings data has been loaded',
76
+ })
77
+ );
78
+ },
79
+ onError() {
80
+ toggleNotification({
81
+ type: 'warning',
82
+ message: { id: getTrad('notification.error'), defaultMessage: 'An error occured' },
83
+ });
84
+ },
85
+ }
86
+ );
79
87
 
80
- const isLoading = isLoadingForPermissions || isLoadingData !== 'success';
88
+ const isLoading = isLoadingForPermissions || isLoadingData;
81
89
 
82
- const submitMutation = useMutation((body) => putAdvancedSettings(body), {
90
+ const submitMutation = useMutation((body) => put('/users-permissions/advanced', body), {
83
91
  async onSuccess() {
84
- await queryClient.invalidateQueries('advanced');
92
+ await queryClient.invalidateQueries(['users-permissions', 'advanced']);
93
+
85
94
  toggleNotification({
86
95
  type: 'success',
87
96
  message: { id: getTrad('notification.success.saved'), defaultMessage: 'Saved' },
@@ -89,11 +98,12 @@ const AdvancedSettingsPage = () => {
89
98
 
90
99
  unlockApp();
91
100
  },
92
- onError() {
101
+ onError(error) {
93
102
  toggleNotification({
94
103
  type: 'warning',
95
- message: { id: getTrad('notification.error'), defaultMessage: 'An error occured' },
104
+ message: formatAPIError(error),
96
105
  });
106
+
97
107
  unlockApp();
98
108
  },
99
109
  refetchActive: true,
@@ -104,9 +114,12 @@ const AdvancedSettingsPage = () => {
104
114
  const handleSubmit = async (body) => {
105
115
  lockApp();
106
116
 
107
- const urlConfirmation = body.email_confirmation ? body.email_confirmation_redirection : '';
108
-
109
- await submitMutation.mutateAsync({ ...body, email_confirmation_redirection: urlConfirmation });
117
+ submitMutation.mutate({
118
+ ...body,
119
+ email_confirmation_redirection: body.email_confirmation
120
+ ? body.email_confirmation_redirection
121
+ : '',
122
+ });
110
123
  };
111
124
 
112
125
  if (isLoading) {
@@ -146,7 +159,7 @@ const AdvancedSettingsPage = () => {
146
159
  validationSchema={schema}
147
160
  enableReinitialize
148
161
  >
149
- {({ errors, values, handleChange, isSubmitting }) => {
162
+ {({ errors, values, handleChange, isSubmitting, dirty }) => {
150
163
  return (
151
164
  <Form>
152
165
  <HeaderLayout
@@ -158,7 +171,7 @@ const AdvancedSettingsPage = () => {
158
171
  <Button
159
172
  loading={isSubmitting}
160
173
  type="submit"
161
- disabled={!canUpdate}
174
+ disabled={canUpdate ? !dirty : !canUpdate}
162
175
  startIcon={<Check />}
163
176
  size="S"
164
177
  >
@@ -1,10 +1,12 @@
1
- import React, { useMemo, useRef, useState } from 'react';
1
+ import * as React from 'react';
2
2
 
3
3
  import { ContentLayout, HeaderLayout, Main, useNotifyAT } from '@strapi/design-system';
4
4
  import {
5
5
  CheckPagePermissions,
6
6
  LoadingIndicatorPage,
7
7
  SettingsPageTitle,
8
+ useAPIErrorHandler,
9
+ useFetchClient,
8
10
  useFocusWhenNavigate,
9
11
  useNotification,
10
12
  useOverlayBlocker,
@@ -14,15 +16,14 @@ import {
14
16
  import { useIntl } from 'react-intl';
15
17
  import { useMutation, useQuery, useQueryClient } from 'react-query';
16
18
 
17
- import pluginPermissions from '../../permissions';
19
+ import { PERMISSIONS } from '../../constants';
18
20
  import { getTrad } from '../../utils';
19
21
 
20
22
  import EmailForm from './components/EmailForm';
21
23
  import EmailTable from './components/EmailTable';
22
- import { fetchData, putEmailTemplate } from './utils/api';
23
24
 
24
25
  const ProtectedEmailTemplatesPage = () => (
25
- <CheckPagePermissions permissions={pluginPermissions.readEmailTemplates}>
26
+ <CheckPagePermissions permissions={PERMISSIONS.readEmailTemplates}>
26
27
  <EmailTemplatesPage />
27
28
  </CheckPagePermissions>
28
29
  );
@@ -33,40 +34,46 @@ const EmailTemplatesPage = () => {
33
34
  const { notifyStatus } = useNotifyAT();
34
35
  const toggleNotification = useNotification();
35
36
  const { lockApp, unlockApp } = useOverlayBlocker();
36
- const trackUsageRef = useRef(trackUsage);
37
37
  const queryClient = useQueryClient();
38
- useFocusWhenNavigate();
38
+ const { get, put } = useFetchClient();
39
+ const { formatAPIError } = useAPIErrorHandler();
39
40
 
40
- const [isModalOpen, setIsModalOpen] = useState(false);
41
- const [templateToEdit, setTemplateToEdit] = useState(null);
41
+ useFocusWhenNavigate();
42
42
 
43
- const updatePermissions = useMemo(() => {
44
- return { update: pluginPermissions.updateEmailTemplates };
45
- }, []);
43
+ const [isModalOpen, setIsModalOpen] = React.useState(false);
44
+ const [templateToEdit, setTemplateToEdit] = React.useState(null);
46
45
 
47
46
  const {
48
47
  isLoading: isLoadingForPermissions,
49
48
  allowedActions: { canUpdate },
50
- } = useRBAC(updatePermissions);
51
-
52
- const { status: isLoadingData, data } = useQuery('email-templates', () => fetchData(), {
53
- onSuccess() {
54
- notifyStatus(
55
- formatMessage({
56
- id: getTrad('Email.template.data.loaded'),
57
- defaultMessage: 'Email templates has been loaded',
58
- })
59
- );
60
- },
61
- onError() {
62
- toggleNotification({
63
- type: 'warning',
64
- message: { id: 'notification.error', defaultMessage: 'An error occured' },
65
- });
49
+ } = useRBAC({ update: PERMISSIONS.updateEmailTemplates });
50
+
51
+ const { isLoading: isLoadingData, data } = useQuery(
52
+ ['users-permissions', 'email-templates'],
53
+ async () => {
54
+ const { data } = await get('/users-permissions/email-templates');
55
+
56
+ return data;
66
57
  },
67
- });
58
+ {
59
+ onSuccess() {
60
+ notifyStatus(
61
+ formatMessage({
62
+ id: getTrad('Email.template.data.loaded'),
63
+ defaultMessage: 'Email templates has been loaded',
64
+ })
65
+ );
66
+ },
67
+ onError(error) {
68
+ toggleNotification({
69
+ type: 'warning',
70
+ message: formatAPIError(error),
71
+ });
72
+ },
73
+ }
74
+ );
68
75
 
69
- const isLoading = isLoadingForPermissions || isLoadingData !== 'success';
76
+ const isLoading = isLoadingForPermissions || isLoadingData;
70
77
 
71
78
  const handleToggle = () => {
72
79
  setIsModalOpen((prev) => !prev);
@@ -77,34 +84,38 @@ const EmailTemplatesPage = () => {
77
84
  handleToggle();
78
85
  };
79
86
 
80
- const submitMutation = useMutation((body) => putEmailTemplate({ 'email-templates': body }), {
81
- async onSuccess() {
82
- await queryClient.invalidateQueries('email-templates');
83
-
84
- toggleNotification({
85
- type: 'success',
86
- message: { id: 'notification.success.saved', defaultMessage: 'Saved' },
87
- });
88
-
89
- trackUsageRef.current('didEditEmailTemplates');
90
-
91
- unlockApp();
92
- handleToggle();
93
- },
94
- onError() {
95
- toggleNotification({
96
- type: 'warning',
97
- message: { id: 'notification.error', defaultMessage: 'An error occured' },
98
- });
99
- unlockApp();
100
- },
101
- refetchActive: true,
102
- });
103
- const { isLoading: isSubmittingForm } = submitMutation;
87
+ const submitMutation = useMutation(
88
+ (body) => put('/users-permissions/email-templates', { 'email-templates': body }),
89
+ {
90
+ async onSuccess() {
91
+ await queryClient.invalidateQueries(['users-permissions', 'email-templates']);
92
+
93
+ toggleNotification({
94
+ type: 'success',
95
+ message: { id: 'notification.success.saved', defaultMessage: 'Saved' },
96
+ });
97
+
98
+ trackUsage('didEditEmailTemplates');
99
+
100
+ unlockApp();
101
+ handleToggle();
102
+ },
103
+ onError(error) {
104
+ toggleNotification({
105
+ type: 'warning',
106
+ message: formatAPIError(error),
107
+ });
108
+
109
+ unlockApp();
110
+ },
111
+ refetchActive: true,
112
+ }
113
+ );
104
114
 
105
115
  const handleSubmit = (body) => {
106
116
  lockApp();
107
- trackUsageRef.current('willEditEmailTemplates');
117
+
118
+ trackUsage('willEditEmailTemplates');
108
119
 
109
120
  const editedTemplates = { ...data, [templateToEdit]: body };
110
121
  submitMutation.mutate(editedTemplates);
@@ -133,7 +144,7 @@ const EmailTemplatesPage = () => {
133
144
  }
134
145
 
135
146
  return (
136
- <Main aria-busy={isSubmittingForm}>
147
+ <Main aria-busy={submitMutation.isLoading}>
137
148
  <SettingsPageTitle
138
149
  name={formatMessage({
139
150
  id: getTrad('HeaderNav.link.emailTemplates'),