Skip to content

Commit

Permalink
[Security Solution] [Endpoint] Search params are reset when opening f…
Browse files Browse the repository at this point in the history
…lyout in policy details artifact tab (#127718)

* Fixes wrong message size

* Fixes error with url params when opening flyout

* Fixes checks errors

* removes unused code

* Fix wrong url page when default one

* Replace old url pagination params by new ones on use_url_pagination hook

* Moves useEffect into a new hook that fixes url pagination params, also adds a unit test for it

* Adds note info in jsdoc for new hook

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
  • Loading branch information
dasansol92 and kibanamachine authored Mar 18, 2022
1 parent 3713296 commit bbb531a
Show file tree
Hide file tree
Showing 9 changed files with 66 additions and 94 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import querystring from 'querystring';
import { generatePath } from 'react-router-dom';
import { appendSearch } from '../../common/components/link_to/helpers';
import { ArtifactListPageUrlParams } from '../components/artifact_list_page';
import { paginationFromUrlParams } from '../components/hooks/use_url_pagination';
import { EndpointIndexUIQueryParams } from '../pages/endpoint_hosts/types';
import { EventFiltersPageLocation } from '../pages/event_filters/types';
import { HostIsolationExceptionsPageLocation } from '../pages/host_isolation_exceptions/types';
Expand Down Expand Up @@ -181,11 +182,11 @@ const normalizePolicyDetailsArtifactsListPageLocation = (
): Partial<PolicyDetailsArtifactsPageLocation> => {
if (location) {
return {
...(!isDefaultOrMissing(location.page_index, MANAGEMENT_DEFAULT_PAGE)
? { page_index: location.page_index }
...(!isDefaultOrMissing(location.page, MANAGEMENT_DEFAULT_PAGE + 1)
? { page: location.page }
: {}),
...(!isDefaultOrMissing(location.page_size, MANAGEMENT_DEFAULT_PAGE_SIZE)
? { page_size: location.page_size }
...(!isDefaultOrMissing(location.pageSize, MANAGEMENT_DEFAULT_PAGE_SIZE)
? { pageSize: location.pageSize }
: {}),
...(!isDefaultOrMissing(location.show, undefined) ? { show: location.show } : {}),
...(!isDefaultOrMissing(location.filter, '') ? { filter: location.filter } : ''),
Expand Down Expand Up @@ -348,9 +349,11 @@ export const extractPolicyDetailsArtifactsListPageLocation = (
query,
'show'
) as PolicyDetailsArtifactsPageLocation['show'];

const pagination = paginationFromUrlParams(query);
return {
...extractListPaginationParams(query),
page: pagination.page,
pageSize: pagination.pageSize,
filter: query.filter as string,
show: showParamValue && 'list' === showParamValue ? showParamValue : undefined,
};
};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { useEffect } from 'react';
import { useHistory } from 'react-router-dom';
import { useUrlParams } from './use_url_params';

/**
* Replaces old page_index and page_size url params by the new ones, page and pageSize
*
* NOTE: This hook will also increment the `page_index` by 1 since `page` is now one-based
*/
export const useOldUrlSearchPaginationReplace = (): void => {
const history = useHistory();
const { urlParams } = useUrlParams();

useEffect(() => {
if ((urlParams.page_index && !urlParams.page) || (urlParams.page_size && !urlParams.pageSize)) {
history.replace(
`${history.location.pathname}${history.location.search
.replaceAll('page_size', 'pageSize')
.replaceAll(
`page_index=${urlParams.page_index}`,
`page=${Number(urlParams.page_index) + 1}`
)}`
);
}
}, [history, urlParams.page, urlParams.pageSize, urlParams.page_index, urlParams.page_size]);
};
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ interface UrlPagination {

type UrlPaginationParams = Partial<Pagination>;

const paginationFromUrlParams = (urlParams: UrlPaginationParams): Pagination => {
export const paginationFromUrlParams = (urlParams: UrlPaginationParams): Pagination => {
const pagination: Pagination = {
pageSize: MANAGEMENT_DEFAULT_PAGE_SIZE,
page: 1,
Expand Down Expand Up @@ -64,6 +64,7 @@ export const useUrlPagination = (): UrlPagination => {
const location = useLocation();
const history = useHistory();
const { urlParams, toUrlParams } = useUrlParams();

const urlPaginationParams = useMemo(() => {
return paginationFromUrlParams(urlParams);
}, [urlParams]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ export const initialPolicyDetailsState: () => Immutable<PolicyDetailsState> = ()
},
artifacts: {
location: {
page_index: MANAGEMENT_DEFAULT_PAGE,
page_size: MANAGEMENT_DEFAULT_PAGE_SIZE,
page: MANAGEMENT_DEFAULT_PAGE,
pageSize: MANAGEMENT_DEFAULT_PAGE_SIZE,
show: undefined,
filter: '',
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,91 +5,12 @@
* 2.0.
*/

import { composeHttpHandlerMocks } from '../../../../common/mock/endpoint/http_handler_mock_factory';
import {
GetTrustedAppsListResponse,
PostTrustedAppCreateResponse,
} from '../../../../../common/endpoint/types';
import { createSampleTrustedApp, createSampleTrustedApps } from '../../trusted_apps/test_utils';
import {
PolicyDetailsArtifactsPageListLocationParams,
PolicyDetailsArtifactsPageLocation,
} from '../types';
import {
fleetGetAgentStatusHttpMock,
FleetGetAgentStatusHttpMockInterface,
fleetGetEndpointPackagePolicyHttpMock,
FleetGetEndpointPackagePolicyHttpMockInterface,
fleetGetEndpointPackagePolicyListHttpMock,
FleetGetEndpointPackagePolicyListHttpMockInterface,
trustedAppsGetListHttpMocks,
TrustedAppsGetListHttpMocksInterface,
trustedAppPutHttpMocks,
TrustedAppPutHttpMocksInterface,
trustedAppsGetOneHttpMocks,
TrustedAppsGetOneHttpMocksInterface,
fleetGetAgentPolicyListHttpMock,
FleetGetAgentPolicyListHttpMockInterface,
trustedAppsPostCreateListHttpMock,
TrustedAppsPostCreateListHttpMockInterface,
} from '../../mocks';
import { GetTrustedAppsListResponse } from '../../../../../common/endpoint/types';
import { createSampleTrustedApps } from '../../trusted_apps/test_utils';

export const getMockListResponse: () => GetTrustedAppsListResponse = () => ({
data: createSampleTrustedApps({}),
per_page: 100,
page: 1,
total: 100,
});

export const getMockPolicyDetailsArtifactsPageLocationUrlParams = (
overrides: Partial<PolicyDetailsArtifactsPageLocation> = {}
): PolicyDetailsArtifactsPageLocation => {
return {
page_index: 0,
page_size: 10,
filter: '',
show: undefined,
...overrides,
};
};

export const getMockPolicyDetailsArtifactListUrlParams = (
overrides: Partial<PolicyDetailsArtifactsPageListLocationParams> = {}
): PolicyDetailsArtifactsPageListLocationParams => {
return {
page_index: 0,
page_size: 10,
filter: '',
...overrides,
};
};

export const getMockCreateResponse: () => PostTrustedAppCreateResponse = () =>
createSampleTrustedApp(1) as unknown as unknown as PostTrustedAppCreateResponse;

export const getAPIError = () => ({
statusCode: 500,
error: 'Internal Server Error',
message: 'Something is not right',
});

export type PolicyDetailsPageAllApiHttpMocksInterface =
FleetGetEndpointPackagePolicyHttpMockInterface &
FleetGetAgentStatusHttpMockInterface &
FleetGetEndpointPackagePolicyListHttpMockInterface &
FleetGetAgentPolicyListHttpMockInterface &
TrustedAppsGetListHttpMocksInterface &
TrustedAppPutHttpMocksInterface &
TrustedAppsGetOneHttpMocksInterface &
TrustedAppsPostCreateListHttpMockInterface;
export const policyDetailsPageAllApiHttpMocks =
composeHttpHandlerMocks<PolicyDetailsPageAllApiHttpMocksInterface>([
fleetGetEndpointPackagePolicyHttpMock,
fleetGetAgentStatusHttpMock,
fleetGetEndpointPackagePolicyListHttpMock,
fleetGetAgentPolicyListHttpMock,
trustedAppsGetListHttpMocks,
trustedAppPutHttpMocks,
trustedAppsGetOneHttpMocks,
trustedAppsPostCreateListHttpMock,
]);
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,8 @@ export interface PolicyArtifactsState {
}

export interface PolicyDetailsArtifactsPageListLocationParams {
page_index: number;
page_size: number;
page: number;
pageSize: number;
filter: string;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,9 @@ export const PolicyArtifactsFlyout = React.memo<PolicyArtifactsFlyoutProps>(
if (!assignableArtifacts) {
return (
<EuiEmptyPrompt
titleSize="xs"
data-test-subj="artifacts-no-assignable-items"
title={<p>{labels.flyoutNoArtifactsToBeAssignedMessage}</p>}
body={<p>{labels.flyoutNoArtifactsToBeAssignedMessage}</p>}
/>
);
}
Expand All @@ -160,8 +161,9 @@ export const PolicyArtifactsFlyout = React.memo<PolicyArtifactsFlyoutProps>(
if (artifacts?.total === 0) {
return (
<EuiEmptyPrompt
titleSize="xs"
data-test-subj="artifacts-no-items-found"
title={<p>{labels.flyoutNoSearchResultsMessage}</p>}
body={<p>{labels.flyoutNoSearchResultsMessage}</p>}
/>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,16 @@ describe('Policy details artifacts list', () => {
expect(renderResult.queryByTestId('remove-from-policy-action')).toBeNull();
});

it('should replace old url search pagination params with correct ones', async () => {
history.replace(`${history.location.pathname}?page_index=0&page_size=10`);
await render();

expect(history.location.search).toMatch('pageSize=10');
expect(history.location.search).toMatch('page=1');
expect(history.location.search).not.toMatch('page_index');
expect(history.location.search).not.toMatch('page_size');
});

describe('without external privileges', () => {
it('should not display the delete action, do show the full details', async () => {
mockedApi.responseProvider.eventFiltersList.mockReturnValue(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { useEndpointPoliciesToArtifactPolicies } from '../../../../../components
import { useUrlParams } from '../../../../../components/hooks/use_url_params';
import { useUrlPagination } from '../../../../../components/hooks/use_url_pagination';
import { useGetEndpointSpecificPolicies } from '../../../../../services/policies/hooks';
import { useOldUrlSearchPaginationReplace } from '../../../../../components/hooks/use_old_url_search_pagination_replace';
import {
ArtifactCardGrid,
ArtifactCardGridProps,
Expand Down Expand Up @@ -58,6 +59,7 @@ export const PolicyArtifactsList = React.memo<PolicyArtifactsListProps>(
onDeleteActionCallback,
externalPrivileges = true,
}) => {
useOldUrlSearchPaginationReplace();
const { getAppUrl } = useAppUrl();
const { canCreateArtifactsByPolicy } = useUserPrivileges().endpointPrivileges;
const policiesRequest = useGetEndpointSpecificPolicies({ perPage: 1000 });
Expand Down

0 comments on commit bbb531a

Please sign in to comment.