@strapi/plugin-users-permissions 4.10.0-beta.0 → 4.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.eslintignore ADDED
@@ -0,0 +1,2 @@
1
+ node_modules/
2
+ .eslintrc.js
package/.eslintrc.js ADDED
@@ -0,0 +1,14 @@
1
+ module.exports = {
2
+ root: true,
3
+ overrides: [
4
+ {
5
+ files: ['admin/**/*'],
6
+ extends: ['custom/front'],
7
+ },
8
+ {
9
+ files: ['**/*'],
10
+ excludedFiles: ['admin/**/*'],
11
+ extends: ['custom/back'],
12
+ },
13
+ ],
14
+ };
@@ -1,5 +1,5 @@
1
1
  import { useCallback, useEffect, useReducer, useRef } from 'react';
2
- import { useRBAC, request, useNotification } from '@strapi/helper-plugin';
2
+ import { useRBAC, useFetchClient, useNotification } from '@strapi/helper-plugin';
3
3
  import { getRequestURL } from '../../utils';
4
4
  import reducer, { initialState } from './reducer';
5
5
 
@@ -9,8 +9,7 @@ const useUserForm = (endPoint, permissions) => {
9
9
  const toggleNotification = useNotification();
10
10
  const isMounted = useRef(true);
11
11
 
12
- const abortController = new AbortController();
13
- const { signal } = abortController;
12
+ const { get } = useFetchClient();
14
13
 
15
14
  useEffect(() => {
16
15
  const getData = async () => {
@@ -19,7 +18,7 @@ const useUserForm = (endPoint, permissions) => {
19
18
  type: 'GET_DATA',
20
19
  });
21
20
 
22
- const data = await request(getRequestURL(endPoint), { method: 'GET', signal });
21
+ const { data } = await get(getRequestURL(endPoint));
23
22
 
24
23
  dispatch({
25
24
  type: 'GET_DATA_SUCCEEDED',
@@ -45,11 +44,9 @@ const useUserForm = (endPoint, permissions) => {
45
44
  }
46
45
 
47
46
  return () => {
48
- abortController.abort();
49
47
  isMounted.current = false;
50
48
  };
51
- // eslint-disable-next-line react-hooks/exhaustive-deps
52
- }, [isLoadingForPermissions, endPoint]);
49
+ }, [isLoadingForPermissions, endPoint, get, toggleNotification]);
53
50
 
54
51
  const dispatchSubmitSucceeded = useCallback((data) => {
55
52
  dispatch({
@@ -1,5 +1,5 @@
1
- import { useEffect, useReducer, useRef } from 'react';
2
- import { request, useNotification } from '@strapi/helper-plugin';
1
+ import { useCallback, useEffect, useReducer, useRef } from 'react';
2
+ import { useFetchClient, useNotification } from '@strapi/helper-plugin';
3
3
  import get from 'lodash/get';
4
4
  import init from './init';
5
5
  import pluginId from '../../pluginId';
@@ -12,28 +12,17 @@ const useRolesList = (shouldFetchData = true) => {
12
12
  const toggleNotification = useNotification();
13
13
 
14
14
  const isMounted = useRef(true);
15
- const abortController = new AbortController();
16
- const { signal } = abortController;
15
+ const fetchClient = useFetchClient();
17
16
 
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 () => {
17
+ const fetchRolesList = useCallback(async () => {
31
18
  try {
32
19
  dispatch({
33
20
  type: 'GET_DATA',
34
21
  });
35
22
 
36
- const { roles } = await request(`/${pluginId}/roles`, { method: 'GET', signal });
23
+ const {
24
+ data: { roles },
25
+ } = await fetchClient.get(`/${pluginId}/roles`);
37
26
 
38
27
  dispatch({
39
28
  type: 'GET_DATA_SUCCEEDED',
@@ -55,7 +44,17 @@ const useRolesList = (shouldFetchData = true) => {
55
44
  }
56
45
  }
57
46
  }
58
- };
47
+ }, [fetchClient, toggleNotification]);
48
+
49
+ useEffect(() => {
50
+ if (shouldFetchData) {
51
+ fetchRolesList();
52
+ }
53
+
54
+ return () => {
55
+ isMounted.current = false;
56
+ };
57
+ }, [shouldFetchData, fetchRolesList]);
59
58
 
60
59
  return { roles, isLoading, getData: fetchRolesList };
61
60
  };
@@ -28,11 +28,12 @@ import {
28
28
  useQueryParams,
29
29
  EmptyStateLayout,
30
30
  ConfirmDialog,
31
+ useFilter,
32
+ useCollator,
31
33
  } from '@strapi/helper-plugin';
32
34
  import { useIntl } from 'react-intl';
33
35
  import { useHistory } from 'react-router-dom';
34
36
  import { useMutation, useQuery, useQueryClient } from 'react-query';
35
- import matchSorter from 'match-sorter';
36
37
 
37
38
  import { fetchData, deleteData } from './utils/api';
38
39
  import { getTrad } from '../../../utils';
@@ -42,7 +43,7 @@ import TableBody from './components/TableBody';
42
43
 
43
44
  const RoleListPage = () => {
44
45
  const { trackUsage } = useTracking();
45
- const { formatMessage } = useIntl();
46
+ const { formatMessage, locale } = useIntl();
46
47
  const { push } = useHistory();
47
48
  const toggleNotification = useNotification();
48
49
  const { notifyStatus } = useNotifyAT();
@@ -78,6 +79,17 @@ const RoleListPage = () => {
78
79
  enabled: canRead,
79
80
  });
80
81
 
82
+ const { includes } = useFilter(locale, {
83
+ sensitivity: 'base',
84
+ });
85
+
86
+ /**
87
+ * @type {Intl.Collator}
88
+ */
89
+ const formatter = useCollator(locale, {
90
+ sensitivity: 'base',
91
+ });
92
+
81
93
  const isLoading = isLoadingForData || isFetching;
82
94
 
83
95
  const handleNewRoleClick = () => {
@@ -118,7 +130,12 @@ const RoleListPage = () => {
118
130
  setIsConfirmButtonLoading(false);
119
131
  };
120
132
 
121
- const sortedRoles = matchSorter(roles || [], _q, { keys: ['name', 'description'] });
133
+ const sortedRoles = (roles || [])
134
+ .filter((role) => includes(role.name, _q) || includes(role.description, _q))
135
+ .sort(
136
+ (a, b) => formatter.compare(a.name, b.name) || formatter.compare(a.description, b.description)
137
+ );
138
+
122
139
  const emptyContent = _q && !sortedRoles.length ? 'search' : 'roles';
123
140
 
124
141
  const colCount = 4;
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import { Switch, Route } from 'react-router-dom';
3
- import { CheckPagePermissions, NotFound } from '@strapi/helper-plugin';
3
+ import { CheckPagePermissions, AnErrorOccurred } from '@strapi/helper-plugin';
4
4
  import pluginId from '../../pluginId';
5
5
  import pluginPermissions from '../../permissions';
6
6
  import ProtectedRolesListPage from './ProtectedListPage';
@@ -18,7 +18,7 @@ const Roles = () => {
18
18
  />
19
19
  <Route path={`/settings/${pluginId}/roles/:id`} component={ProtectedRolesEditPage} exact />
20
20
  <Route path={`/settings/${pluginId}/roles`} component={ProtectedRolesListPage} exact />
21
- <Route path="" component={NotFound} />
21
+ <Route path="" component={AnErrorOccurred} />
22
22
  </Switch>
23
23
  </CheckPagePermissions>
24
24
  );
@@ -12,8 +12,16 @@ tags:
12
12
  url: 'https://docs.strapi.io/developer-docs/latest/plugins/users-permissions.html'
13
13
 
14
14
  paths:
15
- '/connect/(.*)':
15
+ /connect/{provider}:
16
16
  get:
17
+ parameters:
18
+ - name: provider
19
+ in: path
20
+ required: true
21
+ description: Provider name
22
+ schema:
23
+ type: string
24
+ pattern: '.*'
17
25
  tags:
18
26
  - Users-Permissions - Auth
19
27
  summary: Login with a provider
@@ -148,7 +156,7 @@ paths:
148
156
  type: object
149
157
  properties:
150
158
  ok:
151
- type: enum
159
+ type: string
152
160
  enum: [true]
153
161
  default:
154
162
  description: Error
@@ -273,7 +281,7 @@ paths:
273
281
  email:
274
282
  type: string
275
283
  sent:
276
- type: enum
284
+ type: string
277
285
  enum: [true]
278
286
  default:
279
287
  description: Error
@@ -381,7 +389,7 @@ paths:
381
389
  type: object
382
390
  properties:
383
391
  ok:
384
- type: enum
392
+ type: string
385
393
  enum: [true]
386
394
  default:
387
395
  description: Error
@@ -456,7 +464,7 @@ paths:
456
464
  type: object
457
465
  properties:
458
466
  ok:
459
- type: enum
467
+ type: string
460
468
  enum: [true]
461
469
  default:
462
470
  description: Error
@@ -485,7 +493,7 @@ paths:
485
493
  type: object
486
494
  properties:
487
495
  ok:
488
- type: enum
496
+ type: string
489
497
  enum: [true]
490
498
  default:
491
499
  description: Error
@@ -779,9 +787,11 @@ components:
779
787
  type:
780
788
  type: string
781
789
  createdAt:
782
- type: datetime
790
+ type: string
791
+ format: date-time
783
792
  updatedAt:
784
- type: datetime
793
+ type: string
794
+ format: date-time
785
795
 
786
796
  Users-Permissions-User:
787
797
  type: object
@@ -805,10 +815,12 @@ components:
805
815
  type: boolean
806
816
  example: false
807
817
  createdAt:
808
- type: datetime
818
+ type: string
819
+ format: date-time
809
820
  example: '2022-06-02T08:32:06.258Z'
810
821
  updatedAt:
811
- type: datetime
822
+ type: string
823
+ format: date-time
812
824
  example: '2022-06-02T08:32:06.267Z'
813
825
 
814
826
  Users-Permissions-UserRegistration:
@@ -839,10 +851,6 @@ components:
839
851
  type: boolean
840
852
  policy:
841
853
  type: string
842
-
843
- parameters:
844
- responses:
845
- examples:
846
854
  requestBodies:
847
855
  Users-Permissions-RoleRequest:
848
856
  required: true
@@ -1,10 +1,5 @@
1
1
  'use strict';
2
2
 
3
- const baseConfig = require('../../../jest.base-config.front');
4
- const pkg = require('./package.json');
5
-
6
3
  module.exports = {
7
- ...baseConfig,
8
- displayName: (pkg.strapi && pkg.strapi.name) || pkg.name,
9
- roots: [__dirname],
4
+ preset: '../../../jest-preset.front.js',
10
5
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@strapi/plugin-users-permissions",
3
- "version": "4.10.0-beta.0",
3
+ "version": "4.10.0",
4
4
  "description": "Protect your API with a full-authentication process based on JWT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -20,17 +20,19 @@
20
20
  }
21
21
  ],
22
22
  "scripts": {
23
- "test:unit": "jest --verbose",
24
- "test:front": "cross-env IS_EE=true jest --config ./jest.config.front.js",
25
- "test:front:watch": "cross-env IS_EE=true jest --config ./jest.config.front.js --watchAll",
26
- "test:front:ce": "cross-env IS_EE=false jest --config ./jest.config.front.js",
27
- "test:front:watch:ce": "cross-env IS_EE=false jest --config ./jest.config.front.js --watchAll"
23
+ "test:unit": "run -T jest",
24
+ "test:unit:watch": "run -T jest --watch",
25
+ "test:front": "run -T cross-env IS_EE=true jest --config ./jest.config.front.js",
26
+ "test:front:watch": "run -T cross-env IS_EE=true jest --config ./jest.config.front.js --watchAll",
27
+ "test:front:ce": "run -T cross-env IS_EE=false jest --config ./jest.config.front.js",
28
+ "test:front:watch:ce": "run -T cross-env IS_EE=false jest --config ./jest.config.front.js --watchAll",
29
+ "lint": "run -T eslint ."
28
30
  },
29
31
  "dependencies": {
30
32
  "@strapi/design-system": "1.6.6",
31
- "@strapi/helper-plugin": "4.10.0-beta.0",
33
+ "@strapi/helper-plugin": "4.10.0",
32
34
  "@strapi/icons": "1.6.6",
33
- "@strapi/utils": "4.10.0-beta.0",
35
+ "@strapi/utils": "4.10.0",
34
36
  "bcryptjs": "2.4.3",
35
37
  "formik": "2.2.9",
36
38
  "grant-koa": "5.4.8",
@@ -40,7 +42,6 @@
40
42
  "koa": "^2.13.4",
41
43
  "koa2-ratelimit": "^1.1.2",
42
44
  "lodash": "4.17.21",
43
- "match-sorter": "^4.0.2",
44
45
  "prop-types": "^15.7.2",
45
46
  "purest": "4.0.2",
46
47
  "react-intl": "6.3.2",
@@ -65,8 +66,8 @@
65
66
  "peerDependencies": {
66
67
  "react": "^17.0.2",
67
68
  "react-dom": "^17.0.2",
68
- "react-router-dom": "5.3.4",
69
- "styled-components": "5.3.3"
69
+ "react-router-dom": "^5.3.4",
70
+ "styled-components": "^5.3.3"
70
71
  },
71
72
  "engines": {
72
73
  "node": ">=14.19.1 <=18.x.x",
@@ -79,5 +80,5 @@
79
80
  "required": true,
80
81
  "kind": "plugin"
81
82
  },
82
- "gitHead": "1519ef0e56d27b738f24fc88223797651ad47aaf"
83
+ "gitHead": "9b5519778faaedfb837879f9c6f7e28fdfd6750d"
83
84
  }
@@ -280,6 +280,12 @@ module.exports = {
280
280
  'confirmationToken',
281
281
  'resetPasswordToken',
282
282
  'provider',
283
+ 'id',
284
+ 'createdAt',
285
+ 'updatedAt',
286
+ 'createdBy',
287
+ 'updatedBy',
288
+ 'role',
283
289
  ]),
284
290
  provider: 'local',
285
291
  };
@@ -18,6 +18,12 @@ module.exports = ({ strapi }) => {
18
18
  const specPath = path.join(__dirname, '../documentation/content-api.yaml');
19
19
  const spec = fs.readFileSync(specPath, 'utf8');
20
20
 
21
- strapi.plugin('documentation').service('documentation').registerDoc(spec);
21
+ strapi
22
+ .plugin('documentation')
23
+ .service('override')
24
+ .registerOverride(spec, {
25
+ pluginOrigin: 'users-permissions',
26
+ excludeFromGeneration: ['users-permissions'],
27
+ });
22
28
  }
23
29
  };
@@ -176,7 +176,7 @@ const getInitialProviders = ({ purest }) => ({
176
176
  const vk = purest({ provider: 'vk' });
177
177
 
178
178
  return vk
179
- .get('users.get')
179
+ .get('users')
180
180
  .auth(accessToken)
181
181
  .qs({ id: query.raw.user_id, v: '5.122' })
182
182
  .request()
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- const { castArray, map, every, pipe } = require('lodash/fp');
3
+ const { castArray, map, every, pipe, isEmpty } = require('lodash/fp');
4
4
  const { ForbiddenError, UnauthorizedError } = require('@strapi/utils').errors;
5
5
 
6
6
  const { getService } = require('../utils');
@@ -80,6 +80,13 @@ const authenticate = async (ctx) => {
80
80
  const verify = async (auth, config) => {
81
81
  const { credentials: user, ability } = auth;
82
82
 
83
+ strapi.telemetry.send('didReceiveAPIRequest', {
84
+ eventProperties: {
85
+ authenticationMethod: auth?.strategy?.name,
86
+ isAuthenticated: !isEmpty(user),
87
+ },
88
+ });
89
+
83
90
  if (!config.scope) {
84
91
  if (!user) {
85
92
  // A non authenticated user cannot access routes that do not have a scope