@strapi/admin 4.6.1 → 4.7.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/admin/src/assets/images/onboarding-preview.png +0 -0
- package/admin/src/content-manager/components/CollectionTypeFormWrapper/index.js +0 -2
- package/admin/src/hooks/useRegenerate/index.js +2 -2
- package/admin/src/hooks/useSettingsMenu/utils/defaultGlobalLinks.js +7 -0
- package/admin/src/pages/Admin/Onboarding/constants.js +46 -0
- package/admin/src/pages/Admin/Onboarding/index.js +161 -89
- package/admin/src/pages/Admin/index.js +5 -2
- package/admin/src/pages/SettingsPage/{pages/ApiTokens/EditView/components → components/Tokens}/FormHead/index.js +36 -19
- package/admin/src/pages/SettingsPage/components/Tokens/FormiTokenContainer/LifeSpanInput.js +96 -0
- package/admin/src/pages/SettingsPage/components/Tokens/LifeSpanInput/index.js +98 -0
- package/admin/src/pages/SettingsPage/components/Tokens/Regenerate/index.js +73 -0
- package/admin/src/pages/SettingsPage/{pages/ApiTokens/ListView/DynamicTable → components/Tokens/Table}/DefaultButton/index.js +1 -1
- package/admin/src/pages/SettingsPage/{pages/ApiTokens/ListView/DynamicTable → components/Tokens/Table}/DeleteButton/index.js +1 -1
- package/admin/src/pages/SettingsPage/{pages/ApiTokens/ListView/DynamicTable → components/Tokens/Table}/ReadButton/index.js +0 -0
- package/admin/src/pages/SettingsPage/{pages/ApiTokens/ListView/DynamicTable → components/Tokens/Table}/UpdateButton/index.js +0 -0
- package/admin/src/pages/SettingsPage/components/Tokens/Table/index.js +135 -0
- package/admin/src/pages/SettingsPage/{pages/ApiTokens/EditView/components/ContentBox → components/Tokens/TokenBox}/index.js +17 -17
- package/admin/src/pages/SettingsPage/components/Tokens/TokenDescription/index.js +51 -0
- package/admin/src/pages/SettingsPage/components/Tokens/TokenName/index.js +46 -0
- package/admin/src/pages/SettingsPage/components/Tokens/TokenTypeSelect/index.js +69 -0
- package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/CollapsableContentType/index.js +5 -3
- package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/FormApiTokenContainer/index.js +52 -142
- package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/Regenerate/index.js +5 -1
- package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/index.js +37 -14
- package/admin/src/pages/SettingsPage/pages/ApiTokens/ListView/index.js +5 -13
- package/admin/src/pages/SettingsPage/pages/TransferTokens/EditView/components/FormTransferTokenContainer/index.js +105 -0
- package/admin/src/pages/SettingsPage/pages/TransferTokens/EditView/components/LoadingView/index.js +50 -0
- package/admin/src/pages/SettingsPage/pages/TransferTokens/EditView/index.js +201 -0
- package/admin/src/pages/SettingsPage/pages/TransferTokens/EditView/utils/getDateOfExpiration.js +16 -0
- package/admin/src/pages/SettingsPage/pages/TransferTokens/EditView/utils/index.js +4 -0
- package/admin/src/pages/SettingsPage/pages/TransferTokens/EditView/utils/schema.js +10 -0
- package/admin/src/pages/SettingsPage/pages/TransferTokens/ListView/index.js +182 -0
- package/admin/src/pages/SettingsPage/pages/TransferTokens/ListView/utils/tableHeaders.js +48 -0
- package/admin/src/pages/SettingsPage/pages/TransferTokens/ProtectedCreateView/index.js +14 -0
- package/admin/src/pages/SettingsPage/pages/TransferTokens/ProtectedEditView/index.js +14 -0
- package/admin/src/pages/SettingsPage/pages/TransferTokens/ProtectedListView/index.js +12 -0
- package/admin/src/pages/SettingsPage/utils/defaultRoutes.js +33 -0
- package/admin/src/permissions/defaultPermissions.js +8 -0
- package/admin/src/translations/en.json +18 -1
- package/build/19eb2dfcf2603eb55733.png +0 -0
- package/build/4649.15cc0afe.chunk.js +30 -0
- package/build/7259.aa68d808.chunk.js +1 -0
- package/build/7407.883fb1f5.chunk.js +1 -0
- package/build/Admin-authenticatedApp.f29f6021.chunk.js +79 -0
- package/build/{Admin_settingsPage.d1493824.chunk.js → Admin_settingsPage.178dc6e3.chunk.js} +25 -25
- package/build/{admin-app.25934eaa.chunk.js → admin-app.77a50e1f.chunk.js} +19 -19
- package/build/{api-tokens-create-page.d248362d.chunk.js → api-tokens-create-page.0db3aec1.chunk.js} +1 -1
- package/build/{api-tokens-edit-page.8516fa20.chunk.js → api-tokens-edit-page.671e0e26.chunk.js} +1 -1
- package/build/api-tokens-list-page.7387102c.chunk.js +16 -0
- package/build/{content-manager.35ff9726.chunk.js → content-manager.42b24d46.chunk.js} +77 -77
- package/build/en-json.b0748970.chunk.js +1 -0
- package/build/index.html +1 -1
- package/build/main.1022ed01.js +4393 -0
- package/build/runtime~main.84941a97.js +2 -0
- package/build/transfer-tokens-create-page.16e23791.chunk.js +1 -0
- package/build/transfer-tokens-edit-page.3886c973.chunk.js +1 -0
- package/build/transfer-tokens-list-page.e8010a89.chunk.js +16 -0
- package/package.json +12 -12
- package/server/bootstrap.js +2 -0
- package/server/config/admin-actions.js +48 -0
- package/server/content-types/index.js +2 -0
- package/server/content-types/transfer-token-permission.js +36 -0
- package/server/content-types/transfer-token.js +66 -0
- package/server/controllers/api-token.js +4 -5
- package/server/controllers/index.js +1 -0
- package/server/controllers/transfer/index.js +13 -0
- package/server/controllers/transfer/runner.js +24 -0
- package/server/controllers/transfer/token.js +131 -0
- package/server/register.js +2 -9
- package/server/routes/index.js +2 -0
- package/server/routes/transfer.js +95 -0
- package/server/services/api-token.js +2 -3
- package/server/services/constants.js +6 -0
- package/server/services/index.js +1 -0
- package/server/services/transfer/index.js +6 -0
- package/server/services/transfer/permission.js +22 -0
- package/server/services/transfer/token.js +409 -0
- package/server/strategies/api-token.js +4 -2
- package/server/strategies/data-transfer.js +107 -0
- package/server/strategies/index.js +1 -0
- package/server/utils/index.d.ts +2 -0
- package/server/validation/api-tokens.js +1 -6
- package/server/validation/transfer/index.js +5 -0
- package/server/validation/transfer/token.js +34 -0
- package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/FormBody/index.js +0 -78
- package/admin/src/pages/SettingsPage/pages/ApiTokens/ListView/DynamicTable/index.js +0 -112
- package/build/4318.f96a9d4d.chunk.js +0 -30
- package/build/8633.00ccd382.chunk.js +0 -1
- package/build/Admin-authenticatedApp.ce646f66.chunk.js +0 -75
- package/build/api-tokens-list-page.44a79fda.chunk.js +0 -16
- package/build/en-json.1f137a90.chunk.js +0 -1
- package/build/main.7b151630.js +0 -4377
- package/build/runtime~main.a20d633b.js +0 -2
package/server/utils/index.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ import * as token from '../services/token';
|
|
|
7
7
|
import * as auth from '../services/auth';
|
|
8
8
|
import * as apiToken from '../services/api-token';
|
|
9
9
|
import * as projectSettings from '../services/project-settings';
|
|
10
|
+
import * as transfer from '../services/transfer';
|
|
10
11
|
|
|
11
12
|
type S = {
|
|
12
13
|
role: typeof role;
|
|
@@ -18,6 +19,7 @@ type S = {
|
|
|
18
19
|
metrics: typeof metrics;
|
|
19
20
|
'api-token': typeof apiToken;
|
|
20
21
|
'project-settings': typeof projectSettings;
|
|
22
|
+
transfer: typeof transfer;
|
|
21
23
|
};
|
|
22
24
|
|
|
23
25
|
export function getService<T extends keyof S>(name: T): S[T];
|
|
@@ -10,12 +10,7 @@ const apiTokenCreationSchema = yup
|
|
|
10
10
|
description: yup.string().optional(),
|
|
11
11
|
type: yup.string().oneOf(Object.values(constants.API_TOKEN_TYPE)).required(),
|
|
12
12
|
permissions: yup.array().of(yup.string()).nullable(),
|
|
13
|
-
lifespan: yup
|
|
14
|
-
.number()
|
|
15
|
-
.integer()
|
|
16
|
-
.min(1)
|
|
17
|
-
.oneOf(Object.values(constants.API_TOKEN_LIFESPANS))
|
|
18
|
-
.nullable(),
|
|
13
|
+
lifespan: yup.number().min(1).oneOf(Object.values(constants.API_TOKEN_LIFESPANS)).nullable(),
|
|
19
14
|
})
|
|
20
15
|
.noUnknown()
|
|
21
16
|
.strict();
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { yup, validateYupSchema } = require('@strapi/utils');
|
|
4
|
+
const constants = require('../../services/constants');
|
|
5
|
+
|
|
6
|
+
const transferTokenCreationSchema = yup
|
|
7
|
+
.object()
|
|
8
|
+
.shape({
|
|
9
|
+
name: yup.string().min(1).required(),
|
|
10
|
+
description: yup.string().optional(),
|
|
11
|
+
permissions: yup.array().of(yup.string()).nullable(),
|
|
12
|
+
lifespan: yup
|
|
13
|
+
.number()
|
|
14
|
+
.min(1)
|
|
15
|
+
.oneOf(Object.values(constants.TRANSFER_TOKEN_LIFESPANS))
|
|
16
|
+
.nullable(),
|
|
17
|
+
})
|
|
18
|
+
.noUnknown()
|
|
19
|
+
.strict();
|
|
20
|
+
|
|
21
|
+
const transferTokenUpdateSchema = yup
|
|
22
|
+
.object()
|
|
23
|
+
.shape({
|
|
24
|
+
name: yup.string().min(1).notNull(),
|
|
25
|
+
description: yup.string().nullable(),
|
|
26
|
+
permissions: yup.array().of(yup.string()).nullable(),
|
|
27
|
+
})
|
|
28
|
+
.noUnknown()
|
|
29
|
+
.strict();
|
|
30
|
+
|
|
31
|
+
module.exports = {
|
|
32
|
+
validateTransferTokenCreationInput: validateYupSchema(transferTokenCreationSchema),
|
|
33
|
+
validateTransferTokenUpdateInput: validateYupSchema(transferTokenUpdateSchema),
|
|
34
|
+
};
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import PropTypes from 'prop-types';
|
|
3
|
-
import { ContentLayout } from '@strapi/design-system/Layout';
|
|
4
|
-
import { Stack } from '@strapi/design-system/Stack';
|
|
5
|
-
import HeaderContentBox from '../ContentBox';
|
|
6
|
-
import FormApiTokenContainer from '../FormApiTokenContainer';
|
|
7
|
-
import Permissions from '../Permissions';
|
|
8
|
-
|
|
9
|
-
const FormBody = ({
|
|
10
|
-
apiToken,
|
|
11
|
-
errors,
|
|
12
|
-
onChange,
|
|
13
|
-
canEditInputs,
|
|
14
|
-
isCreating,
|
|
15
|
-
values,
|
|
16
|
-
onDispatch,
|
|
17
|
-
setHasChangedPermissions,
|
|
18
|
-
}) => {
|
|
19
|
-
return (
|
|
20
|
-
<ContentLayout>
|
|
21
|
-
<Stack spacing={6}>
|
|
22
|
-
{Boolean(apiToken?.name) && <HeaderContentBox apiToken={apiToken?.accessKey} />}
|
|
23
|
-
<FormApiTokenContainer
|
|
24
|
-
errors={errors}
|
|
25
|
-
onChange={onChange}
|
|
26
|
-
canEditInputs={canEditInputs}
|
|
27
|
-
isCreating={isCreating}
|
|
28
|
-
values={values}
|
|
29
|
-
apiToken={apiToken}
|
|
30
|
-
onDispatch={onDispatch}
|
|
31
|
-
setHasChangedPermissions={setHasChangedPermissions}
|
|
32
|
-
/>
|
|
33
|
-
<Permissions
|
|
34
|
-
disabled={
|
|
35
|
-
!canEditInputs || values?.type === 'read-only' || values?.type === 'full-access'
|
|
36
|
-
}
|
|
37
|
-
/>
|
|
38
|
-
</Stack>
|
|
39
|
-
</ContentLayout>
|
|
40
|
-
);
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
FormBody.propTypes = {
|
|
44
|
-
errors: PropTypes.shape({
|
|
45
|
-
name: PropTypes.string,
|
|
46
|
-
description: PropTypes.string,
|
|
47
|
-
lifespan: PropTypes.string,
|
|
48
|
-
type: PropTypes.string,
|
|
49
|
-
}),
|
|
50
|
-
apiToken: PropTypes.shape({
|
|
51
|
-
id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
|
|
52
|
-
type: PropTypes.string,
|
|
53
|
-
lifespan: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
|
|
54
|
-
name: PropTypes.string,
|
|
55
|
-
accessKey: PropTypes.string,
|
|
56
|
-
permissions: PropTypes.array,
|
|
57
|
-
description: PropTypes.string,
|
|
58
|
-
createdAt: PropTypes.string,
|
|
59
|
-
}),
|
|
60
|
-
onChange: PropTypes.func.isRequired,
|
|
61
|
-
canEditInputs: PropTypes.bool.isRequired,
|
|
62
|
-
isCreating: PropTypes.bool.isRequired,
|
|
63
|
-
values: PropTypes.shape({
|
|
64
|
-
name: PropTypes.string,
|
|
65
|
-
description: PropTypes.string,
|
|
66
|
-
lifespan: PropTypes.string,
|
|
67
|
-
type: PropTypes.string,
|
|
68
|
-
}).isRequired,
|
|
69
|
-
onDispatch: PropTypes.func.isRequired,
|
|
70
|
-
setHasChangedPermissions: PropTypes.func.isRequired,
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
FormBody.defaultProps = {
|
|
74
|
-
errors: {},
|
|
75
|
-
apiToken: {},
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
export default FormBody;
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import PropTypes from 'prop-types';
|
|
3
|
-
import { useHistory } from 'react-router-dom';
|
|
4
|
-
|
|
5
|
-
import { Typography } from '@strapi/design-system/Typography';
|
|
6
|
-
import { Tbody, Tr, Td } from '@strapi/design-system/Table';
|
|
7
|
-
import { Flex } from '@strapi/design-system/Flex';
|
|
8
|
-
import {
|
|
9
|
-
RelativeTime,
|
|
10
|
-
useQueryParams,
|
|
11
|
-
onRowClick,
|
|
12
|
-
pxToRem,
|
|
13
|
-
useTracking,
|
|
14
|
-
} from '@strapi/helper-plugin';
|
|
15
|
-
import DeleteButton from './DeleteButton';
|
|
16
|
-
import UpdateButton from './UpdateButton';
|
|
17
|
-
import ReadButton from './ReadButton';
|
|
18
|
-
|
|
19
|
-
const TableRows = ({ canDelete, canUpdate, canRead, onClickDelete, withBulkActions, rows }) => {
|
|
20
|
-
const [{ query }] = useQueryParams();
|
|
21
|
-
const [, sortOrder] = query.sort.split(':');
|
|
22
|
-
const {
|
|
23
|
-
push,
|
|
24
|
-
location: { pathname },
|
|
25
|
-
} = useHistory();
|
|
26
|
-
const { trackUsage } = useTracking();
|
|
27
|
-
|
|
28
|
-
const apiTokens = rows.sort((a, b) => {
|
|
29
|
-
const comparaison = a.name.localeCompare(b.name);
|
|
30
|
-
|
|
31
|
-
return sortOrder === 'DESC' ? -comparaison : comparaison;
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
return (
|
|
35
|
-
<Tbody>
|
|
36
|
-
{apiTokens.map((apiToken) => {
|
|
37
|
-
return (
|
|
38
|
-
<Tr
|
|
39
|
-
key={apiToken.id}
|
|
40
|
-
{...onRowClick({
|
|
41
|
-
fn() {
|
|
42
|
-
trackUsage('willEditTokenFromList');
|
|
43
|
-
push(`${pathname}/${apiToken.id}`);
|
|
44
|
-
},
|
|
45
|
-
condition: canUpdate,
|
|
46
|
-
})}
|
|
47
|
-
>
|
|
48
|
-
<Td>
|
|
49
|
-
<Typography textColor="neutral800" fontWeight="bold">
|
|
50
|
-
{apiToken.name}
|
|
51
|
-
</Typography>
|
|
52
|
-
</Td>
|
|
53
|
-
<Td maxWidth={pxToRem(250)}>
|
|
54
|
-
<Typography textColor="neutral800" ellipsis>
|
|
55
|
-
{apiToken.description}
|
|
56
|
-
</Typography>
|
|
57
|
-
</Td>
|
|
58
|
-
<Td>
|
|
59
|
-
<Typography textColor="neutral800">
|
|
60
|
-
<RelativeTime timestamp={new Date(apiToken.createdAt)} />
|
|
61
|
-
</Typography>
|
|
62
|
-
</Td>
|
|
63
|
-
<Td>
|
|
64
|
-
{apiToken.lastUsedAt && (
|
|
65
|
-
<Typography textColor="neutral800">
|
|
66
|
-
<RelativeTime timestamp={new Date(apiToken.lastUsedAt)} />
|
|
67
|
-
</Typography>
|
|
68
|
-
)}
|
|
69
|
-
</Td>
|
|
70
|
-
|
|
71
|
-
{withBulkActions && (
|
|
72
|
-
<Td>
|
|
73
|
-
<Flex justifyContent="end">
|
|
74
|
-
{canUpdate && <UpdateButton tokenName={apiToken.name} tokenId={apiToken.id} />}
|
|
75
|
-
{!canUpdate && canRead && (
|
|
76
|
-
<ReadButton tokenName={apiToken.name} tokenId={apiToken.id} />
|
|
77
|
-
)}
|
|
78
|
-
{canDelete && (
|
|
79
|
-
<DeleteButton
|
|
80
|
-
tokenName={apiToken.name}
|
|
81
|
-
onClickDelete={() => onClickDelete(apiToken.id)}
|
|
82
|
-
/>
|
|
83
|
-
)}
|
|
84
|
-
</Flex>
|
|
85
|
-
</Td>
|
|
86
|
-
)}
|
|
87
|
-
</Tr>
|
|
88
|
-
);
|
|
89
|
-
})}
|
|
90
|
-
</Tbody>
|
|
91
|
-
);
|
|
92
|
-
};
|
|
93
|
-
|
|
94
|
-
TableRows.defaultProps = {
|
|
95
|
-
canDelete: false,
|
|
96
|
-
canUpdate: false,
|
|
97
|
-
canRead: false,
|
|
98
|
-
onClickDelete() {},
|
|
99
|
-
rows: [],
|
|
100
|
-
withBulkActions: false,
|
|
101
|
-
};
|
|
102
|
-
|
|
103
|
-
TableRows.propTypes = {
|
|
104
|
-
canDelete: PropTypes.bool,
|
|
105
|
-
canUpdate: PropTypes.bool,
|
|
106
|
-
canRead: PropTypes.bool,
|
|
107
|
-
onClickDelete: PropTypes.func,
|
|
108
|
-
rows: PropTypes.array,
|
|
109
|
-
withBulkActions: PropTypes.bool,
|
|
110
|
-
};
|
|
111
|
-
|
|
112
|
-
export default TableRows;
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
"use strict";(self.webpackChunk_strapi_admin=self.webpackChunk_strapi_admin||[]).push([[4318],{31625:function(ct,ge,o){o.d(ge,{Z:function(){return st}});var e=o(32735),C=o(5636),u=o(88425),w=o(27649),me=o(83281),q=o(5141),_=o(84968),fe=o(64421),ee=o(64213),ye=o(54049),Ee=(n,a,s="en")=>{if(a&&typeof a=="number"){const l=a/24/60/60/1e3;return(0,ee.format)((0,ee.addDays)(new Date(n),l),"PPP",{locale:ye[s]})}return"Unlimited"},I=o(5173),he=I.Ry().shape({name:I.Z_(u.translatedErrors.string).required(u.translatedErrors.required),type:I.Z_(u.translatedErrors.string).oneOf(["read-only","full-access","custom"]).required(u.translatedErrors.required),description:I.Z_().nullable(),lifespan:I.Rx().integer().min(0).nullable().defined(u.translatedErrors.required)}),M=o(92891),te=n=>{const a={allActionsIds:[],permissions:[]};return a.permissions=Object.keys(n).map(s=>({apiId:s,label:s.split("::")[1],controllers:(0,M.flatten)(Object.keys(n[s].controllers).map(l=>({controller:l,actions:(0,M.flatten)(n[s].controllers[l].map(i=>{const r=`${s}.${l}.${i}`;return s.includes("api::")&&a.allActionsIds.push(r),{action:i,actionId:r}}))})))})),a},ne=o(28356),ae=o(17e3),Z=o(41415),se=o(66456),Te=o(60216),t=o.n(Te);const U=({apiTokenName:n})=>{const{formatMessage:a}=(0,C.useIntl)();return(0,u.useFocusWhenNavigate)(),e.createElement(w.o,{"aria-busy":"true"},e.createElement(u.SettingsPageTitle,{name:"API Tokens"}),e.createElement(ne.T,{primaryAction:e.createElement(Z.z,{disabled:!0,startIcon:e.createElement(se.Z,null),type:"button",size:"L"},a({id:"global.save",defaultMessage:"Save"})),title:n||a({id:"Settings.apiTokens.createPage.title",defaultMessage:"Create API Token"})}),e.createElement(ae.D,null,e.createElement(u.LoadingIndicatorPage,null)))};U.defaultProps={apiTokenName:null},U.propTypes={apiTokenName:t().string};var ve=U,Ce=o(29439),k=o(27677),oe=o(44647),Ae=o(8888);const F=({onRegenerate:n,idToRegenerate:a})=>{const{formatMessage:s}=(0,C.useIntl)(),[l,i]=(0,e.useState)(!1),{regenerateData:r,isLoadingConfirmation:p}=(0,Ae.rW)(a,n),f=async()=>{r(),i(!1)};return e.createElement(e.Fragment,null,e.createElement(Z.z,{startIcon:e.createElement(oe.Z,null),type:"button",size:"S",variant:"tertiary",onClick:()=>i(!0),name:"regenerate"},s({id:"Settings.apiTokens.regenerate",defaultMessage:"Regenerate"})),e.createElement(u.ConfirmDialog,{bodyText:{id:"Settings.apiTokens.popUpWarning.message",defaultMessage:"Are you sure you want to regenerate this token?"},iconRightButton:e.createElement(oe.Z,null),isConfirmButtonLoading:p,isOpen:l,onToggleDialog:()=>i(!1),onConfirm:f,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"}}))};F.defaultProps={onRegenerate(){}},F.propTypes={onRegenerate:t().func,idToRegenerate:t().oneOfType([t().number,t().string]).isRequired};var ie=F;const K=({apiToken:n,setApiToken:a,canEditInputs:s,canRegenerate:l,isSubmitting:i})=>{const{formatMessage:r}=(0,C.useIntl)(),p=f=>{a({...n,accessKey:f})};return e.createElement(ne.T,{title:n?.name||r({id:"Settings.apiTokens.createPage.title",defaultMessage:"Create API Token"}),primaryAction:s?e.createElement(k.K,{horizontal:!0,spacing:2},l&&n?.id&&e.createElement(ie,{onRegenerate:p,idToRegenerate:n?.id}),e.createElement(Z.z,{disabled:i,loading:i,startIcon:e.createElement(se.Z,null),type:"submit",size:"S"},r({id:"global.save",defaultMessage:"Save"}))):l&&n?.id&&e.createElement(ie,{onRegenerate:p,idToRegenerate:n?.id}),navigationAction:e.createElement(u.Link,{startIcon:e.createElement(Ce.Z,null),to:"/settings/api-tokens"},r({id:"global.back",defaultMessage:"Back"}))})};K.propTypes={apiToken:t().shape({id:t().oneOfType([t().number,t().string]),type:t().string,lifespan:t().oneOfType([t().number,t().string]),name:t().string,accessKey:t().string,permissions:t().array,description:t().string,createdAt:t().string}),canEditInputs:t().bool.isRequired,canRegenerate:t().bool.isRequired,setApiToken:t().func.isRequired,isSubmitting:t().bool.isRequired},K.defaultProps={apiToken:void 0};var ke=K,Se=o(50563),Re=o(47765),xe=o(59087),Pe=o(11631);const W=({apiToken:n})=>{const{formatMessage:a}=(0,C.useIntl)(),s=(0,u.useNotification)(),{trackUsage:l}=(0,u.useTracking)(),i=(0,e.useRef)(l);return e.createElement(u.ContentBox,{endAction:n&&e.createElement("span",{style:{alignSelf:"start"}},e.createElement(xe.CopyToClipboard,{onCopy:()=>{i.current("didCopyTokenKey"),s({type:"success",message:{id:"Settings.apiTokens.notification.copied"}})},text:n},e.createElement(Se.h,{label:a({id:"app.component.CopyToClipboard.label",defaultMessage:"Copy to clipboard"}),noBorder:!0,icon:e.createElement(Re.Z,null),style:{padding:0,height:"1rem"}}))),title:n||a({id:"Settings.apiTokens.copy.editTitle",defaultMessage:"This token isn\u2019t accessible anymore."}),subtitle:a(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:e.createElement(Pe.Z,null),iconBackground:"neutral100"})};W.defaultProps={apiToken:null},W.propTypes={apiToken:t().string};var Ie=W,S=o(72850),$=o(15335),R=o(5803),re=o(70218),x=o(84967),Me=o(10508),be=o(10369),v=o(49372);const H=({errors:n,onChange:a,canEditInputs:s,isCreating:l,values:i,apiToken:r,onDispatch:p,setHasChangedPermissions:f})=>{const{formatMessage:d}=(0,C.useIntl)(),[A]=(0,u.usePersistentState)("strapi-admin-language","en"),b=({target:{value:y}})=>{f(!1),y==="full-access"&&p({type:"SELECT_ALL_ACTIONS"}),y==="read-only"&&p({type:"ON_CHANGE_READ_ONLY"})};return e.createElement(S.x,{background:"neutral0",hasRadius:!0,shadow:"filterShadow",paddingTop:6,paddingBottom:6,paddingLeft:7,paddingRight:7},e.createElement(k.K,{spacing:4},e.createElement(v.Z,{variant:"delta",as:"h2"},d({id:"global.details",defaultMessage:"Details"})),e.createElement($.r,{gap:5},e.createElement(R.P,{key:"name",col:6,xs:12},e.createElement(be.o,{name:"name",error:n.name?d(n.name?.id?n.name:{id:n.name,defaultMessage:n.name}):null,label:d({id:"Settings.apiTokens.form.name",defaultMessage:"Name"}),onChange:a,value:i.name,disabled:!s,required:!0})),e.createElement(R.P,{key:"description",col:6,xs:12},e.createElement(Me.g,{label:d({id:"Settings.apiTokens.form.description",defaultMessage:"Description"}),name:"description",error:n.description?d(n.description?.id?n.description:{id:n.description,defaultMessage:n.description}):null,onChange:a,disabled:!s},i.description)),e.createElement(R.P,{key:"lifespan",col:6,xs:12},e.createElement(re.P,{name:"lifespan",label:d({id:"Settings.apiTokens.form.duration",defaultMessage:"Token duration"}),value:i.lifespan!==null?i.lifespan:"0",error:n.lifespan?d(n.lifespan?.id?n.lifespan:{id:n.lifespan,defaultMessage:n.lifespan}):null,onChange:y=>{a({target:{name:"lifespan",value:y}})},required:!0,disabled:!l,placeholder:"Select"},e.createElement(x.W,{value:"604800000"},d({id:"Settings.apiTokens.duration.7-days",defaultMessage:"7 days"})),e.createElement(x.W,{value:"2592000000"},d({id:"Settings.apiTokens.duration.30-days",defaultMessage:"30 days"})),e.createElement(x.W,{value:"7776000000"},d({id:"Settings.apiTokens.duration.90-days",defaultMessage:"90 days"})),e.createElement(x.W,{value:"0"},d({id:"Settings.apiTokens.duration.unlimited",defaultMessage:"Unlimited"}))),e.createElement(v.Z,{variant:"pi",textColor:"neutral600"},!l&&`${d({id:"Settings.apiTokens.duration.expiration-date",defaultMessage:"Expiration date"})}: ${Ee(r?.createdAt,parseInt(i.lifespan,10),A)}`)),e.createElement(R.P,{key:"type",col:6,xs:12},e.createElement(re.P,{name:"type",label:d({id:"Settings.apiTokens.form.type",defaultMessage:"Token type"}),value:i?.type,error:n.type?d(n.type?.id?n.type:{id:n.type,defaultMessage:n.type}):null,onChange:y=>{b({target:{value:y}}),a({target:{name:"type",value:y}})},placeholder:"Select",required:!0,disabled:!s},e.createElement(x.W,{value:"read-only"},d({id:"Settings.apiTokens.types.read-only",defaultMessage:"Read-only"})),e.createElement(x.W,{value:"full-access"},d({id:"Settings.apiTokens.types.full-access",defaultMessage:"Full access"})),e.createElement(x.W,{value:"custom"},d({id:"Settings.apiTokens.types.custom",defaultMessage:"Custom"})))))))};H.propTypes={errors:t().shape({name:t().string,description:t().string,lifespan:t().string,type:t().string}),onChange:t().func.isRequired,canEditInputs:t().bool.isRequired,values:t().shape({name:t().string,description:t().string,lifespan:t().oneOfType([t().number,t().string]),type:t().string}).isRequired,isCreating:t().bool.isRequired,apiToken:t().shape({id:t().oneOfType([t().number,t().string]),type:t().string,lifespan:t().string,name:t().string,accessKey:t().string,permissions:t().array,description:t().string,createdAt:t().string}),onDispatch:t().func.isRequired,setHasChangedPermissions:t().func.isRequired},H.defaultProps={errors:{},apiToken:{}};var Oe=H,Le=o(83828),Ne=o(61762),De=o(89966),le=o(8284),Be=o(87933),Ze=o(45112),D=o(83292);const ce=(0,e.createContext)({}),de=({children:n,...a})=>e.createElement(ce.Provider,{value:a},n),G=()=>(0,e.useContext)(ce);de.propTypes={children:t().node.isRequired};const ue=D.css`
|
|
2
|
-
background: ${n=>n.theme.colors.primary100};
|
|
3
|
-
svg {
|
|
4
|
-
opacity: 1;
|
|
5
|
-
}
|
|
6
|
-
`;var Ue=(0,D.default)(S.x)`
|
|
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&&ue}
|
|
20
|
-
&:hover {
|
|
21
|
-
${ue}
|
|
22
|
-
}
|
|
23
|
-
`;const Fe=D.default.div`
|
|
24
|
-
flex: 1;
|
|
25
|
-
align-self: center;
|
|
26
|
-
border-top: 1px solid ${({theme:n})=>n.colors.neutral150};
|
|
27
|
-
`,V=({controllers:n,label:a,orderNumber:s,disabled:l,onExpanded:i,indexExpandendCollapsedContent:r})=>{const{value:{onChangeSelectAll:p,onChange:f,selectedActions:d,setSelectedAction:A,selectedAction:b}}=G(),[y,B]=(0,e.useState)(!1),O=()=>{B(g=>!g),i(s)};(0,e.useEffect)(()=>{r!==null&&r!==s&&y&&B(!1)},[r,s,y]);const m=g=>g===b;return e.createElement(Le.U,{expanded:y,onToggle:O,variant:s%2?"primary":"secondary"},e.createElement(Ne.B,{title:(0,M.capitalize)(a)}),e.createElement(De.v,null,n?.map(g=>{const L=g.actions.every(E=>d.includes(E.actionId)),Q=g.actions.some(E=>d.includes(E.actionId));return e.createElement(S.x,{key:`${a}.${g?.controller}`},e.createElement(Be.k,{justifyContent:"space-between",alignItems:"center",padding:4},e.createElement(S.x,{paddingRight:4},e.createElement(v.Z,{variant:"sigma",textColor:"neutral600"},g?.controller)),e.createElement(Fe,null),e.createElement(S.x,{paddingLeft:4},e.createElement(le.X,{value:L,indeterminate:!L&&Q,onValueChange:()=>{p({target:{value:[...g.actions]}})},disabled:l},"Select all"))),e.createElement($.r,{gap:4,padding:4},g?.actions&&g?.actions.map(E=>e.createElement(R.P,{col:6,key:E.actionId},e.createElement(Ue,{isActive:m(E.actionId),padding:2,hasRadius:!0},e.createElement(le.X,{value:d.includes(E.actionId),name:E.actionId,onValueChange:()=>{f({target:{value:E.actionId}})},disabled:l},E.action),e.createElement("button",{type:"button","data-testid":"action-cog",onClick:()=>A({target:{value:E.actionId}}),style:{display:"inline-flex",alignItems:"center"}},e.createElement(Ze.Z,null)))))))})))};V.defaultProps={controllers:[],orderNumber:0,disabled:!1,onExpanded:()=>null,indexExpandendCollapsedContent:null},V.propTypes={controllers:t().array,orderNumber:t().number,label:t().string.isRequired,disabled:t().bool,onExpanded:t().func,indexExpandendCollapsedContent:t().number};var Ke=V;const z=({section:n,...a})=>{const[s,l]=(0,e.useState)(null),i=r=>l(r);return e.createElement(S.x,{padding:4,background:"neutral0"},n&&n.map((r,p)=>e.createElement(Ke,{key:r.apiId,label:r.label,controllers:r.controllers,orderNumber:p,indexExpandendCollapsedContent:s,onExpanded:i,name:r.apiId,...a})))};z.defaultProps={section:null},z.propTypes={section:t().arrayOf(t().object)};var We=z,$e=o(37213),He=o.n($e),Ge=o(15738),Ve=o.n(Ge),ze=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"}}};const Ye=(0,D.default)(S.x)`
|
|
28
|
-
margin: -1px;
|
|
29
|
-
border-radius: ${({theme:n})=>n.spaces[1]} 0 0 ${({theme:n})=>n.spaces[1]};
|
|
30
|
-
`;function Y({route:n}){const{formatMessage:a}=(0,C.useIntl)(),{method:s,handler:l,path:i}=n,r=i?Ve()(i.split("/")):[],[p="",f=""]=l?l.split("."):[],d=ze(n.method);return e.createElement(k.K,{spacing:2},e.createElement(v.Z,{variant:"delta",as:"h3"},a({id:"Settings.apiTokens.createPage.BoundRoute.title",defaultMessage:"Bound route to"}),"\xA0",e.createElement("span",null,p),e.createElement(v.Z,{variant:"delta",textColor:"primary600"},".",f)),e.createElement(k.K,{horizontal:!0,hasRadius:!0,background:"neutral0",borderColor:"neutral200",spacing:0},e.createElement(Ye,{background:d.background,borderColor:d.border,padding:2},e.createElement(v.Z,{fontWeight:"bold",textColor:d.text},s)),e.createElement(S.x,{paddingLeft:2,paddingRight:2},He()(r,A=>e.createElement(v.Z,{key:A,textColor:A.includes(":")?"neutral600":"neutral900"},"/",A)))))}Y.defaultProps={route:{handler:"Nocontroller.error",method:"GET",path:"/there-is-no-path"}},Y.propTypes={route:t().shape({handler:t().string,method:t().string,path:t().string})};var je=Y,Qe=()=>{const{value:{selectedAction:n,routes:a}}=G(),{formatMessage:s}=(0,C.useIntl)(),l=n?.split(".")[0];return e.createElement(R.P,{col:5,background:"neutral150",paddingTop:6,paddingBottom:6,paddingLeft:7,paddingRight:7,style:{minHeight:"100%"}},n?e.createElement(k.K,{spacing:2},a[l]?.map(i=>i.config.auth?.scope?.includes(n)||i.handler===n?e.createElement(je,{key:i.handler,route:i}):null)):e.createElement(k.K,{spacing:2},e.createElement(v.Z,{variant:"delta",as:"h3"},s({id:"Settings.apiTokens.createPage.permissions.header.title",defaultMessage:"Advanced settings"})),e.createElement(v.Z,{as:"p",textColor:"neutral600"},s({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"}))))};const Xe=({...n})=>{const{value:{data:a}}=G(),{formatMessage:s}=(0,C.useIntl)();return e.createElement($.r,{gap:0,shadow:"filterShadow",hasRadius:!0,background:"neutral0"},e.createElement(R.P,{col:7,paddingTop:6,paddingBottom:6,paddingLeft:7,paddingRight:7},e.createElement(k.K,{spacing:2},e.createElement(v.Z,{variant:"delta",as:"h2"},s({id:"Settings.apiTokens.createPage.permissions.title",defaultMessage:"Permissions"})),e.createElement(v.Z,{as:"p",textColor:"neutral600"},s({id:"Settings.apiTokens.createPage.permissions.description",defaultMessage:"Only actions bound by a route are listed below."}))),a?.permissions&&e.createElement(We,{section:a?.permissions,...n})),e.createElement(Qe,null))};var Je=(0,e.memo)(Xe);const j=({apiToken:n,errors:a,onChange:s,canEditInputs:l,isCreating:i,values:r,onDispatch:p,setHasChangedPermissions:f})=>e.createElement(ae.D,null,e.createElement(k.K,{spacing:6},Boolean(n?.name)&&e.createElement(Ie,{apiToken:n?.accessKey}),e.createElement(Oe,{errors:a,onChange:s,canEditInputs:l,isCreating:i,values:r,apiToken:n,onDispatch:p,setHasChangedPermissions:f}),e.createElement(Je,{disabled:!l||r?.type==="read-only"||r?.type==="full-access"})));j.propTypes={errors:t().shape({name:t().string,description:t().string,lifespan:t().string,type:t().string}),apiToken:t().shape({id:t().oneOfType([t().number,t().string]),type:t().string,lifespan:t().oneOfType([t().number,t().string]),name:t().string,accessKey:t().string,permissions:t().array,description:t().string,createdAt:t().string}),onChange:t().func.isRequired,canEditInputs:t().bool.isRequired,isCreating:t().bool.isRequired,values:t().shape({name:t().string,description:t().string,lifespan:t().string,type:t().string}).isRequired,onDispatch:t().func.isRequired,setHasChangedPermissions:t().func.isRequired},j.defaultProps={errors:{},apiToken:{}};var we=j,qe=o(72041),_e=(n,a=[])=>({...n,selectedAction:null,routes:[],selectedActions:[],data:te(a)}),et=o(97889);const tt={data:{},selectedActions:[]};var nt=(n,a)=>(0,et.default)(n,s=>{switch(a.type){case"ON_CHANGE":{s.selectedActions.includes(a.value)?(0,M.pull)(s.selectedActions,a.value):s.selectedActions.push(a.value);break}case"SELECT_ALL_IN_PERMISSION":{a.value.every(i=>s.selectedActions.includes(i.actionId))?a.value.forEach(i=>{(0,M.pull)(s.selectedActions,i.actionId)}):a.value.forEach(i=>{s.selectedActions.push(i.actionId)});break}case"SELECT_ALL_ACTIONS":{s.selectedActions=[...s.data.allActionsIds];break}case"ON_CHANGE_READ_ONLY":{const l=s.data.allActionsIds.filter(i=>i.includes("find")||i.includes("findOne"));s.selectedActions=[...l];break}case"UPDATE_PERMISSIONS_LAYOUT":{s.data=te(a.value);break}case"UPDATE_ROUTES":{s.routes={...a.value};break}case"UPDATE_PERMISSIONS":{s.selectedActions=[...a.value];break}case"SET_SELECTED_ACTION":{s.selectedAction=a.value;break}default:return s}});const at="Name already taken";var st=()=>{(0,u.useFocusWhenNavigate)();const{formatMessage:n}=(0,C.useIntl)(),{lockApp:a,unlockApp:s}=(0,u.useOverlayBlocker)(),l=(0,u.useNotification)(),i=(0,q.useHistory)(),[r,p]=(0,e.useState)(i.location.state?.apiToken.accessKey?{...i.location.state.apiToken}:null),{trackUsage:f}=(0,u.useTracking)(),d=(0,e.useRef)(f),{setCurrentStep:A}=(0,u.useGuidedTour)(),{allowedActions:{canCreate:b,canUpdate:y,canRegenerate:B}}=(0,u.useRBAC)(qe.Z.settings["api-tokens"]),[O,m]=(0,e.useReducer)(nt,tt,c=>_e(c,{})),{params:{id:g}}=(0,q.useRouteMatch)("/settings/api-tokens/:id"),{get:L,post:Q,put:E}=(0,u.useFetchClient)(),T=g==="create";(0,_.useQuery)("content-api-permissions",async()=>{const[c,P]=await Promise.all(["/admin/content-api/permissions","/admin/content-api/routes"].map(async N=>{const{data:h}=await L(N);return h.data}));m({type:"UPDATE_PERMISSIONS_LAYOUT",value:c}),m({type:"UPDATE_ROUTES",value:P}),r&&(r?.type==="read-only"&&m({type:"ON_CHANGE_READ_ONLY"}),r?.type==="full-access"&&m({type:"SELECT_ALL_ACTIONS"}),r?.type==="custom"&&m({type:"UPDATE_PERMISSIONS",value:r?.permissions}))},{onError(){l({type:"warning",message:{id:"notification.error",defaultMessage:"An error occured"}})}}),(0,e.useEffect)(()=>{d.current(T?"didAddTokenFromList":"didEditTokenFromList")},[T]);const{status:ot}=(0,_.useQuery)(["api-token",g],async()=>{const{data:{data:c}}=await L(`/admin/api-tokens/${g}`);return p({...c}),c?.type==="read-only"&&m({type:"ON_CHANGE_READ_ONLY"}),c?.type==="full-access"&&m({type:"SELECT_ALL_ACTIONS"}),c?.type==="custom"&&m({type:"UPDATE_PERMISSIONS",value:c?.permissions}),c},{enabled:!T&&!r,onError(){l({type:"warning",message:{id:"notification.error",defaultMessage:"An error occured"}})}}),it=async(c,P)=>{d.current(T?"willCreateToken":"willEditToken"),a();const N=c.lifespan&&parseInt(c.lifespan,10)&&c.lifespan!=="0"?parseInt(c.lifespan,10):null;try{const{data:{data:h}}=T?await Q("/admin/api-tokens",{...c,lifespan:N,permissions:c.type==="custom"?O.selectedActions:null}):await E(`/admin/api-tokens/${g}`,{name:c.name,description:c.description,type:c.type,permissions:c.type==="custom"?O.selectedActions:null});T&&(i.replace(`/settings/api-tokens/${h.id}`,{apiToken:h}),A("apiTokens.success")),s(),p({...h}),l({type:"success",message:n(T?{id:"notification.success.tokencreated",defaultMessage:"API Token successfully created"}:{id:"notification.success.tokenedited",defaultMessage:"API Token successfully edited"})}),d.current(T?"didCreateToken":"didEditToken",{type:r.type})}catch(h){const J=(0,fe.Iz)(h.response.data);P.setErrors(J),h?.response?.data?.error?.message===at?l({type:"warning",message:h.response.data.message||"notification.error.tokennamenotunique"}):l({type:"warning",message:h?.response?.data?.message||"notification.error"}),s()}},[rt,X]=(0,e.useState)(!1),lt={...O,onChange:({target:{value:c}})=>{X(!0),m({type:"ON_CHANGE",value:c})},onChangeSelectAll:({target:{value:c}})=>{X(!0),m({type:"SELECT_ALL_IN_PERMISSION",value:c})},setSelectedAction:({target:{value:c}})=>{m({type:"SET_SELECTED_ACTION",value:c})}},pe=y&&!T||b&&T;return!T&&!r&&ot!=="success"?e.createElement(ve,{apiTokenName:r?.name}):e.createElement(de,{value:lt},e.createElement(w.o,null,e.createElement(u.SettingsPageTitle,{name:"API Tokens"}),e.createElement(me.Formik,{validationSchema:he,validateOnChange:!1,initialValues:{name:r?.name||"",description:r?.description||"",type:r?.type,lifespan:r?.lifespan?r.lifespan.toString():r?.lifespan},enableReinitialize:!0,onSubmit:(c,P)=>it(c,P)},({errors:c,handleChange:P,isSubmitting:N,values:h,setFieldValue:J})=>(rt&&h?.type!=="custom"&&J("type","custom"),e.createElement(u.Form,null,e.createElement(ke,{apiToken:r,setApiToken:p,canEditInputs:pe,canRegenerate:B,isSubmitting:N}),e.createElement(we,{apiToken:r,errors:c,onChange:P,canEditInputs:pe,isCreating:T,values:h,onDispatch:m,setHasChangedPermissions:X}))))))}}}]);
|