@strapi/plugin-users-permissions 0.0.0-next.f45143c5e2a8a9d85691d0abf79a3f42024a0c71 → 0.0.0-next.f5b09a8e61e059f02784478e27c310c6290be088
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/.eslintignore +1 -2
- package/.eslintrc +14 -0
- package/admin/src/components/BoundRoute/index.js +5 -3
- package/admin/src/components/FormModal/Input/index.js +6 -3
- package/admin/src/components/FormModal/index.js +13 -10
- package/admin/src/components/Permissions/PermissionRow/CheckboxWrapper.js +1 -1
- package/admin/src/components/Permissions/PermissionRow/SubCategory.js +26 -5
- package/admin/src/components/Permissions/PermissionRow/index.js +4 -2
- package/admin/src/components/Permissions/index.js +6 -5
- package/admin/src/components/Policies/index.js +3 -2
- package/admin/src/components/UsersPermissions/index.js +8 -5
- package/admin/src/{permissions.js → constants.js} +1 -3
- package/admin/src/contexts/UsersPermissionsContext/index.js +1 -0
- package/admin/src/index.js +19 -28
- package/admin/src/pages/AdvancedSettings/index.js +68 -52
- package/admin/src/pages/AdvancedSettings/utils/schema.js +1 -1
- package/admin/src/pages/EmailTemplates/components/EmailForm.js +14 -13
- package/admin/src/pages/EmailTemplates/components/EmailTable.js +9 -7
- package/admin/src/pages/EmailTemplates/index.js +77 -63
- package/admin/src/pages/EmailTemplates/utils/schema.js +1 -1
- package/admin/src/pages/Providers/index.js +91 -86
- package/admin/src/pages/Providers/utils/forms.js +1 -1
- package/admin/src/pages/Roles/{CreatePage/utils/schema.js → constants.js} +2 -4
- package/admin/src/pages/Roles/hooks/usePlugins.js +78 -0
- package/admin/src/pages/Roles/index.js +17 -11
- package/admin/src/pages/Roles/pages/CreatePage.js +199 -0
- package/admin/src/pages/Roles/pages/EditPage.js +220 -0
- package/admin/src/pages/Roles/{ListPage → pages/ListPage}/components/TableBody.js +46 -15
- package/admin/src/pages/Roles/{ListPage → pages/ListPage}/index.js +48 -47
- package/admin/src/pages/Roles/{ListPage → pages/ListPage}/utils/api.js +3 -4
- package/admin/src/translations/ru.json +50 -26
- package/admin/src/translations/zh-Hans.json +80 -80
- package/admin/src/utils/index.js +1 -2
- package/documentation/content-api.yaml +23 -15
- package/jest.config.front.js +2 -0
- package/package.json +47 -30
- package/packup.config.ts +42 -0
- package/server/bootstrap/index.js +36 -0
- package/server/controllers/auth.js +51 -14
- package/server/controllers/user.js +12 -1
- package/server/middlewares/rateLimit.js +41 -21
- package/server/register.js +7 -1
- package/server/services/providers-registry.js +1 -1
- package/server/strategies/users-permissions.js +1 -8
- package/.eslintrc.js +0 -14
- package/admin/src/hooks/index.js +0 -5
- package/admin/src/hooks/useFetchRole/index.js +0 -64
- package/admin/src/hooks/useFetchRole/reducer.js +0 -31
- package/admin/src/hooks/useForm/index.js +0 -70
- package/admin/src/hooks/useForm/reducer.js +0 -40
- package/admin/src/hooks/usePlugins/index.js +0 -67
- package/admin/src/hooks/usePlugins/init.js +0 -5
- package/admin/src/hooks/usePlugins/reducer.js +0 -34
- package/admin/src/hooks/useRolesList/index.js +0 -63
- 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 -17
- package/admin/src/pages/EmailTemplates/utils/api.js +0 -17
- package/admin/src/pages/Providers/reducer.js +0 -54
- package/admin/src/pages/Providers/utils/api.js +0 -25
- package/admin/src/pages/Providers/utils/createProvidersArray.js +0 -21
- package/admin/src/pages/Roles/CreatePage/index.js +0 -182
- package/admin/src/pages/Roles/EditPage/index.js +0 -194
- package/admin/src/pages/Roles/EditPage/utils/schema.js +0 -9
- package/admin/src/pages/Roles/ProtectedCreatePage/index.js +0 -12
- package/admin/src/pages/Roles/ProtectedEditPage/index.js +0 -12
- package/admin/src/pages/Roles/ProtectedListPage/index.js +0 -15
- package/admin/src/utils/getRequestURL.js +0 -5
- package/strapi-admin.js +0 -3
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
Button,
|
|
5
|
+
ContentLayout,
|
|
6
|
+
Flex,
|
|
7
|
+
Grid,
|
|
8
|
+
GridItem,
|
|
9
|
+
HeaderLayout,
|
|
10
|
+
Main,
|
|
11
|
+
Textarea,
|
|
12
|
+
TextInput,
|
|
13
|
+
Typography,
|
|
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';
|
|
24
|
+
import { Check } from '@strapi/icons';
|
|
25
|
+
import { Formik } from 'formik';
|
|
26
|
+
import { useIntl } from 'react-intl';
|
|
27
|
+
import { useMutation } from 'react-query';
|
|
28
|
+
import { useHistory } from 'react-router-dom';
|
|
29
|
+
|
|
30
|
+
import UsersPermissions from '../../../components/UsersPermissions';
|
|
31
|
+
import { PERMISSIONS } from '../../../constants';
|
|
32
|
+
import getTrad from '../../../utils/getTrad';
|
|
33
|
+
import { createRoleSchema } from '../constants';
|
|
34
|
+
import { usePlugins } from '../hooks/usePlugins';
|
|
35
|
+
|
|
36
|
+
export const CreatePage = () => {
|
|
37
|
+
const { formatMessage } = useIntl();
|
|
38
|
+
const toggleNotification = useNotification();
|
|
39
|
+
const { goBack } = useHistory();
|
|
40
|
+
const { lockApp, unlockApp } = useOverlayBlocker();
|
|
41
|
+
const { isLoading: isLoadingPlugins, permissions, routes } = usePlugins();
|
|
42
|
+
const { trackUsage } = useTracking();
|
|
43
|
+
const permissionsRef = React.useRef();
|
|
44
|
+
const { post } = useFetchClient();
|
|
45
|
+
const mutation = useMutation((body) => post(`/users-permissions/roles`, body), {
|
|
46
|
+
onError() {
|
|
47
|
+
toggleNotification({
|
|
48
|
+
type: 'warning',
|
|
49
|
+
message: {
|
|
50
|
+
id: 'notification.error',
|
|
51
|
+
defaultMessage: 'An error occurred',
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
},
|
|
55
|
+
|
|
56
|
+
onSuccess() {
|
|
57
|
+
trackUsage('didCreateRole');
|
|
58
|
+
|
|
59
|
+
toggleNotification({
|
|
60
|
+
type: 'success',
|
|
61
|
+
message: {
|
|
62
|
+
id: getTrad('Settings.roles.created'),
|
|
63
|
+
defaultMessage: 'Role created',
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
// Forcing redirecting since we don't have the id in the response
|
|
68
|
+
goBack();
|
|
69
|
+
},
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
const handleCreateRoleSubmit = async (data) => {
|
|
73
|
+
lockApp();
|
|
74
|
+
|
|
75
|
+
// TODO: refactor. Child -> parent component communication is evil;
|
|
76
|
+
// We should either move the provider one level up or move the state
|
|
77
|
+
// straight into redux.
|
|
78
|
+
const permissions = permissionsRef.current.getPermissions();
|
|
79
|
+
|
|
80
|
+
await mutation.mutate({ ...data, ...permissions, users: [] });
|
|
81
|
+
|
|
82
|
+
unlockApp();
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
return (
|
|
86
|
+
<Main>
|
|
87
|
+
{/* TODO: This needs to be translated */}
|
|
88
|
+
<SettingsPageTitle name="Roles" />
|
|
89
|
+
<Formik
|
|
90
|
+
enableReinitialize
|
|
91
|
+
initialValues={{ name: '', description: '' }}
|
|
92
|
+
onSubmit={handleCreateRoleSubmit}
|
|
93
|
+
validationSchema={createRoleSchema}
|
|
94
|
+
>
|
|
95
|
+
{({ handleSubmit, values, handleChange, errors }) => (
|
|
96
|
+
<Form noValidate onSubmit={handleSubmit}>
|
|
97
|
+
<HeaderLayout
|
|
98
|
+
primaryAction={
|
|
99
|
+
!isLoadingPlugins && (
|
|
100
|
+
<Button type="submit" loading={mutation.isLoading} startIcon={<Check />}>
|
|
101
|
+
{formatMessage({
|
|
102
|
+
id: 'global.save',
|
|
103
|
+
defaultMessage: 'Save',
|
|
104
|
+
})}
|
|
105
|
+
</Button>
|
|
106
|
+
)
|
|
107
|
+
}
|
|
108
|
+
title={formatMessage({
|
|
109
|
+
id: 'Settings.roles.create.title',
|
|
110
|
+
defaultMessage: 'Create a role',
|
|
111
|
+
})}
|
|
112
|
+
subtitle={formatMessage({
|
|
113
|
+
id: 'Settings.roles.create.description',
|
|
114
|
+
defaultMessage: 'Define the rights given to the role',
|
|
115
|
+
})}
|
|
116
|
+
/>
|
|
117
|
+
<ContentLayout>
|
|
118
|
+
<Flex
|
|
119
|
+
background="neutral0"
|
|
120
|
+
direction="column"
|
|
121
|
+
alignItems="stretch"
|
|
122
|
+
gap={7}
|
|
123
|
+
hasRadius
|
|
124
|
+
paddingTop={6}
|
|
125
|
+
paddingBottom={6}
|
|
126
|
+
paddingLeft={7}
|
|
127
|
+
paddingRight={7}
|
|
128
|
+
shadow="filterShadow"
|
|
129
|
+
>
|
|
130
|
+
<Flex direction="column" alignItems="stretch">
|
|
131
|
+
<Typography variant="delta" as="h2">
|
|
132
|
+
{formatMessage({
|
|
133
|
+
id: getTrad('EditPage.form.roles'),
|
|
134
|
+
defaultMessage: 'Role details',
|
|
135
|
+
})}
|
|
136
|
+
</Typography>
|
|
137
|
+
|
|
138
|
+
<Grid gap={4}>
|
|
139
|
+
<GridItem col={6}>
|
|
140
|
+
<TextInput
|
|
141
|
+
name="name"
|
|
142
|
+
value={values.name || ''}
|
|
143
|
+
onChange={handleChange}
|
|
144
|
+
label={formatMessage({
|
|
145
|
+
id: 'global.name',
|
|
146
|
+
defaultMessage: 'Name',
|
|
147
|
+
})}
|
|
148
|
+
error={
|
|
149
|
+
errors?.name
|
|
150
|
+
? formatMessage({ id: errors.name, defaultMessage: 'Name is required' })
|
|
151
|
+
: false
|
|
152
|
+
}
|
|
153
|
+
required
|
|
154
|
+
/>
|
|
155
|
+
</GridItem>
|
|
156
|
+
<GridItem col={6}>
|
|
157
|
+
<Textarea
|
|
158
|
+
id="description"
|
|
159
|
+
value={values.description || ''}
|
|
160
|
+
onChange={handleChange}
|
|
161
|
+
label={formatMessage({
|
|
162
|
+
id: 'global.description',
|
|
163
|
+
defaultMessage: 'Description',
|
|
164
|
+
})}
|
|
165
|
+
error={
|
|
166
|
+
errors?.description
|
|
167
|
+
? formatMessage({
|
|
168
|
+
id: errors.description,
|
|
169
|
+
defaultMessage: 'Description is required',
|
|
170
|
+
})
|
|
171
|
+
: false
|
|
172
|
+
}
|
|
173
|
+
required
|
|
174
|
+
/>
|
|
175
|
+
</GridItem>
|
|
176
|
+
</Grid>
|
|
177
|
+
</Flex>
|
|
178
|
+
|
|
179
|
+
{!isLoadingPlugins && (
|
|
180
|
+
<UsersPermissions
|
|
181
|
+
ref={permissionsRef}
|
|
182
|
+
permissions={permissions}
|
|
183
|
+
routes={routes}
|
|
184
|
+
/>
|
|
185
|
+
)}
|
|
186
|
+
</Flex>
|
|
187
|
+
</ContentLayout>
|
|
188
|
+
</Form>
|
|
189
|
+
)}
|
|
190
|
+
</Formik>
|
|
191
|
+
</Main>
|
|
192
|
+
);
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
export const ProtectedRolesCreatePage = () => (
|
|
196
|
+
<CheckPagePermissions permissions={PERMISSIONS.createRole}>
|
|
197
|
+
<CreatePage />
|
|
198
|
+
</CheckPagePermissions>
|
|
199
|
+
);
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
ContentLayout,
|
|
5
|
+
HeaderLayout,
|
|
6
|
+
Main,
|
|
7
|
+
Button,
|
|
8
|
+
Flex,
|
|
9
|
+
TextInput,
|
|
10
|
+
Textarea,
|
|
11
|
+
Typography,
|
|
12
|
+
GridItem,
|
|
13
|
+
Grid,
|
|
14
|
+
} from '@strapi/design-system';
|
|
15
|
+
import {
|
|
16
|
+
CheckPagePermissions,
|
|
17
|
+
useOverlayBlocker,
|
|
18
|
+
SettingsPageTitle,
|
|
19
|
+
LoadingIndicatorPage,
|
|
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';
|
|
28
|
+
import { useIntl } from 'react-intl';
|
|
29
|
+
import { useQuery, useMutation } from 'react-query';
|
|
30
|
+
import { useRouteMatch } from 'react-router-dom';
|
|
31
|
+
|
|
32
|
+
import UsersPermissions from '../../../components/UsersPermissions';
|
|
33
|
+
import { PERMISSIONS } from '../../../constants';
|
|
34
|
+
import getTrad from '../../../utils/getTrad';
|
|
35
|
+
import { createRoleSchema } from '../constants';
|
|
36
|
+
import { usePlugins } from '../hooks/usePlugins';
|
|
37
|
+
|
|
38
|
+
export const EditPage = () => {
|
|
39
|
+
const { formatMessage } = useIntl();
|
|
40
|
+
const toggleNotification = useNotification();
|
|
41
|
+
const { lockApp, unlockApp } = useOverlayBlocker();
|
|
42
|
+
const {
|
|
43
|
+
params: { id },
|
|
44
|
+
} = useRouteMatch(`/settings/users-permissions/roles/:id`);
|
|
45
|
+
const { get } = useFetchClient();
|
|
46
|
+
const { isLoading: isLoadingPlugins, routes } = usePlugins();
|
|
47
|
+
const {
|
|
48
|
+
data: role,
|
|
49
|
+
isLoading: isLoadingRole,
|
|
50
|
+
refetch: refetchRole,
|
|
51
|
+
} = useQuery(['users-permissions', 'role', id], async () => {
|
|
52
|
+
// TODO: why doesn't this endpoint follow the admin API conventions?
|
|
53
|
+
const {
|
|
54
|
+
data: { role },
|
|
55
|
+
} = await get(`/users-permissions/roles/${id}`);
|
|
56
|
+
|
|
57
|
+
return role;
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
const permissionsRef = React.useRef();
|
|
61
|
+
const { put } = useFetchClient();
|
|
62
|
+
const { formatAPIError } = useAPIErrorHandler();
|
|
63
|
+
const mutation = useMutation((body) => put(`/users-permissions/roles/${id}`, body), {
|
|
64
|
+
onError(error) {
|
|
65
|
+
toggleNotification({
|
|
66
|
+
type: 'warning',
|
|
67
|
+
message: formatAPIError(error),
|
|
68
|
+
});
|
|
69
|
+
},
|
|
70
|
+
|
|
71
|
+
async onSuccess() {
|
|
72
|
+
toggleNotification({
|
|
73
|
+
type: 'success',
|
|
74
|
+
message: {
|
|
75
|
+
id: getTrad('Settings.roles.created'),
|
|
76
|
+
defaultMessage: 'Role edited',
|
|
77
|
+
},
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
await refetchRole();
|
|
81
|
+
},
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
const handleEditRoleSubmit = async (data) => {
|
|
85
|
+
// Set loading state
|
|
86
|
+
lockApp();
|
|
87
|
+
|
|
88
|
+
const permissions = permissionsRef.current.getPermissions();
|
|
89
|
+
|
|
90
|
+
await mutation.mutate({ ...data, ...permissions, users: [] });
|
|
91
|
+
|
|
92
|
+
unlockApp();
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
if (isLoadingRole) {
|
|
96
|
+
return <LoadingIndicatorPage />;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return (
|
|
100
|
+
<Main>
|
|
101
|
+
{/* TODO: this needs to be translated */}
|
|
102
|
+
<SettingsPageTitle name="Roles" />
|
|
103
|
+
<Formik
|
|
104
|
+
enableReinitialize
|
|
105
|
+
initialValues={{ name: role.name, description: role.description }}
|
|
106
|
+
onSubmit={handleEditRoleSubmit}
|
|
107
|
+
validationSchema={createRoleSchema}
|
|
108
|
+
>
|
|
109
|
+
{({ handleSubmit, values, handleChange, errors }) => (
|
|
110
|
+
<Form noValidate onSubmit={handleSubmit}>
|
|
111
|
+
<HeaderLayout
|
|
112
|
+
primaryAction={
|
|
113
|
+
!isLoadingPlugins && (
|
|
114
|
+
<Button
|
|
115
|
+
disabled={role.code === 'strapi-super-admin'}
|
|
116
|
+
type="submit"
|
|
117
|
+
loading={mutation.isLoading}
|
|
118
|
+
startIcon={<Check />}
|
|
119
|
+
>
|
|
120
|
+
{formatMessage({
|
|
121
|
+
id: 'global.save',
|
|
122
|
+
defaultMessage: 'Save',
|
|
123
|
+
})}
|
|
124
|
+
</Button>
|
|
125
|
+
)
|
|
126
|
+
}
|
|
127
|
+
title={role.name}
|
|
128
|
+
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
|
+
}
|
|
137
|
+
/>
|
|
138
|
+
<ContentLayout>
|
|
139
|
+
<Flex
|
|
140
|
+
background="neutral0"
|
|
141
|
+
direction="column"
|
|
142
|
+
alignItems="stretch"
|
|
143
|
+
gap={7}
|
|
144
|
+
hasRadius
|
|
145
|
+
paddingTop={6}
|
|
146
|
+
paddingBottom={6}
|
|
147
|
+
paddingLeft={7}
|
|
148
|
+
paddingRight={7}
|
|
149
|
+
shadow="filterShadow"
|
|
150
|
+
>
|
|
151
|
+
<Flex direction="column" alignItems="stretch" gap={4}>
|
|
152
|
+
<Typography variant="delta" as="h2">
|
|
153
|
+
{formatMessage({
|
|
154
|
+
id: getTrad('EditPage.form.roles'),
|
|
155
|
+
defaultMessage: 'Role details',
|
|
156
|
+
})}
|
|
157
|
+
</Typography>
|
|
158
|
+
|
|
159
|
+
<Grid gap={4}>
|
|
160
|
+
<GridItem col={6}>
|
|
161
|
+
<TextInput
|
|
162
|
+
name="name"
|
|
163
|
+
value={values.name || ''}
|
|
164
|
+
onChange={handleChange}
|
|
165
|
+
label={formatMessage({
|
|
166
|
+
id: 'global.name',
|
|
167
|
+
defaultMessage: 'Name',
|
|
168
|
+
})}
|
|
169
|
+
error={
|
|
170
|
+
errors?.name
|
|
171
|
+
? formatMessage({ id: errors.name, defaultMessage: 'Name is required' })
|
|
172
|
+
: false
|
|
173
|
+
}
|
|
174
|
+
required
|
|
175
|
+
/>
|
|
176
|
+
</GridItem>
|
|
177
|
+
<GridItem col={6}>
|
|
178
|
+
<Textarea
|
|
179
|
+
id="description"
|
|
180
|
+
value={values.description || ''}
|
|
181
|
+
onChange={handleChange}
|
|
182
|
+
label={formatMessage({
|
|
183
|
+
id: 'global.description',
|
|
184
|
+
defaultMessage: 'Description',
|
|
185
|
+
})}
|
|
186
|
+
error={
|
|
187
|
+
errors?.description
|
|
188
|
+
? formatMessage({
|
|
189
|
+
id: errors.description,
|
|
190
|
+
defaultMessage: 'Description is required',
|
|
191
|
+
})
|
|
192
|
+
: false
|
|
193
|
+
}
|
|
194
|
+
required
|
|
195
|
+
/>
|
|
196
|
+
</GridItem>
|
|
197
|
+
</Grid>
|
|
198
|
+
</Flex>
|
|
199
|
+
|
|
200
|
+
{!isLoadingPlugins && (
|
|
201
|
+
<UsersPermissions
|
|
202
|
+
ref={permissionsRef}
|
|
203
|
+
permissions={role.permissions}
|
|
204
|
+
routes={routes}
|
|
205
|
+
/>
|
|
206
|
+
)}
|
|
207
|
+
</Flex>
|
|
208
|
+
</ContentLayout>
|
|
209
|
+
</Form>
|
|
210
|
+
)}
|
|
211
|
+
</Formik>
|
|
212
|
+
</Main>
|
|
213
|
+
);
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
export const ProtectedRolesEditPage = () => (
|
|
217
|
+
<CheckPagePermissions permissions={PERMISSIONS.updateRole}>
|
|
218
|
+
<EditPage />
|
|
219
|
+
</CheckPagePermissions>
|
|
220
|
+
);
|
|
@@ -1,12 +1,39 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
|
|
3
|
-
import {
|
|
2
|
+
|
|
3
|
+
import { Flex, IconButton, Link, Tbody, Td, Tr, Typography } from '@strapi/design-system';
|
|
4
|
+
import { CheckPermissions, onRowClick, pxToRem, stopPropagation } from '@strapi/helper-plugin';
|
|
4
5
|
import { Pencil, Trash } from '@strapi/icons';
|
|
5
|
-
import
|
|
6
|
+
import PropTypes from 'prop-types';
|
|
6
7
|
import { useIntl } from 'react-intl';
|
|
7
8
|
import { useHistory } from 'react-router-dom';
|
|
9
|
+
import styled from 'styled-components';
|
|
10
|
+
|
|
11
|
+
const EditLink = styled(Link)`
|
|
12
|
+
align-items: center;
|
|
13
|
+
height: ${pxToRem(32)};
|
|
14
|
+
display: flex;
|
|
15
|
+
justify-content: center;
|
|
16
|
+
padding: ${({ theme }) => `${theme.spaces[2]}}`};
|
|
17
|
+
width: ${pxToRem(32)};
|
|
8
18
|
|
|
9
|
-
|
|
19
|
+
svg {
|
|
20
|
+
height: ${pxToRem(12)};
|
|
21
|
+
width: ${pxToRem(12)};
|
|
22
|
+
|
|
23
|
+
path {
|
|
24
|
+
fill: ${({ theme }) => theme.colors.neutral500};
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
&:hover,
|
|
29
|
+
&:focus {
|
|
30
|
+
svg {
|
|
31
|
+
path {
|
|
32
|
+
fill: ${({ theme }) => theme.colors.neutral800};
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
`;
|
|
10
37
|
|
|
11
38
|
const TableBody = ({ sortedRoles, canDelete, permissions, setRoleToDelete, onDelete }) => {
|
|
12
39
|
const { formatMessage } = useIntl();
|
|
@@ -22,7 +49,7 @@ const TableBody = ({ sortedRoles, canDelete, permissions, setRoleToDelete, onDel
|
|
|
22
49
|
};
|
|
23
50
|
|
|
24
51
|
const handleClickEdit = (id) => {
|
|
25
|
-
push(`/settings
|
|
52
|
+
push(`/settings/users-permissions/roles/${id}`);
|
|
26
53
|
};
|
|
27
54
|
|
|
28
55
|
return (
|
|
@@ -37,25 +64,29 @@ const TableBody = ({ sortedRoles, canDelete, permissions, setRoleToDelete, onDel
|
|
|
37
64
|
</Td>
|
|
38
65
|
<Td width="30%">
|
|
39
66
|
<Typography>
|
|
40
|
-
{
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
67
|
+
{formatMessage(
|
|
68
|
+
{
|
|
69
|
+
id: 'Roles.RoleRow.user-count',
|
|
70
|
+
defaultMessage: '{number, plural, =0 {# user} one {# user} other {# users}}',
|
|
71
|
+
},
|
|
72
|
+
{ number: role.nb_users }
|
|
73
|
+
)}
|
|
44
74
|
</Typography>
|
|
45
75
|
</Td>
|
|
46
76
|
<Td>
|
|
47
77
|
<Flex justifyContent="end" {...stopPropagation}>
|
|
48
78
|
<CheckPermissions permissions={permissions.updateRole}>
|
|
49
|
-
<
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
icon={<Pencil />}
|
|
53
|
-
label={formatMessage(
|
|
79
|
+
<EditLink
|
|
80
|
+
to={`/settings/users-permissions/roles/${role.id}`}
|
|
81
|
+
aria-label={formatMessage(
|
|
54
82
|
{ id: 'app.component.table.edit', defaultMessage: 'Edit {target}' },
|
|
55
83
|
{ target: `${role.name}` }
|
|
56
84
|
)}
|
|
57
|
-
|
|
85
|
+
>
|
|
86
|
+
<Pencil />
|
|
87
|
+
</EditLink>
|
|
58
88
|
</CheckPermissions>
|
|
89
|
+
|
|
59
90
|
{checkCanDeleteRole(role) && (
|
|
60
91
|
<CheckPermissions permissions={permissions.deleteRole}>
|
|
61
92
|
<IconButton
|
|
@@ -1,50 +1,50 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
|
|
2
3
|
import {
|
|
3
|
-
|
|
4
|
+
ActionLayout,
|
|
5
|
+
ContentLayout,
|
|
4
6
|
HeaderLayout,
|
|
5
7
|
Layout,
|
|
6
|
-
ContentLayout,
|
|
7
|
-
ActionLayout,
|
|
8
8
|
Main,
|
|
9
9
|
Table,
|
|
10
|
-
Tr,
|
|
11
|
-
Thead,
|
|
12
10
|
Th,
|
|
11
|
+
Thead,
|
|
12
|
+
Tr,
|
|
13
13
|
Typography,
|
|
14
14
|
useNotifyAT,
|
|
15
15
|
VisuallyHidden,
|
|
16
16
|
} from '@strapi/design-system';
|
|
17
|
-
import { Plus } from '@strapi/icons';
|
|
18
17
|
import {
|
|
19
|
-
|
|
20
|
-
SettingsPageTitle,
|
|
18
|
+
CheckPagePermissions,
|
|
21
19
|
CheckPermissions,
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
20
|
+
ConfirmDialog,
|
|
21
|
+
EmptyStateLayout,
|
|
22
|
+
LinkButton,
|
|
25
23
|
LoadingIndicatorPage,
|
|
24
|
+
NoPermissions,
|
|
26
25
|
SearchURLQuery,
|
|
26
|
+
SettingsPageTitle,
|
|
27
|
+
useCollator,
|
|
28
|
+
useFilter,
|
|
27
29
|
useFocusWhenNavigate,
|
|
30
|
+
useNotification,
|
|
28
31
|
useQueryParams,
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
useFilter,
|
|
32
|
-
useCollator,
|
|
32
|
+
useRBAC,
|
|
33
|
+
useTracking,
|
|
33
34
|
} from '@strapi/helper-plugin';
|
|
35
|
+
import { Plus } from '@strapi/icons';
|
|
34
36
|
import { useIntl } from 'react-intl';
|
|
35
|
-
import {
|
|
36
|
-
|
|
37
|
+
import { useMutation, useQuery } from 'react-query';
|
|
38
|
+
|
|
39
|
+
import { PERMISSIONS } from '../../../../constants';
|
|
40
|
+
import { getTrad } from '../../../../utils';
|
|
37
41
|
|
|
38
|
-
import { fetchData, deleteData } from './utils/api';
|
|
39
|
-
import { getTrad } from '../../../utils';
|
|
40
|
-
import pluginId from '../../../pluginId';
|
|
41
|
-
import permissions from '../../../permissions';
|
|
42
42
|
import TableBody from './components/TableBody';
|
|
43
|
+
import { deleteData, fetchData } from './utils/api';
|
|
43
44
|
|
|
44
|
-
const
|
|
45
|
+
export const RolesListPage = () => {
|
|
45
46
|
const { trackUsage } = useTracking();
|
|
46
47
|
const { formatMessage, locale } = useIntl();
|
|
47
|
-
const { push } = useHistory();
|
|
48
48
|
const toggleNotification = useNotification();
|
|
49
49
|
const { notifyStatus } = useNotifyAT();
|
|
50
50
|
const [{ query }] = useQueryParams();
|
|
@@ -54,26 +54,21 @@ const RoleListPage = () => {
|
|
|
54
54
|
const [roleToDelete, setRoleToDelete] = useState();
|
|
55
55
|
useFocusWhenNavigate();
|
|
56
56
|
|
|
57
|
-
const queryClient = useQueryClient();
|
|
58
|
-
|
|
59
|
-
const updatePermissions = useMemo(() => {
|
|
60
|
-
return {
|
|
61
|
-
create: permissions.createRole,
|
|
62
|
-
read: permissions.readRoles,
|
|
63
|
-
update: permissions.updateRole,
|
|
64
|
-
delete: permissions.deleteRole,
|
|
65
|
-
};
|
|
66
|
-
}, []);
|
|
67
|
-
|
|
68
57
|
const {
|
|
69
58
|
isLoading: isLoadingForPermissions,
|
|
70
59
|
allowedActions: { canRead, canDelete },
|
|
71
|
-
} = useRBAC(
|
|
60
|
+
} = useRBAC({
|
|
61
|
+
create: PERMISSIONS.createRole,
|
|
62
|
+
read: PERMISSIONS.readRoles,
|
|
63
|
+
update: PERMISSIONS.updateRole,
|
|
64
|
+
delete: PERMISSIONS.deleteRole,
|
|
65
|
+
});
|
|
72
66
|
|
|
73
67
|
const {
|
|
74
68
|
isLoading: isLoadingForData,
|
|
75
69
|
data: { roles },
|
|
76
70
|
isFetching,
|
|
71
|
+
refetch,
|
|
77
72
|
} = useQuery('get-roles', () => fetchData(toggleNotification, notifyStatus), {
|
|
78
73
|
initialData: {},
|
|
79
74
|
enabled: canRead,
|
|
@@ -92,11 +87,6 @@ const RoleListPage = () => {
|
|
|
92
87
|
|
|
93
88
|
const isLoading = isLoadingForData || isFetching;
|
|
94
89
|
|
|
95
|
-
const handleNewRoleClick = () => {
|
|
96
|
-
trackUsage('willCreateRole');
|
|
97
|
-
push(`/settings/${pluginId}/roles/new`);
|
|
98
|
-
};
|
|
99
|
-
|
|
100
90
|
const handleShowConfirmDelete = () => {
|
|
101
91
|
setShowConfirmDelete(!showConfirmDelete);
|
|
102
92
|
};
|
|
@@ -119,7 +109,7 @@ const RoleListPage = () => {
|
|
|
119
109
|
|
|
120
110
|
const deleteMutation = useMutation((id) => deleteData(id, toggleNotification), {
|
|
121
111
|
async onSuccess() {
|
|
122
|
-
await
|
|
112
|
+
await refetch();
|
|
123
113
|
},
|
|
124
114
|
});
|
|
125
115
|
|
|
@@ -155,13 +145,18 @@ const RoleListPage = () => {
|
|
|
155
145
|
defaultMessage: 'List of roles',
|
|
156
146
|
})}
|
|
157
147
|
primaryAction={
|
|
158
|
-
<CheckPermissions permissions={
|
|
159
|
-
<
|
|
148
|
+
<CheckPermissions permissions={PERMISSIONS.createRole}>
|
|
149
|
+
<LinkButton
|
|
150
|
+
to="/settings/users-permissions/roles/new"
|
|
151
|
+
onClick={() => trackUsage('willCreateRole')}
|
|
152
|
+
startIcon={<Plus />}
|
|
153
|
+
size="S"
|
|
154
|
+
>
|
|
160
155
|
{formatMessage({
|
|
161
156
|
id: getTrad('List.button.roles'),
|
|
162
157
|
defaultMessage: 'Add new role',
|
|
163
158
|
})}
|
|
164
|
-
</
|
|
159
|
+
</LinkButton>
|
|
165
160
|
</CheckPermissions>
|
|
166
161
|
}
|
|
167
162
|
/>
|
|
@@ -218,7 +213,7 @@ const RoleListPage = () => {
|
|
|
218
213
|
<TableBody
|
|
219
214
|
sortedRoles={sortedRoles}
|
|
220
215
|
canDelete={canDelete}
|
|
221
|
-
permissions={
|
|
216
|
+
permissions={PERMISSIONS}
|
|
222
217
|
setRoleToDelete={setRoleToDelete}
|
|
223
218
|
onDelete={[showConfirmDelete, setShowConfirmDelete]}
|
|
224
219
|
/>
|
|
@@ -238,4 +233,10 @@ const RoleListPage = () => {
|
|
|
238
233
|
);
|
|
239
234
|
};
|
|
240
235
|
|
|
241
|
-
export
|
|
236
|
+
export const ProtectedRolesListPage = () => {
|
|
237
|
+
return (
|
|
238
|
+
<CheckPagePermissions permissions={PERMISSIONS.accessRoles}>
|
|
239
|
+
<RolesListPage />
|
|
240
|
+
</CheckPagePermissions>
|
|
241
|
+
);
|
|
242
|
+
};
|