mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 09:19:04 -04:00
* toggle to exclude host ID links on host details pg * first attempt at hiding host column * switch to conditionally splicing array of columns * exclude dest from auth table on host details pg * minor overview style touchups * rm some extranous EuiFlexGroup; more need removal * snapshots update * Revert "snapshots update" This reverts commitbdd6b8e316
. * update siem snapshots * remove unused arg * change uncommon process column order per #503 * simplify if condition, per steph * update tests, per steph * simplify `hostIdRenderer` per xavier * update snapshots * fix/improve unit tests, per xavier * Revert "update snapshots" This reverts commitdc0f79606b
. * add host links in uncommon processes table * update uncommon process test, thx to xavier # Conflicts: # x-pack/plugins/siem/public/components/page/network/ip_overview/index.tsx
This commit is contained in:
parent
1c342e3ad6
commit
bc5d6e59b4
13 changed files with 277 additions and 118 deletions
|
@ -36,51 +36,33 @@ exports[`Field Renderers #dateRenderer it renders correctly against snapshot 1`]
|
|||
|
||||
exports[`Field Renderers #hostIdRenderer it renders correctly against snapshot 1`] = `
|
||||
<Component>
|
||||
<EuiFlexGroup
|
||||
alignItems="center"
|
||||
gutterSize="none"
|
||||
<pure(Component)
|
||||
field="host.name"
|
||||
id="ip-overview-host-name"
|
||||
value="raspberrypi"
|
||||
>
|
||||
<EuiFlexItem
|
||||
grow={false}
|
||||
<pure(Component)
|
||||
hostName="raspberrypi"
|
||||
>
|
||||
<pure(Component)
|
||||
field="host.name"
|
||||
id="ip-overview-host-name"
|
||||
value="raspberrypi"
|
||||
>
|
||||
<pure(Component)
|
||||
hostName="raspberrypi"
|
||||
>
|
||||
raspberrypi
|
||||
</pure(Component)>
|
||||
</pure(Component)>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
raspberrypi
|
||||
</pure(Component)>
|
||||
</pure(Component)>
|
||||
</Component>
|
||||
`;
|
||||
|
||||
exports[`Field Renderers #hostNameRenderer it renders correctly against snapshot 1`] = `
|
||||
<Component>
|
||||
<EuiFlexGroup
|
||||
alignItems="center"
|
||||
gutterSize="none"
|
||||
<pure(Component)
|
||||
field="host.name"
|
||||
id="ip-overview-host-name"
|
||||
value="raspberrypi"
|
||||
>
|
||||
<EuiFlexItem
|
||||
grow={false}
|
||||
<pure(Component)
|
||||
hostName="raspberrypi"
|
||||
>
|
||||
<pure(Component)
|
||||
field="host.name"
|
||||
id="ip-overview-host-name"
|
||||
value="raspberrypi"
|
||||
>
|
||||
<pure(Component)
|
||||
hostName="raspberrypi"
|
||||
>
|
||||
raspberrypi
|
||||
</pure(Component)>
|
||||
</pure(Component)>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
raspberrypi
|
||||
</pure(Component)>
|
||||
</pure(Component)>
|
||||
</Component>
|
||||
`;
|
||||
|
||||
|
@ -230,16 +212,14 @@ exports[`Field Renderers #reputationRenderer it renders correctly against snapsh
|
|||
<pure(Component)
|
||||
link="10.10.10.10"
|
||||
>
|
||||
View at virustotal.com
|
||||
virustotal.com
|
||||
</pure(Component)>
|
||||
<pure(Component) />
|
||||
<br />
|
||||
,
|
||||
<pure(Component)
|
||||
domain="10.10.10.10"
|
||||
>
|
||||
View at talosIntelligence.com
|
||||
talosIntelligence.com
|
||||
</pure(Component)>
|
||||
<pure(Component) />
|
||||
</Component>
|
||||
`;
|
||||
|
||||
|
@ -351,8 +331,7 @@ exports[`Field Renderers #whoisRenderer it renders correctly against snapshot 1`
|
|||
<pure(Component)
|
||||
domain="10.10.10.10"
|
||||
>
|
||||
View at iana.org
|
||||
iana.org
|
||||
</pure(Component)>
|
||||
<pure(Component) />
|
||||
</Component>
|
||||
`;
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
import { EuiButtonEmpty, EuiFlexGroup, EuiFlexItem, EuiPopover, EuiText } from '@elastic/eui';
|
||||
import { getOr } from 'lodash/fp';
|
||||
import React, { useState } from 'react';
|
||||
import React, { Fragment, useState } from 'react';
|
||||
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
import { pure } from 'recompose';
|
||||
|
@ -19,7 +19,6 @@ import {
|
|||
} from '../../graphql/types';
|
||||
import { DefaultDraggable } from '../draggables';
|
||||
import { getEmptyTagValue } from '../empty_value';
|
||||
import { ExternalLinkIcon } from '../external_link_icon';
|
||||
import { FormattedDate } from '../formatted_date';
|
||||
import { HostDetailsLink, ReputationLink, VirusTotalLink, WhoIsLink } from '../links';
|
||||
|
||||
|
@ -35,7 +34,7 @@ export const locationRenderer = (fieldNames: string[], data: IpOverviewData): Re
|
|||
{fieldNames.map((fieldName, index) => {
|
||||
const locationValue = getOr('', fieldName, data);
|
||||
return (
|
||||
<React.Fragment key={`${IpOverviewId}-${fieldName}`}>
|
||||
<Fragment key={`${IpOverviewId}-${fieldName}`}>
|
||||
{index ? ',\u00A0' : ''}
|
||||
<EuiFlexItem grow={false}>
|
||||
<DefaultDraggable
|
||||
|
@ -44,7 +43,7 @@ export const locationRenderer = (fieldNames: string[], data: IpOverviewData): Re
|
|||
value={locationValue}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</React.Fragment>
|
||||
</Fragment>
|
||||
);
|
||||
})}
|
||||
</EuiFlexGroup>
|
||||
|
@ -80,52 +79,53 @@ export const autonomousSystemRenderer = (
|
|||
getEmptyTagValue()
|
||||
);
|
||||
|
||||
export const hostIdRenderer = (host: HostEcsFields, ipFilter?: string): React.ReactElement =>
|
||||
host.id && host.ip && (!(ipFilter != null) || host.ip.includes(ipFilter)) ? (
|
||||
<EuiFlexGroup alignItems="center" gutterSize="none">
|
||||
<EuiFlexItem grow={false}>
|
||||
{host.name && host.name[0] != null ? (
|
||||
<DefaultDraggable id={`${IpOverviewId}-host-id`} field={'host.id'} value={host.id[0]}>
|
||||
interface HostIdRendererTypes {
|
||||
host: HostEcsFields;
|
||||
ipFilter?: string;
|
||||
noLink?: boolean;
|
||||
}
|
||||
|
||||
export const hostIdRenderer = ({
|
||||
host,
|
||||
ipFilter,
|
||||
noLink,
|
||||
}: HostIdRendererTypes): React.ReactElement =>
|
||||
host.id && host.ip && (ipFilter == null || host.ip.includes(ipFilter)) ? (
|
||||
<>
|
||||
{host.name && host.name[0] != null ? (
|
||||
<DefaultDraggable id={`${IpOverviewId}-host-id`} field="host.id" value={host.id[0]}>
|
||||
{noLink ? (
|
||||
<>{host.id}</>
|
||||
) : (
|
||||
<HostDetailsLink hostName={host.name[0]}>{host.id}</HostDetailsLink>
|
||||
</DefaultDraggable>
|
||||
) : (
|
||||
<>{host.id}</>
|
||||
)}
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
)}
|
||||
</DefaultDraggable>
|
||||
) : (
|
||||
<>{host.id}</>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
getEmptyTagValue()
|
||||
);
|
||||
|
||||
export const hostNameRenderer = (host: HostEcsFields, ipFilter?: string): React.ReactElement =>
|
||||
host.name && host.name[0] && host.ip && (!(ipFilter != null) || host.ip.includes(ipFilter)) ? (
|
||||
<EuiFlexGroup alignItems="center" gutterSize="none">
|
||||
<EuiFlexItem grow={false}>
|
||||
<DefaultDraggable id={`${IpOverviewId}-host-name`} field={'host.name'} value={host.name[0]}>
|
||||
<HostDetailsLink hostName={host.name[0]}>
|
||||
{host.name ? host.name : getEmptyTagValue()}
|
||||
</HostDetailsLink>
|
||||
</DefaultDraggable>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
<DefaultDraggable id={`${IpOverviewId}-host-name`} field={'host.name'} value={host.name[0]}>
|
||||
<HostDetailsLink hostName={host.name[0]}>
|
||||
{host.name ? host.name : getEmptyTagValue()}
|
||||
</HostDetailsLink>
|
||||
</DefaultDraggable>
|
||||
) : (
|
||||
getEmptyTagValue()
|
||||
);
|
||||
|
||||
export const whoisRenderer = (ip: string) => (
|
||||
<>
|
||||
<WhoIsLink domain={ip}>{i18n.VIEW_WHOIS}</WhoIsLink>
|
||||
<ExternalLinkIcon />
|
||||
</>
|
||||
);
|
||||
export const whoisRenderer = (ip: string) => <WhoIsLink domain={ip}>{i18n.VIEW_WHOIS}</WhoIsLink>;
|
||||
|
||||
export const reputationRenderer = (ip: string): React.ReactElement => (
|
||||
<>
|
||||
<VirusTotalLink link={ip}>{i18n.VIEW_VIRUS_TOTAL}</VirusTotalLink>
|
||||
<ExternalLinkIcon />
|
||||
<br />
|
||||
{', '}
|
||||
<ReputationLink domain={ip}>{i18n.VIEW_TALOS_INTELLIGENCE}</ReputationLink>
|
||||
<ExternalLinkIcon />
|
||||
</>
|
||||
);
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Authentication Table Component rendering it renders the default Authentication table 1`] = `
|
||||
exports[`Authentication Table Component rendering it renders the authentication table 1`] = `
|
||||
<Connect(pure(Component))
|
||||
data={
|
||||
Array [
|
||||
|
|
|
@ -11,10 +11,13 @@ import * as React from 'react';
|
|||
import { Provider as ReduxStoreProvider } from 'react-redux';
|
||||
|
||||
import { apolloClientObservable, mockGlobalState } from '../../../../mock';
|
||||
import { AuthenticationsEdges } from '../../../../graphql/types';
|
||||
import { createStore, hostsModel, State } from '../../../../store';
|
||||
import { Columns } from '../../../load_more_table';
|
||||
|
||||
import { AuthenticationTable } from '.';
|
||||
import { mockData } from './mock';
|
||||
import * as i18n from './translations';
|
||||
import { AuthenticationTable, getAuthenticationColumnsCurated } from '.';
|
||||
|
||||
describe('Authentication Table Component', () => {
|
||||
const loadMore = jest.fn();
|
||||
|
@ -27,7 +30,7 @@ describe('Authentication Table Component', () => {
|
|||
});
|
||||
|
||||
describe('rendering', () => {
|
||||
test('it renders the default Authentication table', () => {
|
||||
test('it renders the authentication table', () => {
|
||||
const wrapper = shallow(
|
||||
<ReduxStoreProvider store={store}>
|
||||
<AuthenticationTable
|
||||
|
@ -45,4 +48,33 @@ describe('Authentication Table Component', () => {
|
|||
expect(toJson(wrapper)).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe('columns', () => {
|
||||
test('on hosts page, we expect to get all columns', () => {
|
||||
expect(getAuthenticationColumnsCurated(hostsModel.HostsType.page).length).toEqual(9);
|
||||
});
|
||||
|
||||
test('on host details page, we expect to remove two columns', () => {
|
||||
const columns = getAuthenticationColumnsCurated(hostsModel.HostsType.details);
|
||||
expect(columns.length).toEqual(7);
|
||||
});
|
||||
|
||||
test('on host details page, we should not have Last Failed Destination column', () => {
|
||||
const columns = getAuthenticationColumnsCurated(hostsModel.HostsType.details);
|
||||
expect(
|
||||
columns.includes(
|
||||
(col: Columns<AuthenticationsEdges>) => col.name === i18n.LAST_FAILED_DESTINATION
|
||||
)
|
||||
).toEqual(false);
|
||||
});
|
||||
|
||||
test('on host details page, we should not have Last Successful Destination column', () => {
|
||||
const columns = getAuthenticationColumnsCurated(hostsModel.HostsType.details);
|
||||
expect(
|
||||
columns.includes(
|
||||
(col: Columns<AuthenticationsEdges>) => col.name === i18n.LAST_SUCCESSFUL_DESTINATION
|
||||
)
|
||||
).toEqual(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -80,7 +80,7 @@ const AuthenticationTableComponent = pure<AuthenticationTableProps>(
|
|||
type,
|
||||
}) => (
|
||||
<LoadMoreTable
|
||||
columns={getAuthenticationColumns()}
|
||||
columns={getAuthenticationColumnsCurated(type)}
|
||||
hasNextPage={hasNextPage}
|
||||
headerCount={totalCount}
|
||||
headerTitle={i18n.AUTHENTICATIONS}
|
||||
|
@ -303,3 +303,17 @@ const getAuthenticationColumns = (): [
|
|||
}),
|
||||
},
|
||||
];
|
||||
|
||||
export const getAuthenticationColumnsCurated = (pageType: hostsModel.HostsType) => {
|
||||
const columns = getAuthenticationColumns();
|
||||
|
||||
// Columns to exclude from host details pages
|
||||
if (pageType === 'details') {
|
||||
return [i18n.LAST_FAILED_DESTINATION, i18n.LAST_SUCCESSFUL_DESTINATION].reduce((acc, name) => {
|
||||
acc.splice(acc.findIndex(column => column.name === name), 1);
|
||||
return acc;
|
||||
}, columns);
|
||||
}
|
||||
|
||||
return columns;
|
||||
};
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Load More Events Table Component rendering it renders the default Events table 1`] = `
|
||||
exports[`Load More Events Table Component rendering it renders the events table 1`] = `
|
||||
<Connect(pure(Component))
|
||||
data={
|
||||
Array [
|
||||
|
|
|
@ -11,10 +11,13 @@ import * as React from 'react';
|
|||
import { Provider as ReduxStoreProvider } from 'react-redux';
|
||||
|
||||
import { apolloClientObservable, mockGlobalState } from '../../../../mock';
|
||||
import { EcsEdges } from '../../../../graphql/types';
|
||||
import { createStore, hostsModel, State } from '../../../../store';
|
||||
import { Columns } from '../../../load_more_table';
|
||||
|
||||
import { EventsTable } from './index';
|
||||
import { EventsTable, getEventsColumnsCurated } from '.';
|
||||
import { mockData } from './mock';
|
||||
import * as i18n from './translations';
|
||||
|
||||
describe('Load More Events Table Component', () => {
|
||||
const loadMore = jest.fn();
|
||||
|
@ -27,7 +30,7 @@ describe('Load More Events Table Component', () => {
|
|||
});
|
||||
|
||||
describe('rendering', () => {
|
||||
test('it renders the default Events table', () => {
|
||||
test('it renders the events table', () => {
|
||||
const wrapper = shallow(
|
||||
<ReduxStoreProvider store={store}>
|
||||
<EventsTable
|
||||
|
@ -46,4 +49,22 @@ describe('Load More Events Table Component', () => {
|
|||
expect(toJson(wrapper)).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe('columns', () => {
|
||||
test('on hosts page, we expect to get all columns', () => {
|
||||
expect(getEventsColumnsCurated(hostsModel.HostsType.page).length).toEqual(8);
|
||||
});
|
||||
|
||||
test('on host details page, we expect to remove one column', () => {
|
||||
const columns = getEventsColumnsCurated(hostsModel.HostsType.details);
|
||||
expect(columns.length).toEqual(7);
|
||||
});
|
||||
|
||||
test('on host details page, we should not have Host Name column', () => {
|
||||
const columns = getEventsColumnsCurated(hostsModel.HostsType.details);
|
||||
expect(columns.includes((col: Columns<EcsEdges>) => col.name === i18n.HOST_NAME)).toEqual(
|
||||
false
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -79,7 +79,7 @@ const EventsTableComponent = pure<EventsTableProps>(
|
|||
type,
|
||||
}) => (
|
||||
<LoadMoreTable
|
||||
columns={getEventsColumns(type)}
|
||||
columns={getEventsColumnsCurated(type)}
|
||||
hasNextPage={hasNextPage}
|
||||
headerCount={totalCount}
|
||||
headerTitle={i18n.EVENTS}
|
||||
|
@ -254,3 +254,17 @@ const getEventsColumns = (
|
|||
},
|
||||
},
|
||||
];
|
||||
|
||||
export const getEventsColumnsCurated = (pageType: hostsModel.HostsType) => {
|
||||
const columns = getEventsColumns(pageType);
|
||||
|
||||
// Columns to exclude from host details pages
|
||||
if (pageType === 'details') {
|
||||
return [i18n.HOST_NAME].reduce((acc, name) => {
|
||||
acc.splice(acc.findIndex(column => column.name === name), 1);
|
||||
return acc;
|
||||
}, columns);
|
||||
}
|
||||
|
||||
return columns;
|
||||
};
|
||||
|
|
|
@ -8,6 +8,8 @@ import { EuiDescriptionList, EuiFlexItem } from '@elastic/eui';
|
|||
import { getOr } from 'lodash/fp';
|
||||
import React from 'react';
|
||||
import { pure } from 'recompose';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import { HostItem } from '../../../../graphql/types';
|
||||
import { getEmptyTagValue } from '../../../empty_value';
|
||||
|
||||
|
@ -30,9 +32,17 @@ interface OwnProps {
|
|||
|
||||
type HostSummaryProps = OwnProps;
|
||||
|
||||
const DescriptionList = styled(EuiDescriptionList)`
|
||||
${({ theme }) => `
|
||||
dt {
|
||||
font-size: ${theme.eui.euiFontSizeXS} !important;
|
||||
}
|
||||
`}
|
||||
`;
|
||||
|
||||
const getDescriptionList = (descriptionList: DescriptionList[], key: number) => (
|
||||
<EuiFlexItem key={key}>
|
||||
<EuiDescriptionList listItems={descriptionList} />
|
||||
<DescriptionList listItems={descriptionList} />
|
||||
</EuiFlexItem>
|
||||
);
|
||||
|
||||
|
@ -49,7 +59,9 @@ export const HostOverview = pure<HostSummaryProps>(({ data, loading }) => {
|
|||
[
|
||||
{
|
||||
title: i18n.HOST_ID,
|
||||
description: data.host ? hostIdRenderer(data.host) : getEmptyTagValue(),
|
||||
description: data.host
|
||||
? hostIdRenderer({ host: data.host, noLink: true })
|
||||
: getEmptyTagValue(),
|
||||
},
|
||||
{
|
||||
title: i18n.FIRST_SEEN,
|
||||
|
|
|
@ -57,12 +57,12 @@ describe('UncommonProcess Table Component', () => {
|
|||
.find('.euiTableRow')
|
||||
.at(0)
|
||||
.find('.euiTableRowCell')
|
||||
.at(5)
|
||||
.at(3)
|
||||
.text()
|
||||
).toBe(`Hosts${getEmptyValue()}`);
|
||||
});
|
||||
|
||||
test('it has a single host without any extra comma when the number of hosts exactly 1', () => {
|
||||
test('it has a single host without any extra comma when the number of hosts is exactly 1', () => {
|
||||
const wrapper = mount(
|
||||
<TestProviders>
|
||||
<UncommonProcessTable
|
||||
|
@ -82,11 +82,36 @@ describe('UncommonProcess Table Component', () => {
|
|||
.find('.euiTableRow')
|
||||
.at(1)
|
||||
.find('.euiTableRowCell')
|
||||
.at(5)
|
||||
.at(3)
|
||||
.text()
|
||||
).toBe('Hostshello-world ');
|
||||
});
|
||||
|
||||
test('it has a single link when the number of hosts is exactly 1', () => {
|
||||
const wrapper = mount(
|
||||
<TestProviders>
|
||||
<UncommonProcessTable
|
||||
loading={false}
|
||||
data={mockData.UncommonProcess.edges}
|
||||
totalCount={mockData.UncommonProcess.totalCount}
|
||||
hasNextPage={getOr(false, 'hasNextPage', mockData.UncommonProcess.pageInfo)!}
|
||||
nextCursor={getOr(null, 'endCursor.value', mockData.UncommonProcess.pageInfo)}
|
||||
loadMore={loadMore}
|
||||
type={hostsModel.HostsType.page}
|
||||
/>
|
||||
</TestProviders>
|
||||
);
|
||||
|
||||
expect(
|
||||
wrapper
|
||||
.find('.euiTableRow')
|
||||
.at(1)
|
||||
.find('.euiTableRowCell')
|
||||
.at(3)
|
||||
.find('a').length
|
||||
).toBe(1);
|
||||
});
|
||||
|
||||
test('it has a comma separated list of hosts when the number of hosts is greater than 1', () => {
|
||||
const wrapper = mount(
|
||||
<TestProviders>
|
||||
|
@ -107,11 +132,36 @@ describe('UncommonProcess Table Component', () => {
|
|||
.find('.euiTableRow')
|
||||
.at(2)
|
||||
.find('.euiTableRowCell')
|
||||
.at(5)
|
||||
.at(3)
|
||||
.text()
|
||||
).toBe('Hostshello-world,hello-world-2 ');
|
||||
});
|
||||
|
||||
test('it has 2 links when the number of hosts is equal to 2', () => {
|
||||
const wrapper = mount(
|
||||
<TestProviders>
|
||||
<UncommonProcessTable
|
||||
loading={false}
|
||||
data={mockData.UncommonProcess.edges}
|
||||
totalCount={mockData.UncommonProcess.totalCount}
|
||||
hasNextPage={getOr(false, 'hasNextPage', mockData.UncommonProcess.pageInfo)!}
|
||||
nextCursor={getOr(null, 'endCursor.value', mockData.UncommonProcess.pageInfo)}
|
||||
loadMore={loadMore}
|
||||
type={hostsModel.HostsType.page}
|
||||
/>
|
||||
</TestProviders>
|
||||
);
|
||||
|
||||
expect(
|
||||
wrapper
|
||||
.find('.euiTableRow')
|
||||
.at(2)
|
||||
.find('.euiTableRowCell')
|
||||
.at(3)
|
||||
.find('a').length
|
||||
).toBe(2);
|
||||
});
|
||||
|
||||
test('it is empty when all hosts are invalid because they do not contain an id and a name', () => {
|
||||
const wrapper = mount(
|
||||
<TestProviders>
|
||||
|
@ -131,11 +181,35 @@ describe('UncommonProcess Table Component', () => {
|
|||
.find('.euiTableRow')
|
||||
.at(3)
|
||||
.find('.euiTableRowCell')
|
||||
.at(5)
|
||||
.at(3)
|
||||
.text()
|
||||
).toBe(`Hosts${getEmptyValue()}`);
|
||||
});
|
||||
|
||||
test('it has no link when all hosts are invalid because they do not contain an id and a name', () => {
|
||||
const wrapper = mount(
|
||||
<TestProviders>
|
||||
<UncommonProcessTable
|
||||
loading={false}
|
||||
data={mockData.UncommonProcess.edges}
|
||||
totalCount={mockData.UncommonProcess.totalCount}
|
||||
hasNextPage={getOr(false, 'hasNextPage', mockData.UncommonProcess.pageInfo)!}
|
||||
nextCursor={getOr(null, 'endCursor.value', mockData.UncommonProcess.pageInfo)}
|
||||
loadMore={loadMore}
|
||||
type={hostsModel.HostsType.page}
|
||||
/>
|
||||
</TestProviders>
|
||||
);
|
||||
expect(
|
||||
wrapper
|
||||
.find('.euiTableRow')
|
||||
.at(3)
|
||||
.find('.euiTableRowCell')
|
||||
.at(3)
|
||||
.find('a').length
|
||||
).toBe(0);
|
||||
});
|
||||
|
||||
test('it is returns two hosts when others are invalid because they do not contain an id and a name', () => {
|
||||
const wrapper = mount(
|
||||
<TestProviders>
|
||||
|
@ -155,7 +229,7 @@ describe('UncommonProcess Table Component', () => {
|
|||
.find('.euiTableRow')
|
||||
.at(4)
|
||||
.find('.euiTableRowCell')
|
||||
.at(5)
|
||||
.at(3)
|
||||
.text()
|
||||
).toBe('Hostshello-world,hello-world-2 ');
|
||||
});
|
||||
|
|
|
@ -13,6 +13,7 @@ import { hostsActions } from '../../../../store/actions';
|
|||
import { UncommonProcessesEdges, UncommonProcessItem } from '../../../../graphql/types';
|
||||
import { hostsModel, hostsSelectors, State } from '../../../../store';
|
||||
import { defaultToEmptyTag, getEmptyValue } from '../../../empty_value';
|
||||
import { HostDetailsLink } from '../../../links';
|
||||
import { Columns, ItemsPerRow, LoadMoreTable } from '../../../load_more_table';
|
||||
|
||||
import * as i18n from './translations';
|
||||
|
@ -130,14 +131,27 @@ const getUncommonColumns = (): [
|
|||
}),
|
||||
},
|
||||
{
|
||||
name: i18n.LAST_USER,
|
||||
name: i18n.NUMBER_OF_HOSTS,
|
||||
truncateText: false,
|
||||
hideForMobile: false,
|
||||
render: ({ node }) => <>{node.hosts != null ? node.hosts.length : getEmptyValue()}</>,
|
||||
},
|
||||
{
|
||||
name: i18n.NUMBER_OF_INSTANCES,
|
||||
truncateText: false,
|
||||
hideForMobile: false,
|
||||
render: ({ node }) => defaultToEmptyTag(node.instances),
|
||||
},
|
||||
{
|
||||
name: i18n.HOSTS,
|
||||
truncateText: false,
|
||||
hideForMobile: false,
|
||||
render: ({ node }) =>
|
||||
getRowItemDraggables({
|
||||
rowItems: node.user != null ? node.user.name : null,
|
||||
attrName: 'user.name',
|
||||
idPrefix: `uncommon-process-table-${node._id}-processUser`,
|
||||
rowItems: getHostNames(node),
|
||||
attrName: 'host.name',
|
||||
idPrefix: `uncommon-process-table-${node._id}-processHost`,
|
||||
render: item => <HostDetailsLink hostName={item} />,
|
||||
}),
|
||||
},
|
||||
{
|
||||
|
@ -153,26 +167,14 @@ const getUncommonColumns = (): [
|
|||
}),
|
||||
},
|
||||
{
|
||||
name: i18n.NUMBER_OF_INSTANCES,
|
||||
truncateText: false,
|
||||
hideForMobile: false,
|
||||
render: ({ node }) => defaultToEmptyTag(node.instances),
|
||||
},
|
||||
{
|
||||
name: i18n.NUMBER_OF_HOSTS,
|
||||
truncateText: false,
|
||||
hideForMobile: false,
|
||||
render: ({ node }) => <>{node.hosts != null ? node.hosts.length : getEmptyValue()}</>,
|
||||
},
|
||||
{
|
||||
name: i18n.HOSTS,
|
||||
name: i18n.LAST_USER,
|
||||
truncateText: false,
|
||||
hideForMobile: false,
|
||||
render: ({ node }) =>
|
||||
getRowItemDraggables({
|
||||
rowItems: getHostNames(node),
|
||||
attrName: 'host.name',
|
||||
idPrefix: `uncommon-process-table-${node._id}-processHost`,
|
||||
rowItems: node.user != null ? node.user.name : null,
|
||||
attrName: 'user.name',
|
||||
idPrefix: `uncommon-process-table-${node._id}-processUser`,
|
||||
}),
|
||||
},
|
||||
];
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
import { EuiDescriptionList, EuiFlexItem } from '@elastic/eui';
|
||||
import React from 'react';
|
||||
import { pure } from 'recompose';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import { FlowTarget, IpOverviewData, Overview } from '../../../../graphql/types';
|
||||
import { networkModel } from '../../../../store';
|
||||
|
@ -40,10 +41,18 @@ interface OwnProps {
|
|||
|
||||
export type IpOverviewProps = OwnProps;
|
||||
|
||||
const DescriptionList = styled(EuiDescriptionList)`
|
||||
${({ theme }) => `
|
||||
dt {
|
||||
font-size: ${theme.eui.euiFontSizeXS} !important;
|
||||
}
|
||||
`}
|
||||
`;
|
||||
|
||||
const getDescriptionList = (descriptionList: DescriptionList[], key: number) => {
|
||||
return (
|
||||
<EuiFlexItem key={key}>
|
||||
<EuiDescriptionList listItems={descriptionList} />
|
||||
<DescriptionList listItems={descriptionList} />
|
||||
</EuiFlexItem>
|
||||
);
|
||||
};
|
||||
|
@ -73,7 +82,9 @@ export const IpOverview = pure<IpOverviewProps>(({ ip, data, loading, flowTarget
|
|||
[
|
||||
{
|
||||
title: i18n.HOST_ID,
|
||||
description: typeData ? hostIdRenderer(data.host, ip) : getEmptyTagValue(),
|
||||
description: typeData
|
||||
? hostIdRenderer({ host: data.host, ipFilter: ip })
|
||||
: getEmptyTagValue(),
|
||||
},
|
||||
{
|
||||
title: i18n.HOST_NAME,
|
||||
|
|
|
@ -42,18 +42,18 @@ export const WHOIS = i18n.translate('xpack.siem.network.ipDetails.ipOverview.who
|
|||
});
|
||||
|
||||
export const VIEW_WHOIS = i18n.translate('xpack.siem.network.ipDetails.ipOverview.viewWhoisTitle', {
|
||||
defaultMessage: 'View at iana.org',
|
||||
defaultMessage: 'iana.org',
|
||||
});
|
||||
export const VIEW_VIRUS_TOTAL = i18n.translate(
|
||||
'xpack.siem.network.ipDetails.ipOverview.viewVirusTotalTitle.',
|
||||
{
|
||||
defaultMessage: 'View at virustotal.com',
|
||||
defaultMessage: 'virustotal.com',
|
||||
}
|
||||
);
|
||||
export const VIEW_TALOS_INTELLIGENCE = i18n.translate(
|
||||
'xpack.siem.network.ipDetails.ipOverview.viewTalosIntelligenceTitle',
|
||||
{
|
||||
defaultMessage: 'View at talosIntelligence.com',
|
||||
defaultMessage: 'talosIntelligence.com',
|
||||
}
|
||||
);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue