@strapi/plugin-users-permissions 0.0.0-next.c8d6478ec519888ce0cd754886474c3189efc733 → 0.0.0-next.ce51df0e18404afc8a1aa7f504c1006a7a221459
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 +16 -35
- package/admin/src/pages/AdvancedSettings/index.js +46 -30
- package/admin/src/pages/EmailTemplates/index.js +64 -53
- package/admin/src/pages/Providers/index.js +64 -62
- 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 +44 -14
- package/admin/src/pages/Roles/{ListPage → pages/ListPage}/index.js +29 -30
- package/admin/src/pages/Roles/{ListPage → pages/ListPage}/utils/api.js +2 -4
- package/admin/src/translations/zh-Hans.json +80 -80
- package/admin/src/utils/index.js +0 -1
- package/documentation/content-api.yaml +1 -1
- package/jest.config.front.js +1 -1
- package/package.json +10 -10
- package/server/bootstrap/index.js +35 -0
- package/server/controllers/auth.js +46 -13
- package/server/controllers/user.js +12 -1
- package/server/middlewares/rateLimit.js +41 -21
- 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 -70
- 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 -18
- package/admin/src/pages/EmailTemplates/utils/api.js +0 -18
- package/admin/src/pages/Providers/reducer.js +0 -54
- package/admin/src/pages/Providers/utils/api.js +0 -26
- 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/utils/getRequestURL.js +0 -5
|
@@ -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>
|
|
@@ -0,0 +1,190 @@
|
|
|
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={errors?.name ? formatMessage({ id: errors.name }) : false}
|
|
149
|
+
required
|
|
150
|
+
/>
|
|
151
|
+
</GridItem>
|
|
152
|
+
<GridItem col={6}>
|
|
153
|
+
<Textarea
|
|
154
|
+
id="description"
|
|
155
|
+
value={values.description || ''}
|
|
156
|
+
onChange={handleChange}
|
|
157
|
+
label={formatMessage({
|
|
158
|
+
id: 'global.description',
|
|
159
|
+
defaultMessage: 'Description',
|
|
160
|
+
})}
|
|
161
|
+
error={
|
|
162
|
+
errors?.description ? formatMessage({ id: errors.description }) : false
|
|
163
|
+
}
|
|
164
|
+
required
|
|
165
|
+
/>
|
|
166
|
+
</GridItem>
|
|
167
|
+
</Grid>
|
|
168
|
+
</Flex>
|
|
169
|
+
|
|
170
|
+
{!isLoadingPlugins && (
|
|
171
|
+
<UsersPermissions
|
|
172
|
+
ref={permissionsRef}
|
|
173
|
+
permissions={permissions}
|
|
174
|
+
routes={routes}
|
|
175
|
+
/>
|
|
176
|
+
)}
|
|
177
|
+
</Flex>
|
|
178
|
+
</ContentLayout>
|
|
179
|
+
</Form>
|
|
180
|
+
)}
|
|
181
|
+
</Formik>
|
|
182
|
+
</Main>
|
|
183
|
+
);
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
export const ProtectedRolesCreatePage = () => (
|
|
187
|
+
<CheckPagePermissions permissions={PERMISSIONS.createRole}>
|
|
188
|
+
<CreatePage />
|
|
189
|
+
</CheckPagePermissions>
|
|
190
|
+
);
|
|
@@ -0,0 +1,211 @@
|
|
|
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={errors?.name ? formatMessage({ id: errors.name }) : false}
|
|
170
|
+
required
|
|
171
|
+
/>
|
|
172
|
+
</GridItem>
|
|
173
|
+
<GridItem col={6}>
|
|
174
|
+
<Textarea
|
|
175
|
+
id="description"
|
|
176
|
+
value={values.description || ''}
|
|
177
|
+
onChange={handleChange}
|
|
178
|
+
label={formatMessage({
|
|
179
|
+
id: 'global.description',
|
|
180
|
+
defaultMessage: 'Description',
|
|
181
|
+
})}
|
|
182
|
+
error={
|
|
183
|
+
errors?.description ? formatMessage({ id: errors.description }) : false
|
|
184
|
+
}
|
|
185
|
+
required
|
|
186
|
+
/>
|
|
187
|
+
</GridItem>
|
|
188
|
+
</Grid>
|
|
189
|
+
</Flex>
|
|
190
|
+
|
|
191
|
+
{!isLoadingPlugins && (
|
|
192
|
+
<UsersPermissions
|
|
193
|
+
ref={permissionsRef}
|
|
194
|
+
permissions={role.permissions}
|
|
195
|
+
routes={routes}
|
|
196
|
+
/>
|
|
197
|
+
)}
|
|
198
|
+
</Flex>
|
|
199
|
+
</ContentLayout>
|
|
200
|
+
</Form>
|
|
201
|
+
)}
|
|
202
|
+
</Formik>
|
|
203
|
+
</Main>
|
|
204
|
+
);
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
export const ProtectedRolesEditPage = () => (
|
|
208
|
+
<CheckPagePermissions permissions={PERMISSIONS.updateRole}>
|
|
209
|
+
<EditPage />
|
|
210
|
+
</CheckPagePermissions>
|
|
211
|
+
);
|
|
@@ -1,13 +1,39 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
|
|
3
|
-
import { Flex, IconButton, Tbody, Td, Tr, Typography } from '@strapi/design-system';
|
|
4
|
-
import { CheckPermissions, onRowClick, stopPropagation } from '@strapi/helper-plugin';
|
|
3
|
+
import { Flex, IconButton, Link, Tbody, Td, Tr, Typography } from '@strapi/design-system';
|
|
4
|
+
import { CheckPermissions, onRowClick, pxToRem, 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
8
|
import { useHistory } from 'react-router-dom';
|
|
9
|
+
import styled from 'styled-components';
|
|
9
10
|
|
|
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)};
|
|
18
|
+
|
|
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
|
+
`;
|
|
11
37
|
|
|
12
38
|
const TableBody = ({ sortedRoles, canDelete, permissions, setRoleToDelete, onDelete }) => {
|
|
13
39
|
const { formatMessage } = useIntl();
|
|
@@ -23,7 +49,7 @@ const TableBody = ({ sortedRoles, canDelete, permissions, setRoleToDelete, onDel
|
|
|
23
49
|
};
|
|
24
50
|
|
|
25
51
|
const handleClickEdit = (id) => {
|
|
26
|
-
push(`/settings
|
|
52
|
+
push(`/settings/users-permissions/roles/${id}`);
|
|
27
53
|
};
|
|
28
54
|
|
|
29
55
|
return (
|
|
@@ -38,25 +64,29 @@ const TableBody = ({ sortedRoles, canDelete, permissions, setRoleToDelete, onDel
|
|
|
38
64
|
</Td>
|
|
39
65
|
<Td width="30%">
|
|
40
66
|
<Typography>
|
|
41
|
-
{
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
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
|
+
)}
|
|
45
74
|
</Typography>
|
|
46
75
|
</Td>
|
|
47
76
|
<Td>
|
|
48
77
|
<Flex justifyContent="end" {...stopPropagation}>
|
|
49
78
|
<CheckPermissions permissions={permissions.updateRole}>
|
|
50
|
-
<
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
icon={<Pencil />}
|
|
54
|
-
label={formatMessage(
|
|
79
|
+
<EditLink
|
|
80
|
+
to={`/settings/users-permissions/roles/${role.id}`}
|
|
81
|
+
aria-label={formatMessage(
|
|
55
82
|
{ id: 'app.component.table.edit', defaultMessage: 'Edit {target}' },
|
|
56
83
|
{ target: `${role.name}` }
|
|
57
84
|
)}
|
|
58
|
-
|
|
85
|
+
>
|
|
86
|
+
<Pencil />
|
|
87
|
+
</EditLink>
|
|
59
88
|
</CheckPermissions>
|
|
89
|
+
|
|
60
90
|
{checkCanDeleteRole(role) && (
|
|
61
91
|
<CheckPermissions permissions={permissions.deleteRole}>
|
|
62
92
|
<IconButton
|