[8.10] [Cloud Security] Fix page size bug (#164428) (#164999)

# Backport

This will backport the following commits from `main` to `8.10`:
- [[Cloud Security] Fix page size bug
(#164428)](https://github.com/elastic/kibana/pull/164428)

<!--- Backport version: 8.9.7 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sqren/backport)

<!--BACKPORT
[{"author":{"name":"Jordan","email":"51442161+JordanSh@users.noreply.github.com"},"sourceCommit":{"committedDate":"2023-08-28T15:33:03Z","message":"[Cloud
Security] Fix page size bug
(#164428)","sha":"191bedaa5dea78ccd928f2177b17919793f01da5","branchLabelMapping":{"^v8.11.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","Team:Cloud
Security","v8.10.0","v8.11.0"],"number":164428,"url":"https://github.com/elastic/kibana/pull/164428","mergeCommit":{"message":"[Cloud
Security] Fix page size bug
(#164428)","sha":"191bedaa5dea78ccd928f2177b17919793f01da5"}},"sourceBranch":"main","suggestedTargetBranches":["8.10"],"targetPullRequestStates":[{"branch":"8.10","label":"v8.10.0","labelRegex":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"main","label":"v8.11.0","labelRegex":"^v8.11.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/164428","number":164428,"mergeCommit":{"message":"[Cloud
Security] Fix page size bug
(#164428)","sha":"191bedaa5dea78ccd928f2177b17919793f01da5"}}]}]
BACKPORT-->

Co-authored-by: Jordan <51442161+JordanSh@users.noreply.github.com>
This commit is contained in:
Kibana Machine 2023-08-28 12:42:52 -04:00 committed by GitHub
parent eb217d5997
commit 65b543b62a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 229 additions and 99 deletions

View file

@ -4,12 +4,39 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { useCallback } from 'react';
import { Dispatch, SetStateAction, useCallback } from 'react';
import { type DataView } from '@kbn/data-views-plugin/common';
import { BoolQuery } from '@kbn/es-query';
import { CriteriaWithPagination } from '@elastic/eui';
import { useUrlQuery } from '../use_url_query';
import { usePageSize } from '../use_page_size';
import { getDefaultQuery, useBaseEsQuery, usePersistedQuery } from './utils';
interface QuerySort {
direction: string;
id: string;
}
export interface CloudPostureTableResult {
setUrlQuery: (query: any) => void;
// TODO: remove any, this sorting is used for both EuiGrid and EuiTable which uses different types of sorts
sort: any;
filters: any[];
query?: { bool: BoolQuery };
queryError?: Error;
pageIndex: number;
// TODO: remove any, urlQuery is an object with query fields but we also add custom fields to it, need to assert usages
urlQuery: any;
setTableOptions: (options: CriteriaWithPagination<object>) => void;
handleUpdateQuery: (query: any) => void;
pageSize: number;
setPageSize: Dispatch<SetStateAction<number | undefined>>;
onChangeItemsPerPage: (newPageSize: number) => void;
onChangePage: (newPageIndex: number) => void;
onSort: (sort: QuerySort[]) => void;
onResetFilters: () => void;
}
/*
Hook for managing common table state and methods for Cloud Posture
*/
@ -21,7 +48,7 @@ export const useCloudPostureTable = ({
defaultQuery?: (params: any) => any;
dataView: DataView;
paginationLocalStorageKey: string;
}) => {
}): CloudPostureTableResult => {
const getPersistedDefaultQuery = usePersistedQuery(defaultQuery);
const { urlQuery, setUrlQuery } = useUrlQuery(getPersistedDefaultQuery);
const { pageSize, setPageSize } = usePageSize(paginationLocalStorageKey);
@ -31,9 +58,10 @@ export const useCloudPostureTable = ({
setPageSize(newPageSize);
setUrlQuery({
pageIndex: 0,
pageSize: newPageSize,
});
},
[setUrlQuery, setPageSize]
[setPageSize, setUrlQuery]
);
const onResetFilters = useCallback(() => {

View file

@ -20,7 +20,10 @@ import React, { useCallback, useMemo, useState, useEffect } from 'react';
import { i18n } from '@kbn/i18n';
import { Routes, Route } from '@kbn/shared-ux-router';
import { LOCAL_STORAGE_PAGE_SIZE_FINDINGS_KEY } from '../../common/constants';
import { useCloudPostureTable } from '../../common/hooks/use_cloud_posture_table';
import {
CloudPostureTableResult,
useCloudPostureTable,
} from '../../common/hooks/use_cloud_posture_table';
import { useLatestVulnerabilities } from './hooks/use_latest_vulnerabilities';
import type { VulnerabilitiesQueryData } from './types';
import { LATEST_VULNERABILITIES_INDEX_PATTERN } from '../../../common/constants';
@ -63,67 +66,35 @@ const getDefaultQuery = ({ query, filters }: any): any => ({
pageIndex: 0,
});
export const Vulnerabilities = () => {
const { data, isLoading, error } = useFilteredDataView(LATEST_VULNERABILITIES_INDEX_PATTERN);
const getSetupStatus = useCspSetupStatusApi();
if (getSetupStatus?.data?.vuln_mgmt?.status !== 'indexed') return <NoVulnerabilitiesStates />;
if (error) {
return <ErrorCallout error={error as Error} />;
}
if (isLoading) {
return defaultLoadingRenderer();
}
if (!data) {
return defaultNoDataRenderer();
}
return (
<Routes>
<Route
exact
path={findingsNavigation.resource_vulnerabilities.path}
render={() => <ResourceVulnerabilities dataView={data} />}
/>
<Route
exact
path={findingsNavigation.vulnerabilities_by_resource.path}
render={() => <VulnerabilitiesByResource dataView={data} />}
/>
<Route
path={findingsNavigation.vulnerabilities.path}
render={() => <VulnerabilitiesContent dataView={data} />}
/>
</Routes>
);
};
const VulnerabilitiesDataGrid = ({
dataView,
data,
isFetching,
onChangeItemsPerPage,
onChangePage,
onSort,
urlQuery,
onResetFilters,
pageSize,
setUrlQuery,
pageIndex,
sort,
}: {
dataView: DataView;
data: VulnerabilitiesQueryData | undefined;
isFetching: boolean;
}) => {
const {
pageIndex,
sort,
pageSize,
onChangeItemsPerPage,
onChangePage,
onSort,
urlQuery,
setUrlQuery,
onResetFilters,
} = useCloudPostureTable({
dataView,
defaultQuery: getDefaultQuery,
paginationLocalStorageKey: LOCAL_STORAGE_PAGE_SIZE_FINDINGS_KEY,
});
} & Pick<
CloudPostureTableResult,
| 'pageIndex'
| 'sort'
| 'pageSize'
| 'onChangeItemsPerPage'
| 'onChangePage'
| 'onSort'
| 'urlQuery'
| 'setUrlQuery'
| 'onResetFilters'
>) => {
const { euiTheme } = useEuiTheme();
const styles = useStyles();
const [showHighlight, setHighlight] = useState(false);
@ -131,7 +102,9 @@ const VulnerabilitiesDataGrid = ({
const invalidIndex = -1;
const selectedVulnerability = useMemo(() => {
return data?.page[urlQuery.vulnerabilityIndex];
if (urlQuery.vulnerabilityIndex !== undefined) {
return data?.page[urlQuery.vulnerabilityIndex];
}
}, [data?.page, urlQuery.vulnerabilityIndex]);
const onCloseFlyout = () => {
@ -194,7 +167,9 @@ const VulnerabilitiesDataGrid = ({
const flyoutVulnerabilityIndex = urlQuery?.vulnerabilityIndex;
const selectedVulnerabilityIndex = flyoutVulnerabilityIndex + pageIndex * pageSize;
const selectedVulnerabilityIndex = flyoutVulnerabilityIndex
? flyoutVulnerabilityIndex + pageIndex * pageSize
: undefined;
const renderCellValue = useMemo(() => {
const Cell: React.FC<EuiDataGridCellValueElementProps> = ({
@ -306,7 +281,9 @@ const VulnerabilitiesDataGrid = ({
[pageSize, setUrlQuery]
);
const showVulnerabilityFlyout = flyoutVulnerabilityIndex > invalidIndex;
const showVulnerabilityFlyout = flyoutVulnerabilityIndex
? flyoutVulnerabilityIndex > invalidIndex
: undefined;
if (data?.page.length === 0) {
return <EmptyState onResetFilters={onResetFilters} />;
@ -392,8 +369,21 @@ const VulnerabilitiesDataGrid = ({
</>
);
};
const VulnerabilitiesContent = ({ dataView }: { dataView: DataView }) => {
const { pageIndex, query, sort, queryError, pageSize, setUrlQuery } = useCloudPostureTable({
const {
sort,
query,
queryError,
pageSize,
pageIndex,
onChangeItemsPerPage,
onChangePage,
onSort,
urlQuery,
setUrlQuery,
onResetFilters,
} = useCloudPostureTable({
dataView,
defaultQuery: getDefaultQuery,
paginationLocalStorageKey: LOCAL_STORAGE_PAGE_SIZE_FINDINGS_KEY,
@ -445,8 +435,58 @@ const VulnerabilitiesContent = ({ dataView }: { dataView: DataView }) => {
<EuiSpacer size="m" />
{error && <ErrorCallout error={error as Error} />}
{!error && (
<VulnerabilitiesDataGrid dataView={dataView} data={data} isFetching={isFetching} />
<VulnerabilitiesDataGrid
dataView={dataView}
data={data}
isFetching={isFetching}
pageIndex={pageIndex}
sort={sort}
pageSize={pageSize}
onChangeItemsPerPage={onChangeItemsPerPage}
onChangePage={onChangePage}
onSort={onSort}
urlQuery={urlQuery}
onResetFilters={onResetFilters}
setUrlQuery={setUrlQuery}
/>
)}
</>
);
};
export const Vulnerabilities = () => {
const { data, isLoading, error } = useFilteredDataView(LATEST_VULNERABILITIES_INDEX_PATTERN);
const getSetupStatus = useCspSetupStatusApi();
if (getSetupStatus?.data?.vuln_mgmt?.status !== 'indexed') return <NoVulnerabilitiesStates />;
if (error) {
return <ErrorCallout error={error as Error} />;
}
if (isLoading) {
return defaultLoadingRenderer();
}
if (!data) {
return defaultNoDataRenderer();
}
return (
<Routes>
<Route
exact
path={findingsNavigation.resource_vulnerabilities.path}
render={() => <ResourceVulnerabilities dataView={data} />}
/>
<Route
exact
path={findingsNavigation.vulnerabilities_by_resource.path}
render={() => <VulnerabilitiesByResource dataView={data} />}
/>
<Route
path={findingsNavigation.vulnerabilities.path}
render={() => <VulnerabilitiesContent dataView={data} />}
/>
</Routes>
);
};

View file

@ -21,7 +21,10 @@ import { FormattedMessage } from '@kbn/i18n-react';
import { Link, useParams, generatePath } from 'react-router-dom';
import type { BoolQuery } from '@kbn/es-query';
import { LOCAL_STORAGE_PAGE_SIZE_FINDINGS_KEY } from '../../../../common/constants';
import { useCloudPostureTable } from '../../../../common/hooks/use_cloud_posture_table';
import {
CloudPostureTableResult,
useCloudPostureTable,
} from '../../../../common/hooks/use_cloud_posture_table';
import { useLatestVulnerabilities } from '../../hooks/use_latest_vulnerabilities';
import type { VulnerabilitiesQueryData } from '../../types';
import { ErrorCallout } from '../../../configurations/layout/error_callout';
@ -68,26 +71,31 @@ const ResourceVulnerabilitiesDataGrid = ({
dataView,
data,
isFetching,
pageIndex,
sort,
pageSize,
onChangeItemsPerPage,
onChangePage,
onSort,
urlQuery,
setUrlQuery,
onResetFilters,
}: {
dataView: DataView;
data: VulnerabilitiesQueryData;
isFetching: boolean;
}) => {
const {
pageIndex,
sort,
pageSize,
onChangeItemsPerPage,
onChangePage,
onSort,
urlQuery,
setUrlQuery,
onResetFilters,
} = useCloudPostureTable({
dataView,
defaultQuery: getDefaultQuery,
paginationLocalStorageKey: LOCAL_STORAGE_PAGE_SIZE_FINDINGS_KEY,
});
} & Pick<
CloudPostureTableResult,
| 'pageIndex'
| 'sort'
| 'pageSize'
| 'onChangeItemsPerPage'
| 'onChangePage'
| 'onSort'
| 'urlQuery'
| 'setUrlQuery'
| 'onResetFilters'
>) => {
const { euiTheme } = useEuiTheme();
const styles = useStyles();
@ -357,7 +365,19 @@ export const ResourceVulnerabilities = ({ dataView }: { dataView: DataView }) =>
const params = useParams<{ resourceId: string }>();
const resourceId = decodeURIComponent(params.resourceId);
const { pageIndex, query, sort, queryError, pageSize, setUrlQuery } = useCloudPostureTable({
const {
pageIndex,
pageSize,
onChangeItemsPerPage,
onChangePage,
query,
sort,
onSort,
queryError,
urlQuery,
setUrlQuery,
onResetFilters,
} = useCloudPostureTable({
dataView,
defaultQuery: getDefaultQuery,
paginationLocalStorageKey: LOCAL_STORAGE_PAGE_SIZE_FINDINGS_KEY,
@ -459,7 +479,20 @@ export const ResourceVulnerabilities = ({ dataView }: { dataView: DataView }) =>
<EuiSpacer size="m" />
{error && <ErrorCallout error={error as Error} />}
{!error && (
<ResourceVulnerabilitiesDataGrid dataView={dataView} data={data} isFetching={isFetching} />
<ResourceVulnerabilitiesDataGrid
dataView={dataView}
data={data}
isFetching={isFetching}
pageIndex={pageIndex}
pageSize={pageSize}
urlQuery={urlQuery}
setUrlQuery={setUrlQuery}
onChangeItemsPerPage={onChangeItemsPerPage}
onChangePage={onChangePage}
onResetFilters={onResetFilters}
onSort={onSort}
sort={sort}
/>
)}
</>
);

View file

@ -19,7 +19,10 @@ import { i18n } from '@kbn/i18n';
import { Link, generatePath } from 'react-router-dom';
import { LOCAL_STORAGE_PAGE_SIZE_FINDINGS_KEY } from '../../../common/constants';
import { findingsNavigation } from '../../../common/navigation/constants';
import { useCloudPostureTable } from '../../../common/hooks/use_cloud_posture_table';
import {
CloudPostureTableResult,
useCloudPostureTable,
} from '../../../common/hooks/use_cloud_posture_table';
import { ErrorCallout } from '../../configurations/layout/error_callout';
import { FindingsSearchBar } from '../../configurations/layout/findings_search_bar';
import { useLimitProperties } from '../../../common/utils/get_limit_properties';
@ -54,26 +57,31 @@ const VulnerabilitiesByResourceDataGrid = ({
dataView,
data,
isFetching,
pageIndex,
sort,
pageSize,
onChangeItemsPerPage,
onChangePage,
onSort,
urlQuery,
setUrlQuery,
onResetFilters,
}: {
dataView: DataView;
data: VulnerabilitiesByResourceQueryData | undefined;
isFetching: boolean;
}) => {
const {
pageIndex,
sort,
pageSize,
onChangeItemsPerPage,
onChangePage,
onSort,
urlQuery,
setUrlQuery,
onResetFilters,
} = useCloudPostureTable({
dataView,
defaultQuery: getDefaultQuery,
paginationLocalStorageKey: LOCAL_STORAGE_PAGE_SIZE_FINDINGS_KEY,
});
} & Pick<
CloudPostureTableResult,
| 'pageIndex'
| 'sort'
| 'pageSize'
| 'onChangeItemsPerPage'
| 'onChangePage'
| 'onSort'
| 'urlQuery'
| 'setUrlQuery'
| 'onResetFilters'
>) => {
const styles = useStyles();
const { isLastLimitedPage, limitedTotalItemCount } = useLimitProperties({
@ -232,7 +240,19 @@ const VulnerabilitiesByResourceDataGrid = ({
};
export const VulnerabilitiesByResource = ({ dataView }: { dataView: DataView }) => {
const { pageIndex, query, sort, queryError, pageSize, setUrlQuery } = useCloudPostureTable({
const {
pageIndex,
onChangeItemsPerPage,
onChangePage,
pageSize,
query,
sort,
onSort,
queryError,
urlQuery,
setUrlQuery,
onResetFilters,
} = useCloudPostureTable({
dataView,
defaultQuery: getDefaultQuery,
paginationLocalStorageKey: LOCAL_STORAGE_PAGE_SIZE_FINDINGS_KEY,
@ -273,6 +293,15 @@ export const VulnerabilitiesByResource = ({ dataView }: { dataView: DataView })
dataView={dataView}
data={data}
isFetching={isFetching}
pageIndex={pageIndex}
sort={sort}
pageSize={pageSize}
onChangeItemsPerPage={onChangeItemsPerPage}
onChangePage={onChangePage}
onSort={onSort}
urlQuery={urlQuery}
setUrlQuery={setUrlQuery}
onResetFilters={onResetFilters}
/>
)}
</>