@strapi/plugin-users-permissions 0.0.0-4fc90398602f
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/LICENSE +22 -0
- package/README.md +1 -0
- package/admin/src/components/BoundRoute/getMethodColor.js +41 -0
- package/admin/src/components/BoundRoute/index.js +72 -0
- package/admin/src/components/FormModal/Input/index.js +121 -0
- package/admin/src/components/FormModal/index.js +121 -0
- package/admin/src/components/Permissions/PermissionRow/CheckboxWrapper.js +30 -0
- package/admin/src/components/Permissions/PermissionRow/SubCategory.js +114 -0
- package/admin/src/components/Permissions/PermissionRow/index.js +53 -0
- package/admin/src/components/Permissions/index.js +56 -0
- package/admin/src/components/Permissions/init.js +9 -0
- package/admin/src/components/Permissions/reducer.js +27 -0
- package/admin/src/components/Policies/index.js +60 -0
- package/admin/src/components/UsersPermissions/index.js +94 -0
- package/admin/src/components/UsersPermissions/init.js +10 -0
- package/admin/src/components/UsersPermissions/reducer.js +60 -0
- package/admin/src/contexts/UsersPermissionsContext/index.js +17 -0
- package/admin/src/hooks/index.js +5 -0
- package/admin/src/hooks/useFetchRole/index.js +64 -0
- package/admin/src/hooks/useFetchRole/reducer.js +31 -0
- package/admin/src/hooks/useForm/index.js +70 -0
- package/admin/src/hooks/useForm/reducer.js +40 -0
- package/admin/src/hooks/usePlugins/index.js +65 -0
- package/admin/src/hooks/usePlugins/init.js +5 -0
- package/admin/src/hooks/usePlugins/reducer.js +34 -0
- package/admin/src/hooks/useRolesList/index.js +63 -0
- package/admin/src/hooks/useRolesList/init.js +5 -0
- package/admin/src/hooks/useRolesList/reducer.js +31 -0
- package/admin/src/index.js +123 -0
- package/admin/src/pages/AdvancedSettings/index.js +238 -0
- package/admin/src/pages/AdvancedSettings/utils/api.js +13 -0
- package/admin/src/pages/AdvancedSettings/utils/layout.js +96 -0
- package/admin/src/pages/AdvancedSettings/utils/schema.js +19 -0
- package/admin/src/pages/EmailTemplates/components/EmailForm.js +173 -0
- package/admin/src/pages/EmailTemplates/components/EmailTable.js +121 -0
- package/admin/src/pages/EmailTemplates/index.js +162 -0
- package/admin/src/pages/EmailTemplates/utils/api.js +13 -0
- package/admin/src/pages/EmailTemplates/utils/schema.js +22 -0
- package/admin/src/pages/Providers/index.js +274 -0
- package/admin/src/pages/Providers/reducer.js +54 -0
- package/admin/src/pages/Providers/utils/api.js +21 -0
- package/admin/src/pages/Providers/utils/createProvidersArray.js +21 -0
- package/admin/src/pages/Providers/utils/forms.js +244 -0
- package/admin/src/pages/Roles/CreatePage/index.js +177 -0
- package/admin/src/pages/Roles/CreatePage/utils/schema.js +9 -0
- package/admin/src/pages/Roles/EditPage/index.js +190 -0
- package/admin/src/pages/Roles/EditPage/utils/schema.js +9 -0
- package/admin/src/pages/Roles/ListPage/components/TableBody.js +96 -0
- package/admin/src/pages/Roles/ListPage/index.js +216 -0
- package/admin/src/pages/Roles/ListPage/utils/api.js +28 -0
- package/admin/src/pages/Roles/ProtectedCreatePage/index.js +12 -0
- package/admin/src/pages/Roles/ProtectedEditPage/index.js +12 -0
- package/admin/src/pages/Roles/ProtectedListPage/index.js +15 -0
- package/admin/src/pages/Roles/index.js +27 -0
- package/admin/src/permissions.js +31 -0
- package/admin/src/pluginId.js +5 -0
- package/admin/src/translations/ar.json +40 -0
- package/admin/src/translations/cs.json +46 -0
- package/admin/src/translations/de.json +58 -0
- package/admin/src/translations/dk.json +83 -0
- package/admin/src/translations/en.json +83 -0
- package/admin/src/translations/es.json +83 -0
- package/admin/src/translations/fr.json +46 -0
- package/admin/src/translations/id.json +58 -0
- package/admin/src/translations/it.json +58 -0
- package/admin/src/translations/ja.json +44 -0
- package/admin/src/translations/ko.json +83 -0
- package/admin/src/translations/ms.json +45 -0
- package/admin/src/translations/nl.json +44 -0
- package/admin/src/translations/pl.json +83 -0
- package/admin/src/translations/pt-BR.json +40 -0
- package/admin/src/translations/pt.json +44 -0
- package/admin/src/translations/ru.json +58 -0
- package/admin/src/translations/sk.json +46 -0
- package/admin/src/translations/sv.json +58 -0
- package/admin/src/translations/th.json +56 -0
- package/admin/src/translations/tr.json +44 -0
- package/admin/src/translations/uk.json +45 -0
- package/admin/src/translations/vi.json +46 -0
- package/admin/src/translations/zh-Hans.json +62 -0
- package/admin/src/translations/zh.json +44 -0
- package/admin/src/utils/axiosInstance.js +36 -0
- package/admin/src/utils/cleanPermissions.js +25 -0
- package/admin/src/utils/formatPluginName.js +26 -0
- package/admin/src/utils/formatPolicies.js +8 -0
- package/admin/src/utils/getRequestURL.js +5 -0
- package/admin/src/utils/getTrad.js +5 -0
- package/admin/src/utils/index.js +5 -0
- package/documentation/content-api.yaml +848 -0
- package/jest.config.front.js +10 -0
- package/package.json +60 -0
- package/server/bootstrap/grant-config.js +123 -0
- package/server/bootstrap/index.js +133 -0
- package/server/bootstrap/users-permissions-actions.js +80 -0
- package/server/config.js +23 -0
- package/server/content-types/index.js +11 -0
- package/server/content-types/permission/index.js +34 -0
- package/server/content-types/role/index.js +51 -0
- package/server/content-types/user/index.js +72 -0
- package/server/content-types/user/schema-config.js +15 -0
- package/server/controllers/auth.js +398 -0
- package/server/controllers/content-manager-user.js +175 -0
- package/server/controllers/index.js +17 -0
- package/server/controllers/permissions.js +26 -0
- package/server/controllers/role.js +77 -0
- package/server/controllers/settings.js +85 -0
- package/server/controllers/user.js +198 -0
- package/server/controllers/validation/auth.js +57 -0
- package/server/controllers/validation/email-template.js +50 -0
- package/server/controllers/validation/user.js +26 -0
- package/server/graphql/index.js +44 -0
- package/server/graphql/mutations/auth/change-password.js +38 -0
- package/server/graphql/mutations/auth/email-confirmation.js +39 -0
- package/server/graphql/mutations/auth/forgot-password.js +35 -0
- package/server/graphql/mutations/auth/login.js +35 -0
- package/server/graphql/mutations/auth/register.js +36 -0
- package/server/graphql/mutations/auth/reset-password.js +38 -0
- package/server/graphql/mutations/crud/role/create-role.js +34 -0
- package/server/graphql/mutations/crud/role/delete-role.js +25 -0
- package/server/graphql/mutations/crud/role/update-role.js +35 -0
- package/server/graphql/mutations/crud/user/create-user.js +45 -0
- package/server/graphql/mutations/crud/user/delete-user.js +39 -0
- package/server/graphql/mutations/crud/user/update-user.js +46 -0
- package/server/graphql/mutations/index.js +43 -0
- package/server/graphql/queries/index.js +13 -0
- package/server/graphql/queries/me.js +17 -0
- package/server/graphql/resolvers-configs.js +42 -0
- package/server/graphql/types/create-role-payload.js +11 -0
- package/server/graphql/types/delete-role-payload.js +11 -0
- package/server/graphql/types/index.js +21 -0
- package/server/graphql/types/login-input.js +13 -0
- package/server/graphql/types/login-payload.js +12 -0
- package/server/graphql/types/me-role.js +14 -0
- package/server/graphql/types/me.js +16 -0
- package/server/graphql/types/password-payload.js +11 -0
- package/server/graphql/types/register-input.js +13 -0
- package/server/graphql/types/update-role-payload.js +11 -0
- package/server/graphql/utils.js +27 -0
- package/server/index.js +21 -0
- package/server/middlewares/index.js +7 -0
- package/server/middlewares/rateLimit.js +27 -0
- package/server/register.js +23 -0
- package/server/routes/admin/index.js +10 -0
- package/server/routes/admin/permissions.js +20 -0
- package/server/routes/admin/role.js +79 -0
- package/server/routes/admin/settings.js +95 -0
- package/server/routes/content-api/auth.js +82 -0
- package/server/routes/content-api/index.js +11 -0
- package/server/routes/content-api/permissions.js +9 -0
- package/server/routes/content-api/role.js +29 -0
- package/server/routes/content-api/user.js +60 -0
- package/server/routes/index.js +6 -0
- package/server/services/index.js +17 -0
- package/server/services/jwt.js +55 -0
- package/server/services/providers-registry.js +292 -0
- package/server/services/providers.js +115 -0
- package/server/services/role.js +177 -0
- package/server/services/user.js +140 -0
- package/server/services/users-permissions.js +236 -0
- package/server/strategies/users-permissions.js +102 -0
- package/server/utils/index.d.ts +16 -0
- package/server/utils/index.js +12 -0
- package/server/utils/sanitize/index.js +9 -0
- package/server/utils/sanitize/sanitizers.js +19 -0
- package/server/utils/sanitize/visitors/index.js +5 -0
- package/server/utils/sanitize/visitors/remove-user-relation-from-role-entities.js +11 -0
- package/strapi-admin.js +3 -0
- package/strapi-server.js +3 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { useIntl } from 'react-intl';
|
|
3
|
+
import { Typography } from '@strapi/design-system/Typography';
|
|
4
|
+
import { Stack } from '@strapi/design-system/Stack';
|
|
5
|
+
import { GridItem } from '@strapi/design-system/Grid';
|
|
6
|
+
import { get, isEmpty, without } from 'lodash';
|
|
7
|
+
import { useUsersPermissions } from '../../contexts/UsersPermissionsContext';
|
|
8
|
+
import BoundRoute from '../BoundRoute';
|
|
9
|
+
|
|
10
|
+
const Policies = () => {
|
|
11
|
+
const { formatMessage } = useIntl();
|
|
12
|
+
const { selectedAction, routes } = useUsersPermissions();
|
|
13
|
+
|
|
14
|
+
const path = without(selectedAction.split('.'), 'controllers');
|
|
15
|
+
const controllerRoutes = get(routes, path[0]);
|
|
16
|
+
const pathResolved = path.slice(1).join('.');
|
|
17
|
+
|
|
18
|
+
const displayedRoutes = isEmpty(controllerRoutes)
|
|
19
|
+
? []
|
|
20
|
+
: controllerRoutes.filter((o) => o.handler.endsWith(pathResolved));
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<GridItem
|
|
24
|
+
col={5}
|
|
25
|
+
background="neutral150"
|
|
26
|
+
paddingTop={6}
|
|
27
|
+
paddingBottom={6}
|
|
28
|
+
paddingLeft={7}
|
|
29
|
+
paddingRight={7}
|
|
30
|
+
style={{ minHeight: '100%' }}
|
|
31
|
+
>
|
|
32
|
+
{selectedAction ? (
|
|
33
|
+
<Stack spacing={2}>
|
|
34
|
+
{displayedRoutes.map((route, key) => (
|
|
35
|
+
// eslint-disable-next-line react/no-array-index-key
|
|
36
|
+
<BoundRoute key={key} route={route} />
|
|
37
|
+
))}
|
|
38
|
+
</Stack>
|
|
39
|
+
) : (
|
|
40
|
+
<Stack spacing={2}>
|
|
41
|
+
<Typography variant="delta" as="h3">
|
|
42
|
+
{formatMessage({
|
|
43
|
+
id: 'users-permissions.Policies.header.title',
|
|
44
|
+
defaultMessage: 'Advanced settings',
|
|
45
|
+
})}
|
|
46
|
+
</Typography>
|
|
47
|
+
<Typography as="p" textColor="neutral600">
|
|
48
|
+
{formatMessage({
|
|
49
|
+
id: 'users-permissions.Policies.header.hint',
|
|
50
|
+
defaultMessage:
|
|
51
|
+
"Select the application's actions or the plugin's actions and click on the cog icon to display the bound route",
|
|
52
|
+
})}
|
|
53
|
+
</Typography>
|
|
54
|
+
</Stack>
|
|
55
|
+
)}
|
|
56
|
+
</GridItem>
|
|
57
|
+
);
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
export default Policies;
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import React, { memo, useReducer, forwardRef, useImperativeHandle } from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import { Typography } from '@strapi/design-system/Typography';
|
|
4
|
+
import { Stack } from '@strapi/design-system/Stack';
|
|
5
|
+
import { Grid, GridItem } from '@strapi/design-system/Grid';
|
|
6
|
+
import { useIntl } from 'react-intl';
|
|
7
|
+
import getTrad from '../../utils/getTrad';
|
|
8
|
+
import Policies from '../Policies';
|
|
9
|
+
import Permissions from '../Permissions';
|
|
10
|
+
import reducer, { initialState } from './reducer';
|
|
11
|
+
import { UsersPermissionsProvider } from '../../contexts/UsersPermissionsContext';
|
|
12
|
+
import init from './init';
|
|
13
|
+
|
|
14
|
+
const UsersPermissions = forwardRef(({ permissions, routes }, ref) => {
|
|
15
|
+
const { formatMessage } = useIntl();
|
|
16
|
+
const [state, dispatch] = useReducer(reducer, initialState, (state) =>
|
|
17
|
+
init(state, permissions, routes)
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
useImperativeHandle(ref, () => ({
|
|
21
|
+
getPermissions() {
|
|
22
|
+
return {
|
|
23
|
+
permissions: state.modifiedData,
|
|
24
|
+
};
|
|
25
|
+
},
|
|
26
|
+
resetForm() {
|
|
27
|
+
dispatch({ type: 'ON_RESET' });
|
|
28
|
+
},
|
|
29
|
+
setFormAfterSubmit() {
|
|
30
|
+
dispatch({ type: 'ON_SUBMIT_SUCCEEDED' });
|
|
31
|
+
},
|
|
32
|
+
}));
|
|
33
|
+
|
|
34
|
+
const handleChange = ({ target: { name, value } }) =>
|
|
35
|
+
dispatch({
|
|
36
|
+
type: 'ON_CHANGE',
|
|
37
|
+
keys: name.split('.'),
|
|
38
|
+
value: value === 'empty__string_value' ? '' : value,
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
const handleChangeSelectAll = ({ target: { name, value } }) =>
|
|
42
|
+
dispatch({
|
|
43
|
+
type: 'ON_CHANGE_SELECT_ALL',
|
|
44
|
+
keys: name.split('.'),
|
|
45
|
+
value,
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
const handleSelectedAction = (actionToSelect) =>
|
|
49
|
+
dispatch({
|
|
50
|
+
type: 'SELECT_ACTION',
|
|
51
|
+
actionToSelect,
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
const providerValue = {
|
|
55
|
+
...state,
|
|
56
|
+
onChange: handleChange,
|
|
57
|
+
onChangeSelectAll: handleChangeSelectAll,
|
|
58
|
+
onSelectedAction: handleSelectedAction,
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
return (
|
|
62
|
+
<UsersPermissionsProvider value={providerValue}>
|
|
63
|
+
<Grid gap={0} shadow="filterShadow" hasRadius background="neutral0">
|
|
64
|
+
<GridItem col={7} paddingTop={6} paddingBottom={6} paddingLeft={7} paddingRight={7}>
|
|
65
|
+
<Stack spacing={6}>
|
|
66
|
+
<Stack spacing={2}>
|
|
67
|
+
<Typography variant="delta" as="h2">
|
|
68
|
+
{formatMessage({
|
|
69
|
+
id: getTrad('Plugins.header.title'),
|
|
70
|
+
defaultMessage: 'Permissions',
|
|
71
|
+
})}
|
|
72
|
+
</Typography>
|
|
73
|
+
<Typography as="p" textColor="neutral600">
|
|
74
|
+
{formatMessage({
|
|
75
|
+
id: getTrad('Plugins.header.description'),
|
|
76
|
+
defaultMessage: 'Only actions bound by a route are listed below.',
|
|
77
|
+
})}
|
|
78
|
+
</Typography>
|
|
79
|
+
</Stack>
|
|
80
|
+
<Permissions />
|
|
81
|
+
</Stack>
|
|
82
|
+
</GridItem>
|
|
83
|
+
<Policies />
|
|
84
|
+
</Grid>
|
|
85
|
+
</UsersPermissionsProvider>
|
|
86
|
+
);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
UsersPermissions.propTypes = {
|
|
90
|
+
permissions: PropTypes.object.isRequired,
|
|
91
|
+
routes: PropTypes.object.isRequired,
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
export default memo(UsersPermissions);
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/* eslint-disable consistent-return */
|
|
2
|
+
import produce from 'immer';
|
|
3
|
+
import { set, get, take } from 'lodash';
|
|
4
|
+
|
|
5
|
+
export const initialState = {
|
|
6
|
+
initialData: {},
|
|
7
|
+
modifiedData: {},
|
|
8
|
+
routes: {},
|
|
9
|
+
selectedAction: '',
|
|
10
|
+
policies: [],
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const reducer = (state, action) =>
|
|
14
|
+
produce(state, (draftState) => {
|
|
15
|
+
switch (action.type) {
|
|
16
|
+
case 'ON_CHANGE': {
|
|
17
|
+
const keysLength = action.keys.length;
|
|
18
|
+
const isChangingCheckbox = action.keys[keysLength - 1] === 'enabled';
|
|
19
|
+
|
|
20
|
+
if (action.value && isChangingCheckbox) {
|
|
21
|
+
const selectedAction = take(action.keys, keysLength - 1).join('.');
|
|
22
|
+
draftState.selectedAction = selectedAction;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
set(draftState, ['modifiedData', ...action.keys], action.value);
|
|
26
|
+
break;
|
|
27
|
+
}
|
|
28
|
+
case 'ON_CHANGE_SELECT_ALL': {
|
|
29
|
+
const pathToValue = ['modifiedData', ...action.keys];
|
|
30
|
+
const oldValues = get(state, pathToValue, {});
|
|
31
|
+
const updatedValues = Object.keys(oldValues).reduce((acc, current) => {
|
|
32
|
+
acc[current] = { ...oldValues[current], enabled: action.value };
|
|
33
|
+
|
|
34
|
+
return acc;
|
|
35
|
+
}, {});
|
|
36
|
+
|
|
37
|
+
set(draftState, pathToValue, updatedValues);
|
|
38
|
+
|
|
39
|
+
break;
|
|
40
|
+
}
|
|
41
|
+
case 'ON_RESET': {
|
|
42
|
+
draftState.modifiedData = state.initialData;
|
|
43
|
+
break;
|
|
44
|
+
}
|
|
45
|
+
case 'ON_SUBMIT_SUCCEEDED': {
|
|
46
|
+
draftState.initialData = state.modifiedData;
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
case 'SELECT_ACTION': {
|
|
51
|
+
const { actionToSelect } = action;
|
|
52
|
+
draftState.selectedAction = actionToSelect === state.selectedAction ? '' : actionToSelect;
|
|
53
|
+
break;
|
|
54
|
+
}
|
|
55
|
+
default:
|
|
56
|
+
return draftState;
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
export default reducer;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React, { createContext, useContext } from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
|
|
4
|
+
const UsersPermissions = createContext({});
|
|
5
|
+
|
|
6
|
+
const UsersPermissionsProvider = ({ children, value }) => {
|
|
7
|
+
return <UsersPermissions.Provider value={value}>{children}</UsersPermissions.Provider>;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
const useUsersPermissions = () => useContext(UsersPermissions);
|
|
11
|
+
|
|
12
|
+
UsersPermissionsProvider.propTypes = {
|
|
13
|
+
children: PropTypes.node.isRequired,
|
|
14
|
+
value: PropTypes.object.isRequired,
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export { UsersPermissions, UsersPermissionsProvider, useUsersPermissions };
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
// eslint-disable-next-line import/prefer-default-export
|
|
2
|
+
export { default as useForm } from './useForm';
|
|
3
|
+
export { default as useRolesList } from './useRolesList';
|
|
4
|
+
export { default as usePlugins } from './usePlugins';
|
|
5
|
+
export { default as useFetchRole } from './useFetchRole';
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { useCallback, useReducer, useEffect, useRef } from 'react';
|
|
2
|
+
import { useNotification } from '@strapi/helper-plugin';
|
|
3
|
+
import reducer, { initialState } from './reducer';
|
|
4
|
+
import axiosIntance from '../../utils/axiosInstance';
|
|
5
|
+
import pluginId from '../../pluginId';
|
|
6
|
+
|
|
7
|
+
const useFetchRole = (id) => {
|
|
8
|
+
const [state, dispatch] = useReducer(reducer, initialState);
|
|
9
|
+
const toggleNotification = useNotification();
|
|
10
|
+
const isMounted = useRef(null);
|
|
11
|
+
|
|
12
|
+
useEffect(() => {
|
|
13
|
+
isMounted.current = true;
|
|
14
|
+
|
|
15
|
+
if (id) {
|
|
16
|
+
fetchRole(id);
|
|
17
|
+
} else {
|
|
18
|
+
dispatch({
|
|
19
|
+
type: 'GET_DATA_SUCCEEDED',
|
|
20
|
+
role: {},
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return () => (isMounted.current = false);
|
|
25
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
26
|
+
}, [id]);
|
|
27
|
+
|
|
28
|
+
const fetchRole = async (roleId) => {
|
|
29
|
+
try {
|
|
30
|
+
const {
|
|
31
|
+
data: { role },
|
|
32
|
+
} = await axiosIntance.get(`/${pluginId}/roles/${roleId}`);
|
|
33
|
+
|
|
34
|
+
// Prevent updating state on an unmounted component
|
|
35
|
+
if (isMounted.current) {
|
|
36
|
+
dispatch({
|
|
37
|
+
type: 'GET_DATA_SUCCEEDED',
|
|
38
|
+
role,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
} catch (err) {
|
|
42
|
+
console.error(err);
|
|
43
|
+
|
|
44
|
+
dispatch({
|
|
45
|
+
type: 'GET_DATA_ERROR',
|
|
46
|
+
});
|
|
47
|
+
toggleNotification({
|
|
48
|
+
type: 'warning',
|
|
49
|
+
message: { id: 'notification.error' },
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const handleSubmitSucceeded = useCallback((data) => {
|
|
55
|
+
dispatch({
|
|
56
|
+
type: 'ON_SUBMIT_SUCCEEDED',
|
|
57
|
+
...data,
|
|
58
|
+
});
|
|
59
|
+
}, []);
|
|
60
|
+
|
|
61
|
+
return { ...state, onSubmitSucceeded: handleSubmitSucceeded };
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
export default useFetchRole;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/* eslint-disable consistent-return */
|
|
2
|
+
import produce from 'immer';
|
|
3
|
+
|
|
4
|
+
export const initialState = {
|
|
5
|
+
role: {},
|
|
6
|
+
isLoading: true,
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
const reducer = (state, action) =>
|
|
10
|
+
produce(state, (draftState) => {
|
|
11
|
+
switch (action.type) {
|
|
12
|
+
case 'GET_DATA_SUCCEEDED': {
|
|
13
|
+
draftState.role = action.role;
|
|
14
|
+
draftState.isLoading = false;
|
|
15
|
+
break;
|
|
16
|
+
}
|
|
17
|
+
case 'GET_DATA_ERROR': {
|
|
18
|
+
draftState.isLoading = false;
|
|
19
|
+
break;
|
|
20
|
+
}
|
|
21
|
+
case 'ON_SUBMIT_SUCCEEDED': {
|
|
22
|
+
draftState.role.name = action.name;
|
|
23
|
+
draftState.role.description = action.description;
|
|
24
|
+
break;
|
|
25
|
+
}
|
|
26
|
+
default:
|
|
27
|
+
return draftState;
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
export default reducer;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { useCallback, useEffect, useReducer, useRef } from 'react';
|
|
2
|
+
import { useRBAC, request, useNotification } from '@strapi/helper-plugin';
|
|
3
|
+
import { getRequestURL } from '../../utils';
|
|
4
|
+
import reducer, { initialState } from './reducer';
|
|
5
|
+
|
|
6
|
+
const useUserForm = (endPoint, permissions) => {
|
|
7
|
+
const { isLoading: isLoadingForPermissions, allowedActions } = useRBAC(permissions);
|
|
8
|
+
const [{ isLoading, modifiedData }, dispatch] = useReducer(reducer, initialState);
|
|
9
|
+
const toggleNotification = useNotification();
|
|
10
|
+
const isMounted = useRef(true);
|
|
11
|
+
|
|
12
|
+
const abortController = new AbortController();
|
|
13
|
+
const { signal } = abortController;
|
|
14
|
+
|
|
15
|
+
useEffect(() => {
|
|
16
|
+
const getData = async () => {
|
|
17
|
+
try {
|
|
18
|
+
dispatch({
|
|
19
|
+
type: 'GET_DATA',
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
const data = await request(getRequestURL(endPoint), { method: 'GET', signal });
|
|
23
|
+
|
|
24
|
+
dispatch({
|
|
25
|
+
type: 'GET_DATA_SUCCEEDED',
|
|
26
|
+
data,
|
|
27
|
+
});
|
|
28
|
+
} catch (err) {
|
|
29
|
+
// The user aborted the request
|
|
30
|
+
if (isMounted.current) {
|
|
31
|
+
dispatch({
|
|
32
|
+
type: 'GET_DATA_ERROR',
|
|
33
|
+
});
|
|
34
|
+
console.error(err);
|
|
35
|
+
toggleNotification({
|
|
36
|
+
type: 'warning',
|
|
37
|
+
message: { id: 'notification.error' },
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
if (!isLoadingForPermissions) {
|
|
44
|
+
getData();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return () => {
|
|
48
|
+
abortController.abort();
|
|
49
|
+
isMounted.current = false;
|
|
50
|
+
};
|
|
51
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
52
|
+
}, [isLoadingForPermissions, endPoint]);
|
|
53
|
+
|
|
54
|
+
const dispatchSubmitSucceeded = useCallback((data) => {
|
|
55
|
+
dispatch({
|
|
56
|
+
type: 'ON_SUBMIT_SUCCEEDED',
|
|
57
|
+
data,
|
|
58
|
+
});
|
|
59
|
+
}, []);
|
|
60
|
+
|
|
61
|
+
return {
|
|
62
|
+
allowedActions,
|
|
63
|
+
dispatchSubmitSucceeded,
|
|
64
|
+
isLoading,
|
|
65
|
+
isLoadingForPermissions,
|
|
66
|
+
modifiedData,
|
|
67
|
+
};
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export default useUserForm;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import produce from 'immer';
|
|
2
|
+
|
|
3
|
+
const initialState = {
|
|
4
|
+
isLoading: true,
|
|
5
|
+
modifiedData: {},
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
const reducer = (state, action) =>
|
|
9
|
+
// eslint-disable-next-line consistent-return
|
|
10
|
+
produce(state, (draftState) => {
|
|
11
|
+
switch (action.type) {
|
|
12
|
+
case 'GET_DATA': {
|
|
13
|
+
draftState.isLoading = true;
|
|
14
|
+
draftState.modifiedData = {};
|
|
15
|
+
|
|
16
|
+
break;
|
|
17
|
+
}
|
|
18
|
+
case 'GET_DATA_SUCCEEDED': {
|
|
19
|
+
draftState.isLoading = false;
|
|
20
|
+
draftState.modifiedData = action.data;
|
|
21
|
+
|
|
22
|
+
break;
|
|
23
|
+
}
|
|
24
|
+
case 'GET_DATA_ERROR': {
|
|
25
|
+
draftState.isLoading = true;
|
|
26
|
+
break;
|
|
27
|
+
}
|
|
28
|
+
case 'ON_SUBMIT_SUCCEEDED': {
|
|
29
|
+
draftState.modifiedData = action.data;
|
|
30
|
+
|
|
31
|
+
break;
|
|
32
|
+
}
|
|
33
|
+
default: {
|
|
34
|
+
return draftState;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
export default reducer;
|
|
40
|
+
export { initialState };
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { useCallback, useEffect, useReducer } from 'react';
|
|
2
|
+
import { useNotification } from '@strapi/helper-plugin';
|
|
3
|
+
import { get } from 'lodash';
|
|
4
|
+
import init from './init';
|
|
5
|
+
import pluginId from '../../pluginId';
|
|
6
|
+
import { cleanPermissions } from '../../utils';
|
|
7
|
+
import axiosInstance from '../../utils/axiosInstance';
|
|
8
|
+
import reducer, { initialState } from './reducer';
|
|
9
|
+
|
|
10
|
+
const usePlugins = (shouldFetchData = true) => {
|
|
11
|
+
const toggleNotification = useNotification();
|
|
12
|
+
const [{ permissions, routes, isLoading }, dispatch] = useReducer(reducer, initialState, () =>
|
|
13
|
+
init(initialState, shouldFetchData)
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
const fetchPlugins = useCallback(async () => {
|
|
17
|
+
try {
|
|
18
|
+
dispatch({
|
|
19
|
+
type: 'GET_DATA',
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
const [{ permissions }, { routes }] = await Promise.all(
|
|
23
|
+
[`/${pluginId}/permissions`, `/${pluginId}/routes`].map(async (endpoint) => {
|
|
24
|
+
const res = await axiosInstance.get(endpoint);
|
|
25
|
+
|
|
26
|
+
return res.data;
|
|
27
|
+
})
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
dispatch({
|
|
31
|
+
type: 'GET_DATA_SUCCEEDED',
|
|
32
|
+
permissions: cleanPermissions(permissions),
|
|
33
|
+
routes,
|
|
34
|
+
});
|
|
35
|
+
} catch (err) {
|
|
36
|
+
const message = get(err, ['response', 'payload', 'message'], 'An error occured');
|
|
37
|
+
|
|
38
|
+
dispatch({
|
|
39
|
+
type: 'GET_DATA_ERROR',
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
if (message !== 'Forbidden') {
|
|
43
|
+
toggleNotification({
|
|
44
|
+
type: 'warning',
|
|
45
|
+
message,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}, [toggleNotification]);
|
|
50
|
+
|
|
51
|
+
useEffect(() => {
|
|
52
|
+
if (shouldFetchData) {
|
|
53
|
+
fetchPlugins();
|
|
54
|
+
}
|
|
55
|
+
}, [fetchPlugins, shouldFetchData]);
|
|
56
|
+
|
|
57
|
+
return {
|
|
58
|
+
permissions,
|
|
59
|
+
routes,
|
|
60
|
+
getData: fetchPlugins,
|
|
61
|
+
isLoading,
|
|
62
|
+
};
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
export default usePlugins;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/* eslint-disable consistent-return */
|
|
2
|
+
import produce from 'immer';
|
|
3
|
+
|
|
4
|
+
export const initialState = {
|
|
5
|
+
permissions: {},
|
|
6
|
+
routes: {},
|
|
7
|
+
isLoading: true,
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
const reducer = (state, action) =>
|
|
11
|
+
produce(state, (draftState) => {
|
|
12
|
+
switch (action.type) {
|
|
13
|
+
case 'GET_DATA': {
|
|
14
|
+
draftState.isLoading = true;
|
|
15
|
+
draftState.permissions = {};
|
|
16
|
+
draftState.routes = {};
|
|
17
|
+
break;
|
|
18
|
+
}
|
|
19
|
+
case 'GET_DATA_SUCCEEDED': {
|
|
20
|
+
draftState.permissions = action.permissions;
|
|
21
|
+
draftState.routes = action.routes;
|
|
22
|
+
draftState.isLoading = false;
|
|
23
|
+
break;
|
|
24
|
+
}
|
|
25
|
+
case 'GET_DATA_ERROR': {
|
|
26
|
+
draftState.isLoading = false;
|
|
27
|
+
break;
|
|
28
|
+
}
|
|
29
|
+
default:
|
|
30
|
+
return draftState;
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
export default reducer;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { useEffect, useReducer, useRef } from 'react';
|
|
2
|
+
import { request, useNotification } from '@strapi/helper-plugin';
|
|
3
|
+
import { get } from 'lodash';
|
|
4
|
+
import init from './init';
|
|
5
|
+
import pluginId from '../../pluginId';
|
|
6
|
+
import reducer, { initialState } from './reducer';
|
|
7
|
+
|
|
8
|
+
const useRolesList = (shouldFetchData = true) => {
|
|
9
|
+
const [{ roles, isLoading }, dispatch] = useReducer(reducer, initialState, () =>
|
|
10
|
+
init(initialState, shouldFetchData)
|
|
11
|
+
);
|
|
12
|
+
const toggleNotification = useNotification();
|
|
13
|
+
|
|
14
|
+
const isMounted = useRef(true);
|
|
15
|
+
const abortController = new AbortController();
|
|
16
|
+
const { signal } = abortController;
|
|
17
|
+
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
if (shouldFetchData) {
|
|
20
|
+
fetchRolesList();
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return () => {
|
|
24
|
+
abortController.abort();
|
|
25
|
+
isMounted.current = false;
|
|
26
|
+
};
|
|
27
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
28
|
+
}, [shouldFetchData]);
|
|
29
|
+
|
|
30
|
+
const fetchRolesList = async () => {
|
|
31
|
+
try {
|
|
32
|
+
dispatch({
|
|
33
|
+
type: 'GET_DATA',
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
const { roles } = await request(`/${pluginId}/roles`, { method: 'GET', signal });
|
|
37
|
+
|
|
38
|
+
dispatch({
|
|
39
|
+
type: 'GET_DATA_SUCCEEDED',
|
|
40
|
+
data: roles,
|
|
41
|
+
});
|
|
42
|
+
} catch (err) {
|
|
43
|
+
const message = get(err, ['response', 'payload', 'message'], 'An error occured');
|
|
44
|
+
|
|
45
|
+
if (isMounted.current) {
|
|
46
|
+
dispatch({
|
|
47
|
+
type: 'GET_DATA_ERROR',
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
if (message !== 'Forbidden') {
|
|
51
|
+
toggleNotification({
|
|
52
|
+
type: 'warning',
|
|
53
|
+
message,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
return { roles, isLoading, getData: fetchRolesList };
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
export default useRolesList;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/* eslint-disable consistent-return */
|
|
2
|
+
import produce from 'immer';
|
|
3
|
+
|
|
4
|
+
export const initialState = {
|
|
5
|
+
roles: [],
|
|
6
|
+
isLoading: true,
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
const reducer = (state, action) =>
|
|
10
|
+
produce(state, (draftState) => {
|
|
11
|
+
switch (action.type) {
|
|
12
|
+
case 'GET_DATA': {
|
|
13
|
+
draftState.isLoading = true;
|
|
14
|
+
draftState.roles = [];
|
|
15
|
+
break;
|
|
16
|
+
}
|
|
17
|
+
case 'GET_DATA_SUCCEEDED': {
|
|
18
|
+
draftState.roles = action.data;
|
|
19
|
+
draftState.isLoading = false;
|
|
20
|
+
break;
|
|
21
|
+
}
|
|
22
|
+
case 'GET_DATA_ERROR': {
|
|
23
|
+
draftState.isLoading = false;
|
|
24
|
+
break;
|
|
25
|
+
}
|
|
26
|
+
default:
|
|
27
|
+
return draftState;
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
export default reducer;
|