Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add field links in discover document details #6843

Merged
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ All notable changes to the Wazuh app project will be documented in this file.

### Changed

- Removed embedded discover [#6120](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6120) [#6235](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6235) [#6254](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6254) [#6285](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6285) [#6288](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6288) [#6290](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6290) [#6289](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6289) [#6286](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6286) [#6275](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6275) [#6287](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6287) [#6297](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6297) [#6291](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6287) [#6459](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6459) [#6434](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6434) [#6504](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6504) [#6649](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6649) [#6506](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6506) [#6537](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6537) [#6528](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6528) [#6675](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6675) [#6674](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6674) [#6558](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6558) [#6685](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6685) [#6691](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6691) [#6712](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6712) [#6734](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6734) [#6746](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6746) [#6752](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6752) [#6753](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6753) [#6756](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6756) [#6771](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6771) [#6792](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6792) [#6845](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6845) [#6857](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6857) [#6847](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6847) [#6865](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6865) [#6848](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6848)
- Removed embedded discover [#6120](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6120) [#6235](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6235) [#6254](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6254) [#6285](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6285) [#6288](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6288) [#6290](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6290) [#6289](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6289) [#6286](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6286) [#6275](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6275) [#6287](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6287) [#6297](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6297) [#6291](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6287) [#6459](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6459) [#6434](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6434) [#6504](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6504) [#6649](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6649) [#6506](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6506) [#6537](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6537) [#6528](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6528) [#6675](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6675) [#6674](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6674) [#6558](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6558) [#6685](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6685) [#6691](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6691) [#6712](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6712) [#6734](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6734) [#6746](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6746) [#6752](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6752) [#6753](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6753) [#6756](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6756) [#6771](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6771) [#6792](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6792) [#6845](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6845) [#6857](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6857) [#6847](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6847) [#6865](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6865) [#6848](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6848) [#6843](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6843)
- Allow editing groups for an agent from Endpoints Summary [#6250](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6250)
- Change how the configuration is managed in the backend side [#6337](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6337) [#6519](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6519) [#6573](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6573)
- Change the view of API is down and check connection to Server APIs application [#6337](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6337)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ export const MAX_ENTRIES_PER_QUERY = 10000;
import { EuiDataGridColumn } from '@elastic/eui';
import { tDataGridColumn } from './use-data-grid';

export const parseData = (resultsHits: SearchResponse['hits']['hits']): any[] => {
const data = resultsHits.map((hit) => {
export const parseData = (
resultsHits: SearchResponse['hits']['hits'],
): any[] => {
const data = resultsHits.map(hit => {
if (!hit) {
return {};
}
Expand All @@ -25,15 +27,20 @@ export const parseData = (resultsHits: SearchResponse['hits']['hits']): any[] =>
return data;
};

export const getFieldFormatted = (rowIndex, columnId, indexPattern, rowsParsed) => {
const field = indexPattern.fields.find((field) => field.name === columnId);
export const getFieldFormatted = (
rowIndex,
columnId,
indexPattern,
rowsParsed,
) => {
const field = indexPattern.fields.find(field => field.name === columnId);
let fieldValue = null;
if (columnId.includes('.')) {
// when the column is a nested field. The column could have 2 to n levels
// get dinamically the value of the nested field
const nestedFields = columnId.split('.');
fieldValue = rowsParsed[rowIndex];
nestedFields.forEach((field) => {
nestedFields.forEach(field => {
if (fieldValue) {
fieldValue = fieldValue[field];
}
Expand Down Expand Up @@ -66,14 +73,25 @@ export const getFieldFormatted = (rowIndex, columnId, indexPattern, rowsParsed)
};

// receive search params
export const exportSearchToCSV = async (params: SearchParams): Promise<void> => {
export const exportSearchToCSV = async (
params: SearchParams,
): Promise<void> => {
const DEFAULT_MAX_SIZE_PER_CALL = 1000;
const { indexPattern, filters = [], query, sorting, fields, pagination } = params;
const {
indexPattern,
filters = [],
query,
sorting,
fields,
pagination,
} = params;
// when the pageSize is greater than the default max size per call (10000)
// then we need to paginate the search
const mustPaginateSearch =
pagination?.pageSize && pagination?.pageSize > DEFAULT_MAX_SIZE_PER_CALL;
const pageSize = mustPaginateSearch ? DEFAULT_MAX_SIZE_PER_CALL : pagination?.pageSize;
const pageSize = mustPaginateSearch
? DEFAULT_MAX_SIZE_PER_CALL
: pagination?.pageSize;
const totalHits = pagination?.pageSize || DEFAULT_MAX_SIZE_PER_CALL;
let pageIndex = params.pagination?.pageIndex || 0;
let hitsCount = 0;
Expand Down Expand Up @@ -104,13 +122,13 @@ export const exportSearchToCSV = async (params: SearchParams): Promise<void> =>
}

const resultsFields = fields;
const data = allHits.map((hit) => {
const data = allHits.map(hit => {
// check if the field type is a date
const dateFields = indexPattern.fields.getByType('date');
const dateFieldsNames = dateFields.map((field) => field.name);
const dateFieldsNames = dateFields.map(field => field.name);
const flattenHit = indexPattern.flattenHit(hit);
// replace the date fields with the formatted date
dateFieldsNames.forEach((field) => {
dateFieldsNames.forEach(field => {
if (flattenHit[field]) {
flattenHit[field] = beautifyDate(flattenHit[field]);
}
Expand All @@ -125,8 +143,8 @@ export const exportSearchToCSV = async (params: SearchParams): Promise<void> =>
if (!data || data.length === 0) return;

const parsedData = data
.map((row) => {
const parsedRow = resultsFields?.map((field) => {
.map(row => {
const parsedRow = resultsFields?.map(field => {
const value = row[field];
if (value === undefined || value === null) {
return '';
Expand All @@ -153,14 +171,16 @@ export const exportSearchToCSV = async (params: SearchParams): Promise<void> =>

export const parseColumns = (
fields: IFieldType[],
defaultColumns: tDataGridColumn[] = []
defaultColumns: tDataGridColumn[] = [],
): EuiDataGridColumn[] => {
// remove _source field becuase is a object field and is not supported
fields = fields.filter((field) => field.name !== '_source');
fields = fields.filter(field => field.name !== '_source');
// merge the properties of the field with the default columns
const columns =
fields.map((field) => {
const defaultColumn = defaultColumns.find((column) => column.id === field.name);
fields.map(field => {
const defaultColumn = defaultColumns.find(
column => column.id === field.name,
);
return {
...field,
id: field.name,
Expand All @@ -174,3 +194,24 @@ export const parseColumns = (
}) || [];
return columns;
};

/**
* Merge the defaults columns and the wzDiscoverRenderColumns
* The custom columns renders will override the defaults columns.
* Only consider the fields that have the render method
* @param customColumns
* @param defaultColumns
*/
export const getAllCustomRenders = (
customColumns: tDataGridColumn[],
discoverColumns: tDataGridColumn[],
): tDataGridColumn[] => {
const customColumnsWithRender = customColumns.filter(column => column.render);
const allColumns = discoverColumns.map(column => {
const customColumn = customColumnsWithRender.find(
customColumn => customColumn.id === column.id,
);
return customColumn || column;
});
return allColumns;
};
36 changes: 24 additions & 12 deletions plugins/main/public/components/common/doc-viewer/doc-viewer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ const DOT_PREFIX_RE = /(.).+?\./g;
export type tDocViewerProps = {
flattened: any;
formatted: any;
renderFields: () => {};
mapping: any;
indexPattern: any;
docJSON: any;
};

/**
Expand Down Expand Up @@ -80,7 +82,8 @@ const DocViewer = (props: tDocViewerProps) => {
const [fieldRowOpen, setFieldRowOpen] = useState(
{} as Record<string, boolean>,
);
const { flattened, formatted, mapping, indexPattern } = props;
const { flattened, formatted, mapping, indexPattern, renderFields, docJSON } =
props;

return (
<>
Expand Down Expand Up @@ -144,17 +147,26 @@ const DocViewer = (props: tDocViewerProps) => {
</EuiFlexGroup>
</td>
<td>
<div
className={valueClassName}
data-test-subj={`tableDocViewRow-${field}-value`}
/*
* Justification for dangerouslySetInnerHTML:
* We just use values encoded by our field formatters
*/
// eslint-disable-next-line react/no-danger
dangerouslySetInnerHTML={{ __html: value as string }}
style={{ overflowY: 'auto', wordBreak: 'break-all' }}
/>
{renderFields &&
renderFields?.find(
(field: string) => field?.id === displayName,
) ? (
renderFields
?.find((field: string) => field.id === displayName)
.render(flattened[displayName], docJSON)
) : (
<div
className={valueClassName}
data-test-subj={`tableDocViewRow-${field}-value`}
/*
* Justification for dangerouslySetInnerHTML:
* We just use values encoded by our field formatters
*/
// eslint-disable-next-line react/no-danger
dangerouslySetInnerHTML={{ __html: value as string }}
style={{ overflowY: 'auto', wordBreak: 'break-all' }}
/>
)}
</td>
</tr>
);
Expand Down
45 changes: 23 additions & 22 deletions plugins/main/public/components/common/doc-viewer/use-doc-viewer.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,29 @@
import { tDocViewerProps } from "./doc-viewer"
import { IndexPattern } from "../../../../../../src/plugins/data/common";
import { tDocViewerProps } from './doc-viewer';
import { IndexPattern } from '../../../../../../src/plugins/data/common';

type tUseDocViewerInputs = {
indexPattern: IndexPattern;
doc: any;
}
indexPattern: IndexPattern;
doc: any;
};

export const useDocViewer = (props: tUseDocViewerInputs): tDocViewerProps => {
const { indexPattern, doc } = props;
const { indexPattern, doc } = props;

if (!indexPattern || !doc) {
return {
flattened: {},
formatted: {},
indexPattern: undefined,
mapping: undefined
}
}

const mapping = indexPattern?.fields.getByName;
if (!indexPattern || !doc) {
return {
flattened: indexPattern?.flattenHit(doc),
formatted: indexPattern?.formatHit(doc, 'html'),
indexPattern,
mapping
}
}
flattened: {},
formatted: {},
indexPattern: undefined,
mapping: undefined,
};
}

const mapping = indexPattern?.fields.getByName;
return {
flattened: indexPattern?.flattenHit(doc),
formatted: indexPattern?.formatHit(doc, 'html'),
indexPattern,
mapping,
docJSON: doc._source,
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,12 @@ import {
EuiFlyoutBody,
EuiFlexGroup,
} from '@elastic/eui';
import { useDataGrid, exportSearchToCSV, tDataGridColumn } from '../data-grid';
import {
useDataGrid,
exportSearchToCSV,
tDataGridColumn,
getAllCustomRenders,
} from '../data-grid';
import { getWazuhCorePlugin } from '../../../kibana-services';
import {
IndexPattern,
Expand Down Expand Up @@ -189,6 +194,10 @@ const WazuhDataGrid = (props: tWazuhDataGridProps) => {
<DocumentViewTableAndJson
document={inspectedHit}
indexPattern={indexPattern as IndexPattern}
renderFields={getAllCustomRenders(
defaultTableColumns,
wzDiscoverRenderColumns,
)}
/>
</EuiFlexItem>
</EuiFlexGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import React from 'react';
import { EuiFlexItem, EuiCodeBlock, EuiTabbedContent } from '@elastic/eui';
import { IndexPattern } from '../../../../../../../../src/plugins/data/common';
import DocViewer from '../../doc-viewer/doc-viewer'
import DocViewer from '../../doc-viewer/doc-viewer';
import { useDocViewer } from '../../doc-viewer';

export const DocumentViewTableAndJson = ({ document, indexPattern }) => {
export const DocumentViewTableAndJson = ({
document,
indexPattern,
renderFields,
}) => {
const docViewerProps = useDocViewer({
doc: document,
indexPattern: indexPattern as IndexPattern,
Expand All @@ -17,7 +21,9 @@ export const DocumentViewTableAndJson = ({ document, indexPattern }) => {
{
id: 'table',
name: 'Table',
content: <DocViewer {...docViewerProps} />,
content: (
<DocViewer {...docViewerProps} renderFields={renderFields} />
),
},
{
id: 'json',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,12 @@ import { IndexPattern } from '../../../../../../src/plugins/data/common';
import { SearchResponse } from '../../../../../../src/core/server';
import { DiscoverNoResults } from '../no-results/no-results';
import { LoadingSpinner } from '../loading-spinner/loading-spinner';
import { useDataGrid, tDataGridColumn, exportSearchToCSV } from '../data-grid';
import {
useDataGrid,
tDataGridColumn,
exportSearchToCSV,
getAllCustomRenders,
} from '../data-grid';
import { DocumentViewTableAndJson } from './components/document-view-table-and-json';
import {
ErrorHandler,
Expand Down Expand Up @@ -277,6 +282,10 @@ const WazuhDiscoverComponent = (props: WazuhDiscoverProps) => {
<DocumentViewTableAndJson
document={inspectedHit}
indexPattern={indexPattern}
renderFields={getAllCustomRenders(
defaultTableColumns,
wzDiscoverRenderColumns,
)}
/>
</EuiFlexItem>
</EuiFlexGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import {
import {
MAX_ENTRIES_PER_QUERY,
exportSearchToCSV,
getAllCustomRenders,
} from '../../../common/data-grid/data-grid-service';
import { useDocViewer } from '../../../common/doc-viewer/use-doc-viewer';
import { useDataGrid } from '../../../common/data-grid/use-data-grid';
Expand Down Expand Up @@ -339,7 +340,13 @@ const DashboardTH: React.FC = () => {
<EuiFlyoutBody>
<EuiFlexGroup direction='column'>
<EuiFlexItem>
<DocViewer {...docViewerProps} />
<DocViewer
{...docViewerProps}
renderFields={getAllCustomRenders(
threatHuntingTableDefaultColumns,
wzDiscoverRenderColumns,
)}
/>
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlyoutBody>
Expand Down
Loading
Loading