Skip to content

Commit 6c08d90

Browse files
authored
5.2.1 release (#63)
* 5.2.1 release
1 parent cfe0299 commit 6c08d90

24 files changed

Lines changed: 755 additions & 514 deletions

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
"get-intrinsic": "~1.1.3",
4646
"serialize-javascript": "~3.1.0",
4747
"qs": "6.9.7",
48+
"ua-parser-js": "0.7.35",
4849
"url-parse": "^1.5.9",
4950
"fast-json-patch": "3.1.1"
5051
}

packages/layer7-apihub/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
"@material-ui/core": "~4.9.3",
1818
"@material-ui/lab": "~4.0.0-alpha.45",
1919
"@rehooks/local-storage": "~2.4.0",
20+
"decode-uri-component": "0.2.1",
2021
"final-form-calculate": "~1.3.2",
2122
"focus-trap-react": "~6.0.0",
2223
"jsencrypt": "~3.0.0-rc.1",
@@ -28,12 +29,13 @@
2829
"react-dnd": "~10.0.2",
2930
"react-dnd-html5-backend": "~10.0.2",
3031
"react-markdown-editor-lite": "~1.0.2",
31-
"trim": "0.0.3",
32+
"recompose":"~0.30.0",
3233
"remark-parse": "9.0.0",
3334
"remark-react": "~7.0.1",
3435
"remove-markdown": "~0.3.0",
3536
"slugify": "~1.4.4",
3637
"swagger-ui-react": "~3.27.0",
38+
"trim": "0.0.3",
3739
"unified": "~8.4.2"
3840
},
3941
"peerDependencies": {

packages/layer7-apihub/src/apis/ApiAssetsField.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,10 @@ export const ApiAssetsField = props => {
6161

6262
export const AssetsList = ({ record, links, ...rest }) => {
6363
const { urlWithTenant } = useApiHub();
64+
const { apiServiceType, publishedByPortal } = record;
6465

66+
const isGatewayPublishedSoapApi =
67+
apiServiceType === 'SOAP' && !publishedByPortal;
6568
return (
6669
<>
6770
<List {...rest}>
@@ -70,7 +73,11 @@ export const AssetsList = ({ record, links, ...rest }) => {
7073
<ListItem key={link.id} disableGutters>
7174
<Link
7275
type={link.type}
73-
href={`${urlWithTenant}${link.href}`}
76+
href={
77+
isGatewayPublishedSoapApi
78+
? `${link.href}`
79+
: `${urlWithTenant}${link.href}`
80+
}
7481
download={link.name}
7582
>
7683
{link.name}

packages/layer7-apihub/src/apis/Application/ApiApplications.js

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,6 @@ export const ApiApplications = ({ id }) => {
5959
React.useEffect(() => {
6060
let active = true;
6161

62-
if (!search || search.length < 2) {
63-
return undefined;
64-
}
65-
6662
(async () => {
6763
const [data, total] = await fetchApplications(search);
6864

@@ -71,10 +67,8 @@ export const ApiApplications = ({ id }) => {
7167
setApplications(data);
7268
setLoading(false);
7369
} else if (applications.length < total) {
74-
setApplications(
75-
uniqBy([ ...applications, ...data ], 'uuid')
76-
);
77-
setCurrentPage(currentPage+1);
70+
setApplications(uniqBy([...applications, ...data], 'uuid'));
71+
setCurrentPage(currentPage + 1);
7872
} else {
7973
setLoading(false);
8074
}
@@ -102,10 +96,10 @@ export const ApiApplications = ({ id }) => {
10296
open={open}
10397
onOpen={() => setOpen(true)}
10498
onClose={(event, reason) => setOpen(false)}
105-
onChange={(event, app, reason) => {
106-
setSelectedApp(app)
99+
onChange={(event, app, reason) => {
100+
setSelectedApp(app);
107101
if (reason == 'clear') {
108-
setApplications([])
102+
setApplications([]);
109103
}
110104
}}
111105
getOptionSelected={(option, value) =>

packages/layer7-apihub/src/apis/Application/ApiApplications.test.js

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,16 @@ describe('Applications', () => {
5252
id: 3,
5353
name: 'application 3',
5454
},
55+
{
56+
id: 4,
57+
name: 'app 4',
58+
},
59+
{
60+
id: 5,
61+
name: 'app 5',
62+
},
5563
],
56-
total: 3,
64+
total: 5,
5765
}),
5866
};
5967

@@ -64,22 +72,29 @@ describe('Applications', () => {
6472
initialState
6573
);
6674

67-
await wait(() => {
68-
const select = getByLabelText(
69-
'resources.apis.specification.actions.search_or_select_application'
70-
);
71-
fireEvent.mouseDown(select);
72-
// Enter search criteria
73-
fireEvent.change(select, { target: { value: 'application' } });
74-
});
75+
const select = getByLabelText(
76+
'resources.apis.specification.actions.search_or_select_application'
77+
);
7578

76-
await wait(() => {
77-
expect(queryByText('application 1')).not.toBeNull();
78-
expect(queryByText('application 2')).not.toBeNull();
79-
expect(queryByText('application 3')).not.toBeNull();
80-
});
79+
// Show all applications when select when no search criteria
80+
await wait(() => fireEvent.mouseDown(select));
81+
expect(queryByText('application 1')).not.toBeNull();
82+
expect(queryByText('application 2')).not.toBeNull();
83+
expect(queryByText('application 3')).not.toBeNull();
84+
expect(queryByText('app 4')).not.toBeNull();
85+
expect(queryByText('app 5')).not.toBeNull();
8186

82-
expect.assertions(3);
87+
// Enter search criteria
88+
await wait(() =>
89+
fireEvent.change(select, { target: { value: 'application' } })
90+
);
91+
expect(queryByText('application 1')).not.toBeNull();
92+
expect(queryByText('application 2')).not.toBeNull();
93+
expect(queryByText('application 3')).not.toBeNull();
94+
expect(queryByText('app 4')).toBeNull();
95+
expect(queryByText('app 5')).toBeNull();
96+
97+
expect.assertions(10);
8398
});
8499

85100
test('should display the selected application credentials', async () => {

packages/layer7-apihub/src/applications/ApplicationDetails.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import Typography from '@material-ui/core/Typography';
77
import List from '@material-ui/core/List';
88
import { makeStyles } from '@material-ui/core/styles';
99
import sortBy from 'lodash/sortBy';
10+
import get from 'lodash/get';
1011

1112
import { useUserContext } from '../userContexts';
1213
import { ApplicationApisList } from './ApplicationApisList';
@@ -54,6 +55,19 @@ export const ApplicationDetails = ({ record }) => {
5455
resource: 'applications',
5556
payload: { id: record.id },
5657
});
58+
59+
const { data: applicationApiKeyExpirySettings } = useQuery({
60+
type: 'getKeyExpirySettings',
61+
resource: 'applications',
62+
payload: {},
63+
});
64+
65+
const isKeyExpiryEnabled = get(
66+
applicationApiKeyExpirySettings,
67+
'enabled',
68+
false
69+
);
70+
5771
React.useEffect(() => {
5872
if (apisData && apisData.length > 0) {
5973
setApiIds(apisData.map(item => item.uuid));
@@ -256,6 +270,7 @@ export const ApplicationDetails = ({ record }) => {
256270
key={apiKey.id}
257271
data={apiKey}
258272
includeSecret={true}
273+
isKeyExpiryEnabled={isKeyExpiryEnabled}
259274
labelClasses={contentLabelClasses}
260275
dataProvider={dataProvider}
261276
refreshApiKeys={fetchApiKeys}

packages/layer7-apihub/src/applications/ApplicationDetailsKeyClient.js

Lines changed: 103 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React from 'react';
1+
import React, { Fragment } from 'react';
22
import { Labeled, TextField } from 'react-admin';
33
import { useTranslate } from 'ra-core';
44
import Grid from '@material-ui/core/Grid';
@@ -13,6 +13,7 @@ import ExpansionPanel from '@material-ui/core/ExpansionPanel';
1313
import ExpansionPanelSummary from '@material-ui/core/ExpansionPanelSummary';
1414
import ExpansionPanelDetails from '@material-ui/core/ExpansionPanelDetails';
1515
import classnames from 'classnames';
16+
import moment from 'moment';
1617

1718
import { useCopyToClipboard } from '../ui';
1819

@@ -33,6 +34,11 @@ const getStatusColor = (classes, status) => {
3334
statusLabel: 'Delete_Failed',
3435
statusColorClass: classes.disabled,
3536
};
37+
case 'EXPIRED':
38+
return {
39+
statusLabel: 'Expired',
40+
statusColorClass: classes.expired,
41+
};
3642
default:
3743
return {
3844
statusLabel: 'Disabled',
@@ -42,7 +48,7 @@ const getStatusColor = (classes, status) => {
4248
};
4349

4450
export const ApplicationDetailsKeyClient = props => {
45-
const { data, includeSecret } = props;
51+
const { data, includeSecret, isKeyExpiryEnabled } = props;
4652
const classes = useStyles();
4753
const translate = useTranslate();
4854
const copyToClipboard = useCopyToClipboard({
@@ -58,6 +64,56 @@ export const ApplicationDetailsKeyClient = props => {
5864
data.status
5965
);
6066

67+
const getExpiryDateText = data => {
68+
let expiryDateText = translate(
69+
'resources.applications.fields.none'
70+
);
71+
const secretExpiryTs = data.secretExpiryTs;
72+
if (isKeyExpiryEnabled && secretExpiryTs) {
73+
const keyExpiryDate = moment(secretExpiryTs);
74+
expiryDateText = keyExpiryDate.format(
75+
'dddd, MMMM Do YYYY, HH:mm:ss'
76+
);
77+
}
78+
return expiryDateText;
79+
};
80+
81+
const getExpiryDateSubText = data => {
82+
let expiryDateSubText = '';
83+
const secretExpiryTs = data.secretExpiryTs;
84+
const keyStatus = data.status;
85+
if (isKeyExpiryEnabled && secretExpiryTs) {
86+
const keyExpiryDate = moment(secretExpiryTs);
87+
const currentTime = moment();
88+
if (keyStatus === 'EXPIRED') {
89+
expiryDateSubText = translate(
90+
'resources.applications.status.expired'
91+
);
92+
} else {
93+
const days = keyExpiryDate.diff(currentTime, 'days');
94+
let suffix = translate(
95+
'resources.applications.fields.days'
96+
);
97+
if (days === 1) {
98+
suffix = translate(
99+
'resources.applications.fields.day'
100+
);
101+
}
102+
expiryDateSubText = `${days} ${suffix}`;
103+
}
104+
}
105+
return expiryDateSubText;
106+
};
107+
108+
const getExpiryDateSubTextClass = data => {
109+
let expiryDateSubTextClass = '';
110+
const keyStatus = data.status;
111+
if (keyStatus === 'EXPIRED') {
112+
expiryDateSubTextClass = classes.expiredKeyStatus;
113+
}
114+
return expiryDateSubTextClass;
115+
};
116+
61117
return (
62118
<ListItem
63119
disableGutters
@@ -225,7 +281,7 @@ export const ApplicationDetailsKeyClient = props => {
225281
</Grid>
226282
)}
227283
</Grid>
228-
<Grid>
284+
<Grid container>
229285
{data.oauthType && (
230286
<Grid item md={6} sm={6} xs={12}>
231287
<Labeled
@@ -245,6 +301,40 @@ export const ApplicationDetailsKeyClient = props => {
245301
</Labeled>
246302
</Grid>
247303
)}
304+
{isKeyExpiryEnabled && (
305+
<Grid item md={6} sm={6} xs={12}>
306+
<Labeled
307+
// On <Labeled />, this will translate in a correct `for` attribute on the label
308+
id="expiryDate"
309+
label={
310+
'resources.applications.fields.expiryDate'
311+
}
312+
classes={classes}
313+
className={classes.fieldLabel}
314+
>
315+
<Fragment>
316+
<Typography
317+
variant="body2"
318+
className={classes.fieldContent}
319+
>
320+
<span
321+
className={classes.fieldValue}
322+
>
323+
{getExpiryDateText(data)}
324+
</span>
325+
</Typography>
326+
<Typography
327+
className={getExpiryDateSubTextClass(
328+
data
329+
)}
330+
variant="body2"
331+
>
332+
{getExpiryDateSubText(data)}
333+
</Typography>
334+
</Fragment>
335+
</Labeled>
336+
</Grid>
337+
)}
248338
</Grid>
249339
</ExpansionPanelDetails>
250340
</ExpansionPanel>
@@ -277,6 +367,16 @@ const useStyles = makeStyles(
277367
backgroundColor: '#4CAF50',
278368
},
279369
},
370+
expired: {
371+
color: '#B30303',
372+
'&:before': {
373+
backgroundColor: '#B30303',
374+
},
375+
},
376+
expiredKeyStatus: {
377+
color: '#B30303',
378+
fontFamily: 'clear-sans-bold',
379+
},
280380
disabled: {
281381
color: '#696969',
282382
'&:before': {

0 commit comments

Comments
 (0)