@strapi/admin 4.4.0-beta.3 → 4.4.0-beta.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/admin/src/content-manager/components/DynamicTable/index.js +2 -2
- package/admin/src/contexts/ApiTokenPermissions/index.js +24 -0
- package/admin/src/hooks/index.js +1 -0
- package/admin/src/hooks/useRegenerate/index.js +34 -0
- package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/ActionBoundRoutes/index.js +56 -0
- package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/BoundRoute/getMethodColor.js +41 -0
- package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/BoundRoute/index.js +72 -0
- package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/CollapsableContentType/CheckBoxWrapper.js +30 -0
- package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/CollapsableContentType/index.js +150 -0
- package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/ContenTypesSection/index.js +37 -0
- package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/Permissions/index.js +40 -0
- package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/Regenerate/index.js +68 -0
- package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/index.js +450 -180
- package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/init.js +13 -0
- package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/reducer.js +72 -0
- package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/utils/getDateOfExpiration.js +16 -0
- package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/utils/index.js +5 -0
- package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/utils/schema.js +2 -1
- package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/utils/transformPermissionsData.js +36 -0
- package/admin/src/pages/SettingsPage/pages/ApiTokens/ListView/DynamicTable/DefaultButton/index.js +63 -0
- package/admin/src/pages/SettingsPage/pages/ApiTokens/ListView/DynamicTable/DeleteButton/index.js +1 -0
- package/admin/src/pages/SettingsPage/pages/ApiTokens/ListView/DynamicTable/ReadButton/index.js +19 -0
- package/admin/src/pages/SettingsPage/pages/ApiTokens/ListView/DynamicTable/UpdateButton/index.js +3 -36
- package/admin/src/pages/SettingsPage/pages/ApiTokens/ListView/DynamicTable/index.js +13 -11
- package/admin/src/pages/SettingsPage/pages/ApiTokens/ListView/index.js +3 -2
- package/admin/src/pages/SettingsPage/pages/ApiTokens/ListView/utils/tableHeaders.js +8 -8
- package/admin/src/pages/SettingsPage/pages/ApiTokens/ProtectedEditView/index.js +1 -1
- package/admin/src/permissions/defaultPermissions.js +2 -6
- package/admin/src/translations/en.json +17 -0
- package/build/4235.c44d8565.chunk.js +30 -0
- package/build/7379.d246dd38.chunk.js +1 -0
- package/build/{Admin-authenticatedApp.50e41ff2.chunk.js → Admin-authenticatedApp.6ad28580.chunk.js} +1 -1
- package/build/{Admin_homePage.118926e0.chunk.js → Admin_homePage.6d5e3236.chunk.js} +1 -1
- package/build/{Admin_profilePage.9d50ac44.chunk.js → Admin_profilePage.da32abbc.chunk.js} +1 -1
- package/build/{Admin_settingsPage.98a711e5.chunk.js → Admin_settingsPage.fc9c607a.chunk.js} +16 -16
- package/build/admin-app.7b7f9463.chunk.js +112 -0
- package/build/admin-edit-roles-page.4dd6bcb9.chunk.js +1 -0
- package/build/api-tokens-create-page.29cc87b6.chunk.js +1 -0
- package/build/api-tokens-edit-page.c294a88f.chunk.js +1 -0
- package/build/api-tokens-list-page.bb36535f.chunk.js +16 -0
- package/build/{content-manager.2a6f876d.chunk.js → content-manager.5ac9916a.chunk.js} +1 -1
- package/build/en-json.a9918c93.chunk.js +1 -0
- package/build/index.html +1 -1
- package/build/{main.fdc482f3.js → main.c04d580d.js} +1 -1
- package/build/{runtime~main.29105d25.js → runtime~main.3bd4f055.js} +2 -2
- package/build/sso-settings-page.9ceb0140.chunk.js +1 -0
- package/build/{webhook-edit-page.d2ea3351.chunk.js → webhook-edit-page.9e46fc3f.chunk.js} +1 -1
- package/package.json +8 -7
- package/server/bootstrap.js +19 -1
- package/server/config/admin-actions.js +20 -0
- package/server/content-types/api-token-permission.js +36 -0
- package/server/content-types/api-token.js +25 -1
- package/server/content-types/index.js +1 -0
- package/server/controllers/api-token.js +24 -1
- package/server/controllers/content-api.js +15 -0
- package/server/controllers/index.js +1 -0
- package/server/routes/api-tokens.js +11 -0
- package/server/routes/content-api.js +20 -0
- package/server/routes/index.js +2 -0
- package/server/services/api-token.js +310 -29
- package/server/services/constants.js +10 -0
- package/server/services/permission/engine.js +36 -226
- package/server/services/permission.js +4 -1
- package/server/strategies/admin.js +7 -1
- package/server/strategies/api-token.js +71 -11
- package/server/validation/api-tokens.js +12 -2
- package/build/admin-app.8bc3e80f.chunk.js +0 -112
- package/build/admin-edit-roles-page.554ba3fa.chunk.js +0 -1
- package/build/api-tokens-create-page.4c262d6e.chunk.js +0 -1
- package/build/api-tokens-edit-page.10a9d368.chunk.js +0 -1
- package/build/api-tokens-list-page.442c9f3c.chunk.js +0 -15
- package/build/en-json.12bc5a14.chunk.js +0 -1
- package/build/sso-settings-page.445184e0.chunk.js +0 -1
- 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,72 @@
|
|
|
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_IN_PERMISSION': {
|
|
23
|
+
const areAllSelected = action.value.every((item) =>
|
|
24
|
+
draftState.selectedActions.includes(item.actionId)
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
if (areAllSelected) {
|
|
28
|
+
action.value.forEach((item) => {
|
|
29
|
+
pull(draftState.selectedActions, item.actionId);
|
|
30
|
+
});
|
|
31
|
+
} else {
|
|
32
|
+
action.value.forEach((item) => {
|
|
33
|
+
draftState.selectedActions.push(item.actionId);
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
break;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
case 'SELECT_ALL_ACTIONS': {
|
|
40
|
+
draftState.selectedActions = [...draftState.data.allActionsIds];
|
|
41
|
+
|
|
42
|
+
break;
|
|
43
|
+
}
|
|
44
|
+
case 'ON_CHANGE_READ_ONLY': {
|
|
45
|
+
const onlyReadOnlyActions = draftState.data.allActionsIds.filter(
|
|
46
|
+
(actionId) => actionId.includes('find') || actionId.includes('findOne')
|
|
47
|
+
);
|
|
48
|
+
draftState.selectedActions = [...onlyReadOnlyActions];
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
case 'UPDATE_PERMISSIONS_LAYOUT': {
|
|
52
|
+
draftState.data = transformPermissionsData(action.value);
|
|
53
|
+
break;
|
|
54
|
+
}
|
|
55
|
+
case 'UPDATE_ROUTES': {
|
|
56
|
+
draftState.routes = { ...action.value };
|
|
57
|
+
break;
|
|
58
|
+
}
|
|
59
|
+
case 'UPDATE_PERMISSIONS': {
|
|
60
|
+
draftState.selectedActions = [...action.value];
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
case 'SET_SELECTED_ACTION': {
|
|
64
|
+
draftState.selectedAction = action.value;
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
default:
|
|
68
|
+
return draftState;
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
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;
|
|
@@ -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;
|
package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/utils/transformPermissionsData.js
ADDED
|
@@ -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;
|
package/admin/src/pages/SettingsPage/pages/ApiTokens/ListView/DynamicTable/DefaultButton/index.js
ADDED
|
@@ -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;
|
package/admin/src/pages/SettingsPage/pages/ApiTokens/ListView/DynamicTable/ReadButton/index.js
ADDED
|
@@ -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;
|
package/admin/src/pages/SettingsPage/pages/ApiTokens/ListView/DynamicTable/UpdateButton/index.js
CHANGED
|
@@ -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
|
|
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
|
-
<
|
|
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
|
-
</
|
|
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
|
-
{
|
|
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
|
-
|
|
70
|
-
<
|
|
71
|
-
|
|
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: '
|
|
26
|
-
key: '
|
|
25
|
+
name: 'createdAt',
|
|
26
|
+
key: 'createdAt',
|
|
27
27
|
metadatas: {
|
|
28
28
|
label: {
|
|
29
|
-
id: 'Settings.apiTokens.ListView.headers.
|
|
30
|
-
defaultMessage: '
|
|
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: '
|
|
37
|
-
key: '
|
|
36
|
+
name: 'lastUsedAt',
|
|
37
|
+
key: 'lastUsedAt',
|
|
38
38
|
metadatas: {
|
|
39
39
|
label: {
|
|
40
|
-
id: 'Settings.apiTokens.ListView.headers.
|
|
41
|
-
defaultMessage: '
|
|
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'].
|
|
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",
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";(self.webpackChunk_strapi_admin=self.webpackChunk_strapi_admin||[]).push([[4235],{54235:(on,Le,r)=>{r.d(Le,{Z:()=>Qt});var a=r(32735),k=r(5636),m=r(88425),B=r(11856),oe=r(16540),z=r(44526),Ne=r(88677),se=r.n(Ne),Be=r(98599),we=r.n(Be),De=r(83281),O=r(90662),A=r(9808),T=r(95602),S=r(78330),je=r(37178),Ve=r(90353),P=r(25716),I=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)}),ce=n=>{const e={allActionsIds:[],permissions:[]};return e.permissions=Object.keys(n).map(t=>({apiId:t,label:t.split("::")[1],controllers:(0,I.flatten)(Object.keys(n[t].controllers).map(o=>({controller:o,actions:(0,I.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(B.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(B.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),de=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:c,selectedActions:d,setSelectedAction:y,selectedAction:te}}=Q(),[L,U]=(0,a.useState)(!1),$=()=>{U(g=>!g),l(t)};(0,a.useEffect)(()=>{p!==null&&p!==t&&L&&U(!1)},[p,t,L]);const ne=g=>g===te;return a.createElement(Z.Accordion,{expanded:L,onToggle:$,variant:t%2?"primary":"secondary"},a.createElement(Z.AccordionToggle,{title:(0,I.capitalize)(e)}),a.createElement(Z.AccordionContent,null,n==null?void 0:n.map(g=>{const E=g.actions.every(u=>d.includes(u.actionId)),R=g.actions.some(u=>d.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(T.Typography,{variant:"sigma",textColor:"neutral600"},g==null?void 0:g.controller)),a.createElement(st,null),a.createElement(A.Box,{paddingLeft:4},a.createElement(de.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(de.Checkbox,{value:d.includes(u.actionId),name:u.actionId,onValueChange:()=>{c({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},ct=(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=ct(e,["section"]);const[l,p]=(0,a.useState)(null),i=c=>p(c);return a.createElement(A.Box,{padding:4,background:"neutral0"},t&&t.map((c,d)=>a.createElement(it,lt({key:c.apiId,label:c.label,controllers:c.controllers,orderNumber:d,indexExpandendCollapsedContent:l,onExpanded:i,name:c.apiId},o))))};X.defaultProps={section:null},X.propTypes={section:f().arrayOf(f().object)};const dt=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="",c=""]=o?o.split("."):[],d=ft(n.method);return a.createElement(O.Stack,{spacing:2},a.createElement(T.Typography,{variant:"delta",as:"h3"},e({id:"Settings.apiTokens.createPage.BoundRoute.title",defaultMessage:"Bound route to"}),"\xA0",a.createElement("span",null,i),a.createElement(T.Typography,{variant:"delta",textColor:"primary600"},".",c)),a.createElement(O.Stack,{horizontal:!0,hasRadius:!0,background:"neutral0",borderColor:"neutral200",spacing:0},a.createElement(yt,{background:d.background,borderColor:d.border,padding:2},a.createElement(T.Typography,{fontWeight:"bold",textColor:d.text},t)),a.createElement(A.Box,{paddingLeft:2,paddingRight:2},ut()(p,y=>a.createElement(T.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,c;return((c=(i=p.config.auth)==null?void 0:i.scope)==null?void 0:c.includes(e))||p.handler===e?a.createElement(vt,{key:p.handler,route:p}):null})):a.createElement(O.Stack,{spacing:2},a.createElement(T.Typography,{variant:"delta",as:"h3"},o({id:"Settings.apiTokens.createPage.permissions.header.title",defaultMessage:"Advanced settings"})),a.createElement(T.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},St=(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 Ct=n=>{var e=St(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(T.Typography,{variant:"delta",as:"h2"},o({id:"Settings.apiTokens.createPage.permissions.title",defaultMessage:"Permissions"})),a.createElement(T.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(dt,Tt({section:t==null?void 0:t.permissions},e))),a.createElement(Et,null))},Pt=(0,a.memo)(Ct);var Ot=r(23101),Se=r.n(Ot),At=r(775),kt=(n,e,t)=>new Promise((o,l)=>{var p=d=>{try{c(t.next(d))}catch(y){l(y)}},i=d=>{try{c(t.throw(d))}catch(y){l(y)}},c=d=>d.done?o(d.value):Promise.resolve(d.value).then(p,i);c((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),c=()=>kt(void 0,null,function*(){p(),l(!1)});return a.createElement(a.Fragment,null,a.createElement(z.Button,{startIcon:a.createElement(Se(),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(Se(),null),isConfirmButtonLoading:i,isOpen:o,onToggleDialog:()=>l(!1),onConfirm:c,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 Ce=_;var It=r(83983),xt=Object.defineProperty,bt=Object.defineProperties,Rt=Object.getOwnPropertyDescriptors,Pe=Object.getOwnPropertySymbols,Mt=Object.prototype.hasOwnProperty,Lt=Object.prototype.propertyIsEnumerable,Oe=(n,e,t)=>e in n?xt(n,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):n[e]=t,Nt=(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))Lt.call(e,t)&&Oe(n,t,e[t]);return n},Bt=(n,e)=>bt(n,Rt(e));const wt=(n,e=[])=>Bt(Nt({},n),{selectedAction:null,routes:[],selectedActions:[],data:ce(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,I.pull)(t.selectedActions,e.value):t.selectedActions.push(e.value);break}case"SELECT_ALL_IN_PERMISSION":{e.value.every(l=>t.selectedActions.includes(l.actionId))?e.value.forEach(l=>{(0,I.pull)(t.selectedActions,l.actionId)}):e.value.forEach(l=>{t.selectedActions.push(l.actionId)});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=ce(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,Ie=Object.getOwnPropertySymbols,Kt=Object.prototype.hasOwnProperty,Yt=Object.prototype.propertyIsEnumerable,xe=(n,e,t)=>e in n?Ft(n,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):n[e]=t,b=(n,e)=>{for(var t in e||(e={}))Kt.call(e,t)&&xe(n,t,e[t]);if(Ie)for(var t of Ie(e))Yt.call(e,t)&&xe(n,t,e[t]);return n},ee=(n,e)=>Wt(n,zt(e)),G=(n,e,t)=>new Promise((o,l)=>{var p=d=>{try{c(t.next(d))}catch(y){l(y)}},i=d=>{try{c(t.throw(d))}catch(y){l(y)}},c=d=>d.done?o(d.value):Promise.resolve(d.value).then(p,i);c((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,c]=(0,a.useState)((n=p.location.state)!=null&&n.apiToken.accessKey?b({},p.location.state.apiToken):null),{trackUsage:d}=(0,m.useTracking)(),y=(0,a.useRef)(d),{setCurrentStep:te}=(0,m.useGuidedTour)(),{allowedActions:{canCreate:L,canUpdate:U,canRegenerate:$}}=(0,m.useRBAC)(It.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,C]=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:C}),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 c(b({},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,C)=>G(void 0,null,function*(){var x,v,H;y.current(u?"willCreateToken":"willEditToken"),t();try{const{data:{data:h}}=u?yield w.be.post("/admin/api-tokens",ee(b({},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/${h.id}`,{apiToken:h}),te("apiTokens.success")),o(),c(b({},h)),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(h){const F=(0,Ge.Iz)(h.response.data);C.setErrors(F),((H=(v=(x=h==null?void 0:h.response)==null?void 0:x.data)==null?void 0:v.error)==null?void 0:H.message)===Zt?l({type:"warning",message:(0,I.get)(h,"response.data.message","notification.error.tokennamenotunique")}):l({type:"warning",message:(0,I.get)(h,"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),E({type:"SELECT_ALL_IN_PERMISSION",value:s})},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})},be=s=>{c(ee(b({},i),{accessKey:s}))},an=ee(b({},g),{onChange:_t,onChangeSelectAll:en,setSelectedAction:nn}),N=U&&!u||L&&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,C)=>Xt(s,C)},({errors:s,handleChange:C,isSubmitting:x,values:v,setFieldValue:H})=>{var h,F,Re,Me;return qt&&(v==null?void 0:v.type)!=="custom"&&H("type","custom"),a.createElement(m.Form,null,a.createElement(B.HeaderLayout,{title:(i==null?void 0:i.name)||e({id:"Settings.apiTokens.createPage.title",defaultMessage:"Create API Token"}),primaryAction:N?a.createElement(O.Stack,{horizontal:!0,spacing:2},$&&(i==null?void 0:i.id)&&a.createElement(Ce,{onRegenerate:be,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(Ce,{onRegenerate:be,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(B.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(T.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((h=s.name)!=null&&h.id?s.name:{id:s.name,defaultMessage:s.name}):null,label:e({id:"Settings.apiTokens.form.name",defaultMessage:"Name"}),onChange:C,value:v.name,disabled:!N,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:C,disabled:!N},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=>{C({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(T.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}}),C({target:{name:"type",value:W}})},placeholder:"Select",required:!0,disabled:!N},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:!N||(v==null?void 0:v.type)==="read-only"||(v==null?void 0:v.type)==="full-access"}))))})))}}}]);
|