@strapi/admin 4.3.7 → 4.4.0-beta.1

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 (78) hide show
  1. package/admin/src/contexts/ApiTokenPermissions/index.js +24 -0
  2. package/admin/src/hooks/index.js +1 -0
  3. package/admin/src/hooks/useRegenerate/index.js +34 -0
  4. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/ActionBoundRoutes/index.js +56 -0
  5. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/BoundRoute/getMethodColor.js +41 -0
  6. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/BoundRoute/index.js +72 -0
  7. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/CollapsableContentType/CheckBoxWrapper.js +30 -0
  8. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/CollapsableContentType/index.js +150 -0
  9. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/ContenTypesSection/index.js +37 -0
  10. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/Permissions/index.js +40 -0
  11. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/Regenerate/index.js +68 -0
  12. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/index.js +452 -180
  13. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/init.js +13 -0
  14. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/reducer.js +55 -0
  15. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/utils/getDateOfExpiration.js +16 -0
  16. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/utils/index.js +5 -0
  17. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/utils/schema.js +2 -1
  18. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/utils/transformPermissionsData.js +36 -0
  19. package/admin/src/pages/SettingsPage/pages/ApiTokens/ListView/DynamicTable/DefaultButton/index.js +63 -0
  20. package/admin/src/pages/SettingsPage/pages/ApiTokens/ListView/DynamicTable/DeleteButton/index.js +1 -0
  21. package/admin/src/pages/SettingsPage/pages/ApiTokens/ListView/DynamicTable/ReadButton/index.js +19 -0
  22. package/admin/src/pages/SettingsPage/pages/ApiTokens/ListView/DynamicTable/UpdateButton/index.js +3 -36
  23. package/admin/src/pages/SettingsPage/pages/ApiTokens/ListView/DynamicTable/index.js +13 -11
  24. package/admin/src/pages/SettingsPage/pages/ApiTokens/ListView/index.js +3 -2
  25. package/admin/src/pages/SettingsPage/pages/ApiTokens/ListView/utils/tableHeaders.js +8 -8
  26. package/admin/src/pages/SettingsPage/pages/ApiTokens/ProtectedEditView/index.js +1 -1
  27. package/admin/src/permissions/defaultPermissions.js +2 -6
  28. package/admin/src/translations/en.json +17 -0
  29. package/admin/src/translations/fr.json +32 -0
  30. package/build/4235.982b5799.chunk.js +30 -0
  31. package/build/7379.d246dd38.chunk.js +1 -0
  32. package/build/{Admin-authenticatedApp.0d299d1a.chunk.js → Admin-authenticatedApp.3a31a087.chunk.js} +1 -1
  33. package/build/{Admin_homePage.118926e0.chunk.js → Admin_homePage.6d5e3236.chunk.js} +1 -1
  34. package/build/{Admin_profilePage.8617313a.chunk.js → Admin_profilePage.83991a6c.chunk.js} +1 -1
  35. package/build/{Admin_settingsPage.98a711e5.chunk.js → Admin_settingsPage.fc9c607a.chunk.js} +16 -16
  36. package/build/admin-app.41b6472c.chunk.js +112 -0
  37. package/build/admin-edit-roles-page.4dd6bcb9.chunk.js +1 -0
  38. package/build/api-tokens-create-page.29cc87b6.chunk.js +1 -0
  39. package/build/api-tokens-edit-page.c294a88f.chunk.js +1 -0
  40. package/build/api-tokens-list-page.bb36535f.chunk.js +16 -0
  41. package/build/en-json.a9918c93.chunk.js +1 -0
  42. package/build/{fr-json.6d5a7e14.chunk.js → fr-json.4ed1fc2c.chunk.js} +1 -1
  43. package/build/index.html +1 -1
  44. package/build/{main.e73468bf.js → main.cdfda31e.js} +1 -1
  45. package/build/{runtime~main.edd06c9f.js → runtime~main.fa8f8898.js} +2 -2
  46. package/build/sso-settings-page.9ceb0140.chunk.js +1 -0
  47. package/build/{webhook-edit-page.d2ea3351.chunk.js → webhook-edit-page.9e46fc3f.chunk.js} +1 -1
  48. package/package.json +9 -8
  49. package/scripts/build.js +2 -4
  50. package/server/bootstrap.js +19 -1
  51. package/server/config/admin-actions.js +20 -0
  52. package/server/content-types/api-token-permission.js +36 -0
  53. package/server/content-types/api-token.js +25 -1
  54. package/server/content-types/index.js +1 -0
  55. package/server/controllers/api-token.js +24 -1
  56. package/server/controllers/content-api.js +15 -0
  57. package/server/controllers/index.js +1 -0
  58. package/server/routes/api-tokens.js +11 -0
  59. package/server/routes/content-api.js +20 -0
  60. package/server/routes/index.js +2 -0
  61. package/server/services/api-token.js +310 -29
  62. package/server/services/constants.js +10 -0
  63. package/server/services/permission/engine.js +36 -226
  64. package/server/services/permission/permissions-manager/query-builers.js +3 -2
  65. package/server/services/permission/queries.js +1 -1
  66. package/server/services/permission.js +4 -1
  67. package/server/strategies/admin.js +7 -1
  68. package/server/strategies/api-token.js +71 -11
  69. package/server/validation/api-tokens.js +12 -2
  70. package/server/validation/common-functions/check-fields-are-correctly-nested.js +1 -1
  71. package/build/admin-app.05edc328.chunk.js +0 -112
  72. package/build/admin-edit-roles-page.554ba3fa.chunk.js +0 -1
  73. package/build/api-tokens-create-page.4c262d6e.chunk.js +0 -1
  74. package/build/api-tokens-edit-page.10a9d368.chunk.js +0 -1
  75. package/build/api-tokens-list-page.442c9f3c.chunk.js +0 -15
  76. package/build/en-json.12bc5a14.chunk.js +0 -1
  77. package/build/sso-settings-page.445184e0.chunk.js +0 -1
  78. package/server/services/permission/engine-hooks.js +0 -82
@@ -0,0 +1,13 @@
1
+ import { transformPermissionsData } from './utils';
2
+
3
+ const init = (state, permissions = []) => {
4
+ return {
5
+ ...state,
6
+ selectedAction: null,
7
+ routes: [],
8
+ selectedActions: [],
9
+ data: transformPermissionsData(permissions),
10
+ };
11
+ };
12
+
13
+ export default init;
@@ -0,0 +1,55 @@
1
+ /* eslint-disable consistent-return */
2
+ import produce from 'immer';
3
+ import { pull } from 'lodash';
4
+ import { transformPermissionsData } from './utils';
5
+
6
+ export const initialState = {
7
+ data: {},
8
+ selectedActions: [],
9
+ };
10
+
11
+ const reducer = (state, action) =>
12
+ produce(state, (draftState) => {
13
+ switch (action.type) {
14
+ case 'ON_CHANGE': {
15
+ if (draftState.selectedActions.includes(action.value)) {
16
+ pull(draftState.selectedActions, action.value);
17
+ } else {
18
+ draftState.selectedActions.push(action.value);
19
+ }
20
+ break;
21
+ }
22
+ case 'SELECT_ALL_ACTIONS': {
23
+ draftState.selectedActions = [...draftState.data.allActionsIds];
24
+
25
+ break;
26
+ }
27
+ case 'ON_CHANGE_READ_ONLY': {
28
+ const onlyReadOnlyActions = draftState.data.allActionsIds.filter(
29
+ (actionId) => actionId.includes('find') || actionId.includes('findOne')
30
+ );
31
+ draftState.selectedActions = [...onlyReadOnlyActions];
32
+ break;
33
+ }
34
+ case 'UPDATE_PERMISSIONS_LAYOUT': {
35
+ draftState.data = transformPermissionsData(action.value);
36
+ break;
37
+ }
38
+ case 'UPDATE_ROUTES': {
39
+ draftState.routes = { ...action.value };
40
+ break;
41
+ }
42
+ case 'UPDATE_PERMISSIONS': {
43
+ draftState.selectedActions = [...action.value];
44
+ break;
45
+ }
46
+ case 'SET_SELECTED_ACTION': {
47
+ draftState.selectedAction = action.value;
48
+ break;
49
+ }
50
+ default:
51
+ return draftState;
52
+ }
53
+ });
54
+
55
+ export default reducer;
@@ -0,0 +1,16 @@
1
+ import { addDays, format } from 'date-fns';
2
+ import * as locales from 'date-fns/locale';
3
+
4
+ const getDateOfExpiration = (createdAt, duration, language = 'en') => {
5
+ if (duration && typeof duration === 'number') {
6
+ const durationInDays = duration / 24 / 60 / 60 / 1000;
7
+
8
+ return format(addDays(new Date(createdAt), durationInDays), 'PPP', {
9
+ locale: locales[language],
10
+ });
11
+ }
12
+
13
+ return 'Unlimited';
14
+ };
15
+
16
+ export default getDateOfExpiration;
@@ -0,0 +1,5 @@
1
+ import getDateOfExpiration from './getDateOfExpiration';
2
+ import schema from './schema';
3
+ import transformPermissionsData from './transformPermissionsData';
4
+
5
+ export { getDateOfExpiration, schema, transformPermissionsData };
@@ -5,9 +5,10 @@ const schema = yup.object().shape({
5
5
  name: yup.string(translatedErrors.string).required(translatedErrors.required),
6
6
  type: yup
7
7
  .string(translatedErrors.string)
8
- .oneOf(['read-only', 'full-access'])
8
+ .oneOf(['read-only', 'full-access', 'custom'])
9
9
  .required(translatedErrors.required),
10
10
  description: yup.string().nullable(),
11
+ lifespan: yup.number().integer().min(1).nullable().defined(translatedErrors.required),
11
12
  });
12
13
 
13
14
  export default schema;
@@ -0,0 +1,36 @@
1
+ import { flatten } from 'lodash';
2
+
3
+ const transformPermissionsData = (data) => {
4
+ const layout = {
5
+ allActionsIds: [],
6
+ permissions: [],
7
+ };
8
+
9
+ layout.permissions = Object.keys(data).map((apiId) => ({
10
+ apiId,
11
+ label: apiId.split('::')[1],
12
+ controllers: flatten(
13
+ Object.keys(data[apiId].controllers).map((controller) => ({
14
+ controller,
15
+ actions: flatten(
16
+ data[apiId].controllers[controller].map((action) => {
17
+ const actionId = `${apiId}.${controller}.${action}`;
18
+
19
+ if (apiId.includes('api::')) {
20
+ layout.allActionsIds.push(actionId);
21
+ }
22
+
23
+ return {
24
+ action,
25
+ actionId,
26
+ };
27
+ })
28
+ ),
29
+ }))
30
+ ),
31
+ }));
32
+
33
+ return layout;
34
+ };
35
+
36
+ export default transformPermissionsData;
@@ -0,0 +1,63 @@
1
+ import React from 'react';
2
+ import { useIntl } from 'react-intl';
3
+ import PropTypes from 'prop-types';
4
+ import { Link } from '@strapi/helper-plugin';
5
+ import { useHistory } from 'react-router-dom';
6
+ import styled from 'styled-components';
7
+
8
+ const MESSAGES_MAP = {
9
+ edit: {
10
+ id: 'app.component.table.edit',
11
+ defaultMessage: 'Edit {target}',
12
+ },
13
+ read: {
14
+ id: 'app.component.table.read',
15
+ defaultMessage: 'Read {target}',
16
+ },
17
+ };
18
+
19
+ const LinkStyled = styled(Link)`
20
+ svg {
21
+ path {
22
+ fill: ${({ theme }) => theme.colors.neutral500};
23
+ }
24
+ }
25
+
26
+ &:hover,
27
+ &:focus {
28
+ svg {
29
+ path {
30
+ fill: ${({ theme }) => theme.colors.neutral800};
31
+ }
32
+ }
33
+ }
34
+ `;
35
+
36
+ const DefaultButton = ({ tokenName, tokenId, buttonType, children }) => {
37
+ const { formatMessage } = useIntl();
38
+ const {
39
+ location: { pathname },
40
+ } = useHistory();
41
+
42
+ return (
43
+ <LinkStyled
44
+ to={`${pathname}/${tokenId}`}
45
+ title={formatMessage(MESSAGES_MAP[buttonType], { target: tokenName })}
46
+ >
47
+ {children}
48
+ </LinkStyled>
49
+ );
50
+ };
51
+
52
+ DefaultButton.propTypes = {
53
+ tokenName: PropTypes.string.isRequired,
54
+ tokenId: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
55
+ buttonType: PropTypes.string,
56
+ children: PropTypes.node.isRequired,
57
+ };
58
+
59
+ DefaultButton.defaultProps = {
60
+ buttonType: 'edit',
61
+ };
62
+
63
+ export default DefaultButton;
@@ -24,6 +24,7 @@ const DeleteButton = ({ tokenName, onClickDelete }) => {
24
24
  },
25
25
  { target: `${tokenName}` }
26
26
  )}
27
+ name="delete"
27
28
  noBorder
28
29
  icon={<Trash />}
29
30
  />
@@ -0,0 +1,19 @@
1
+ import React from 'react';
2
+ import Eye from '@strapi/icons/Eye';
3
+ import PropTypes from 'prop-types';
4
+ import DefaultButton from '../DefaultButton';
5
+
6
+ const ReadButton = ({ tokenName, tokenId }) => {
7
+ return (
8
+ <DefaultButton tokenName={tokenName} tokenId={tokenId} buttonType="read">
9
+ <Eye />
10
+ </DefaultButton>
11
+ );
12
+ };
13
+
14
+ ReadButton.propTypes = {
15
+ tokenName: PropTypes.string.isRequired,
16
+ tokenId: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
17
+ };
18
+
19
+ export default ReadButton;
@@ -1,46 +1,13 @@
1
1
  import React from 'react';
2
2
  import Pencil from '@strapi/icons/Pencil';
3
- import { useIntl } from 'react-intl';
4
3
  import PropTypes from 'prop-types';
5
- import { Link } from '@strapi/helper-plugin';
6
- import { useHistory } from 'react-router-dom';
7
- import styled from 'styled-components';
8
-
9
- const LinkUpdate = styled(Link)`
10
- svg {
11
- path {
12
- fill: ${({ theme }) => theme.colors.neutral500};
13
- }
14
- }
15
-
16
- &:hover {
17
- svg {
18
- path {
19
- fill: ${({ theme }) => theme.colors.neutral800};
20
- }
21
- }
22
- }
23
- `;
4
+ import DefaultButton from '../DefaultButton';
24
5
 
25
6
  const UpdateButton = ({ tokenName, tokenId }) => {
26
- const { formatMessage } = useIntl();
27
- const {
28
- location: { pathname },
29
- } = useHistory();
30
-
31
7
  return (
32
- <LinkUpdate
33
- to={`${pathname}/${tokenId}`}
34
- title={formatMessage(
35
- {
36
- id: 'app.component.table.edit',
37
- defaultMessage: 'Edit {target}',
38
- },
39
- { target: `${tokenName}` }
40
- )}
41
- >
8
+ <DefaultButton tokenName={tokenName} tokenId={tokenId}>
42
9
  <Pencil />
43
- </LinkUpdate>
10
+ </DefaultButton>
44
11
  );
45
12
  };
46
13
 
@@ -1,5 +1,4 @@
1
1
  import React from 'react';
2
- import { useIntl } from 'react-intl';
3
2
  import PropTypes from 'prop-types';
4
3
  import { useHistory } from 'react-router-dom';
5
4
 
@@ -13,12 +12,11 @@ import {
13
12
  pxToRem,
14
13
  useTracking,
15
14
  } from '@strapi/helper-plugin';
16
-
17
15
  import DeleteButton from './DeleteButton';
18
16
  import UpdateButton from './UpdateButton';
17
+ import ReadButton from './ReadButton';
19
18
 
20
- const TableRows = ({ canDelete, canUpdate, onClickDelete, withBulkActions, rows }) => {
21
- const { formatMessage } = useIntl();
19
+ const TableRows = ({ canDelete, canUpdate, canRead, onClickDelete, withBulkActions, rows }) => {
22
20
  const [{ query }] = useQueryParams();
23
21
  const [, sortOrder] = query.sort.split(':');
24
22
  const {
@@ -59,22 +57,24 @@ const TableRows = ({ canDelete, canUpdate, onClickDelete, withBulkActions, rows
59
57
  </Td>
60
58
  <Td>
61
59
  <Typography textColor="neutral800">
62
- {formatMessage({
63
- id: `Settings.apiTokens.types.${apiToken.type}`,
64
- defaultMessage: 'Type unknown',
65
- })}
60
+ <RelativeTime timestamp={new Date(apiToken.createdAt)} />
66
61
  </Typography>
67
62
  </Td>
68
63
  <Td>
69
- <Typography textColor="neutral800">
70
- <RelativeTime timestamp={new Date(apiToken.createdAt)} />
71
- </Typography>
64
+ {apiToken.lastUsedAt && (
65
+ <Typography textColor="neutral800">
66
+ <RelativeTime timestamp={new Date(apiToken.lastUsedAt)} />
67
+ </Typography>
68
+ )}
72
69
  </Td>
73
70
 
74
71
  {withBulkActions && (
75
72
  <Td>
76
73
  <Flex justifyContent="end">
77
74
  {canUpdate && <UpdateButton tokenName={apiToken.name} tokenId={apiToken.id} />}
75
+ {!canUpdate && canRead && (
76
+ <ReadButton tokenName={apiToken.name} tokenId={apiToken.id} />
77
+ )}
78
78
  {canDelete && (
79
79
  <DeleteButton
80
80
  tokenName={apiToken.name}
@@ -94,6 +94,7 @@ const TableRows = ({ canDelete, canUpdate, onClickDelete, withBulkActions, rows
94
94
  TableRows.defaultProps = {
95
95
  canDelete: false,
96
96
  canUpdate: false,
97
+ canRead: false,
97
98
  onClickDelete() {},
98
99
  rows: [],
99
100
  withBulkActions: false,
@@ -102,6 +103,7 @@ TableRows.defaultProps = {
102
103
  TableRows.propTypes = {
103
104
  canDelete: PropTypes.bool,
104
105
  canUpdate: PropTypes.bool,
106
+ canRead: PropTypes.bool,
105
107
  onClickDelete: PropTypes.func,
106
108
  rows: PropTypes.array,
107
109
  withBulkActions: PropTypes.bool,
@@ -147,15 +147,16 @@ const ApiTokenListView = () => {
147
147
  headers={headers}
148
148
  contentType="api-tokens"
149
149
  rows={apiTokens}
150
- withBulkActions={canDelete || canUpdate}
150
+ withBulkActions={canDelete || canUpdate || canRead}
151
151
  isLoading={isLoading}
152
152
  onConfirmDelete={(id) => deleteMutation.mutateAsync(id)}
153
153
  >
154
154
  <TableRows
155
+ canRead={canRead}
155
156
  canDelete={canDelete}
156
157
  canUpdate={canUpdate}
157
158
  rows={apiTokens}
158
- withBulkActions={canDelete || canUpdate}
159
+ withBulkActions={canDelete || canUpdate || canRead}
159
160
  />
160
161
  </DynamicTable>
161
162
  )}
@@ -22,23 +22,23 @@ const tableHeaders = [
22
22
  },
23
23
  },
24
24
  {
25
- name: 'type',
26
- key: 'type',
25
+ name: 'createdAt',
26
+ key: 'createdAt',
27
27
  metadatas: {
28
28
  label: {
29
- id: 'Settings.apiTokens.ListView.headers.type',
30
- defaultMessage: 'Token type',
29
+ id: 'Settings.apiTokens.ListView.headers.createdAt',
30
+ defaultMessage: 'Created at',
31
31
  },
32
32
  sortable: false,
33
33
  },
34
34
  },
35
35
  {
36
- name: 'createdAt',
37
- key: 'createdAt',
36
+ name: 'lastUsedAt',
37
+ key: 'lastUsedAt',
38
38
  metadatas: {
39
39
  label: {
40
- id: 'Settings.apiTokens.ListView.headers.createdAt',
41
- defaultMessage: 'Created at',
40
+ id: 'Settings.apiTokens.ListView.headers.lastUsedAt',
41
+ defaultMessage: 'Last used',
42
42
  },
43
43
  sortable: false,
44
44
  },
@@ -5,7 +5,7 @@ import EditView from '../EditView';
5
5
 
6
6
  const ProtectedApiTokenCreateView = () => {
7
7
  return (
8
- <CheckPagePermissions permissions={adminPermissions.settings['api-tokens'].update}>
8
+ <CheckPagePermissions permissions={adminPermissions.settings['api-tokens'].read}>
9
9
  <EditView />
10
10
  </CheckPagePermissions>
11
11
  );
@@ -76,16 +76,12 @@ const permissions = {
76
76
  update: [{ action: 'admin::webhooks.update', subject: null }],
77
77
  },
78
78
  'api-tokens': {
79
- main: [
80
- { action: 'admin::api-tokens.create', subject: null },
81
- { action: 'admin::api-tokens.read', subject: null },
82
- { action: 'admin::api-tokens.update', subject: null },
83
- { action: 'admin::api-tokens.delete', subject: null },
84
- ],
79
+ main: [{ action: 'admin::api-tokens.access', subject: null }],
85
80
  create: [{ action: 'admin::api-tokens.create', subject: null }],
86
81
  delete: [{ action: 'admin::api-tokens.delete', subject: null }],
87
82
  read: [{ action: 'admin::api-tokens.read', subject: null }],
88
83
  update: [{ action: 'admin::api-tokens.update', subject: null }],
84
+ regenerate: [{ action: 'admin::api-tokens.regenerate', subject: null }],
89
85
  },
90
86
  },
91
87
  };
@@ -91,10 +91,24 @@
91
91
  "Settings.apiTokens.ListView.headers.description": "Description",
92
92
  "Settings.apiTokens.ListView.headers.type": "Token type",
93
93
  "Settings.apiTokens.ListView.headers.createdAt": "Created at",
94
+ "Settings.apiTokens.ListView.headers.lastUsedAt": "Last used",
94
95
  "Settings.apiTokens.notification.copied": "Token copied to clipboard.",
95
96
  "Settings.apiTokens.title": "API Tokens",
96
97
  "Settings.apiTokens.types.full-access": "Full access",
97
98
  "Settings.apiTokens.types.read-only": "Read-only",
99
+ "Settings.apiTokens.duration.7-days": "7 days",
100
+ "Settings.apiTokens.duration.30-days": "30 days",
101
+ "Settings.apiTokens.duration.90-days": "90 days",
102
+ "Settings.apiTokens.duration.unlimited": "Unlimited",
103
+ "Settings.apiTokens.form.duration":"Token duration",
104
+ "Settings.apiTokens.form.type":"Token type",
105
+ "Settings.apiTokens.duration.expiration-date":"Expiration date",
106
+ "Settings.apiTokens.createPage.permissions.title":"Permissions",
107
+ "Settings.apiTokens.createPage.permissions.description":"Only actions bound by a route are listed below.",
108
+ "Settings.apiTokens.RegenerateDialog.title": "Regenerate token",
109
+ "Settings.apiTokens.popUpWarning.message": "Are you sure you want to regenerate this token?",
110
+ "Settings.apiTokens.Button.cancel": "Cancel",
111
+ "Settings.apiTokens.Button.regenerate": "Regenerate",
98
112
  "Settings.application.description": "Administration panel’s global information",
99
113
  "Settings.application.edition-title": "current plan",
100
114
  "Settings.application.get-help": "Get help",
@@ -758,6 +772,9 @@
758
772
  "notification.success.delete": "The item has been deleted",
759
773
  "notification.success.saved": "Saved",
760
774
  "notification.success.title": "Success:",
775
+ "notification.success.tokencreated": "API Token successfully created",
776
+ "notification.success.tokenedited": "API Token successfully edited",
777
+ "notification.error.tokennamenotunique": "Name already assigned to another token",
761
778
  "notification.version.update.message": "A new version of Strapi is available!",
762
779
  "notification.warning.title": "Warning:",
763
780
  "notification.warning.404": "404 - Not found",
@@ -588,6 +588,38 @@
588
588
  "content-manager.success.record.save": "Sauvegardé",
589
589
  "content-manager.success.record.unpublish": "Publication annulée",
590
590
  "content-manager.utils.data-loaded": "{number, plural, =1 {L'entrée a été chargée} other {Les entrées on été chargées} avec succès",
591
+ "content-manager.apiError.This attribute must be unique": "Le champ {field} doit être unique",
592
+ "form.button.continue": "Continuer",
593
+ "global.search": "Rechercher",
594
+ "global.actions": "Actions",
595
+ "global.back": "Retour",
596
+ "global.cancel": "Annuler",
597
+ "global.change-password": "Modifier le mot de passe",
598
+ "global.content-manager": "Gestion du contenu",
599
+ "global.continue": "Continuer",
600
+ "global.delete": "Supprimer",
601
+ "global.delete-target": "Supprimer {target}",
602
+ "global.description": "Description",
603
+ "global.details": "Détails",
604
+ "global.disabled": "Désactivé",
605
+ "global.documentation": "Documentation",
606
+ "global.enabled": "Activé",
607
+ "global.finish": "Terminer",
608
+ "global.marketplace": "Marketplace",
609
+ "global.name": "Nom",
610
+ "global.none": "Aucun",
611
+ "global.password": "Mot de passe",
612
+ "global.plugins": "Plugins",
613
+ "global.profile": "Profil",
614
+ "global.reset-password": "Réinitialiser le mot de passe",
615
+ "global.roles": "Rôles",
616
+ "global.save": "Enregistrer",
617
+ "global.see-more": "Voir plus",
618
+ "global.select": "Sélectionner",
619
+ "global.select-all-entries": "Sélectionner toutes les entrées",
620
+ "global.settings": "Paramètres",
621
+ "global.type": "Type",
622
+ "global.users": "Utilisateurs",
591
623
  "form.button.done": "Terminer",
592
624
  "global.prompt.unsaved": "Êtes-vous sûr de vouloir quitter cette page? Toutes vos modifications seront perdues",
593
625
  "notification.contentType.relations.conflict": "Le Type de Contenu à des relations qui rentrent en conflit",
@@ -0,0 +1,30 @@
1
+ "use strict";(self.webpackChunk_strapi_admin=self.webpackChunk_strapi_admin||[]).push([[4235],{54235:(on,Ne,r)=>{r.d(Ne,{Z:()=>Qt});var a=r(32735),k=r(5636),m=r(88425),L=r(11856),oe=r(16540),z=r(44526),Be=r(88677),se=r.n(Be),Le=r(98599),we=r.n(Le),De=r(83281),O=r(90662),A=r(9808),C=r(95602),S=r(78330),je=r(37178),Ve=r(90353),P=r(25716),b=r(92891),ie=r(5141),re=r(84968),Ge=r(7602),w=r(17247),le=r(64213),Ue=r(54049);const $e=(n,e,t="en")=>{if(e&&typeof e=="number"){const o=e/24/60/60/1e3;return(0,le.format)((0,le.addDays)(new Date(n),o),"PPP",{locale:Ue[t]})}return"Unlimited"};var M=r(5173);const He=M.Ry().shape({name:M.Z_(m.translatedErrors.string).required(m.translatedErrors.required),type:M.Z_(m.translatedErrors.string).oneOf(["read-only","full-access","custom"]).required(m.translatedErrors.required),description:M.Z_().nullable(),lifespan:M.Rx().integer().min(1).nullable().defined(m.translatedErrors.required)}),de=n=>{const e={allActionsIds:[],permissions:[]};return e.permissions=Object.keys(n).map(t=>({apiId:t,label:t.split("::")[1],controllers:(0,b.flatten)(Object.keys(n[t].controllers).map(o=>({controller:o,actions:(0,b.flatten)(n[t].controllers[o].map(l=>{const p=`${t}.${o}.${l}`;return t.includes("api::")&&e.allActionsIds.push(p),{action:l,actionId:p}}))})))})),e};var Fe=r(60216),f=r.n(Fe);const K=({apiTokenName:n})=>{const{formatMessage:e}=(0,k.useIntl)();return(0,m.useFocusWhenNavigate)(),a.createElement(oe.Main,{"aria-busy":"true"},a.createElement(m.SettingsPageTitle,{name:"API Tokens"}),a.createElement(L.HeaderLayout,{primaryAction:a.createElement(z.Button,{disabled:!0,startIcon:a.createElement(se(),null),type:"button",size:"L"},e({id:"global.save",defaultMessage:"Save"})),title:n||e({id:"Settings.apiTokens.createPage.title",defaultMessage:"Create API Token"})}),a.createElement(L.ContentLayout,null,a.createElement(m.LoadingIndicatorPage,null)))};K.defaultProps={apiTokenName:null},K.propTypes={apiTokenName:f().string};const We=K;var ze=r(20763),Ke=r(68192),Ye=r.n(Ke),Ze=r(59087),Qe=r(18909),Je=r.n(Qe);const Y=({apiToken:n})=>{const{formatMessage:e}=(0,k.useIntl)(),t=(0,m.useNotification)(),{trackUsage:o}=(0,m.useTracking)(),l=(0,a.useRef)(o);return a.createElement(m.ContentBox,{endAction:n&&a.createElement("span",{style:{alignSelf:"start"}},a.createElement(Ze.CopyToClipboard,{onCopy:()=>{l.current("didCopyTokenKey"),t({type:"success",message:{id:"Settings.apiTokens.notification.copied"}})},text:n},a.createElement(ze.IconButton,{label:e({id:"app.component.CopyToClipboard.label",defaultMessage:"Copy to clipboard"}),noBorder:!0,icon:a.createElement(Ye(),null),style:{padding:0,height:"1rem"}}))),title:n||e({id:"Settings.apiTokens.copy.editTitle",defaultMessage:"This token isn\u2019t accessible anymore."}),subtitle:e(n?{id:"Settings.apiTokens.copy.lastWarning",defaultMessage:"Make sure to copy this token, you won\u2019t be able to see it again!"}:{id:"Settings.apiTokens.copy.editMessage",defaultMessage:"For security reasons, you can only see your token once."}),icon:a.createElement(Je(),null),iconBackground:"neutral100"})};Y.defaultProps={apiToken:null},Y.propTypes={apiToken:f().string};const Xe=Y;var Z=r(12001),ce=r(52111),qe=r(19192),_e=r(42258),et=r.n(_e),D=r(19615),pe=Object.getOwnPropertySymbols,tt=Object.prototype.hasOwnProperty,nt=Object.prototype.propertyIsEnumerable,at=(n,e)=>{var t={};for(var o in n)tt.call(n,o)&&e.indexOf(o)<0&&(t[o]=n[o]);if(n!=null&&pe)for(var o of pe(n))e.indexOf(o)<0&&nt.call(n,o)&&(t[o]=n[o]);return t};const ue=(0,a.createContext)({}),me=n=>{var e=n,{children:t}=e,o=at(e,["children"]);return a.createElement(ue.Provider,{value:o},t)},Q=()=>(0,a.useContext)(ue);me.propTypes={children:f().node.isRequired};const ge=D.css`
2
+ background: ${n=>n.theme.colors.primary100};
3
+ svg {
4
+ opacity: 1;
5
+ }
6
+ `,ot=(0,D.default)(A.Box)`
7
+ display: flex;
8
+ justify-content: space-between;
9
+ align-items: center;
10
+
11
+ svg {
12
+ opacity: 0;
13
+ path {
14
+ fill: ${n=>n.theme.colors.primary600};
15
+ }
16
+ }
17
+
18
+ /* Show active style both on hover and when the action is selected */
19
+ ${n=>n.isActive&&ge}
20
+ &:hover {
21
+ ${ge}
22
+ }
23
+ `,st=D.default.div`
24
+ flex: 1;
25
+ align-self: center;
26
+ border-top: 1px solid ${({theme:n})=>n.colors.neutral150};
27
+ `,J=({controllers:n,label:e,orderNumber:t,disabled:o,onExpanded:l,indexExpandendCollapsedContent:p})=>{const{value:{onChangeSelectAll:i,onChange:d,selectedActions:c,setSelectedAction:y,selectedAction:te}}=Q(),[N,U]=(0,a.useState)(!1),$=()=>{U(g=>!g),l(t)};(0,a.useEffect)(()=>{p!==null&&p!==t&&N&&U(!1)},[p,t,N]);const ne=g=>g===te;return a.createElement(Z.Accordion,{expanded:N,onToggle:$,variant:t%2?"primary":"secondary"},a.createElement(Z.AccordionToggle,{title:(0,b.capitalize)(e)}),a.createElement(Z.AccordionContent,null,n==null?void 0:n.map(g=>{const E=g.actions.every(u=>c.includes(u.actionId)),R=g.actions.some(u=>c.includes(u.actionId));return a.createElement(A.Box,{key:`${e}.${g==null?void 0:g.controller}`},a.createElement(qe.Flex,{justifyContent:"space-between",alignItems:"center",padding:4},a.createElement(A.Box,{paddingRight:4},a.createElement(C.Typography,{variant:"sigma",textColor:"neutral600"},g==null?void 0:g.controller)),a.createElement(st,null),a.createElement(A.Box,{paddingLeft:4},a.createElement(ce.Checkbox,{value:E,indeterminate:!E&&R,onValueChange:()=>{i({target:{value:[...g.actions]}})},disabled:o},"Select all"))),a.createElement(S.Grid,{gap:4,padding:4},(g==null?void 0:g.actions)&&(g==null?void 0:g.actions.map(u=>a.createElement(S.GridItem,{col:6,key:u.actionId},a.createElement(ot,{isActive:ne(u.actionId),padding:2,hasRadius:!0},a.createElement(ce.Checkbox,{value:c.includes(u.actionId),name:u.actionId,onValueChange:()=>{d({target:{value:u.actionId}})},disabled:o},u.action),a.createElement("button",{type:"button","data-testid":"action-cog",onClick:()=>y({target:{value:u.actionId}}),style:{display:"inline-flex",alignItems:"center"}},a.createElement(et(),null))))))))})))};J.defaultProps={controllers:[],orderNumber:0,disabled:!1,onExpanded:()=>null,indexExpandendCollapsedContent:null},J.propTypes={controllers:f().array,orderNumber:f().number,label:f().string.isRequired,disabled:f().bool,onExpanded:f().func,indexExpandendCollapsedContent:f().number};const it=J;var rt=Object.defineProperty,j=Object.getOwnPropertySymbols,fe=Object.prototype.hasOwnProperty,ye=Object.prototype.propertyIsEnumerable,ve=(n,e,t)=>e in n?rt(n,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):n[e]=t,lt=(n,e)=>{for(var t in e||(e={}))fe.call(e,t)&&ve(n,t,e[t]);if(j)for(var t of j(e))ye.call(e,t)&&ve(n,t,e[t]);return n},dt=(n,e)=>{var t={};for(var o in n)fe.call(n,o)&&e.indexOf(o)<0&&(t[o]=n[o]);if(n!=null&&j)for(var o of j(n))e.indexOf(o)<0&&ye.call(n,o)&&(t[o]=n[o]);return t};const X=n=>{var e=n,{section:t}=e,o=dt(e,["section"]);const[l,p]=(0,a.useState)(null),i=d=>p(d);return a.createElement(A.Box,{padding:4,background:"neutral0"},t&&t.map((d,c)=>a.createElement(it,lt({key:d.apiId,label:d.label,controllers:d.controllers,orderNumber:c,indexExpandendCollapsedContent:l,onExpanded:i,name:d.apiId},o))))};X.defaultProps={section:null},X.propTypes={section:f().arrayOf(f().object)};const ct=X;var pt=r(37213),ut=r.n(pt),mt=r(15738),gt=r.n(mt);const ft=n=>{switch(n){case"POST":return{text:"success600",border:"success200",background:"success100"};case"GET":return{text:"secondary600",border:"secondary200",background:"secondary100"};case"PUT":return{text:"warning600",border:"warning200",background:"warning100"};case"DELETE":return{text:"danger600",border:"danger200",background:"danger100"};default:return{text:"neutral600",border:"neutral200",background:"neutral100"}}},yt=(0,D.default)(A.Box)`
28
+ margin: -1px;
29
+ border-radius: ${({theme:n})=>n.spaces[1]} 0 0 ${({theme:n})=>n.spaces[1]};
30
+ `;function q({route:n}){const{formatMessage:e}=(0,k.useIntl)(),{method:t,handler:o,path:l}=n,p=l?gt()(l.split("/")):[],[i="",d=""]=o?o.split("."):[],c=ft(n.method);return a.createElement(O.Stack,{spacing:2},a.createElement(C.Typography,{variant:"delta",as:"h3"},e({id:"Settings.apiTokens.createPage.BoundRoute.title",defaultMessage:"Bound route to"}),"\xA0",a.createElement("span",null,i),a.createElement(C.Typography,{variant:"delta",textColor:"primary600"},".",d)),a.createElement(O.Stack,{horizontal:!0,hasRadius:!0,background:"neutral0",borderColor:"neutral200",spacing:0},a.createElement(yt,{background:c.background,borderColor:c.border,padding:2},a.createElement(C.Typography,{fontWeight:"bold",textColor:c.text},t)),a.createElement(A.Box,{paddingLeft:2,paddingRight:2},ut()(p,y=>a.createElement(C.Typography,{key:y,textColor:y.includes(":")?"neutral600":"neutral900"},"/",y)))))}q.defaultProps={route:{handler:"Nocontroller.error",method:"GET",path:"/there-is-no-path"}},q.propTypes={route:f().shape({handler:f().string,method:f().string,path:f().string})};const vt=q,Et=()=>{var n;const{value:{selectedAction:e,routes:t}}=Q(),{formatMessage:o}=(0,k.useIntl)(),l=e==null?void 0:e.split(".")[0];return a.createElement(S.GridItem,{col:5,background:"neutral150",paddingTop:6,paddingBottom:6,paddingLeft:7,paddingRight:7,style:{minHeight:"100%"}},e?a.createElement(O.Stack,{spacing:2},(n=t[l])==null?void 0:n.map(p=>{var i,d;return((d=(i=p.config.auth)==null?void 0:i.scope)==null?void 0:d.includes(e))||p.handler===e?a.createElement(vt,{key:p.handler,route:p}):null})):a.createElement(O.Stack,{spacing:2},a.createElement(C.Typography,{variant:"delta",as:"h3"},o({id:"Settings.apiTokens.createPage.permissions.header.title",defaultMessage:"Advanced settings"})),a.createElement(C.Typography,{as:"p",textColor:"neutral600"},o({id:"Settings.apiTokens.createPage.permissions.header.hint",defaultMessage:"Select the application's actions or the plugin's actions and click on the cog icon to display the bound route"}))))};var ht=Object.defineProperty,V=Object.getOwnPropertySymbols,Ee=Object.prototype.hasOwnProperty,he=Object.prototype.propertyIsEnumerable,Te=(n,e,t)=>e in n?ht(n,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):n[e]=t,Tt=(n,e)=>{for(var t in e||(e={}))Ee.call(e,t)&&Te(n,t,e[t]);if(V)for(var t of V(e))he.call(e,t)&&Te(n,t,e[t]);return n},Ct=(n,e)=>{var t={};for(var o in n)Ee.call(n,o)&&e.indexOf(o)<0&&(t[o]=n[o]);if(n!=null&&V)for(var o of V(n))e.indexOf(o)<0&&he.call(n,o)&&(t[o]=n[o]);return t};const St=n=>{var e=Ct(n,[]);const{value:{data:t}}=Q(),{formatMessage:o}=(0,k.useIntl)();return a.createElement(S.Grid,{gap:0,shadow:"filterShadow",hasRadius:!0,background:"neutral0"},a.createElement(S.GridItem,{col:7,paddingTop:6,paddingBottom:6,paddingLeft:7,paddingRight:7},a.createElement(O.Stack,{spacing:2},a.createElement(C.Typography,{variant:"delta",as:"h2"},o({id:"Settings.apiTokens.createPage.permissions.title",defaultMessage:"Permissions"})),a.createElement(C.Typography,{as:"p",textColor:"neutral600"},o({id:"Settings.apiTokens.createPage.permissions.description",defaultMessage:"Only actions bound by a route are listed below."}))),(t==null?void 0:t.permissions)&&a.createElement(ct,Tt({section:t==null?void 0:t.permissions},e))),a.createElement(Et,null))},Pt=(0,a.memo)(St);var Ot=r(23101),Ce=r.n(Ot),At=r(775),kt=(n,e,t)=>new Promise((o,l)=>{var p=c=>{try{d(t.next(c))}catch(y){l(y)}},i=c=>{try{d(t.throw(c))}catch(y){l(y)}},d=c=>c.done?o(c.value):Promise.resolve(c.value).then(p,i);d((t=t.apply(n,e)).next())});const _=({onRegenerate:n,idToRegenerate:e})=>{const{formatMessage:t}=(0,k.useIntl)(),[o,l]=(0,a.useState)(!1),{regenerateData:p,isLoadingConfirmation:i}=(0,At.rW)(e,n),d=()=>kt(void 0,null,function*(){p(),l(!1)});return a.createElement(a.Fragment,null,a.createElement(z.Button,{startIcon:a.createElement(Ce(),null),type:"button",size:"S",variant:"tertiary",onClick:()=>l(!0),name:"regenerate"},t({id:"Settings.apiTokens.regenerate",defaultMessage:"Regenerate"})),a.createElement(m.ConfirmDialog,{bodyText:{id:"Settings.apiTokens.popUpWarning.message",defaultMessage:"Are you sure you want to regenerate this token?"},iconRightButton:a.createElement(Ce(),null),isConfirmButtonLoading:i,isOpen:o,onToggleDialog:()=>l(!1),onConfirm:d,leftButtonText:{id:"Settings.apiTokens.Button.cancel",defaultMessage:"Cancel"},rightButtonText:{id:"Settings.apiTokens.Button.regenerate",defaultMessage:"Regenerate"},title:{id:"Settings.apiTokens.RegenerateDialog.title",defaultMessage:"Regenerate token"}}))};_.defaultProps={onRegenerate(){}},_.propTypes={onRegenerate:f().func,idToRegenerate:f().string.isRequired};const Se=_;var xt=r(83983),bt=Object.defineProperty,It=Object.defineProperties,Rt=Object.getOwnPropertyDescriptors,Pe=Object.getOwnPropertySymbols,Mt=Object.prototype.hasOwnProperty,Nt=Object.prototype.propertyIsEnumerable,Oe=(n,e,t)=>e in n?bt(n,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):n[e]=t,Bt=(n,e)=>{for(var t in e||(e={}))Mt.call(e,t)&&Oe(n,t,e[t]);if(Pe)for(var t of Pe(e))Nt.call(e,t)&&Oe(n,t,e[t]);return n},Lt=(n,e)=>It(n,Rt(e));const wt=(n,e=[])=>Lt(Bt({},n),{selectedAction:null,routes:[],selectedActions:[],data:de(e)});var Dt=r(49415),jt=Object.defineProperty,Ae=Object.getOwnPropertySymbols,Vt=Object.prototype.hasOwnProperty,Gt=Object.prototype.propertyIsEnumerable,ke=(n,e,t)=>e in n?jt(n,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):n[e]=t,Ut=(n,e)=>{for(var t in e||(e={}))Vt.call(e,t)&&ke(n,t,e[t]);if(Ae)for(var t of Ae(e))Gt.call(e,t)&&ke(n,t,e[t]);return n};const $t={data:{},selectedActions:[]},Ht=(n,e)=>(0,Dt.default)(n,t=>{switch(e.type){case"ON_CHANGE":{t.selectedActions.includes(e.value)?(0,b.pull)(t.selectedActions,e.value):t.selectedActions.push(e.value);break}case"SELECT_ALL_ACTIONS":{t.selectedActions=[...t.data.allActionsIds];break}case"ON_CHANGE_READ_ONLY":{const o=t.data.allActionsIds.filter(l=>l.includes("find")||l.includes("findOne"));t.selectedActions=[...o];break}case"UPDATE_PERMISSIONS_LAYOUT":{t.data=de(e.value);break}case"UPDATE_ROUTES":{t.routes=Ut({},e.value);break}case"UPDATE_PERMISSIONS":{t.selectedActions=[...e.value];break}case"SET_SELECTED_ACTION":{t.selectedAction=e.value;break}default:return t}});var Ft=Object.defineProperty,Wt=Object.defineProperties,zt=Object.getOwnPropertyDescriptors,xe=Object.getOwnPropertySymbols,Kt=Object.prototype.hasOwnProperty,Yt=Object.prototype.propertyIsEnumerable,be=(n,e,t)=>e in n?Ft(n,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):n[e]=t,I=(n,e)=>{for(var t in e||(e={}))Kt.call(e,t)&&be(n,t,e[t]);if(xe)for(var t of xe(e))Yt.call(e,t)&&be(n,t,e[t]);return n},ee=(n,e)=>Wt(n,zt(e)),G=(n,e,t)=>new Promise((o,l)=>{var p=c=>{try{d(t.next(c))}catch(y){l(y)}},i=c=>{try{d(t.throw(c))}catch(y){l(y)}},d=c=>c.done?o(c.value):Promise.resolve(c.value).then(p,i);d((t=t.apply(n,e)).next())});const Zt="Name already taken",Qt=()=>{var n;(0,m.useFocusWhenNavigate)();const{formatMessage:e}=(0,k.useIntl)(),{lockApp:t,unlockApp:o}=(0,m.useOverlayBlocker)(),l=(0,m.useNotification)(),p=(0,ie.useHistory)(),[i,d]=(0,a.useState)((n=p.location.state)!=null&&n.apiToken.accessKey?I({},p.location.state.apiToken):null),{trackUsage:c}=(0,m.useTracking)(),y=(0,a.useRef)(c),{setCurrentStep:te}=(0,m.useGuidedTour)(),{allowedActions:{canCreate:N,canUpdate:U,canRegenerate:$}}=(0,m.useRBAC)(xt.Z.settings["api-tokens"]),[ne]=(0,m.usePersistentState)("strapi-admin-language","en"),[g,E]=(0,a.useReducer)(Ht,$t,s=>wt(s,{})),{params:{id:R}}=(0,ie.useRouteMatch)("/settings/api-tokens/:id"),u=R==="create";(0,re.useQuery)("content-api-permissions",()=>G(void 0,null,function*(){const[s,h]=yield Promise.all(["/admin/content-api/permissions","/admin/content-api/routes"].map(x=>G(void 0,null,function*(){const{data:v}=yield w.be.get(x);return v.data})));E({type:"UPDATE_PERMISSIONS_LAYOUT",value:s}),E({type:"UPDATE_ROUTES",value:h}),i&&((i==null?void 0:i.type)==="read-only"&&E({type:"ON_CHANGE_READ_ONLY"}),(i==null?void 0:i.type)==="full-access"&&E({type:"SELECT_ALL_ACTIONS"}),(i==null?void 0:i.type)==="custom"&&E({type:"UPDATE_PERMISSIONS",value:i==null?void 0:i.permissions}))}),{onError(){l({type:"warning",message:{id:"notification.error",defaultMessage:"An error occured"}})}}),(0,a.useEffect)(()=>{y.current(u?"didAddTokenFromList":"didEditTokenFromList")},[u]);const{status:Jt}=(0,re.useQuery)(["api-token",R],()=>G(void 0,null,function*(){const{data:{data:s}}=yield w.be.get(`/admin/api-tokens/${R}`);return d(I({},s)),(s==null?void 0:s.type)==="read-only"&&E({type:"ON_CHANGE_READ_ONLY"}),(s==null?void 0:s.type)==="full-access"&&E({type:"SELECT_ALL_ACTIONS"}),(s==null?void 0:s.type)==="custom"&&E({type:"UPDATE_PERMISSIONS",value:s==null?void 0:s.permissions}),s}),{enabled:!u&&!i,onError(){l({type:"warning",message:{id:"notification.error",defaultMessage:"An error occured"}})}}),Xt=(s,h)=>G(void 0,null,function*(){var x,v,H;y.current(u?"willCreateToken":"willEditToken"),t();try{const{data:{data:T}}=u?yield w.be.post("/admin/api-tokens",ee(I({},s),{lifespan:s.lifespan&&parseInt(s.lifespan,10)?parseInt(s.lifespan,10):s.lifespan,permissions:s.type==="custom"?g.selectedActions:null})):yield w.be.put(`/admin/api-tokens/${R}`,{name:s.name,description:s.description,type:s.type,permissions:s.type==="custom"?g.selectedActions:null});u&&(p.replace(`/settings/api-tokens/${T.id}`,{apiToken:T}),te("apiTokens.success")),o(),d(I({},T)),l({type:"success",message:e(u?{id:"notification.success.tokencreated",defaultMessage:"API Token successfully created"}:{id:"notification.success.tokenedited",defaultMessage:"API Token successfully edited"})}),y.current(u?"didCreateToken":"didEditToken",{type:i.type})}catch(T){const F=(0,Ge.Iz)(T.response.data);h.setErrors(F),((H=(v=(x=T==null?void 0:T.response)==null?void 0:x.data)==null?void 0:v.error)==null?void 0:H.message)===Zt?l({type:"warning",message:(0,b.get)(T,"response.data.message","notification.error.tokennamenotunique")}):l({type:"warning",message:(0,b.get)(T,"response.data.message","notification.error")}),o()}}),[qt,ae]=(0,a.useState)(!1),_t=({target:{value:s}})=>{ae(!0),E({type:"ON_CHANGE",value:s})},en=({target:{value:s}})=>{ae(!0),s.forEach(h=>{E({type:"ON_CHANGE",value:h.actionId})})},tn=({target:{value:s}})=>{ae(!1),s==="full-access"&&E({type:"SELECT_ALL_ACTIONS"}),s==="read-only"&&E({type:"ON_CHANGE_READ_ONLY"})},nn=({target:{value:s}})=>{E({type:"SET_SELECTED_ACTION",value:s})},Ie=s=>{d(ee(I({},i),{accessKey:s}))},an=ee(I({},g),{onChange:_t,onChangeSelectAll:en,setSelectedAction:nn}),B=U&&!u||N&&u;return!u&&!i&&Jt!=="success"?a.createElement(We,{apiTokenName:i==null?void 0:i.name}):a.createElement(me,{value:an},a.createElement(oe.Main,null,a.createElement(m.SettingsPageTitle,{name:"API Tokens"}),a.createElement(De.Formik,{validationSchema:He,validateOnChange:!1,initialValues:{name:(i==null?void 0:i.name)||"",description:(i==null?void 0:i.description)||"",type:i==null?void 0:i.type,lifespan:i!=null&&i.lifespan?i.lifespan.toString():i==null?void 0:i.lifespan},enableReinitialize:!0,onSubmit:(s,h)=>Xt(s,h)},({errors:s,handleChange:h,isSubmitting:x,values:v,setFieldValue:H})=>{var T,F,Re,Me;return qt&&(v==null?void 0:v.type)!=="custom"&&H("type","custom"),a.createElement(m.Form,null,a.createElement(L.HeaderLayout,{title:(i==null?void 0:i.name)||e({id:"Settings.apiTokens.createPage.title",defaultMessage:"Create API Token"}),primaryAction:B?a.createElement(O.Stack,{horizontal:!0,spacing:2},$&&(i==null?void 0:i.id)&&a.createElement(Se,{onRegenerate:Ie,idToRegenerate:i==null?void 0:i.id}),a.createElement(z.Button,{disabled:x,loading:x,startIcon:a.createElement(se(),null),type:"submit",size:"S"},e({id:"global.save",defaultMessage:"Save"}))):$&&(i==null?void 0:i.id)&&a.createElement(Se,{onRegenerate:Ie,idToRegenerate:i==null?void 0:i.id}),navigationAction:a.createElement(m.Link,{startIcon:a.createElement(we(),null),to:"/settings/api-tokens"},e({id:"global.back",defaultMessage:"Back"}))}),a.createElement(L.ContentLayout,null,a.createElement(O.Stack,{spacing:6},Boolean(i==null?void 0:i.name)&&a.createElement(Xe,{apiToken:i.accessKey}),a.createElement(A.Box,{background:"neutral0",hasRadius:!0,shadow:"filterShadow",paddingTop:6,paddingBottom:6,paddingLeft:7,paddingRight:7},a.createElement(O.Stack,{spacing:4},a.createElement(C.Typography,{variant:"delta",as:"h2"},e({id:"global.details",defaultMessage:"Details"})),a.createElement(S.Grid,{gap:5},a.createElement(S.GridItem,{key:"name",col:6,xs:12},a.createElement(je.TextInput,{name:"name",error:s.name?e((T=s.name)!=null&&T.id?s.name:{id:s.name,defaultMessage:s.name}):null,label:e({id:"Settings.apiTokens.form.name",defaultMessage:"Name"}),onChange:h,value:v.name,disabled:!B,required:!0})),a.createElement(S.GridItem,{key:"description",col:6,xs:12},a.createElement(Ve.Textarea,{label:e({id:"Settings.apiTokens.form.description",defaultMessage:"Description"}),name:"description",error:s.description?e((F=s.description)!=null&&F.id?s.description:{id:s.description,defaultMessage:s.description}):null,onChange:h,disabled:!B},v.description)),a.createElement(S.GridItem,{key:"lifespan",col:6,xs:12},a.createElement(P.Select,{name:"lifespan",label:e({id:"Settings.apiTokens.form.duration",defaultMessage:"Token duration"}),value:v.lifespan,error:s.lifespan?e((Re=s.lifespan)!=null&&Re.id?s.lifespan:{id:s.lifespan,defaultMessage:s.lifespan}):null,onChange:W=>{h({target:{name:"lifespan",value:W}})},required:!0,disabled:!u,placeholder:"Select"},a.createElement(P.Option,{value:"604800000"},e({id:"Settings.apiTokens.duration.7-days",defaultMessage:"7 days"})),a.createElement(P.Option,{value:"2592000000"},e({id:"Settings.apiTokens.duration.30-days",defaultMessage:"30 days"})),a.createElement(P.Option,{value:"7776000000"},e({id:"Settings.apiTokens.duration.90-days",defaultMessage:"90 days"})),a.createElement(P.Option,{value:null},e({id:"Settings.apiTokens.duration.unlimited",defaultMessage:"Unlimited"}))),a.createElement(C.Typography,{variant:"pi",textColor:"neutral600"},!u&&`${e({id:"Settings.apiTokens.duration.expiration-date",defaultMessage:"Expiration date"})}: ${$e(i==null?void 0:i.createdAt,parseInt(v.lifespan,10),ne)}`)),a.createElement(S.GridItem,{key:"type",col:6,xs:12},a.createElement(P.Select,{name:"type",label:e({id:"Settings.apiTokens.form.type",defaultMessage:"Token type"}),value:v==null?void 0:v.type,error:s.type?e((Me=s.type)!=null&&Me.id?s.type:{id:s.type,defaultMessage:s.type}):null,onChange:W=>{tn({target:{value:W}}),h({target:{name:"type",value:W}})},placeholder:"Select",required:!0,disabled:!B},a.createElement(P.Option,{value:"read-only"},e({id:"Settings.apiTokens.types.read-only",defaultMessage:"Read-only"})),a.createElement(P.Option,{value:"full-access"},e({id:"Settings.apiTokens.types.full-access",defaultMessage:"Full access"})),a.createElement(P.Option,{value:"custom"},e({id:"Settings.apiTokens.types.custom",defaultMessage:"Custom"}))))))),a.createElement(Pt,{disabled:!B||(v==null?void 0:v.type)==="read-only"||(v==null?void 0:v.type)==="full-access"}))))})))}}}]);