@strapi/plugin-users-permissions 4.12.7 → 4.13.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/admin/src/components/Permissions/index.js +2 -4
- package/admin/src/index.js +7 -8
- package/admin/src/pages/AdvancedSettings/index.js +41 -24
- package/admin/src/pages/EmailTemplates/index.js +62 -47
- package/admin/src/pages/Providers/index.js +64 -58
- package/admin/src/{hooks → pages/Roles/hooks}/usePlugins.js +15 -8
- package/admin/src/pages/Roles/index.js +10 -7
- package/admin/src/pages/Roles/pages/CreatePage.js +190 -0
- package/admin/src/pages/Roles/pages/EditPage.js +211 -0
- package/admin/src/pages/Roles/{ListPage → pages/ListPage}/components/TableBody.js +41 -11
- package/admin/src/pages/Roles/{ListPage → pages/ListPage}/index.js +19 -15
- package/jest.config.front.js +1 -1
- package/package.json +4 -4
- package/server/bootstrap/index.js +35 -0
- package/server/controllers/auth.js +46 -13
- package/server/controllers/user.js +12 -1
- package/admin/src/hooks/index.js +0 -5
- package/admin/src/hooks/useFetchRole/index.js +0 -67
- package/admin/src/hooks/useFetchRole/reducer.js +0 -31
- package/admin/src/hooks/useForm/index.js +0 -68
- package/admin/src/hooks/useForm/reducer.js +0 -40
- package/admin/src/hooks/useRolesList/index.js +0 -65
- package/admin/src/hooks/useRolesList/init.js +0 -5
- package/admin/src/hooks/useRolesList/reducer.js +0 -31
- package/admin/src/pages/AdvancedSettings/utils/api.js +0 -16
- package/admin/src/pages/EmailTemplates/utils/api.js +0 -16
- package/admin/src/pages/Providers/reducer.js +0 -54
- package/admin/src/pages/Providers/utils/api.js +0 -24
- package/admin/src/pages/Providers/utils/createProvidersArray.js +0 -21
- package/admin/src/pages/Roles/CreatePage.js +0 -185
- package/admin/src/pages/Roles/EditPage.js +0 -197
- package/admin/src/pages/Roles/ProtectedCreatePage.js +0 -15
- package/admin/src/pages/Roles/ProtectedEditPage.js +0 -15
- package/admin/src/pages/Roles/ProtectedListPage.js +0 -17
- /package/admin/src/pages/Roles/{ListPage → pages/ListPage}/utils/api.js +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, { useReducer } from 'react';
|
|
2
2
|
|
|
3
|
-
import { Accordion, AccordionContent, AccordionToggle,
|
|
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
|
-
<
|
|
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
|
))}
|
package/admin/src/index.js
CHANGED
|
@@ -9,7 +9,6 @@ import { prefixPluginTranslations } from '@strapi/helper-plugin';
|
|
|
9
9
|
import pluginPkg from '../../package.json';
|
|
10
10
|
|
|
11
11
|
import { PERMISSIONS } from './constants';
|
|
12
|
-
import pluginId from './pluginId';
|
|
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:
|
|
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
|
|
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'
|
|
@@ -48,7 +47,7 @@ export default {
|
|
|
48
47
|
defaultMessage: 'Providers',
|
|
49
48
|
},
|
|
50
49
|
id: 'providers',
|
|
51
|
-
to: `/settings
|
|
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'
|
|
@@ -64,7 +63,7 @@ export default {
|
|
|
64
63
|
defaultMessage: 'Email templates',
|
|
65
64
|
},
|
|
66
65
|
id: 'email-templates',
|
|
67
|
-
to: `/settings
|
|
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'
|
|
@@ -80,7 +79,7 @@ export default {
|
|
|
80
79
|
defaultMessage: 'Advanced Settings',
|
|
81
80
|
},
|
|
82
81
|
id: 'advanced-settings',
|
|
83
|
-
to: `/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'
|
|
@@ -94,7 +93,7 @@ export default {
|
|
|
94
93
|
);
|
|
95
94
|
|
|
96
95
|
app.registerPlugin({
|
|
97
|
-
id:
|
|
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,
|
|
109
|
+
data: prefixPluginTranslations(data, 'users-permissions'),
|
|
111
110
|
locale,
|
|
112
111
|
};
|
|
113
112
|
})
|
|
@@ -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,
|
|
@@ -33,7 +35,6 @@ import { useMutation, useQuery, useQueryClient } from 'react-query';
|
|
|
33
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
|
|
|
@@ -49,6 +50,9 @@ 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
58
|
const {
|
|
@@ -56,28 +60,37 @@ const AdvancedSettingsPage = () => {
|
|
|
56
60
|
allowedActions: { canUpdate },
|
|
57
61
|
} = useRBAC({ update: PERMISSIONS.updateAdvancedSettings });
|
|
58
62
|
|
|
59
|
-
const {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
})
|
|
66
|
-
);
|
|
67
|
-
},
|
|
68
|
-
onError() {
|
|
69
|
-
toggleNotification({
|
|
70
|
-
type: 'warning',
|
|
71
|
-
message: { id: getTrad('notification.error'), defaultMessage: 'An error occured' },
|
|
72
|
-
});
|
|
63
|
+
const { isLoading: isLoadingData, data } = useQuery(
|
|
64
|
+
['users-permissions', 'advanced'],
|
|
65
|
+
async () => {
|
|
66
|
+
const { data } = await get('/users-permissions/advanced');
|
|
67
|
+
|
|
68
|
+
return data;
|
|
73
69
|
},
|
|
74
|
-
|
|
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
|
+
);
|
|
75
87
|
|
|
76
|
-
const isLoading = isLoadingForPermissions || isLoadingData
|
|
88
|
+
const isLoading = isLoadingForPermissions || isLoadingData;
|
|
77
89
|
|
|
78
|
-
const submitMutation = useMutation((body) =>
|
|
90
|
+
const submitMutation = useMutation((body) => put('/users-permissions/advanced', body), {
|
|
79
91
|
async onSuccess() {
|
|
80
|
-
await queryClient.invalidateQueries('advanced');
|
|
92
|
+
await queryClient.invalidateQueries(['users-permissions', 'advanced']);
|
|
93
|
+
|
|
81
94
|
toggleNotification({
|
|
82
95
|
type: 'success',
|
|
83
96
|
message: { id: getTrad('notification.success.saved'), defaultMessage: 'Saved' },
|
|
@@ -85,11 +98,12 @@ const AdvancedSettingsPage = () => {
|
|
|
85
98
|
|
|
86
99
|
unlockApp();
|
|
87
100
|
},
|
|
88
|
-
onError() {
|
|
101
|
+
onError(error) {
|
|
89
102
|
toggleNotification({
|
|
90
103
|
type: 'warning',
|
|
91
|
-
message:
|
|
104
|
+
message: formatAPIError(error),
|
|
92
105
|
});
|
|
106
|
+
|
|
93
107
|
unlockApp();
|
|
94
108
|
},
|
|
95
109
|
refetchActive: true,
|
|
@@ -100,9 +114,12 @@ const AdvancedSettingsPage = () => {
|
|
|
100
114
|
const handleSubmit = async (body) => {
|
|
101
115
|
lockApp();
|
|
102
116
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
117
|
+
submitMutation.mutate({
|
|
118
|
+
...body,
|
|
119
|
+
email_confirmation_redirection: body.email_confirmation
|
|
120
|
+
? body.email_confirmation_redirection
|
|
121
|
+
: '',
|
|
122
|
+
});
|
|
106
123
|
};
|
|
107
124
|
|
|
108
125
|
if (isLoading) {
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
import
|
|
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,
|
|
@@ -19,7 +21,6 @@ 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
26
|
<CheckPagePermissions permissions={PERMISSIONS.readEmailTemplates}>
|
|
@@ -33,36 +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
|
+
const { get, put } = useFetchClient();
|
|
39
|
+
const { formatAPIError } = useAPIErrorHandler();
|
|
40
|
+
|
|
38
41
|
useFocusWhenNavigate();
|
|
39
42
|
|
|
40
|
-
const [isModalOpen, setIsModalOpen] = useState(false);
|
|
41
|
-
const [templateToEdit, setTemplateToEdit] = useState(null);
|
|
43
|
+
const [isModalOpen, setIsModalOpen] = React.useState(false);
|
|
44
|
+
const [templateToEdit, setTemplateToEdit] = React.useState(null);
|
|
42
45
|
|
|
43
46
|
const {
|
|
44
47
|
isLoading: isLoadingForPermissions,
|
|
45
48
|
allowedActions: { canUpdate },
|
|
46
49
|
} = useRBAC({ update: PERMISSIONS.updateEmailTemplates });
|
|
47
50
|
|
|
48
|
-
const {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
})
|
|
55
|
-
);
|
|
56
|
-
},
|
|
57
|
-
onError() {
|
|
58
|
-
toggleNotification({
|
|
59
|
-
type: 'warning',
|
|
60
|
-
message: { id: 'notification.error', defaultMessage: 'An error occured' },
|
|
61
|
-
});
|
|
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;
|
|
62
57
|
},
|
|
63
|
-
|
|
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
|
+
);
|
|
64
75
|
|
|
65
|
-
const isLoading = isLoadingForPermissions || isLoadingData
|
|
76
|
+
const isLoading = isLoadingForPermissions || isLoadingData;
|
|
66
77
|
|
|
67
78
|
const handleToggle = () => {
|
|
68
79
|
setIsModalOpen((prev) => !prev);
|
|
@@ -73,34 +84,38 @@ const EmailTemplatesPage = () => {
|
|
|
73
84
|
handleToggle();
|
|
74
85
|
};
|
|
75
86
|
|
|
76
|
-
const submitMutation = useMutation(
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
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
|
+
);
|
|
100
114
|
|
|
101
115
|
const handleSubmit = (body) => {
|
|
102
116
|
lockApp();
|
|
103
|
-
|
|
117
|
+
|
|
118
|
+
trackUsage('willEditEmailTemplates');
|
|
104
119
|
|
|
105
120
|
const editedTemplates = { ...data, [templateToEdit]: body };
|
|
106
121
|
submitMutation.mutate(editedTemplates);
|
|
@@ -129,7 +144,7 @@ const EmailTemplatesPage = () => {
|
|
|
129
144
|
}
|
|
130
145
|
|
|
131
146
|
return (
|
|
132
|
-
<Main aria-busy={
|
|
147
|
+
<Main aria-busy={submitMutation.isLoading}>
|
|
133
148
|
<SettingsPageTitle
|
|
134
149
|
name={formatMessage({
|
|
135
150
|
id: getTrad('HeaderNav.link.emailTemplates'),
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as React from 'react';
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
4
|
ContentLayout,
|
|
@@ -13,7 +13,6 @@ import {
|
|
|
13
13
|
Thead,
|
|
14
14
|
Tr,
|
|
15
15
|
Typography,
|
|
16
|
-
useNotifyAT,
|
|
17
16
|
VisuallyHidden,
|
|
18
17
|
} from '@strapi/design-system';
|
|
19
18
|
import {
|
|
@@ -22,6 +21,9 @@ import {
|
|
|
22
21
|
onRowClick,
|
|
23
22
|
SettingsPageTitle,
|
|
24
23
|
stopPropagation,
|
|
24
|
+
useAPIErrorHandler,
|
|
25
|
+
useCollator,
|
|
26
|
+
useFetchClient,
|
|
25
27
|
useFocusWhenNavigate,
|
|
26
28
|
useNotification,
|
|
27
29
|
useOverlayBlocker,
|
|
@@ -29,7 +31,6 @@ import {
|
|
|
29
31
|
useTracking,
|
|
30
32
|
} from '@strapi/helper-plugin';
|
|
31
33
|
import { Pencil } from '@strapi/icons';
|
|
32
|
-
import has from 'lodash/has';
|
|
33
34
|
import upperFirst from 'lodash/upperFirst';
|
|
34
35
|
import { useIntl } from 'react-intl';
|
|
35
36
|
import { useMutation, useQuery, useQueryClient } from 'react-query';
|
|
@@ -38,90 +39,94 @@ import FormModal from '../../components/FormModal';
|
|
|
38
39
|
import { PERMISSIONS } from '../../constants';
|
|
39
40
|
import { getTrad } from '../../utils';
|
|
40
41
|
|
|
41
|
-
import { fetchData, putProvider } from './utils/api';
|
|
42
|
-
import createProvidersArray from './utils/createProvidersArray';
|
|
43
42
|
import forms from './utils/forms';
|
|
44
43
|
|
|
45
44
|
export const ProvidersPage = () => {
|
|
46
|
-
const { formatMessage } = useIntl();
|
|
47
|
-
useFocusWhenNavigate();
|
|
48
|
-
const { notifyStatus } = useNotifyAT();
|
|
45
|
+
const { formatMessage, locale } = useIntl();
|
|
49
46
|
const queryClient = useQueryClient();
|
|
50
47
|
const { trackUsage } = useTracking();
|
|
51
|
-
const
|
|
52
|
-
const [
|
|
53
|
-
const [isSubmiting, setIsSubmiting] = useState(false);
|
|
54
|
-
const [providerToEditName, setProviderToEditName] = useState(null);
|
|
48
|
+
const [isOpen, setIsOpen] = React.useState(false);
|
|
49
|
+
const [providerToEditName, setProviderToEditName] = React.useState(null);
|
|
55
50
|
const toggleNotification = useNotification();
|
|
56
51
|
const { lockApp, unlockApp } = useOverlayBlocker();
|
|
52
|
+
const { get, put } = useFetchClient();
|
|
53
|
+
const { formatAPIError } = useAPIErrorHandler();
|
|
54
|
+
const formatter = useCollator(locale, {
|
|
55
|
+
sensitivity: 'base',
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
useFocusWhenNavigate();
|
|
57
59
|
|
|
58
60
|
const {
|
|
59
|
-
isLoading:
|
|
61
|
+
isLoading: isLoadingPermissions,
|
|
60
62
|
allowedActions: { canUpdate },
|
|
61
63
|
} = useRBAC({ update: PERMISSIONS.updateProviders });
|
|
62
64
|
|
|
63
|
-
const {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
} = useQuery('get-providers', () => fetchData(toggleNotification), {
|
|
68
|
-
onSuccess() {
|
|
69
|
-
notifyStatus(
|
|
70
|
-
formatMessage({
|
|
71
|
-
id: getTrad('Providers.data.loaded'),
|
|
72
|
-
defaultMessage: 'Providers have been loaded',
|
|
73
|
-
})
|
|
74
|
-
);
|
|
75
|
-
},
|
|
76
|
-
initialData: {},
|
|
77
|
-
});
|
|
65
|
+
const { isLoading: isLoadingData, data } = useQuery(
|
|
66
|
+
['users-permissions', 'get-providers'],
|
|
67
|
+
async () => {
|
|
68
|
+
const { data } = await get('/users-permissions/providers');
|
|
78
69
|
|
|
79
|
-
|
|
70
|
+
return data;
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
initialData: {},
|
|
74
|
+
}
|
|
75
|
+
);
|
|
80
76
|
|
|
81
|
-
const submitMutation = useMutation(
|
|
77
|
+
const submitMutation = useMutation((body) => put('/users-permissions/providers', body), {
|
|
82
78
|
async onSuccess() {
|
|
83
|
-
await queryClient.invalidateQueries('
|
|
79
|
+
await queryClient.invalidateQueries(['users-permissions', 'providers']);
|
|
80
|
+
|
|
84
81
|
toggleNotification({
|
|
85
|
-
type: '
|
|
82
|
+
type: 'success',
|
|
86
83
|
message: { id: getTrad('notification.success.submit') },
|
|
87
84
|
});
|
|
88
85
|
|
|
89
|
-
|
|
90
|
-
|
|
86
|
+
trackUsage('didEditAuthenticationProvider');
|
|
87
|
+
|
|
91
88
|
handleToggleModal();
|
|
92
89
|
unlockApp();
|
|
93
90
|
},
|
|
94
|
-
onError() {
|
|
91
|
+
onError(error) {
|
|
95
92
|
toggleNotification({
|
|
96
93
|
type: 'warning',
|
|
97
|
-
message:
|
|
94
|
+
message: formatAPIError(error),
|
|
98
95
|
});
|
|
96
|
+
|
|
99
97
|
unlockApp();
|
|
100
|
-
setIsSubmiting(false);
|
|
101
98
|
},
|
|
102
99
|
refetchActive: false,
|
|
103
100
|
});
|
|
104
101
|
|
|
105
|
-
const providers =
|
|
102
|
+
const providers = Object.entries(data)
|
|
103
|
+
.reduce((acc, [name, provider]) => {
|
|
104
|
+
const { icon, enabled, subdomain } = provider;
|
|
105
|
+
|
|
106
|
+
acc.push({
|
|
107
|
+
name,
|
|
108
|
+
icon: icon === 'envelope' ? ['fas', 'envelope'] : ['fab', icon],
|
|
109
|
+
enabled,
|
|
110
|
+
subdomain,
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
return acc;
|
|
114
|
+
}, [])
|
|
115
|
+
.sort((a, b) => formatter.compare(a.name, b.name));
|
|
106
116
|
|
|
107
|
-
const
|
|
117
|
+
const isLoading = isLoadingData || isLoadingPermissions;
|
|
108
118
|
|
|
109
|
-
const isProviderWithSubdomain = useMemo(() => {
|
|
119
|
+
const isProviderWithSubdomain = React.useMemo(() => {
|
|
110
120
|
if (!providerToEditName) {
|
|
111
121
|
return false;
|
|
112
122
|
}
|
|
113
123
|
|
|
114
124
|
const providerToEdit = providers.find((obj) => obj.name === providerToEditName);
|
|
115
125
|
|
|
116
|
-
return
|
|
126
|
+
return !!providerToEdit?.subdomain;
|
|
117
127
|
}, [providers, providerToEditName]);
|
|
118
128
|
|
|
119
|
-
const
|
|
120
|
-
id: getTrad('HeaderNav.link.providers'),
|
|
121
|
-
defaultMessage: 'Providers',
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
const layoutToRender = useMemo(() => {
|
|
129
|
+
const layoutToRender = React.useMemo(() => {
|
|
125
130
|
if (providerToEditName === 'email') {
|
|
126
131
|
return forms.email;
|
|
127
132
|
}
|
|
@@ -145,20 +150,21 @@ export const ProvidersPage = () => {
|
|
|
145
150
|
};
|
|
146
151
|
|
|
147
152
|
const handleSubmit = async (values) => {
|
|
148
|
-
setIsSubmiting(true);
|
|
149
|
-
|
|
150
153
|
lockApp();
|
|
151
154
|
|
|
152
|
-
|
|
155
|
+
trackUsage('willEditAuthenticationProvider');
|
|
153
156
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
submitMutation.mutate({ providers: body });
|
|
157
|
+
submitMutation.mutate({ providers: { ...data, [providerToEditName]: values } });
|
|
157
158
|
};
|
|
158
159
|
|
|
159
160
|
return (
|
|
160
161
|
<Layout>
|
|
161
|
-
<SettingsPageTitle
|
|
162
|
+
<SettingsPageTitle
|
|
163
|
+
name={formatMessage({
|
|
164
|
+
id: getTrad('HeaderNav.link.providers'),
|
|
165
|
+
defaultMessage: 'Providers',
|
|
166
|
+
})}
|
|
167
|
+
/>
|
|
162
168
|
<Main>
|
|
163
169
|
<HeaderLayout
|
|
164
170
|
title={formatMessage({
|
|
@@ -166,11 +172,11 @@ export const ProvidersPage = () => {
|
|
|
166
172
|
defaultMessage: 'Providers',
|
|
167
173
|
})}
|
|
168
174
|
/>
|
|
169
|
-
{isLoading
|
|
175
|
+
{isLoading ? (
|
|
170
176
|
<LoadingIndicatorPage />
|
|
171
177
|
) : (
|
|
172
178
|
<ContentLayout>
|
|
173
|
-
<Table colCount={3} rowCount={
|
|
179
|
+
<Table colCount={3} rowCount={providers.length + 1}>
|
|
174
180
|
<Thead>
|
|
175
181
|
<Tr>
|
|
176
182
|
<Th>
|
|
@@ -243,9 +249,9 @@ export const ProvidersPage = () => {
|
|
|
243
249
|
)}
|
|
244
250
|
</Main>
|
|
245
251
|
<FormModal
|
|
246
|
-
initialData={
|
|
252
|
+
initialData={data[providerToEditName]}
|
|
247
253
|
isOpen={isOpen}
|
|
248
|
-
isSubmiting={
|
|
254
|
+
isSubmiting={submitMutation.isLoading}
|
|
249
255
|
layout={layoutToRender}
|
|
250
256
|
headerBreadcrumbs={[
|
|
251
257
|
formatMessage({
|
|
@@ -3,8 +3,7 @@ import { useEffect } from 'react';
|
|
|
3
3
|
import { useNotification, useFetchClient, useAPIErrorHandler } from '@strapi/helper-plugin';
|
|
4
4
|
import { useQueries } from 'react-query';
|
|
5
5
|
|
|
6
|
-
import
|
|
7
|
-
import { cleanPermissions, getTrad } from '../utils';
|
|
6
|
+
import { cleanPermissions, getTrad } from '../../../utils';
|
|
8
7
|
|
|
9
8
|
export const usePlugins = () => {
|
|
10
9
|
const toggleNotification = useNotification();
|
|
@@ -21,19 +20,23 @@ export const usePlugins = () => {
|
|
|
21
20
|
{ data: routes, isLoading: isLoadingRoutes, error: routesError, refetch: refetchRoutes },
|
|
22
21
|
] = useQueries([
|
|
23
22
|
{
|
|
24
|
-
queryKey: [
|
|
23
|
+
queryKey: ['users-permissions', 'permissions'],
|
|
25
24
|
async queryFn() {
|
|
26
|
-
const
|
|
25
|
+
const {
|
|
26
|
+
data: { permissions },
|
|
27
|
+
} = await get(`/users-permissions/permissions`);
|
|
27
28
|
|
|
28
|
-
return
|
|
29
|
+
return permissions;
|
|
29
30
|
},
|
|
30
31
|
},
|
|
31
32
|
{
|
|
32
|
-
queryKey: [
|
|
33
|
+
queryKey: ['users-permissions', 'routes'],
|
|
33
34
|
async queryFn() {
|
|
34
|
-
const
|
|
35
|
+
const {
|
|
36
|
+
data: { routes },
|
|
37
|
+
} = await get(`/users-permissions/routes`);
|
|
35
38
|
|
|
36
|
-
return
|
|
39
|
+
return routes;
|
|
37
40
|
},
|
|
38
41
|
},
|
|
39
42
|
]);
|
|
@@ -63,8 +66,12 @@ export const usePlugins = () => {
|
|
|
63
66
|
const isLoading = isLoadingPermissions || isLoadingRoutes;
|
|
64
67
|
|
|
65
68
|
return {
|
|
69
|
+
// TODO: these return values need to be memoized, otherwise
|
|
70
|
+
// they will create infinite rendering loops when used as
|
|
71
|
+
// effect dependencies
|
|
66
72
|
permissions: permissions ? cleanPermissions(permissions) : {},
|
|
67
73
|
routes: routes ?? {},
|
|
74
|
+
|
|
68
75
|
getData: refetchQueries,
|
|
69
76
|
isLoading,
|
|
70
77
|
};
|
|
@@ -4,23 +4,26 @@ import { AnErrorOccurred, CheckPagePermissions } from '@strapi/helper-plugin';
|
|
|
4
4
|
import { Route, Switch } from 'react-router-dom';
|
|
5
5
|
|
|
6
6
|
import { PERMISSIONS } from '../../constants';
|
|
7
|
-
import pluginId from '../../pluginId';
|
|
8
7
|
|
|
9
|
-
import ProtectedRolesCreatePage from './
|
|
10
|
-
import ProtectedRolesEditPage from './
|
|
11
|
-
import ProtectedRolesListPage from './
|
|
8
|
+
import { ProtectedRolesCreatePage } from './pages/CreatePage';
|
|
9
|
+
import { ProtectedRolesEditPage } from './pages/EditPage';
|
|
10
|
+
import { ProtectedRolesListPage } from './pages/ListPage';
|
|
12
11
|
|
|
13
12
|
const Roles = () => {
|
|
14
13
|
return (
|
|
15
14
|
<CheckPagePermissions permissions={PERMISSIONS.accessRoles}>
|
|
16
15
|
<Switch>
|
|
17
16
|
<Route
|
|
18
|
-
path=
|
|
17
|
+
path="/settings/users-permissions/roles/new"
|
|
19
18
|
component={ProtectedRolesCreatePage}
|
|
20
19
|
exact
|
|
21
20
|
/>
|
|
22
|
-
<Route
|
|
23
|
-
|
|
21
|
+
<Route
|
|
22
|
+
path="/settings/users-permissions/roles/:id"
|
|
23
|
+
component={ProtectedRolesEditPage}
|
|
24
|
+
exact
|
|
25
|
+
/>
|
|
26
|
+
<Route path="/settings/users-permissions/roles" component={ProtectedRolesListPage} exact />
|
|
24
27
|
<Route path="" component={AnErrorOccurred} />
|
|
25
28
|
</Switch>
|
|
26
29
|
</CheckPagePermissions>
|