@strapi/plugin-users-permissions 4.20.5 → 5.0.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.
- package/admin/src/components/FormModal/index.jsx +1 -2
- package/admin/src/components/Permissions/reducer.js +1 -1
- package/admin/src/components/UsersPermissions/reducer.js +1 -1
- package/admin/src/index.js +14 -30
- package/admin/src/pages/AdvancedSettings/index.jsx +69 -107
- package/admin/src/pages/AdvancedSettings/utils/layout.js +20 -35
- package/admin/src/pages/AdvancedSettings/utils/schema.js +5 -2
- package/admin/src/pages/EmailTemplates/components/EmailForm.jsx +47 -74
- package/admin/src/pages/EmailTemplates/index.jsx +22 -50
- package/admin/src/pages/EmailTemplates/utils/schema.js +18 -6
- package/admin/src/pages/Providers/index.jsx +91 -96
- package/admin/src/pages/Providers/utils/forms.js +11 -11
- package/admin/src/pages/Roles/constants.js +3 -3
- package/admin/src/pages/Roles/hooks/usePlugins.js +5 -4
- package/admin/src/pages/Roles/index.jsx +9 -18
- package/admin/src/pages/Roles/pages/CreatePage.jsx +21 -28
- package/admin/src/pages/Roles/pages/EditPage.jsx +23 -40
- package/admin/src/pages/Roles/pages/ListPage/components/TableBody.jsx +23 -27
- package/admin/src/pages/Roles/pages/ListPage/index.jsx +42 -38
- package/admin/src/pages/Roles/pages/ListPage/utils/api.js +6 -6
- package/admin/src/translations/en.json +1 -1
- package/dist/_chunks/EditViewPage-xYzUSAwS-5mOQ_-nB.mjs +84370 -0
- package/dist/_chunks/EditViewPage-xYzUSAwS-5mOQ_-nB.mjs.map +1 -0
- package/dist/_chunks/EditViewPage-xYzUSAwS-wpHlxdkC.js +84398 -0
- package/dist/_chunks/EditViewPage-xYzUSAwS-wpHlxdkC.js.map +1 -0
- package/dist/_chunks/Helmet-d9JljxUo.js +1010 -0
- package/dist/_chunks/Helmet-d9JljxUo.js.map +1 -0
- package/dist/_chunks/Helmet-kyJ1Zklj.mjs +1008 -0
- package/dist/_chunks/Helmet-kyJ1Zklj.mjs.map +1 -0
- package/dist/_chunks/ListViewPage-xOVa04T_-elahT0e9.js +1618 -0
- package/dist/_chunks/ListViewPage-xOVa04T_-elahT0e9.js.map +1 -0
- package/dist/_chunks/ListViewPage-xOVa04T_-lbfb219V.mjs +1595 -0
- package/dist/_chunks/ListViewPage-xOVa04T_-lbfb219V.mjs.map +1 -0
- package/dist/_chunks/ReviewWorkflowsColumn-FDxVKdto-IWfB3WVH.mjs +33 -0
- package/dist/_chunks/ReviewWorkflowsColumn-FDxVKdto-IWfB3WVH.mjs.map +1 -0
- package/dist/_chunks/ReviewWorkflowsColumn-FDxVKdto-m8hslkeI.js +33 -0
- package/dist/_chunks/ReviewWorkflowsColumn-FDxVKdto-m8hslkeI.js.map +1 -0
- package/dist/_chunks/constants-WjN6I3sL-7e3gpx4b.mjs +190 -0
- package/dist/_chunks/constants-WjN6I3sL-7e3gpx4b.mjs.map +1 -0
- package/dist/_chunks/constants-WjN6I3sL-cDZPE6ED.js +209 -0
- package/dist/_chunks/constants-WjN6I3sL-cDZPE6ED.js.map +1 -0
- package/dist/_chunks/{en-m608rMZx.js → en-TaNIVnDO.js} +2 -2
- package/dist/_chunks/en-TaNIVnDO.js.map +1 -0
- package/dist/_chunks/{en-CE3wEy_c.mjs → en-jvJ-d-Qq.mjs} +2 -2
- package/dist/_chunks/en-jvJ-d-Qq.mjs.map +1 -0
- package/dist/_chunks/{index-iNtwnT3f.mjs → index-53jX2hhF.mjs} +26 -34
- package/dist/_chunks/index-53jX2hhF.mjs.map +1 -0
- package/dist/_chunks/index-5ZvCaCyY-06DLg5eU.mjs +16421 -0
- package/dist/_chunks/index-5ZvCaCyY-06DLg5eU.mjs.map +1 -0
- package/dist/_chunks/index-5ZvCaCyY-JgYo3Jws.js +16446 -0
- package/dist/_chunks/index-5ZvCaCyY-JgYo3Jws.js.map +1 -0
- package/dist/_chunks/{index-rryiT0-Z.mjs → index-A3oJlPcE.mjs} +111 -108
- package/dist/_chunks/index-A3oJlPcE.mjs.map +1 -0
- package/dist/_chunks/{index-XqdaO5WZ.js → index-MEUac_4V.js} +124 -122
- package/dist/_chunks/index-MEUac_4V.js.map +1 -0
- package/dist/_chunks/index-N-GcFWtg.mjs +261 -0
- package/dist/_chunks/index-N-GcFWtg.mjs.map +1 -0
- package/dist/_chunks/{index-O9AAUvyy.js → index-TJUxOCtJ.js} +26 -34
- package/dist/_chunks/index-TJUxOCtJ.js.map +1 -0
- package/dist/_chunks/{index-6Kdo3KXv.js → index-VgvlwVA7.js} +106 -147
- package/dist/_chunks/index-VgvlwVA7.js.map +1 -0
- package/dist/_chunks/{index-1uupZmu0.js → index-bRuKnVcH.js} +39 -32
- package/dist/_chunks/index-bRuKnVcH.js.map +1 -0
- package/dist/_chunks/{index-ethhTEkj.mjs → index-ee_14Ldw.mjs} +36 -29
- package/dist/_chunks/index-ee_14Ldw.mjs.map +1 -0
- package/dist/_chunks/index-mzJ2Vb5u.js +280 -0
- package/dist/_chunks/index-mzJ2Vb5u.js.map +1 -0
- package/dist/_chunks/{index-a9oKDd3C.mjs → index-vXywiVeM.mjs} +101 -142
- package/dist/_chunks/index-vXywiVeM.mjs.map +1 -0
- package/dist/_chunks/useSyncRbac-Kt8Li0Yf-Z54sMEPM.mjs +39 -0
- package/dist/_chunks/useSyncRbac-Kt8Li0Yf-Z54sMEPM.mjs.map +1 -0
- package/dist/_chunks/useSyncRbac-Kt8Li0Yf-h8HqtZ6y.js +57 -0
- package/dist/_chunks/useSyncRbac-Kt8Li0Yf-h8HqtZ6y.js.map +1 -0
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +1 -1
- package/dist/style.css +84 -0
- package/package.json +13 -13
- package/server/bootstrap/grant-config.js +9 -0
- package/server/bootstrap/index.js +2 -39
- package/server/content-types/user/index.js +0 -1
- package/server/controllers/auth.js +24 -53
- package/server/controllers/content-manager-user.js +24 -28
- package/server/controllers/role.js +1 -1
- package/server/controllers/user.js +5 -5
- package/server/middlewares/rateLimit.js +1 -1
- package/server/register.js +1 -1
- package/server/services/jwt.js +3 -3
- package/server/services/permission.js +3 -7
- package/server/services/providers-registry.js +15 -0
- package/server/services/providers.js +10 -5
- package/server/services/role.js +15 -13
- package/server/services/user.js +28 -14
- package/server/services/users-permissions.js +12 -10
- package/server/utils/sanitize/sanitizers.js +2 -2
- package/dist/_chunks/en-CE3wEy_c.mjs.map +0 -1
- package/dist/_chunks/en-m608rMZx.js.map +0 -1
- package/dist/_chunks/index-1uupZmu0.js.map +0 -1
- package/dist/_chunks/index-6Kdo3KXv.js.map +0 -1
- package/dist/_chunks/index-O9AAUvyy.js.map +0 -1
- package/dist/_chunks/index-Un-J-cxQ.js +0 -320
- package/dist/_chunks/index-Un-J-cxQ.js.map +0 -1
- package/dist/_chunks/index-X0yw_GgN.mjs +0 -301
- package/dist/_chunks/index-X0yw_GgN.mjs.map +0 -1
- package/dist/_chunks/index-XqdaO5WZ.js.map +0 -1
- package/dist/_chunks/index-a9oKDd3C.mjs.map +0 -1
- package/dist/_chunks/index-ethhTEkj.mjs.map +0 -1
- package/dist/_chunks/index-iNtwnT3f.mjs.map +0 -1
- package/dist/_chunks/index-rryiT0-Z.mjs.map +0 -1
|
@@ -12,20 +12,14 @@ import {
|
|
|
12
12
|
TextInput,
|
|
13
13
|
Typography,
|
|
14
14
|
} from '@strapi/design-system';
|
|
15
|
-
import {
|
|
16
|
-
CheckPagePermissions,
|
|
17
|
-
Form,
|
|
18
|
-
SettingsPageTitle,
|
|
19
|
-
useFetchClient,
|
|
20
|
-
useNotification,
|
|
21
|
-
useOverlayBlocker,
|
|
22
|
-
useTracking,
|
|
23
|
-
} from '@strapi/helper-plugin';
|
|
15
|
+
import { useFetchClient } from '@strapi/helper-plugin';
|
|
24
16
|
import { Check } from '@strapi/icons';
|
|
25
|
-
import {
|
|
17
|
+
import { Page, useTracking, useNotification } from '@strapi/strapi/admin';
|
|
18
|
+
import { Formik, Form } from 'formik';
|
|
19
|
+
import { Helmet } from 'react-helmet';
|
|
26
20
|
import { useIntl } from 'react-intl';
|
|
27
21
|
import { useMutation } from 'react-query';
|
|
28
|
-
import {
|
|
22
|
+
import { useNavigate } from 'react-router-dom';
|
|
29
23
|
|
|
30
24
|
import UsersPermissions from '../../../components/UsersPermissions';
|
|
31
25
|
import { PERMISSIONS } from '../../../constants';
|
|
@@ -35,9 +29,8 @@ import { usePlugins } from '../hooks/usePlugins';
|
|
|
35
29
|
|
|
36
30
|
export const CreatePage = () => {
|
|
37
31
|
const { formatMessage } = useIntl();
|
|
38
|
-
const toggleNotification = useNotification();
|
|
39
|
-
const
|
|
40
|
-
const { lockApp, unlockApp } = useOverlayBlocker();
|
|
32
|
+
const { toggleNotification } = useNotification();
|
|
33
|
+
const navigate = useNavigate();
|
|
41
34
|
const { isLoading: isLoadingPlugins, permissions, routes } = usePlugins();
|
|
42
35
|
const { trackUsage } = useTracking();
|
|
43
36
|
const permissionsRef = React.useRef();
|
|
@@ -45,11 +38,11 @@ export const CreatePage = () => {
|
|
|
45
38
|
const mutation = useMutation((body) => post(`/users-permissions/roles`, body), {
|
|
46
39
|
onError() {
|
|
47
40
|
toggleNotification({
|
|
48
|
-
type: '
|
|
49
|
-
message: {
|
|
41
|
+
type: 'danger',
|
|
42
|
+
message: formatMessage({
|
|
50
43
|
id: 'notification.error',
|
|
51
44
|
defaultMessage: 'An error occurred',
|
|
52
|
-
},
|
|
45
|
+
}),
|
|
53
46
|
});
|
|
54
47
|
},
|
|
55
48
|
|
|
@@ -58,34 +51,34 @@ export const CreatePage = () => {
|
|
|
58
51
|
|
|
59
52
|
toggleNotification({
|
|
60
53
|
type: 'success',
|
|
61
|
-
message: {
|
|
54
|
+
message: formatMessage({
|
|
62
55
|
id: getTrad('Settings.roles.created'),
|
|
63
56
|
defaultMessage: 'Role created',
|
|
64
|
-
},
|
|
57
|
+
}),
|
|
65
58
|
});
|
|
66
59
|
|
|
67
60
|
// Forcing redirecting since we don't have the id in the response
|
|
68
|
-
|
|
61
|
+
navigate(-1);
|
|
69
62
|
},
|
|
70
63
|
});
|
|
71
64
|
|
|
72
65
|
const handleCreateRoleSubmit = async (data) => {
|
|
73
|
-
lockApp();
|
|
74
|
-
|
|
75
66
|
// TODO: refactor. Child -> parent component communication is evil;
|
|
76
67
|
// We should either move the provider one level up or move the state
|
|
77
68
|
// straight into redux.
|
|
78
69
|
const permissions = permissionsRef.current.getPermissions();
|
|
79
70
|
|
|
80
71
|
await mutation.mutate({ ...data, ...permissions, users: [] });
|
|
81
|
-
|
|
82
|
-
unlockApp();
|
|
83
72
|
};
|
|
84
73
|
|
|
85
74
|
return (
|
|
86
75
|
<Main>
|
|
87
|
-
|
|
88
|
-
|
|
76
|
+
<Helmet
|
|
77
|
+
title={formatMessage(
|
|
78
|
+
{ id: 'Settings.PageTitle', defaultMessage: 'Settings - {name}' },
|
|
79
|
+
{ name: 'Roles' }
|
|
80
|
+
)}
|
|
81
|
+
/>
|
|
89
82
|
<Formik
|
|
90
83
|
enableReinitialize
|
|
91
84
|
initialValues={{ name: '', description: '' }}
|
|
@@ -193,7 +186,7 @@ export const CreatePage = () => {
|
|
|
193
186
|
};
|
|
194
187
|
|
|
195
188
|
export const ProtectedRolesCreatePage = () => (
|
|
196
|
-
<
|
|
189
|
+
<Page.Protect permissions={PERMISSIONS.createRole}>
|
|
197
190
|
<CreatePage />
|
|
198
|
-
</
|
|
191
|
+
</Page.Protect>
|
|
199
192
|
);
|
|
@@ -12,22 +12,14 @@ import {
|
|
|
12
12
|
GridItem,
|
|
13
13
|
Grid,
|
|
14
14
|
} from '@strapi/design-system';
|
|
15
|
-
import {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
Form,
|
|
21
|
-
useAPIErrorHandler,
|
|
22
|
-
useFetchClient,
|
|
23
|
-
useNotification,
|
|
24
|
-
Link,
|
|
25
|
-
} from '@strapi/helper-plugin';
|
|
26
|
-
import { ArrowLeft, Check } from '@strapi/icons';
|
|
27
|
-
import { Formik } from 'formik';
|
|
15
|
+
import { useFetchClient } from '@strapi/helper-plugin';
|
|
16
|
+
import { Check } from '@strapi/icons';
|
|
17
|
+
import { Page, BackButton, useAPIErrorHandler, useNotification } from '@strapi/strapi/admin';
|
|
18
|
+
import { Formik, Form } from 'formik';
|
|
19
|
+
import { Helmet } from 'react-helmet';
|
|
28
20
|
import { useIntl } from 'react-intl';
|
|
29
21
|
import { useQuery, useMutation } from 'react-query';
|
|
30
|
-
import {
|
|
22
|
+
import { useMatch } from 'react-router-dom';
|
|
31
23
|
|
|
32
24
|
import UsersPermissions from '../../../components/UsersPermissions';
|
|
33
25
|
import { PERMISSIONS } from '../../../constants';
|
|
@@ -37,11 +29,10 @@ import { usePlugins } from '../hooks/usePlugins';
|
|
|
37
29
|
|
|
38
30
|
export const EditPage = () => {
|
|
39
31
|
const { formatMessage } = useIntl();
|
|
40
|
-
const toggleNotification = useNotification();
|
|
41
|
-
const { lockApp, unlockApp } = useOverlayBlocker();
|
|
32
|
+
const { toggleNotification } = useNotification();
|
|
42
33
|
const {
|
|
43
34
|
params: { id },
|
|
44
|
-
} =
|
|
35
|
+
} = useMatch(`/settings/users-permissions/roles/:id`);
|
|
45
36
|
const { get } = useFetchClient();
|
|
46
37
|
const { isLoading: isLoadingPlugins, routes } = usePlugins();
|
|
47
38
|
const {
|
|
@@ -63,7 +54,7 @@ export const EditPage = () => {
|
|
|
63
54
|
const mutation = useMutation((body) => put(`/users-permissions/roles/${id}`, body), {
|
|
64
55
|
onError(error) {
|
|
65
56
|
toggleNotification({
|
|
66
|
-
type: '
|
|
57
|
+
type: 'danger',
|
|
67
58
|
message: formatAPIError(error),
|
|
68
59
|
});
|
|
69
60
|
},
|
|
@@ -71,10 +62,10 @@ export const EditPage = () => {
|
|
|
71
62
|
async onSuccess() {
|
|
72
63
|
toggleNotification({
|
|
73
64
|
type: 'success',
|
|
74
|
-
message: {
|
|
65
|
+
message: formatMessage({
|
|
75
66
|
id: getTrad('Settings.roles.created'),
|
|
76
67
|
defaultMessage: 'Role edited',
|
|
77
|
-
},
|
|
68
|
+
}),
|
|
78
69
|
});
|
|
79
70
|
|
|
80
71
|
await refetchRole();
|
|
@@ -82,24 +73,23 @@ export const EditPage = () => {
|
|
|
82
73
|
});
|
|
83
74
|
|
|
84
75
|
const handleEditRoleSubmit = async (data) => {
|
|
85
|
-
// Set loading state
|
|
86
|
-
lockApp();
|
|
87
|
-
|
|
88
76
|
const permissions = permissionsRef.current.getPermissions();
|
|
89
77
|
|
|
90
78
|
await mutation.mutate({ ...data, ...permissions, users: [] });
|
|
91
|
-
|
|
92
|
-
unlockApp();
|
|
93
79
|
};
|
|
94
80
|
|
|
95
81
|
if (isLoadingRole) {
|
|
96
|
-
return <
|
|
82
|
+
return <Page.Loading />;
|
|
97
83
|
}
|
|
98
84
|
|
|
99
85
|
return (
|
|
100
86
|
<Main>
|
|
101
|
-
|
|
102
|
-
|
|
87
|
+
<Helmet
|
|
88
|
+
title={formatMessage(
|
|
89
|
+
{ id: 'Settings.PageTitle', defaultMessage: 'Settings - {name}' },
|
|
90
|
+
{ name: 'Roles' }
|
|
91
|
+
)}
|
|
92
|
+
/>
|
|
103
93
|
<Formik
|
|
104
94
|
enableReinitialize
|
|
105
95
|
initialValues={{ name: role.name, description: role.description }}
|
|
@@ -110,7 +100,7 @@ export const EditPage = () => {
|
|
|
110
100
|
<Form noValidate onSubmit={handleSubmit}>
|
|
111
101
|
<HeaderLayout
|
|
112
102
|
primaryAction={
|
|
113
|
-
!isLoadingPlugins
|
|
103
|
+
!isLoadingPlugins ? (
|
|
114
104
|
<Button
|
|
115
105
|
disabled={role.code === 'strapi-super-admin'}
|
|
116
106
|
type="submit"
|
|
@@ -122,18 +112,11 @@ export const EditPage = () => {
|
|
|
122
112
|
defaultMessage: 'Save',
|
|
123
113
|
})}
|
|
124
114
|
</Button>
|
|
125
|
-
)
|
|
115
|
+
) : null
|
|
126
116
|
}
|
|
127
117
|
title={role.name}
|
|
128
118
|
subtitle={role.description}
|
|
129
|
-
navigationAction={
|
|
130
|
-
<Link startIcon={<ArrowLeft />} to="/settings/users-permissions/roles">
|
|
131
|
-
{formatMessage({
|
|
132
|
-
id: 'global.back',
|
|
133
|
-
defaultMessage: 'Back',
|
|
134
|
-
})}
|
|
135
|
-
</Link>
|
|
136
|
-
}
|
|
119
|
+
navigationAction={<BackButton />}
|
|
137
120
|
/>
|
|
138
121
|
<ContentLayout>
|
|
139
122
|
<Flex
|
|
@@ -214,7 +197,7 @@ export const EditPage = () => {
|
|
|
214
197
|
};
|
|
215
198
|
|
|
216
199
|
export const ProtectedRolesEditPage = () => (
|
|
217
|
-
<
|
|
200
|
+
<Page.Protect permissions={PERMISSIONS.updateRole}>
|
|
218
201
|
<EditPage />
|
|
219
|
-
</
|
|
202
|
+
</Page.Protect>
|
|
220
203
|
);
|
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
|
|
3
3
|
import { Flex, IconButton, Link, Tbody, Td, Tr, Typography } from '@strapi/design-system';
|
|
4
|
-
import {
|
|
4
|
+
import { onRowClick, stopPropagation } from '@strapi/helper-plugin';
|
|
5
5
|
import { Pencil, Trash } from '@strapi/icons';
|
|
6
6
|
import PropTypes from 'prop-types';
|
|
7
7
|
import { useIntl } from 'react-intl';
|
|
8
|
-
import {
|
|
8
|
+
import { useNavigate } from 'react-router-dom';
|
|
9
9
|
import styled from 'styled-components';
|
|
10
10
|
|
|
11
11
|
const EditLink = styled(Link)`
|
|
12
12
|
align-items: center;
|
|
13
|
-
height: ${
|
|
13
|
+
height: ${32 / 16}rem;
|
|
14
14
|
display: flex;
|
|
15
15
|
justify-content: center;
|
|
16
16
|
padding: ${({ theme }) => `${theme.spaces[2]}}`};
|
|
17
|
-
width: ${
|
|
17
|
+
width: ${32 / 16}rem;
|
|
18
18
|
|
|
19
19
|
svg {
|
|
20
|
-
height: ${
|
|
21
|
-
width: ${
|
|
20
|
+
height: ${12 / 16}rem;
|
|
21
|
+
width: ${12 / 16}rem;
|
|
22
22
|
|
|
23
23
|
path {
|
|
24
24
|
fill: ${({ theme }) => theme.colors.neutral500};
|
|
@@ -35,9 +35,9 @@ const EditLink = styled(Link)`
|
|
|
35
35
|
}
|
|
36
36
|
`;
|
|
37
37
|
|
|
38
|
-
const TableBody = ({ sortedRoles, canDelete,
|
|
38
|
+
const TableBody = ({ sortedRoles, canDelete, canUpdate, setRoleToDelete, onDelete }) => {
|
|
39
39
|
const { formatMessage } = useIntl();
|
|
40
|
-
const
|
|
40
|
+
const navigate = useNavigate();
|
|
41
41
|
const [showConfirmDelete, setShowConfirmDelete] = onDelete;
|
|
42
42
|
|
|
43
43
|
const checkCanDeleteRole = (role) =>
|
|
@@ -48,14 +48,10 @@ const TableBody = ({ sortedRoles, canDelete, permissions, setRoleToDelete, onDel
|
|
|
48
48
|
setShowConfirmDelete(!showConfirmDelete);
|
|
49
49
|
};
|
|
50
50
|
|
|
51
|
-
const handleClickEdit = (id) => {
|
|
52
|
-
push(`/settings/users-permissions/roles/${id}`);
|
|
53
|
-
};
|
|
54
|
-
|
|
55
51
|
return (
|
|
56
52
|
<Tbody>
|
|
57
53
|
{sortedRoles?.map((role) => (
|
|
58
|
-
<Tr key={role.name} {...onRowClick({ fn: () =>
|
|
54
|
+
<Tr key={role.name} {...onRowClick({ fn: () => navigate(role.id.toString()) })}>
|
|
59
55
|
<Td width="20%">
|
|
60
56
|
<Typography>{role.name}</Typography>
|
|
61
57
|
</Td>
|
|
@@ -75,9 +71,9 @@ const TableBody = ({ sortedRoles, canDelete, permissions, setRoleToDelete, onDel
|
|
|
75
71
|
</Td>
|
|
76
72
|
<Td>
|
|
77
73
|
<Flex justifyContent="end" {...stopPropagation}>
|
|
78
|
-
|
|
74
|
+
{canUpdate ? (
|
|
79
75
|
<EditLink
|
|
80
|
-
to={
|
|
76
|
+
to={role.id.toString()}
|
|
81
77
|
aria-label={formatMessage(
|
|
82
78
|
{ id: 'app.component.table.edit', defaultMessage: 'Edit {target}' },
|
|
83
79
|
{ target: `${role.name}` }
|
|
@@ -85,20 +81,18 @@ const TableBody = ({ sortedRoles, canDelete, permissions, setRoleToDelete, onDel
|
|
|
85
81
|
>
|
|
86
82
|
<Pencil />
|
|
87
83
|
</EditLink>
|
|
88
|
-
|
|
84
|
+
) : null}
|
|
89
85
|
|
|
90
86
|
{checkCanDeleteRole(role) && (
|
|
91
|
-
<
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
/>
|
|
101
|
-
</CheckPermissions>
|
|
87
|
+
<IconButton
|
|
88
|
+
onClick={() => handleClickDelete(role.id.toString())}
|
|
89
|
+
noBorder
|
|
90
|
+
icon={<Trash />}
|
|
91
|
+
label={formatMessage(
|
|
92
|
+
{ id: 'global.delete-target', defaultMessage: 'Delete {target}' },
|
|
93
|
+
{ target: `${role.name}` }
|
|
94
|
+
)}
|
|
95
|
+
/>
|
|
102
96
|
)}
|
|
103
97
|
</Flex>
|
|
104
98
|
</Td>
|
|
@@ -112,6 +106,7 @@ export default TableBody;
|
|
|
112
106
|
|
|
113
107
|
TableBody.defaultProps = {
|
|
114
108
|
canDelete: false,
|
|
109
|
+
canUpdate: false,
|
|
115
110
|
};
|
|
116
111
|
|
|
117
112
|
TableBody.propTypes = {
|
|
@@ -120,4 +115,5 @@ TableBody.propTypes = {
|
|
|
120
115
|
setRoleToDelete: PropTypes.func.isRequired,
|
|
121
116
|
sortedRoles: PropTypes.array.isRequired,
|
|
122
117
|
canDelete: PropTypes.bool,
|
|
118
|
+
canUpdate: PropTypes.bool,
|
|
123
119
|
};
|
|
@@ -13,28 +13,25 @@ import {
|
|
|
13
13
|
Typography,
|
|
14
14
|
useNotifyAT,
|
|
15
15
|
VisuallyHidden,
|
|
16
|
-
} from '@strapi/design-system';
|
|
17
|
-
import {
|
|
18
|
-
CheckPagePermissions,
|
|
19
|
-
CheckPermissions,
|
|
20
|
-
ConfirmDialog,
|
|
21
16
|
EmptyStateLayout,
|
|
22
|
-
LinkButton,
|
|
23
|
-
LoadingIndicatorPage,
|
|
24
|
-
NoPermissions,
|
|
25
|
-
SearchURLQuery,
|
|
26
|
-
SettingsPageTitle,
|
|
27
17
|
useCollator,
|
|
28
18
|
useFilter,
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
useRBAC,
|
|
33
|
-
useTracking,
|
|
34
|
-
} from '@strapi/helper-plugin';
|
|
19
|
+
} from '@strapi/design-system';
|
|
20
|
+
import { LinkButton } from '@strapi/design-system/v2';
|
|
21
|
+
import { useFocusWhenNavigate, useQueryParams, useRBAC } from '@strapi/helper-plugin';
|
|
35
22
|
import { Plus } from '@strapi/icons';
|
|
23
|
+
import {
|
|
24
|
+
ConfirmDialog,
|
|
25
|
+
useTracking,
|
|
26
|
+
Page,
|
|
27
|
+
SearchInput,
|
|
28
|
+
BackButton,
|
|
29
|
+
useNotification,
|
|
30
|
+
} from '@strapi/strapi/admin';
|
|
31
|
+
import { Helmet } from 'react-helmet';
|
|
36
32
|
import { useIntl } from 'react-intl';
|
|
37
33
|
import { useMutation, useQuery } from 'react-query';
|
|
34
|
+
import { NavLink } from 'react-router-dom';
|
|
38
35
|
|
|
39
36
|
import { PERMISSIONS } from '../../../../constants';
|
|
40
37
|
import { getTrad } from '../../../../utils';
|
|
@@ -45,18 +42,17 @@ import { deleteData, fetchData } from './utils/api';
|
|
|
45
42
|
export const RolesListPage = () => {
|
|
46
43
|
const { trackUsage } = useTracking();
|
|
47
44
|
const { formatMessage, locale } = useIntl();
|
|
48
|
-
const toggleNotification = useNotification();
|
|
45
|
+
const { toggleNotification } = useNotification();
|
|
49
46
|
const { notifyStatus } = useNotifyAT();
|
|
50
47
|
const [{ query }] = useQueryParams();
|
|
51
48
|
const _q = query?._q || '';
|
|
52
49
|
const [showConfirmDelete, setShowConfirmDelete] = useState(false);
|
|
53
|
-
const [isConfirmButtonLoading, setIsConfirmButtonLoading] = useState(false);
|
|
54
50
|
const [roleToDelete, setRoleToDelete] = useState();
|
|
55
51
|
useFocusWhenNavigate();
|
|
56
52
|
|
|
57
53
|
const {
|
|
58
54
|
isLoading: isLoadingForPermissions,
|
|
59
|
-
allowedActions: { canRead, canDelete },
|
|
55
|
+
allowedActions: { canRead, canDelete, canCreate, canUpdate },
|
|
60
56
|
} = useRBAC({
|
|
61
57
|
create: PERMISSIONS.createRole,
|
|
62
58
|
read: PERMISSIONS.readRoles,
|
|
@@ -69,12 +65,12 @@ export const RolesListPage = () => {
|
|
|
69
65
|
data: { roles },
|
|
70
66
|
isFetching,
|
|
71
67
|
refetch,
|
|
72
|
-
} = useQuery('get-roles', () => fetchData(toggleNotification, notifyStatus), {
|
|
68
|
+
} = useQuery('get-roles', () => fetchData(toggleNotification, formatMessage, notifyStatus), {
|
|
73
69
|
initialData: {},
|
|
74
70
|
enabled: canRead,
|
|
75
71
|
});
|
|
76
72
|
|
|
77
|
-
const {
|
|
73
|
+
const { contains } = useFilter(locale, {
|
|
78
74
|
sensitivity: 'base',
|
|
79
75
|
});
|
|
80
76
|
|
|
@@ -85,7 +81,7 @@ export const RolesListPage = () => {
|
|
|
85
81
|
sensitivity: 'base',
|
|
86
82
|
});
|
|
87
83
|
|
|
88
|
-
const isLoading = isLoadingForData || isFetching;
|
|
84
|
+
const isLoading = isLoadingForData || isFetching || isLoadingForPermissions;
|
|
89
85
|
|
|
90
86
|
const handleShowConfirmDelete = () => {
|
|
91
87
|
setShowConfirmDelete(!showConfirmDelete);
|
|
@@ -107,21 +103,19 @@ export const RolesListPage = () => {
|
|
|
107
103
|
defaultMessage: 'Roles',
|
|
108
104
|
});
|
|
109
105
|
|
|
110
|
-
const deleteMutation = useMutation((id) => deleteData(id, toggleNotification), {
|
|
106
|
+
const deleteMutation = useMutation((id) => deleteData(id, formatMessage, toggleNotification), {
|
|
111
107
|
async onSuccess() {
|
|
112
108
|
await refetch();
|
|
113
109
|
},
|
|
114
110
|
});
|
|
115
111
|
|
|
116
112
|
const handleConfirmDelete = async () => {
|
|
117
|
-
setIsConfirmButtonLoading(true);
|
|
118
113
|
await deleteMutation.mutateAsync(roleToDelete);
|
|
119
114
|
setShowConfirmDelete(!showConfirmDelete);
|
|
120
|
-
setIsConfirmButtonLoading(false);
|
|
121
115
|
};
|
|
122
116
|
|
|
123
117
|
const sortedRoles = (roles || [])
|
|
124
|
-
.filter((role) =>
|
|
118
|
+
.filter((role) => contains(role.name, _q) || contains(role.description, _q))
|
|
125
119
|
.sort(
|
|
126
120
|
(a, b) => formatter.compare(a.name, b.name) || formatter.compare(a.description, b.description)
|
|
127
121
|
);
|
|
@@ -131,9 +125,18 @@ export const RolesListPage = () => {
|
|
|
131
125
|
const colCount = 4;
|
|
132
126
|
const rowCount = (roles?.length || 0) + 1;
|
|
133
127
|
|
|
128
|
+
if (isLoading) {
|
|
129
|
+
return <Page.Loading />;
|
|
130
|
+
}
|
|
131
|
+
|
|
134
132
|
return (
|
|
135
133
|
<Layout>
|
|
136
|
-
<
|
|
134
|
+
<Helmet
|
|
135
|
+
title={formatMessage(
|
|
136
|
+
{ id: 'Settings.PageTitle', defaultMessage: 'Settings - {name}' },
|
|
137
|
+
{ name: pageTitle }
|
|
138
|
+
)}
|
|
139
|
+
/>
|
|
137
140
|
<Main aria-busy={isLoading}>
|
|
138
141
|
<HeaderLayout
|
|
139
142
|
title={formatMessage({
|
|
@@ -145,9 +148,10 @@ export const RolesListPage = () => {
|
|
|
145
148
|
defaultMessage: 'List of roles',
|
|
146
149
|
})}
|
|
147
150
|
primaryAction={
|
|
148
|
-
|
|
151
|
+
canCreate ? (
|
|
149
152
|
<LinkButton
|
|
150
|
-
to="
|
|
153
|
+
to="new"
|
|
154
|
+
as={NavLink}
|
|
151
155
|
onClick={() => trackUsage('willCreateRole')}
|
|
152
156
|
startIcon={<Plus />}
|
|
153
157
|
size="S"
|
|
@@ -157,13 +161,14 @@ export const RolesListPage = () => {
|
|
|
157
161
|
defaultMessage: 'Add new role',
|
|
158
162
|
})}
|
|
159
163
|
</LinkButton>
|
|
160
|
-
|
|
164
|
+
) : null
|
|
161
165
|
}
|
|
166
|
+
navigationAction={<BackButton />}
|
|
162
167
|
/>
|
|
163
168
|
|
|
164
169
|
<ActionLayout
|
|
165
170
|
startActions={
|
|
166
|
-
<
|
|
171
|
+
<SearchInput
|
|
167
172
|
label={formatMessage({
|
|
168
173
|
id: 'app.component.search.label',
|
|
169
174
|
defaultMessage: 'Search',
|
|
@@ -173,8 +178,7 @@ export const RolesListPage = () => {
|
|
|
173
178
|
/>
|
|
174
179
|
|
|
175
180
|
<ContentLayout>
|
|
176
|
-
{!canRead && <NoPermissions />}
|
|
177
|
-
{(isLoading || isLoadingForPermissions) && <LoadingIndicatorPage />}
|
|
181
|
+
{!canRead && <Page.NoPermissions />}
|
|
178
182
|
{canRead && sortedRoles && sortedRoles?.length ? (
|
|
179
183
|
<Table colCount={colCount} rowCount={rowCount}>
|
|
180
184
|
<Thead>
|
|
@@ -213,19 +217,19 @@ export const RolesListPage = () => {
|
|
|
213
217
|
<TableBody
|
|
214
218
|
sortedRoles={sortedRoles}
|
|
215
219
|
canDelete={canDelete}
|
|
220
|
+
canUpdate={canUpdate}
|
|
216
221
|
permissions={PERMISSIONS}
|
|
217
222
|
setRoleToDelete={setRoleToDelete}
|
|
218
223
|
onDelete={[showConfirmDelete, setShowConfirmDelete]}
|
|
219
224
|
/>
|
|
220
225
|
</Table>
|
|
221
226
|
) : (
|
|
222
|
-
<EmptyStateLayout content={emptyLayout[emptyContent]} />
|
|
227
|
+
<EmptyStateLayout content={formatMessage(emptyLayout[emptyContent])} />
|
|
223
228
|
)}
|
|
224
229
|
</ContentLayout>
|
|
225
230
|
<ConfirmDialog
|
|
226
|
-
isConfirmButtonLoading={isConfirmButtonLoading}
|
|
227
231
|
onConfirm={handleConfirmDelete}
|
|
228
|
-
|
|
232
|
+
onClose={handleShowConfirmDelete}
|
|
229
233
|
isOpen={showConfirmDelete}
|
|
230
234
|
/>
|
|
231
235
|
</Main>
|
|
@@ -235,8 +239,8 @@ export const RolesListPage = () => {
|
|
|
235
239
|
|
|
236
240
|
export const ProtectedRolesListPage = () => {
|
|
237
241
|
return (
|
|
238
|
-
<
|
|
242
|
+
<Page.Protect permissions={PERMISSIONS.accessRoles}>
|
|
239
243
|
<RolesListPage />
|
|
240
|
-
</
|
|
244
|
+
</Page.Protect>
|
|
241
245
|
);
|
|
242
246
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getFetchClient } from '@strapi/helper-plugin';
|
|
2
2
|
|
|
3
|
-
export const fetchData = async (toggleNotification, notifyStatus) => {
|
|
3
|
+
export const fetchData = async (toggleNotification, formatMessage, notifyStatus) => {
|
|
4
4
|
try {
|
|
5
5
|
const { get } = getFetchClient();
|
|
6
6
|
const { data } = await get('/users-permissions/roles');
|
|
@@ -9,22 +9,22 @@ export const fetchData = async (toggleNotification, notifyStatus) => {
|
|
|
9
9
|
return data;
|
|
10
10
|
} catch (err) {
|
|
11
11
|
toggleNotification({
|
|
12
|
-
type: '
|
|
13
|
-
message: { id: 'notification.error' },
|
|
12
|
+
type: 'danger',
|
|
13
|
+
message: formatMessage({ id: 'notification.error' }),
|
|
14
14
|
});
|
|
15
15
|
|
|
16
16
|
throw new Error(err);
|
|
17
17
|
}
|
|
18
18
|
};
|
|
19
19
|
|
|
20
|
-
export const deleteData = async (id, toggleNotification) => {
|
|
20
|
+
export const deleteData = async (id, formatMessage, toggleNotification) => {
|
|
21
21
|
try {
|
|
22
22
|
const { del } = getFetchClient();
|
|
23
23
|
await del(`/users-permissions/roles/${id}`);
|
|
24
24
|
} catch (error) {
|
|
25
25
|
toggleNotification({
|
|
26
|
-
type: '
|
|
27
|
-
message: { id: 'notification.error', defaultMessage: 'An error occured' },
|
|
26
|
+
type: 'danger',
|
|
27
|
+
message: formatMessage({ id: 'notification.error', defaultMessage: 'An error occured' }),
|
|
28
28
|
});
|
|
29
29
|
}
|
|
30
30
|
};
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
"Settings.roles.deleted": "Role deleted",
|
|
61
61
|
"Settings.roles.edited": "Role edited",
|
|
62
62
|
"Settings.section-label": "Users & Permissions plugin",
|
|
63
|
-
"components.Input.error.validation.email": "This is
|
|
63
|
+
"components.Input.error.validation.email": "This is not a valid email",
|
|
64
64
|
"components.Input.error.validation.json": "This doesn't match the JSON format",
|
|
65
65
|
"components.Input.error.validation.max": "The value is too high.",
|
|
66
66
|
"components.Input.error.validation.maxLength": "The value is too long.",
|