@akemona-org/strapi-plugin-users-permissions 3.7.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.
Files changed (143) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +19 -0
  3. package/admin/src/assets/images/logo.svg +1 -0
  4. package/admin/src/components/BaselineAlignement/index.js +33 -0
  5. package/admin/src/components/Bloc/index.js +10 -0
  6. package/admin/src/components/BoundRoute/Components.js +78 -0
  7. package/admin/src/components/BoundRoute/index.js +56 -0
  8. package/admin/src/components/ContainerFluid/index.js +13 -0
  9. package/admin/src/components/FormBloc/index.js +61 -0
  10. package/admin/src/components/IntlInput/index.js +38 -0
  11. package/admin/src/components/ListBaselineAlignment/index.js +8 -0
  12. package/admin/src/components/ListRow/Components.js +74 -0
  13. package/admin/src/components/ListRow/index.js +35 -0
  14. package/admin/src/components/ModalForm/Wrapper.js +12 -0
  15. package/admin/src/components/ModalForm/index.js +59 -0
  16. package/admin/src/components/Permissions/ListWrapper.js +9 -0
  17. package/admin/src/components/Permissions/PermissionRow/BaselineAlignment.js +7 -0
  18. package/admin/src/components/Permissions/PermissionRow/CheckboxWrapper.js +37 -0
  19. package/admin/src/components/Permissions/PermissionRow/RowStyle.js +28 -0
  20. package/admin/src/components/Permissions/PermissionRow/SubCategory/ConditionsButtonWrapper.js +13 -0
  21. package/admin/src/components/Permissions/PermissionRow/SubCategory/PolicyWrapper.js +8 -0
  22. package/admin/src/components/Permissions/PermissionRow/SubCategory/SubCategoryWrapper.js +26 -0
  23. package/admin/src/components/Permissions/PermissionRow/SubCategory/index.js +116 -0
  24. package/admin/src/components/Permissions/PermissionRow/index.js +92 -0
  25. package/admin/src/components/Permissions/index.js +44 -0
  26. package/admin/src/components/Permissions/init.js +14 -0
  27. package/admin/src/components/Permissions/reducer.js +27 -0
  28. package/admin/src/components/Policies/Components.js +26 -0
  29. package/admin/src/components/Policies/index.js +61 -0
  30. package/admin/src/components/PrefixedIcon/index.js +27 -0
  31. package/admin/src/components/Roles/EmptyRole/BaselineAlignment.js +7 -0
  32. package/admin/src/components/Roles/EmptyRole/index.js +27 -0
  33. package/admin/src/components/Roles/RoleListWrapper/index.js +17 -0
  34. package/admin/src/components/Roles/RoleRow/RoleDescription.js +9 -0
  35. package/admin/src/components/Roles/RoleRow/index.js +45 -0
  36. package/admin/src/components/Roles/index.js +3 -0
  37. package/admin/src/components/SizedInput/index.js +24 -0
  38. package/admin/src/components/UsersPermissions/index.js +91 -0
  39. package/admin/src/components/UsersPermissions/init.js +11 -0
  40. package/admin/src/components/UsersPermissions/reducer.js +60 -0
  41. package/admin/src/containers/AdvancedSettings/index.js +218 -0
  42. package/admin/src/containers/AdvancedSettings/reducer.js +65 -0
  43. package/admin/src/containers/AdvancedSettings/utils/form.js +52 -0
  44. package/admin/src/containers/EmailTemplates/CustomTextInput.js +105 -0
  45. package/admin/src/containers/EmailTemplates/Wrapper.js +36 -0
  46. package/admin/src/containers/EmailTemplates/index.js +222 -0
  47. package/admin/src/containers/EmailTemplates/reducer.js +58 -0
  48. package/admin/src/containers/EmailTemplates/utils/forms.js +81 -0
  49. package/admin/src/containers/EmailTemplates/utils/schema.js +25 -0
  50. package/admin/src/containers/Providers/index.js +283 -0
  51. package/admin/src/containers/Providers/reducer.js +54 -0
  52. package/admin/src/containers/Providers/utils/createProvidersArray.js +21 -0
  53. package/admin/src/containers/Providers/utils/forms.js +205 -0
  54. package/admin/src/containers/Roles/CreatePage/index.js +167 -0
  55. package/admin/src/containers/Roles/CreatePage/utils/schema.js +9 -0
  56. package/admin/src/containers/Roles/EditPage/index.js +161 -0
  57. package/admin/src/containers/Roles/EditPage/utils/schema.js +9 -0
  58. package/admin/src/containers/Roles/ListPage/BaselineAlignment.js +8 -0
  59. package/admin/src/containers/Roles/ListPage/index.js +188 -0
  60. package/admin/src/containers/Roles/ProtectedCreatePage/index.js +12 -0
  61. package/admin/src/containers/Roles/ProtectedEditPage/index.js +12 -0
  62. package/admin/src/containers/Roles/ProtectedListPage/index.js +15 -0
  63. package/admin/src/containers/Roles/index.js +35 -0
  64. package/admin/src/contexts/EditPage/index.js +26 -0
  65. package/admin/src/contexts/HomePage/index.js +27 -0
  66. package/admin/src/contexts/UsersPermissionsContext/index.js +17 -0
  67. package/admin/src/hooks/index.js +5 -0
  68. package/admin/src/hooks/useFetchRole/index.js +55 -0
  69. package/admin/src/hooks/useFetchRole/reducer.js +31 -0
  70. package/admin/src/hooks/useForm/index.js +96 -0
  71. package/admin/src/hooks/useForm/reducer.js +59 -0
  72. package/admin/src/hooks/usePlugins/index.js +73 -0
  73. package/admin/src/hooks/usePlugins/init.js +5 -0
  74. package/admin/src/hooks/usePlugins/reducer.js +37 -0
  75. package/admin/src/hooks/useRolesList/index.js +62 -0
  76. package/admin/src/hooks/useRolesList/init.js +5 -0
  77. package/admin/src/hooks/useRolesList/reducer.js +31 -0
  78. package/admin/src/index.js +109 -0
  79. package/admin/src/permissions.js +33 -0
  80. package/admin/src/pluginId.js +5 -0
  81. package/admin/src/translations/ar.json +49 -0
  82. package/admin/src/translations/cs.json +55 -0
  83. package/admin/src/translations/de.json +68 -0
  84. package/admin/src/translations/dk.json +116 -0
  85. package/admin/src/translations/en.json +104 -0
  86. package/admin/src/translations/es.json +70 -0
  87. package/admin/src/translations/fr.json +55 -0
  88. package/admin/src/translations/id.json +69 -0
  89. package/admin/src/translations/index.js +55 -0
  90. package/admin/src/translations/it.json +68 -0
  91. package/admin/src/translations/ja.json +53 -0
  92. package/admin/src/translations/ko.json +55 -0
  93. package/admin/src/translations/ms.json +54 -0
  94. package/admin/src/translations/nl.json +53 -0
  95. package/admin/src/translations/pl.json +55 -0
  96. package/admin/src/translations/pt-BR.json +49 -0
  97. package/admin/src/translations/pt.json +53 -0
  98. package/admin/src/translations/ru.json +68 -0
  99. package/admin/src/translations/sk.json +57 -0
  100. package/admin/src/translations/sv.json +68 -0
  101. package/admin/src/translations/th.json +66 -0
  102. package/admin/src/translations/tr.json +53 -0
  103. package/admin/src/translations/uk.json +54 -0
  104. package/admin/src/translations/vi.json +55 -0
  105. package/admin/src/translations/zh-Hans.json +104 -0
  106. package/admin/src/translations/zh.json +53 -0
  107. package/admin/src/utils/cleanPermissions.js +25 -0
  108. package/admin/src/utils/formatPolicies.js +8 -0
  109. package/admin/src/utils/getRequestURL.js +5 -0
  110. package/admin/src/utils/getTrad.js +5 -0
  111. package/admin/src/utils/index.js +4 -0
  112. package/config/functions/bootstrap.js +234 -0
  113. package/config/layout.js +10 -0
  114. package/config/policies/isAuthenticated.js +9 -0
  115. package/config/policies/permissions.js +93 -0
  116. package/config/policies/rateLimit.js +33 -0
  117. package/config/request.json +6 -0
  118. package/config/routes.json +397 -0
  119. package/config/schema.graphql.js +280 -0
  120. package/config/security.json +5 -0
  121. package/config/users-permissions-actions.js +80 -0
  122. package/controllers/Auth.js +612 -0
  123. package/controllers/User.js +125 -0
  124. package/controllers/UsersPermissions.js +291 -0
  125. package/controllers/user/admin.js +224 -0
  126. package/controllers/user/api.js +173 -0
  127. package/controllers/validation/email-template.js +40 -0
  128. package/documentation/1.0.0/overrides/users-permissions-Role.json +281 -0
  129. package/documentation/1.0.0/overrides/users-permissions-User.json +325 -0
  130. package/middlewares/users-permissions/defaults.json +5 -0
  131. package/middlewares/users-permissions/index.js +40 -0
  132. package/models/Permission.js +7 -0
  133. package/models/Permission.settings.json +43 -0
  134. package/models/Role.js +7 -0
  135. package/models/Role.settings.json +42 -0
  136. package/models/User.config.js +15 -0
  137. package/models/User.js +7 -0
  138. package/models/User.settings.json +62 -0
  139. package/package.json +70 -0
  140. package/services/Jwt.js +65 -0
  141. package/services/Providers.js +596 -0
  142. package/services/User.js +167 -0
  143. package/services/UsersPermissions.js +416 -0
@@ -0,0 +1,188 @@
1
+ import React, { useCallback, useMemo, useState } from 'react';
2
+ import { List, Header } from '@buffetjs/custom';
3
+ import { Helmet } from 'react-helmet';
4
+ import { useIntl } from 'react-intl';
5
+ import { useHistory } from 'react-router-dom';
6
+ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
7
+ import { useUserPermissions, PopUpWarning, request, useGlobalContext } from 'strapi-helper-plugin';
8
+
9
+ import permissions from '../../../permissions';
10
+ import { EmptyRole, RoleListWrapper, RoleRow } from '../../../components/Roles';
11
+ import { useRolesList } from '../../../hooks';
12
+ import BaselineAlignment from './BaselineAlignment';
13
+ import pluginId from '../../../pluginId';
14
+ import { getTrad } from '../../../utils';
15
+
16
+ const RoleListPage = () => {
17
+ const { formatMessage } = useIntl();
18
+ const { emitEvent } = useGlobalContext();
19
+ const { push } = useHistory();
20
+
21
+ const [modalToDelete, setModalDelete] = useState();
22
+ const [shouldRefetchData, setShouldRefetchData] = useState(false);
23
+ const [showModalConfirmButtonLoading, setModalButtonLoading] = useState(false);
24
+
25
+ const updatePermissions = useMemo(() => {
26
+ return {
27
+ update: permissions.updateRole,
28
+ create: permissions.createRole,
29
+ delete: permissions.deleteRole,
30
+ read: permissions.readRoles,
31
+ };
32
+ }, []);
33
+ const {
34
+ isLoading: isLoadingForPermissions,
35
+ allowedActions: { canCreate, canUpdate, canDelete, canRead },
36
+ } = useUserPermissions(updatePermissions);
37
+ const shouldFetchData = !isLoadingForPermissions && canRead;
38
+
39
+ const { roles, getData, isLoading } = useRolesList(shouldFetchData);
40
+
41
+ const handleGoTo = id => {
42
+ if (canUpdate) {
43
+ push(`/settings/${pluginId}/roles/${id}`);
44
+ }
45
+ };
46
+
47
+ const handleDelete = () => {
48
+ strapi.lockAppWithOverlay();
49
+
50
+ setModalButtonLoading(true);
51
+
52
+ Promise.resolve(
53
+ request(`/${pluginId}/roles/${modalToDelete}`, {
54
+ method: 'DELETE',
55
+ })
56
+ )
57
+ .then(() => {
58
+ setShouldRefetchData(true);
59
+ strapi.notification.toggle({
60
+ type: 'success',
61
+ message: { id: getTrad('Settings.roles.deleted') },
62
+ });
63
+ })
64
+ .catch(err => {
65
+ console.error(err);
66
+ strapi.notification.toggle({
67
+ type: 'warning',
68
+ message: { id: 'notification.error' },
69
+ });
70
+ })
71
+ .finally(() => {
72
+ setModalDelete(null);
73
+ strapi.unlockApp();
74
+ });
75
+ };
76
+
77
+ const handleClosedModalDelete = () => {
78
+ if (shouldRefetchData) {
79
+ getData();
80
+ }
81
+ setModalButtonLoading(false);
82
+ setShouldRefetchData(false);
83
+ };
84
+
85
+ const handleNewRoleClick = () => {
86
+ emitEvent('willCreateRole');
87
+ push(`/settings/${pluginId}/roles/new`);
88
+ };
89
+
90
+ /* eslint-disable indent */
91
+ const headerActions = canCreate
92
+ ? [
93
+ {
94
+ label: formatMessage({
95
+ id: getTrad('List.button.roles'),
96
+ defaultMessage: 'Add new role',
97
+ }),
98
+ onClick: handleNewRoleClick,
99
+ color: 'primary',
100
+ type: 'button',
101
+ icon: true,
102
+ },
103
+ ]
104
+ : [];
105
+ /* eslint-enable indent */
106
+
107
+ const checkCanDeleteRole = useCallback(
108
+ role => {
109
+ return canDelete && !['public', 'authenticated'].includes(role.type);
110
+ },
111
+ [canDelete]
112
+ );
113
+
114
+ const getLinks = role => {
115
+ const links = [];
116
+
117
+ if (canUpdate) {
118
+ links.push({
119
+ icon: <FontAwesomeIcon icon="pencil-alt" />,
120
+ onClick: () => handleGoTo(role.id),
121
+ });
122
+ }
123
+ if (checkCanDeleteRole(role)) {
124
+ links.push({
125
+ icon: <FontAwesomeIcon icon="trash-alt" />,
126
+ onClick: e => {
127
+ e.preventDefault();
128
+ setModalDelete(role.id);
129
+ e.stopPropagation();
130
+ },
131
+ });
132
+ }
133
+
134
+ return links;
135
+ };
136
+
137
+ return (
138
+ <>
139
+ <Helmet title={formatMessage({ id: getTrad('page.title') })} />
140
+
141
+ <Header
142
+ icon
143
+ title={{
144
+ label: formatMessage({
145
+ id: getTrad('Settings.roles.title'),
146
+ defaultMessage: 'Roles & Permissions',
147
+ }),
148
+ }}
149
+ content={formatMessage({
150
+ id: getTrad('Settings.roles.list.description'),
151
+ defaultMessage: 'Define the roles and permissions for your users.',
152
+ })}
153
+ actions={headerActions}
154
+ // Show a loader in the header while requesting data
155
+ isLoading={isLoading || isLoadingForPermissions}
156
+ />
157
+
158
+ <BaselineAlignment />
159
+ {canRead && (
160
+ <RoleListWrapper>
161
+ <List
162
+ title={formatMessage(
163
+ {
164
+ id: `Settings.roles.list.title${roles.length > 1 ? '.plural' : '.singular'}`,
165
+ },
166
+ { number: roles.length }
167
+ )}
168
+ items={roles}
169
+ isLoading={isLoading || isLoadingForPermissions}
170
+ customRowComponent={role => (
171
+ <RoleRow onClick={() => handleGoTo(role.id)} links={getLinks(role)} role={role} />
172
+ )}
173
+ />
174
+ {!roles && !isLoading && !isLoadingForPermissions && <EmptyRole />}
175
+ <PopUpWarning
176
+ isOpen={Boolean(modalToDelete)}
177
+ onConfirm={handleDelete}
178
+ onClosed={handleClosedModalDelete}
179
+ toggleModal={() => setModalDelete(null)}
180
+ isConfirmButtonLoading={showModalConfirmButtonLoading}
181
+ />
182
+ </RoleListWrapper>
183
+ )}
184
+ </>
185
+ );
186
+ };
187
+
188
+ export default RoleListPage;
@@ -0,0 +1,12 @@
1
+ import React from 'react';
2
+ import { CheckPagePermissions } from 'strapi-helper-plugin';
3
+ import pluginPermissions from '../../../permissions';
4
+ import RolesCreatePage from '../CreatePage';
5
+
6
+ const ProtectedRolesCreatePage = () => (
7
+ <CheckPagePermissions permissions={pluginPermissions.createRole}>
8
+ <RolesCreatePage />
9
+ </CheckPagePermissions>
10
+ );
11
+
12
+ export default ProtectedRolesCreatePage;
@@ -0,0 +1,12 @@
1
+ import React from 'react';
2
+ import { CheckPagePermissions } from 'strapi-helper-plugin';
3
+ import pluginPermissions from '../../../permissions';
4
+ import RolesEditPage from '../EditPage';
5
+
6
+ const ProtectedRolesEditPage = () => (
7
+ <CheckPagePermissions permissions={pluginPermissions.updateRole}>
8
+ <RolesEditPage />
9
+ </CheckPagePermissions>
10
+ );
11
+
12
+ export default ProtectedRolesEditPage;
@@ -0,0 +1,15 @@
1
+ import React from 'react';
2
+ import { CheckPagePermissions } from 'strapi-helper-plugin';
3
+ import pluginPermissions from '../../../permissions';
4
+
5
+ import RolesListPage from '../ListPage';
6
+
7
+ const ProtectedRolesListPage = () => {
8
+ return (
9
+ <CheckPagePermissions permissions={pluginPermissions.accessRoles}>
10
+ <RolesListPage />
11
+ </CheckPagePermissions>
12
+ );
13
+ };
14
+
15
+ export default ProtectedRolesListPage;
@@ -0,0 +1,35 @@
1
+ import React from 'react';
2
+ import { Switch, Route } from 'react-router-dom';
3
+ import { useGlobalContext, NotFound } from 'strapi-helper-plugin';
4
+ import pluginId from '../../pluginId';
5
+
6
+ import ProtectedRolesListPage from './ProtectedListPage';
7
+ import ProtectedRolesEditPage from './ProtectedEditPage';
8
+ import ProtectedRolesCreatePage from './ProtectedCreatePage';
9
+
10
+ const Roles = () => {
11
+ const { settingsBaseURL } = useGlobalContext();
12
+
13
+ return (
14
+ <Switch>
15
+ <Route
16
+ path={`${settingsBaseURL}/${pluginId}/roles/new`}
17
+ component={ProtectedRolesCreatePage}
18
+ exact
19
+ />
20
+ <Route
21
+ path={`${settingsBaseURL}/${pluginId}/roles/:id`}
22
+ component={ProtectedRolesEditPage}
23
+ exact
24
+ />
25
+ <Route
26
+ path={`${settingsBaseURL}/${pluginId}/roles`}
27
+ component={ProtectedRolesListPage}
28
+ exact
29
+ />
30
+ <Route path="" component={NotFound} />
31
+ </Switch>
32
+ );
33
+ };
34
+
35
+ export default Roles;
@@ -0,0 +1,26 @@
1
+ import React, { createContext, useContext } from 'react';
2
+ import PropTypes from 'prop-types';
3
+
4
+ const EditPageContext = createContext({});
5
+
6
+ const EditPageContextProvider = ({ children, ...rest }) => {
7
+ return <EditPageContext.Provider value={rest}>{children}</EditPageContext.Provider>;
8
+ };
9
+
10
+ const useEditPageContext = () => useContext(EditPageContext);
11
+
12
+ EditPageContextProvider.defaultProps = {
13
+ emitEvent: () => {},
14
+ };
15
+
16
+ EditPageContextProvider.propTypes = {
17
+ children: PropTypes.node.isRequired,
18
+ emitEvent: PropTypes.func,
19
+ onChange: PropTypes.func.isRequired,
20
+ selectAllActions: PropTypes.func.isRequired,
21
+ setInputPoliciesPath: PropTypes.func.isRequired,
22
+ setShouldDisplayPolicieshint: PropTypes.func.isRequired,
23
+ resetShouldDisplayPoliciesHint: PropTypes.func.isRequired,
24
+ };
25
+
26
+ export { EditPageContext, EditPageContextProvider, useEditPageContext };
@@ -0,0 +1,27 @@
1
+ import React, { createContext, useContext } from 'react';
2
+ import PropTypes from 'prop-types';
3
+
4
+ const HomePageContext = createContext({});
5
+
6
+ const HomePageContextProvider = ({ children, ...rest }) => {
7
+ return <HomePageContext.Provider value={rest}>{children}</HomePageContext.Provider>;
8
+ };
9
+
10
+ const useHomePageContext = () => useContext(HomePageContext);
11
+
12
+ HomePageContextProvider.defaultProps = {
13
+ pathname: '',
14
+ push: () => {},
15
+ setDataToEdit: () => {},
16
+ unsetDataToEdit: () => {},
17
+ };
18
+
19
+ HomePageContextProvider.propTypes = {
20
+ children: PropTypes.node.isRequired,
21
+ pathname: PropTypes.string,
22
+ push: PropTypes.func,
23
+ setDataToEdit: PropTypes.func,
24
+ unsetDataToEdit: PropTypes.func,
25
+ };
26
+
27
+ export { HomePageContext, HomePageContextProvider, useHomePageContext };
@@ -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,55 @@
1
+ import { useCallback, useReducer, useEffect } from 'react';
2
+ import { request } from 'strapi-helper-plugin';
3
+
4
+ import reducer, { initialState } from './reducer';
5
+
6
+ import pluginId from '../../pluginId';
7
+
8
+ const useFetchRole = id => {
9
+ const [state, dispatch] = useReducer(reducer, initialState);
10
+
11
+ useEffect(() => {
12
+ if (id) {
13
+ fetchRole(id);
14
+ } else {
15
+ dispatch({
16
+ type: 'GET_DATA_SUCCEEDED',
17
+ role: {},
18
+ });
19
+ }
20
+
21
+ // eslint-disable-next-line react-hooks/exhaustive-deps
22
+ }, [id]);
23
+
24
+ const fetchRole = async roleId => {
25
+ try {
26
+ const { role } = await request(`/${pluginId}/roles/${roleId}`, { method: 'GET' });
27
+
28
+ dispatch({
29
+ type: 'GET_DATA_SUCCEEDED',
30
+ role,
31
+ });
32
+ } catch (err) {
33
+ console.error(err);
34
+
35
+ dispatch({
36
+ type: 'GET_DATA_ERROR',
37
+ });
38
+ strapi.notification.toggle({
39
+ type: 'warning',
40
+ message: { id: 'notification.error' },
41
+ });
42
+ }
43
+ };
44
+
45
+ const handleSubmitSucceeded = useCallback(data => {
46
+ dispatch({
47
+ type: 'ON_SUBMIT_SUCCEEDED',
48
+ ...data,
49
+ });
50
+ }, []);
51
+
52
+ return { ...state, onSubmitSucceeded: handleSubmitSucceeded };
53
+ };
54
+
55
+ 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,96 @@
1
+ import { useCallback, useEffect, useReducer, useRef } from 'react';
2
+ import { useUserPermissions, request } 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 } = useUserPermissions(permissions);
8
+ const [{ formErrors, initialData, isLoading, modifiedData }, dispatch] = useReducer(
9
+ reducer,
10
+ initialState
11
+ );
12
+
13
+ const isMounted = useRef(true);
14
+
15
+ const abortController = new AbortController();
16
+ const { signal } = abortController;
17
+
18
+ useEffect(() => {
19
+ const getData = async () => {
20
+ try {
21
+ dispatch({
22
+ type: 'GET_DATA',
23
+ });
24
+
25
+ const data = await request(getRequestURL(endPoint), { method: 'GET', signal });
26
+
27
+ dispatch({
28
+ type: 'GET_DATA_SUCCEEDED',
29
+ data,
30
+ });
31
+ } catch (err) {
32
+ // The user aborted the request
33
+ if (isMounted.current) {
34
+ dispatch({
35
+ type: 'GET_DATA_ERROR',
36
+ });
37
+ console.error(err);
38
+ strapi.notification.toggle({
39
+ type: 'warning',
40
+ message: { id: 'notification.error' },
41
+ });
42
+ }
43
+ }
44
+ };
45
+
46
+ if (!isLoadingForPermissions) {
47
+ getData();
48
+ }
49
+
50
+ return () => {
51
+ abortController.abort();
52
+ isMounted.current = false;
53
+ };
54
+ // eslint-disable-next-line react-hooks/exhaustive-deps
55
+ }, [isLoadingForPermissions, endPoint]);
56
+
57
+ const handleChange = useCallback(({ target: { name, value } }) => {
58
+ dispatch({
59
+ type: 'ON_CHANGE',
60
+ keys: name,
61
+ value,
62
+ });
63
+ }, []);
64
+
65
+ const dispatchResetForm = useCallback(() => {
66
+ dispatch({
67
+ type: 'RESET_FORM',
68
+ });
69
+ }, []);
70
+
71
+ const dispatchSetFormErrors = useCallback(errors => {
72
+ dispatch({ type: 'SET_ERRORS', errors });
73
+ }, []);
74
+
75
+ const dispatchSubmitSucceeded = useCallback(() => {
76
+ dispatch({
77
+ type: 'ON_SUBMIT_SUCCEEDED',
78
+ });
79
+ }, []);
80
+
81
+ return {
82
+ allowedActions,
83
+ dispatch,
84
+ dispatchResetForm,
85
+ dispatchSetFormErrors,
86
+ dispatchSubmitSucceeded,
87
+ formErrors,
88
+ handleChange,
89
+ initialData,
90
+ isLoading,
91
+ isLoadingForPermissions,
92
+ modifiedData,
93
+ };
94
+ };
95
+
96
+ export default useUserForm;
@@ -0,0 +1,59 @@
1
+ import produce from 'immer';
2
+ import { set } from 'lodash';
3
+
4
+ const initialState = {
5
+ formErrors: {},
6
+ isLoading: true,
7
+ initialData: {},
8
+ modifiedData: {},
9
+ };
10
+
11
+ const reducer = (state, action) =>
12
+ // eslint-disable-next-line consistent-return
13
+ produce(state, draftState => {
14
+ switch (action.type) {
15
+ case 'GET_DATA': {
16
+ draftState.isLoading = true;
17
+ draftState.initialData = {};
18
+ draftState.modifiedData = {};
19
+
20
+ break;
21
+ }
22
+
23
+ case 'GET_DATA_SUCCEEDED': {
24
+ draftState.isLoading = false;
25
+ draftState.initialData = action.data;
26
+ draftState.modifiedData = action.data;
27
+
28
+ break;
29
+ }
30
+ case 'GET_DATA_ERROR': {
31
+ draftState.isLoading = true;
32
+ break;
33
+ }
34
+ case 'ON_CHANGE': {
35
+ set(draftState, ['modifiedData', ...action.keys.split('.')], action.value);
36
+ break;
37
+ }
38
+ case 'ON_SUBMIT_SUCCEEDED': {
39
+ draftState.initialData = state.modifiedData;
40
+ draftState.formErrors = {};
41
+ break;
42
+ }
43
+ case 'RESET_FORM': {
44
+ draftState.modifiedData = state.initialData;
45
+ draftState.formErrors = {};
46
+ break;
47
+ }
48
+ case 'SET_ERRORS': {
49
+ draftState.formErrors = action.errors;
50
+ break;
51
+ }
52
+ default: {
53
+ return draftState;
54
+ }
55
+ }
56
+ });
57
+
58
+ export default reducer;
59
+ export { initialState };
@@ -0,0 +1,73 @@
1
+ import { useCallback, useEffect, useReducer } from 'react';
2
+ import { request } from 'strapi-helper-plugin';
3
+ import { useIntl } from 'react-intl';
4
+ import { get } from 'lodash';
5
+ import init from './init';
6
+ import pluginId from '../../pluginId';
7
+ import { cleanPermissions, formatPolicies, getTrad } from '../../utils';
8
+ import reducer, { initialState } from './reducer';
9
+
10
+ const usePlugins = (shouldFetchData = true) => {
11
+ const { formatMessage } = useIntl();
12
+ const [{ permissions, routes, policies, isLoading }, dispatch] = useReducer(
13
+ reducer,
14
+ initialState,
15
+ () => init(initialState, shouldFetchData)
16
+ );
17
+
18
+ const fetchPlugins = useCallback(async () => {
19
+ try {
20
+ dispatch({
21
+ type: 'GET_DATA',
22
+ });
23
+
24
+ const [{ permissions }, { routes }, { policies }] = await Promise.all(
25
+ [`/${pluginId}/permissions`, `/${pluginId}/routes`, `/${pluginId}/policies`].map(endpoint =>
26
+ request(endpoint, { method: 'GET' })
27
+ )
28
+ );
29
+
30
+ dispatch({
31
+ type: 'GET_DATA_SUCCEEDED',
32
+ permissions: cleanPermissions(permissions),
33
+ routes,
34
+ policies: [
35
+ {
36
+ label: formatMessage({ id: getTrad('Policies.InputSelect.empty') }),
37
+ value: 'empty__string_value',
38
+ },
39
+ ...formatPolicies(policies),
40
+ ],
41
+ });
42
+ } catch (err) {
43
+ const message = get(err, ['response', 'payload', 'message'], 'An error occured');
44
+
45
+ dispatch({
46
+ type: 'GET_DATA_ERROR',
47
+ });
48
+
49
+ if (message !== 'Forbidden') {
50
+ strapi.notification.toggle({
51
+ type: 'warning',
52
+ message,
53
+ });
54
+ }
55
+ }
56
+ }, [formatMessage]);
57
+
58
+ useEffect(() => {
59
+ if (shouldFetchData) {
60
+ fetchPlugins();
61
+ }
62
+ }, [fetchPlugins, shouldFetchData]);
63
+
64
+ return {
65
+ permissions,
66
+ routes,
67
+ policies,
68
+ getData: fetchPlugins,
69
+ isLoading,
70
+ };
71
+ };
72
+
73
+ export default usePlugins;
@@ -0,0 +1,5 @@
1
+ const init = (initialState, shouldFetchData) => {
2
+ return { ...initialState, isLoading: shouldFetchData };
3
+ };
4
+
5
+ export default init;