[Security Solution] [Sourcerer] Field browser missing runtime fields and matchedIndices filtering out indices with data in it (#156311)

## Summary

fixes two bugs - the first being an
[issue](https://github.com/elastic/kibana/issues/156263) where the
replaceAll(*) function was not working if names were aliased and would
incorrectly filter out matches. The second bug is related to us not
passing in runtimeFields to the fields property, so we were missing
those fields in the field browser UI element
This commit is contained in:
Devin W. Hurley 2023-05-05 09:09:58 -04:00 committed by GitHub
parent 8c336b24d4
commit 07234d935c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 85 additions and 9 deletions

View file

@ -60,6 +60,7 @@ describe('Timeline search and filters', () => {
waitForTimelinesPanelToBeLoaded();
openTimelineUsingToggle();
cy.intercept('PATCH', '/api/timeline').as('update');
cy.get('[data-test-subj="globalLoadingIndicator"]').should('not.exist');
cy.get(TIMELINE_SEARCH_OR_FILTER)
.pipe(($el) => $el.trigger('click'))
.should('exist');

View file

@ -286,7 +286,7 @@ describe('url state', () => {
populateTimeline();
cy.intercept('PATCH', '/api/timeline').as('timeline');
cy.get('[data-test-subj="globalLoadingIndicator"]').should('not.exist');
cy.wait('@timeline').then(({ response }) => {
addNameToTimeline(getTimeline().title);
closeTimeline();

View file

@ -180,6 +180,11 @@ jest.mock('../../common/lib/kibana', () => {
},
],
getIndexPattern: () => 'hello*,world*,refreshed*',
getRuntimeMappings: () => ({
myfield: {
type: 'keyword',
},
}),
})
),
},

View file

@ -81,8 +81,15 @@ describe('source/index.tsx', () => {
? ['hello', 'world', 'refreshed']
: ['hello', 'world'],
fields: mocksSource.indexFields,
getIndexPattern: () => 'hello*,world*,refreshed*',
getIndexPattern: () =>
refreshFields ? 'hello*,world*,refreshed*' : 'hello*,world*',
getRuntimeMappings: () => ({
myfield: {
type: 'keyword',
},
}),
}),
getFieldsForWildcard: async () => Promise.resolve(),
},
search: {
search: jest.fn().mockReturnValue({

View file

@ -7,27 +7,53 @@
import type { DataViewsContract } from '@kbn/data-views-plugin/common';
import { ensurePatternFormat } from '../../../../common/utils/sourcerer';
import type { SourcererDataView } from '../../store/sourcerer/model';
import { getDataViewStateFromIndexFields } from '../source/use_data_view';
export const getSourcererDataView = async (
dataViewId: string,
dataViewsService: DataViewsContract,
refreshFields = false
) => {
): Promise<SourcererDataView> => {
const dataViewData = await dataViewsService.get(dataViewId, true, refreshFields);
const defaultPatternsList = ensurePatternFormat(dataViewData.getIndexPattern().split(','));
const patternList = defaultPatternsList.reduce((res: string[], pattern) => {
if (dataViewData.matchedIndices.find((q) => q.includes(pattern.replaceAll('*', '')))) {
res.push(pattern);
}
return res;
}, []);
// typeguard used to assert that pattern is a string, otherwise
// typescript expects patternList to be (string | null)[]
// but we want it to always be string[]
const filterTypeGuard = (str: unknown): str is string => str != null;
const patternList = await Promise.all(
defaultPatternsList.map(async (pattern) => {
try {
await dataViewsService.getFieldsForWildcard({
type: dataViewData.type,
rollupIndex: dataViewData?.typeMeta?.params?.rollup_index,
allowNoIndex: false,
pattern,
});
return pattern;
} catch {
return null;
}
})
)
.then((allPatterns) =>
allPatterns.filter((pattern): pattern is string => filterTypeGuard(pattern))
)
.catch(() => defaultPatternsList);
return {
loading: false,
id: dataViewData.id ?? '',
title: dataViewData.getIndexPattern(),
indexFields: dataViewData.fields,
fields: dataViewData.fields,
patternList,
dataView: dataViewData,
browserFields: getDataViewStateFromIndexFields(
dataViewData.id ?? '',
dataViewData.fields != null ? dataViewData.fields : []
).browserFields,
runtimeMappings: dataViewData.getRuntimeMappings(),
};
};

View file

@ -136,6 +136,11 @@ jest.mock('../../lib/kibana', () => ({
},
],
getIndexPattern: () => 'hello*,world*,refreshed*',
getRuntimeMappings: () => ({
myfield: {
type: 'keyword',
},
}),
})
),
},

View file

@ -125,6 +125,8 @@ export const createStartServicesMock = (
getIdsWithTitle: jest.fn(),
get: jest.fn(),
getIndexPattern: jest.fn(),
getFieldsForWildcard: jest.fn(),
getRuntimeMappings: jest.fn(),
},
query: {
...data.query,

View file

@ -159,6 +159,11 @@ jest.mock('../../../../common/lib/kibana', () => {
},
],
getIndexPattern: () => title,
getRuntimeMappings: () => ({
myfield: {
type: 'keyword',
},
}),
}),
get: async (dataViewId: string, displayErrors?: boolean, refreshFields = false) =>
Promise.resolve({
@ -202,6 +207,11 @@ jest.mock('../../../../common/lib/kibana', () => {
},
],
getIndexPattern: () => 'hello*,world*,refreshed*',
getRuntimeMappings: () => ({
myfield: {
type: 'keyword',
},
}),
}),
},
search: {

View file

@ -96,6 +96,11 @@ jest.mock('../../../../common/lib/kibana', () => {
},
],
getIndexPattern: () => 'hello*,world*,refreshed*',
getRuntimeMappings: () => ({
myfield: {
type: 'keyword',
},
}),
}),
get: async (dataViewId: string, displayErrors?: boolean, refreshFields = false) =>
Promise.resolve({
@ -139,6 +144,11 @@ jest.mock('../../../../common/lib/kibana', () => {
},
],
getIndexPattern: () => 'hello*,world*,refreshed*',
getRuntimeMappings: () => ({
myfield: {
type: 'keyword',
},
}),
}),
},
search: {

View file

@ -98,6 +98,11 @@ describe('Event filter flyout', () => {
},
],
getIndexPattern: () => title,
getRuntimeMappings: () => ({
myfield: {
type: 'keyword',
},
}),
}),
get: jest
.fn()
@ -144,6 +149,11 @@ describe('Event filter flyout', () => {
},
],
getIndexPattern: () => 'hello*,world*,refreshed*',
getRuntimeMappings: () => ({
myfield: {
type: 'keyword',
},
}),
})
),
},