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

Replace common components vuls module #6235

Merged
merged 11 commits into from
Dec 29, 2023
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ All notable changes to the Wazuh app project will be documented in this file.

- Support for Wazuh 4.9.0
- Added AngularJS dependencies [#6145](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6145)

### Changed

- Removed embedded discover [#6120](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6120) [#6235](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6235)
- Remove embedded discover [#6120](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6120)
jbiset marked this conversation as resolved.
Show resolved Hide resolved
- Develop logic of a new index for the fim module [#6227](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6227)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,13 @@ describe('[hook] useSearchBarConfiguration', () => {
spyUseQueryManager.mockImplementation(() => [mockQueryResult, jest.fn()]);
});

it.only('should return default app index pattern when not receiving a default index pattern', async () => {
it('should return default app index pattern when not receiving a default index pattern', async () => {
jest
.spyOn(mockDataPlugin.indexPatterns, 'getDefault')
.mockResolvedValue(mockedDefaultIndexPatternData);
jest.spyOn(mockDataPlugin.query.filterManager, 'getFilters').mockReturnValue([]);
jest
.spyOn(mockDataPlugin.query.filterManager, 'getFilters')
.mockReturnValue([]);
const { result, waitForNextUpdate } = renderHook(() => useSearchBar({}));
await waitForNextUpdate();
expect(mockDataPlugin.indexPatterns.getDefault).toBeCalled();
Expand All @@ -93,15 +95,21 @@ describe('[hook] useSearchBarConfiguration', () => {
id: exampleIndexPatternId,
title: '',
};
jest.spyOn(mockDataPlugin.indexPatterns, 'get').mockResolvedValue(mockedIndexPatternData);
jest
.spyOn(mockDataPlugin.indexPatterns, 'get')
.mockResolvedValue(mockedIndexPatternData);
const { result, waitForNextUpdate } = renderHook(() =>
useSearchBar({
defaultIndexPatternID: 'wazuh-index-pattern',
})
}),
);
await waitForNextUpdate();
expect(mockDataPlugin.indexPatterns.get).toBeCalledWith(exampleIndexPatternId);
expect(result.current.searchBarProps.indexPatterns).toMatchObject([mockedIndexPatternData]);
expect(mockDataPlugin.indexPatterns.get).toBeCalledWith(
exampleIndexPatternId,
);
expect(result.current.searchBarProps.indexPatterns).toMatchObject([
mockedIndexPatternData,
]);
});

it('should show an ERROR message and get the default app index pattern when not found the index pattern data by the ID received', async () => {
Expand All @@ -112,19 +120,25 @@ describe('[hook] useSearchBarConfiguration', () => {
jest
.spyOn(mockDataPlugin.indexPatterns, 'getDefault')
.mockResolvedValue(mockedDefaultIndexPatternData);
jest.spyOn(mockDataPlugin.query.filterManager, 'getFilters').mockReturnValue([]);
jest
.spyOn(mockDataPlugin.query.filterManager, 'getFilters')
.mockReturnValue([]);

// mocking console error to avoid logs in test and check if is called
const mockedConsoleError = jest.spyOn(console, 'error').mockImplementationOnce(() => {});
const mockedConsoleError = jest
.spyOn(console, 'error')
.mockImplementationOnce(() => {});
const { result, waitForNextUpdate } = renderHook(() =>
useSearchBar({
defaultIndexPatternID: 'invalid-index-pattern-id',
})
}),
);

await waitForNextUpdate();
expect(mockDataPlugin.indexPatterns.getDefault).toBeCalled();
expect(mockDataPlugin.indexPatterns.get).toBeCalledWith('invalid-index-pattern-id');
expect(mockDataPlugin.indexPatterns.get).toBeCalledWith(
'invalid-index-pattern-id',
);
expect(result.current.searchBarProps.indexPatterns).toMatchObject([
mockedDefaultIndexPatternData,
]);
Expand All @@ -145,50 +159,22 @@ describe('[hook] useSearchBarConfiguration', () => {
jest
.spyOn(mockDataPlugin.indexPatterns, 'getDefault')
.mockResolvedValue(mockedDefaultIndexPatternData);
jest.spyOn(mockDataPlugin.query.filterManager, 'getFilters').mockReturnValue(defaultFilters);
jest
.spyOn(mockDataPlugin.query.filterManager, 'getFilters')
.mockReturnValue(defaultFilters);
const { result, waitForNextUpdate } = renderHook(() =>
useSearchBar({
filters: defaultFilters,
})
}),
);

await waitForNextUpdate();

expect(result.current.searchBarProps.filters).toMatchObject(defaultFilters);
expect(mockDataPlugin.query.filterManager.setFilters).toBeCalledWith(defaultFilters);
expect(mockDataPlugin.query.filterManager.getFilters).toBeCalled();
});

it('should return and preserve filters when the index pattern received is equal to the index pattern already selected in the app', async () => {
const defaultIndexFilters: Filter[] = [
{
query: 'something to filter',
meta: {
alias: 'filter-mocked',
disabled: false,
negate: true,
},
},
];
jest
.spyOn(mockDataPlugin.indexPatterns, 'getDefault')
.mockResolvedValue(mockedDefaultIndexPatternData);
jest
.spyOn(mockDataPlugin.indexPatterns, 'get')
.mockResolvedValue(mockedDefaultIndexPatternData);
jest
.spyOn(mockDataPlugin.query.filterManager, 'getFilters')
.mockReturnValue(defaultIndexFilters);
const { result, waitForNextUpdate } = renderHook(() =>
useSearchBar({
defaultIndexPatternID: mockedDefaultIndexPatternData.id,
})
expect(mockDataPlugin.query.filterManager.setFilters).toBeCalledWith(
defaultFilters,
);
await waitForNextUpdate();
expect(result.current.searchBarProps.indexPatterns).toMatchObject([
mockedDefaultIndexPatternData,
]);
expect(result.current.searchBarProps.filters).toMatchObject(defaultIndexFilters);
expect(mockDataPlugin.query.filterManager.getFilters).toBeCalled();
});

it('should return empty filters when the index pattern is NOT equal to the default app index pattern', async () => {
Expand All @@ -204,16 +190,18 @@ describe('[hook] useSearchBarConfiguration', () => {
jest
.spyOn(mockDataPlugin.indexPatterns, 'getDefault')
.mockResolvedValue(mockedDefaultIndexPatternData);
jest.spyOn(mockDataPlugin.query.filterManager, 'getFilters').mockReturnValue([]);
jest
.spyOn(mockDataPlugin.query.filterManager, 'getFilters')
.mockReturnValue([]);
const { result, waitForNextUpdate } = renderHook(() =>
useSearchBar({
defaultIndexPatternID: exampleIndexPatternId,
})
}),
);
await waitForNextUpdate();
expect(result.current.searchBarProps.indexPatterns).toMatchObject([
mockedExampleIndexPatternData,
]);
expect(result.current.searchBarProps.filters).toStrictEqual([]);
});
});
});
111 changes: 63 additions & 48 deletions plugins/main/public/components/common/search-bar/use-search-bar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { getDataPlugin } from '../../../kibana-services';
import { useFilterManager, useQueryManager, useTimeFilter } from '../hooks';
import { AUTHORIZED_AGENTS } from '../../../../common/constants';

// Input - types
type tUseSearchBarCustomInputs = {
defaultIndexPatternID: IIndexPattern['id'];
onFiltersUpdated?: (filters: Filter[]) => void;
Expand All @@ -37,6 +38,7 @@ const useSearchBar = (
props?: tUseSearchBarProps,
): tUserSearchBarResponse => {
// dependencies
const SESSION_STORAGE_FILTERS_NAME = 'wazuh_persistent_searchbar_filters';
const filterManager = useFilterManager().filterManager as FilterManager;
const { filters } = useFilterManager();
const [query, setQuery] = props?.query
Expand All @@ -49,29 +51,38 @@ const useSearchBar = (
useState<IIndexPattern>();

useEffect(() => {
if (filters && filters.length > 0) {
sessionStorage.setItem(
SESSION_STORAGE_FILTERS_NAME,
JSON.stringify(filters),
);
}
initSearchBar();
/**
* When the component is disassembled, the original filters that arrived
* when the component was assembled are added.
*/
return () => {
const storagePreviousFilters = sessionStorage.getItem(
SESSION_STORAGE_FILTERS_NAME,
);
if (storagePreviousFilters) {
const previousFilters = JSON.parse(storagePreviousFilters);
const cleanedFilters = cleanFilters(previousFilters);
filterManager.setFilters(cleanedFilters);
}
};
}, []);

useEffect(() => {
const defaultIndex = props?.defaultIndexPatternID;
/* Filters that do not belong to the default index are filtered */
const cleanedFilters = filters.filter(
filter => filter.meta.index === defaultIndex,
);
if (cleanedFilters.length !== filters.length) {
filterManager.setFilters(cleanedFilters);
}
}, [filters]);

/**
* Initialize the searchbar props with the corresponding index pattern and filters
*/
const initSearchBar = async () => {
setIsLoading(true);
const indexPattern = await getIndexPattern(props?.defaultIndexPatternID);
setIndexPatternSelected(indexPattern);
const filters = await getInitialFilters(indexPattern);
filterManager.setFilters(filters);
const initialFilters = props?.filters ?? filters;
filterManager.setFilters(initialFilters);
setIsLoading(false);
};

Expand All @@ -87,7 +98,7 @@ const useSearchBar = (
try {
return await indexPatternService.get(indexPatternID);
} catch (error) {
// when the index pattern id not exists will get the default defined in the index pattern service
// when the index pattern id not exists will get the default
console.error(error);
return await indexPatternService.getDefault();
}
Expand All @@ -97,44 +108,33 @@ const useSearchBar = (
};

/**
* Return the initial filters considering if hook receives initial filters
* When the default index pattern is the same like the received preserve the filters
* @param indexPattern
* Return filters from filters manager.
* Additionally solve the known issue with the auto loaded agent.id filters from the searchbar
* and filters those filters that are not related to the default index pattern
* @returns
*/
const getInitialFilters = async (indexPattern: IIndexPattern) => {
const indexPatternService = getDataPlugin()
.indexPatterns as IndexPatternsContract;
let initialFilters: Filter[] = [];
if (props?.filters) {
return props?.filters;
}
if (indexPattern) {
// get filtermanager and filters
// if the index is the same, get filters stored
// else clear filters
const defaultIndexPattern =
(await indexPatternService.getDefault()) as IIndexPattern;
initialFilters =
defaultIndexPattern.id === indexPattern.id
? filterManager.getFilters()
: [];
} else {
initialFilters = [];
}
return initialFilters;
const getFilters = () => {
const originalFilters = filterManager ? filterManager.getFilters() : [];
return originalFilters.filter(
(filter: Filter) =>
filter?.meta?.controlledBy !== AUTHORIZED_AGENTS && // remove auto loaded agent.id filters
filter?.meta?.index === props?.defaultIndexPatternID,
);
};

/**
* Return filters from filters manager.
* Additionally solve the known issue with the auto loaded agent.id filters from the searchbar
* Return cleaned filters.
* Clean the known issue with the auto loaded agent.id filters from the searchbar
* and filters those filters that are not related to the default index pattern
* @param previousFilters
* @returns
*/
const getFilters = () => {
const filters = filterManager ? filterManager.getFilters() : [];
return filters.filter(
filter => filter.meta.controlledBy !== AUTHORIZED_AGENTS,
); // remove auto loaded agent.id filters
const cleanFilters = (previousFilters: Filter[]) => {
return previousFilters.filter(
(filter: Filter) =>
filter?.meta?.controlledBy !== AUTHORIZED_AGENTS &&
filter?.meta?.index !== props?.defaultIndexPatternID,
);
};

/**
Expand All @@ -149,9 +149,24 @@ const useSearchBar = (
dateRangeFrom: timeFilter.from,
dateRangeTo: timeFilter.to,
onFiltersUpdated: (filters: Filter[]) => {
// its necessary execute setter to apply filters
filterManager.setFilters(filters);
props?.onFiltersUpdated && props?.onFiltersUpdated(filters);
const storagePreviousFilters = sessionStorage.getItem(
SESSION_STORAGE_FILTERS_NAME,
);
/**
* If there are persisted filters, it is necessary to add them when
* updating the filters in the filterManager
*/
if (storagePreviousFilters) {
const previousFilters = JSON.parse(storagePreviousFilters);
const cleanedFilters = cleanFilters(previousFilters);
filterManager.setFilters([...cleanedFilters, ...filters]);

props?.onFiltersUpdated &&
props?.onFiltersUpdated([...cleanedFilters, ...filters]);
} else {
filterManager.setFilters(filters);
props?.onFiltersUpdated && props?.onFiltersUpdated(filters);
}
},
onQuerySubmit: (
payload: { dateRange: TimeRange; query?: Query },
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useState, useEffect } from 'react';
import { search } from '../../dashboards/inventory/inventory_service';
import { search } from '../../../../common/search-bar/search-bar-service';
import {
IIndexPattern,
IndexPattern,
Expand Down Expand Up @@ -69,7 +69,7 @@ const useCheckIndexFields = (

checkIndexFields();
}
}, [indexPatternId]);
}, [indexPatternId, query, indexPattern]);

return {
isError,
Expand Down
Loading
Loading