[Security Solution][Exceptions] - Update exceptions tab privileges checks (#122902)

### Summary

Addresses #122227.
This commit is contained in:
Yara Tercero 2022-01-18 12:49:57 -08:00 committed by GitHub
parent 8c11be1154
commit fc64d172e7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 196 additions and 82 deletions

View file

@ -88,7 +88,7 @@ export const getReadPrivilegeMock = (
manage_index_templates: booleanValues,
manage_ingest_pipelines: booleanValues,
manage_ml: booleanValues,
manage_own_api_key: false,
manage_own_api_key: booleanValues,
manage_pipeline: booleanValues,
manage_rollup: booleanValues,
manage_saml: booleanValues,
@ -105,7 +105,7 @@ export const getReadPrivilegeMock = (
read_ilm: booleanValues,
transport_client: booleanValues,
},
has_all_requested: false,
has_all_requested: booleanValues,
index: {
[listItemsIndex]: {
all: booleanValues,
@ -141,7 +141,7 @@ export const getReadPrivilegeMock = (
manage_index_templates: booleanValues,
manage_ingest_pipelines: booleanValues,
manage_ml: booleanValues,
manage_own_api_key: false,
manage_own_api_key: booleanValues,
manage_pipeline: booleanValues,
manage_rollup: booleanValues,
manage_saml: booleanValues,
@ -158,7 +158,7 @@ export const getReadPrivilegeMock = (
read_ilm: booleanValues,
transport_client: booleanValues,
},
has_all_requested: false,
has_all_requested: booleanValues,
index: {
[listIndex]: {
all: booleanValues,

View file

@ -20,7 +20,7 @@ import { login, loginAndWaitForPage, waitForPageWithoutDateRange } from '../../t
import { refreshPage } from '../../tasks/security_header';
import { ALERTS_URL } from '../../urls/navigation';
import { ATTACH_ALERT_TO_CASE_BUTTON } from '../../screens/alerts';
import { ATTACH_ALERT_TO_CASE_BUTTON, TIMELINE_CONTEXT_MENU_BTN } from '../../screens/alerts';
const loadDetectionsPage = (role: ROLES) => {
waitForPageWithoutDateRange(ALERTS_URL, role);
@ -48,8 +48,8 @@ describe('Alerts timeline', () => {
});
it('should not allow user with read only privileges to attach alerts to cases', () => {
expandFirstAlertActions();
cy.get(ATTACH_ALERT_TO_CASE_BUTTON).should('not.exist');
// Disabled actions for read only users are hidden, so actions button should not show
cy.get(TIMELINE_CONTEXT_MENU_BTN).should('not.exist');
});
});

View file

@ -23,7 +23,7 @@ describe('ExceptionEntries', () => {
const wrapper = mount(
<ThemeProvider theme={mockTheme}>
<ExceptionEntries
disableDelete={false}
disableActions={false}
entries={[getFormattedEntryMock()]}
onDelete={jest.fn()}
onEdit={jest.fn()}
@ -38,7 +38,7 @@ describe('ExceptionEntries', () => {
const wrapper = mount(
<ThemeProvider theme={mockTheme}>
<ExceptionEntries
disableDelete={false}
disableActions={false}
entries={[getFormattedEntryMock(), getFormattedEntryMock()]}
onDelete={jest.fn()}
onEdit={jest.fn()}
@ -54,7 +54,7 @@ describe('ExceptionEntries', () => {
const wrapper = mount(
<ThemeProvider theme={mockTheme}>
<ExceptionEntries
disableDelete={false}
disableActions={false}
entries={[getFormattedEntryMock()]}
onDelete={jest.fn()}
onEdit={mockOnEdit}
@ -72,7 +72,7 @@ describe('ExceptionEntries', () => {
const wrapper = mount(
<ThemeProvider theme={mockTheme}>
<ExceptionEntries
disableDelete={false}
disableActions={false}
entries={[getFormattedEntryMock()]}
onDelete={mockOnDelete}
onEdit={jest.fn()}
@ -85,37 +85,36 @@ describe('ExceptionEntries', () => {
expect(mockOnDelete).toHaveBeenCalledTimes(1);
});
test('it renders edit button disabled if "disableDelete" is "true"', () => {
test('it does not render edit button if "disableActions" is "true"', () => {
const wrapper = mount(
<ThemeProvider theme={mockTheme}>
<ExceptionEntries
disableDelete={true}
disableActions={true}
entries={[getFormattedEntryMock()]}
onDelete={jest.fn()}
onEdit={jest.fn()}
/>
</ThemeProvider>
);
const editBtn = wrapper.find('[data-test-subj="exceptionsViewerEditBtn"] button').at(0);
const editBtns = wrapper.find('[data-test-subj="exceptionsViewerEditBtn"] button');
expect(editBtn.prop('disabled')).toBeTruthy();
expect(editBtns).toHaveLength(0);
});
test('it renders delete button in loading state if "disableDelete" is "true"', () => {
test('it does not render delete button if "disableActions" is "true"', () => {
const wrapper = mount(
<ThemeProvider theme={mockTheme}>
<ExceptionEntries
disableDelete={true}
disableActions={true}
entries={[getFormattedEntryMock()]}
onDelete={jest.fn()}
onEdit={jest.fn()}
/>
</ThemeProvider>
);
const deleteBtn = wrapper.find('[data-test-subj="exceptionsViewerDeleteBtn"] button').at(0);
const deleteBtns = wrapper.find('[data-test-subj="exceptionsViewerDeleteBtn"] button').at(0);
expect(deleteBtn.prop('disabled')).toBeTruthy();
expect(deleteBtn.find('.euiLoadingSpinner')).toBeTruthy();
expect(deleteBtns).toHaveLength(0);
});
test('it renders nested entry', () => {
@ -126,7 +125,7 @@ describe('ExceptionEntries', () => {
const wrapper = mount(
<ThemeProvider theme={mockTheme}>
<ExceptionEntries
disableDelete={false}
disableActions={false}
entries={[parentEntry, getFormattedEntryMock(true)]}
onDelete={jest.fn()}
onEdit={jest.fn()}
@ -168,7 +167,7 @@ describe('ExceptionEntries', () => {
const wrapper = mount(
<ThemeProvider theme={mockTheme}>
<ExceptionEntries
disableDelete={false}
disableActions={false}
entries={[getFormattedEntryMock()]}
onDelete={jest.fn()}
onEdit={jest.fn()}

View file

@ -75,14 +75,14 @@ const ValueBadgeGroup = styled(EuiBadgeGroup)`
interface ExceptionEntriesComponentProps {
entries: FormattedEntry[];
disableDelete: boolean;
disableActions: boolean;
onDelete: () => void;
onEdit: () => void;
}
const ExceptionEntriesComponent = ({
entries,
disableDelete,
disableActions,
onDelete,
onEdit,
}: ExceptionEntriesComponentProps): JSX.Element => {
@ -181,32 +181,32 @@ const ExceptionEntriesComponent = ({
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlexItem>
<EuiFlexItem grow={1}>
<EuiFlexGroup gutterSize="s" justifyContent="flexEnd">
<MyActionButton grow={false}>
<MyEditButton
size="s"
color="primary"
onClick={onEdit}
isDisabled={disableDelete}
data-test-subj="exceptionsViewerEditBtn"
>
{i18n.EDIT}
</MyEditButton>
</MyActionButton>
<MyActionButton grow={false}>
<MyRemoveButton
size="s"
color="danger"
onClick={onDelete}
isLoading={disableDelete}
data-test-subj="exceptionsViewerDeleteBtn"
>
{i18n.REMOVE}
</MyRemoveButton>
</MyActionButton>
</EuiFlexGroup>
</EuiFlexItem>
{!disableActions && (
<EuiFlexItem grow={1}>
<EuiFlexGroup gutterSize="s" justifyContent="flexEnd">
<MyActionButton grow={false}>
<MyEditButton
size="s"
color="primary"
onClick={onEdit}
data-test-subj="exceptionsViewerEditBtn"
>
{i18n.EDIT}
</MyEditButton>
</MyActionButton>
<MyActionButton grow={false}>
<MyRemoveButton
size="s"
color="danger"
onClick={onDelete}
data-test-subj="exceptionsViewerDeleteBtn"
>
{i18n.REMOVE}
</MyRemoveButton>
</MyActionButton>
</EuiFlexGroup>
</EuiFlexItem>
)}
</EuiFlexGroup>
</MyEntriesDetails>
);

View file

@ -35,6 +35,7 @@ storiesOf('Components/ExceptionItem', module)
return (
<ExceptionItem
disableActions={false}
loadingItemIds={[]}
commentsAccordionId={'accordion--comments'}
exceptionItem={payload}
@ -57,6 +58,7 @@ storiesOf('Components/ExceptionItem', module)
return (
<ExceptionItem
disableActions={false}
loadingItemIds={[]}
commentsAccordionId={'accordion--comments'}
exceptionItem={payload}
@ -80,6 +82,7 @@ storiesOf('Components/ExceptionItem', module)
return (
<ExceptionItem
disableActions={false}
loadingItemIds={[]}
commentsAccordionId={'accordion--comments'}
exceptionItem={payload}
@ -95,6 +98,7 @@ storiesOf('Components/ExceptionItem', module)
return (
<ExceptionItem
disableActions={false}
loadingItemIds={[]}
commentsAccordionId={'accordion--comments'}
exceptionItem={payload}
@ -108,6 +112,7 @@ storiesOf('Components/ExceptionItem', module)
payload.comments = getCommentsArrayMock();
return (
<ExceptionItem
disableActions={false}
loadingItemIds={[]}
commentsAccordionId={'accordion--comments'}
exceptionItem={payload}
@ -122,6 +127,7 @@ storiesOf('Components/ExceptionItem', module)
return (
<ExceptionItem
disableActions={false}
loadingItemIds={[{ id, namespaceType: namespace_type }]}
commentsAccordionId={'accordion--comments'}
exceptionItem={{ id, namespace_type, ...rest }}
@ -129,4 +135,28 @@ storiesOf('Components/ExceptionItem', module)
onEditException={action('onClick')}
/>
);
})
.add('with actions disabled', () => {
const payload = getExceptionListItemSchemaMock();
payload.description = '';
payload.comments = getCommentsArrayMock();
payload.entries = [
{
field: 'actingProcess.file.signer',
type: 'match',
operator: 'included',
value: 'Elastic, N.V.',
},
];
return (
<ExceptionItem
disableActions
loadingItemIds={[]}
commentsAccordionId={'accordion--comments'}
exceptionItem={payload}
onDeleteException={action('onClick')}
onEditException={action('onClick')}
/>
);
});

View file

@ -32,6 +32,7 @@ describe('ExceptionItem', () => {
const wrapper = mount(
<ThemeProvider theme={mockTheme}>
<ExceptionItem
disableActions={false}
loadingItemIds={[]}
commentsAccordionId={'accordion--comments'}
onDeleteException={jest.fn()}
@ -51,6 +52,7 @@ describe('ExceptionItem', () => {
const wrapper = mount(
<ThemeProvider theme={mockTheme}>
<ExceptionItem
disableActions={false}
loadingItemIds={[]}
commentsAccordionId={'accordion--comments'}
onDeleteException={jest.fn()}
@ -70,6 +72,30 @@ describe('ExceptionItem', () => {
);
});
it('it does not render edit or delete action buttons when "disableActions" is "true"', () => {
const mockOnEditException = jest.fn();
const exceptionItem = getExceptionListItemSchemaMock();
const wrapper = mount(
<ThemeProvider theme={mockTheme}>
<ExceptionItem
disableActions
loadingItemIds={[]}
commentsAccordionId={'accordion--comments'}
onDeleteException={jest.fn()}
onEditException={mockOnEditException}
exceptionItem={exceptionItem}
/>
</ThemeProvider>
);
const editBtn = wrapper.find('[data-test-subj="exceptionsViewerEditBtn"] button');
const deleteBtn = wrapper.find('[data-test-subj="exceptionsViewerDeleteBtn"] button');
expect(editBtn).toHaveLength(0);
expect(deleteBtn).toHaveLength(0);
});
it('it invokes "onEditException" when edit button clicked', () => {
const mockOnEditException = jest.fn();
const exceptionItem = getExceptionListItemSchemaMock();
@ -77,6 +103,7 @@ describe('ExceptionItem', () => {
const wrapper = mount(
<ThemeProvider theme={mockTheme}>
<ExceptionItem
disableActions={false}
loadingItemIds={[]}
commentsAccordionId={'accordion--comments'}
onDeleteException={jest.fn()}
@ -99,6 +126,7 @@ describe('ExceptionItem', () => {
const wrapper = mount(
<ThemeProvider theme={mockTheme}>
<ExceptionItem
disableActions={false}
loadingItemIds={[]}
commentsAccordionId={'accordion--comments'}
onDeleteException={mockOnDeleteException}
@ -108,8 +136,8 @@ describe('ExceptionItem', () => {
</ThemeProvider>
);
const editBtn = wrapper.find('[data-test-subj="exceptionsViewerDeleteBtn"] button').at(0);
editBtn.simulate('click');
const deleteBtn = wrapper.find('[data-test-subj="exceptionsViewerDeleteBtn"] button').at(0);
deleteBtn.simulate('click');
expect(mockOnDeleteException).toHaveBeenCalledWith({
id: '1',
@ -124,6 +152,7 @@ describe('ExceptionItem', () => {
const wrapper = mount(
<ThemeProvider theme={mockTheme}>
<ExceptionItem
disableActions={false}
loadingItemIds={[]}
commentsAccordionId={'accordion--comments'}
onDeleteException={mockOnDeleteException}
@ -143,6 +172,7 @@ describe('ExceptionItem', () => {
const wrapper = mount(
<ThemeProvider theme={mockTheme}>
<ExceptionItem
disableActions={false}
loadingItemIds={[]}
commentsAccordionId={'accordion--comments'}
onDeleteException={mockOnDeleteException}

View file

@ -38,10 +38,12 @@ export interface ExceptionItemProps {
onEditException: (item: ExceptionListItemSchema) => void;
showName?: boolean;
showModified?: boolean;
disableActions: boolean;
'data-test-subj'?: string;
}
const ExceptionItemComponent = ({
disableActions,
loadingItemIds,
exceptionItem,
commentsAccordionId,
@ -78,7 +80,7 @@ const ExceptionItemComponent = ({
return getFormattedComments(exceptionItem.comments);
}, [exceptionItem.comments]);
const disableDelete = useMemo((): boolean => {
const disableItemActions = useMemo((): boolean => {
const foundItems = loadingItemIds.filter(({ id }) => id === exceptionItem.id);
return foundItems.length > 0;
}, [loadingItemIds, exceptionItem.id]);
@ -96,7 +98,7 @@ const ExceptionItemComponent = ({
showName={showName}
/>
<ExceptionEntries
disableDelete={disableDelete}
disableActions={disableItemActions || disableActions}
entries={entryItems}
onDelete={handleDelete}
onEdit={handleEdit}

View file

@ -42,6 +42,22 @@ describe('ExceptionsViewerHeader', () => {
).toBeTruthy();
});
// This occurs if user does not have sufficient privileges
it('it does not display add exception button if no list types available', () => {
const wrapper = mount(
<ExceptionsViewerHeader
supportedListTypes={[]}
isInitLoading={false}
detectionsListItems={0}
endpointListItems={0}
onFilterChange={jest.fn()}
onAddExceptionClick={jest.fn()}
/>
);
expect(wrapper.find('[data-test-subj="exceptionsHeaderAddExceptionBtn"]').exists()).toBeFalsy();
});
it('it displays toggles and add exception popover when more than one list type available', () => {
const wrapper = mount(
<ExceptionsViewerHeader

View file

@ -133,7 +133,7 @@ const ExceptionsViewerHeaderComponent = ({
/>
</EuiFlexItem>
{supportedListTypes.length < 2 && (
{supportedListTypes.length === 1 && (
<EuiFlexItem grow={false}>
<EuiButton
data-test-subj="exceptionsHeaderAddExceptionBtn"

View file

@ -29,6 +29,7 @@ describe('ExceptionsViewerItems', () => {
showEmpty
showNoResults={false}
isInitLoading={false}
disableActions={false}
exceptions={[]}
loadingItemIds={[]}
commentsAccordionId="comments-accordion-id"
@ -54,6 +55,7 @@ describe('ExceptionsViewerItems', () => {
showEmpty={false}
showNoResults
isInitLoading={false}
disableActions={false}
exceptions={[]}
loadingItemIds={[]}
commentsAccordionId="comments-accordion-id"
@ -78,6 +80,7 @@ describe('ExceptionsViewerItems', () => {
showEmpty={false}
showNoResults={false}
isInitLoading={false}
disableActions={false}
exceptions={[getExceptionListItemSchemaMock()]}
loadingItemIds={[]}
commentsAccordionId="comments-accordion-id"
@ -98,6 +101,7 @@ describe('ExceptionsViewerItems', () => {
showEmpty={false}
showNoResults={false}
isInitLoading={true}
disableActions={false}
exceptions={[]}
loadingItemIds={[]}
commentsAccordionId="comments-accordion-id"
@ -122,6 +126,7 @@ describe('ExceptionsViewerItems', () => {
showEmpty={false}
showNoResults={false}
isInitLoading={false}
disableActions={false}
exceptions={[exception1, exception2]}
loadingItemIds={[]}
commentsAccordionId="comments-accordion-id"
@ -147,6 +152,7 @@ describe('ExceptionsViewerItems', () => {
showEmpty={false}
showNoResults={false}
isInitLoading={false}
disableActions={false}
exceptions={[exception1, exception2]}
loadingItemIds={[]}
commentsAccordionId="comments-accordion-id"
@ -172,6 +178,7 @@ describe('ExceptionsViewerItems', () => {
showEmpty={false}
showNoResults={false}
isInitLoading={false}
disableActions={false}
exceptions={[getExceptionListItemSchemaMock()]}
loadingItemIds={[]}
commentsAccordionId="comments-accordion-id"

View file

@ -36,6 +36,7 @@ interface ExceptionsViewerItemsProps {
showEmpty: boolean;
showNoResults: boolean;
isInitLoading: boolean;
disableActions: boolean;
exceptions: ExceptionListItemSchema[];
loadingItemIds: ExceptionListItemIdentifiers[];
commentsAccordionId: string;
@ -52,6 +53,7 @@ const ExceptionsViewerItemsComponent: React.FC<ExceptionsViewerItemsProps> = ({
commentsAccordionId,
onDeleteException,
onEditExceptionItem,
disableActions,
}): JSX.Element => (
<MyExceptionsContainer direction="column" className="eui-yScrollWithShadows">
{showEmpty || showNoResults || isInitLoading ? (
@ -93,6 +95,7 @@ const ExceptionsViewerItemsComponent: React.FC<ExceptionsViewerItemsProps> = ({
<EuiSpacer size="s" />
)}
<ExceptionItem
disableActions={disableActions}
loadingItemIds={loadingItemIds}
commentsAccordionId={commentsAccordionId}
exceptionItem={exception}

View file

@ -5,7 +5,7 @@
* 2.0.
*/
import React, { useCallback, useEffect, useReducer } from 'react';
import React, { useCallback, useEffect, useReducer, useState } from 'react';
import { EuiSpacer } from '@elastic/eui';
import uuid from 'uuid';
@ -18,6 +18,7 @@ import type {
import { useApi, useExceptionListItems } from '@kbn/securitysolution-list-hooks';
import * as i18n from '../translations';
import { useStateToaster } from '../../toasters';
import { useUserData } from '../../../../../public/detections/components/user_info';
import { useKibana } from '../../../../common/lib/kibana';
import { Panel } from '../../../../common/components/panel';
import { Loader } from '../../../../common/components/loader';
@ -105,6 +106,17 @@ const ExceptionsViewerComponent = ({
dispatch,
] = useReducer(allExceptionItemsReducer(), { ...initialState });
const { deleteExceptionItem, getExceptionListsItems } = useApi(services.http);
const [supportedListTypes, setSupportedListTypes] = useState<ExceptionListTypeEnum[]>([]);
const [{ canUserCRUD, hasIndexWrite }] = useUserData();
useEffect((): void => {
if (!canUserCRUD || !hasIndexWrite) {
setSupportedListTypes([]);
} else {
setSupportedListTypes(availableListTypes);
}
}, [availableListTypes, canUserCRUD, hasIndexWrite]);
const setExceptions = useCallback(
({
@ -356,7 +368,7 @@ const ExceptionsViewerComponent = ({
<ExceptionsViewerHeader
isInitLoading={isInitLoading}
supportedListTypes={availableListTypes}
supportedListTypes={supportedListTypes}
detectionsListItems={totalDetectionsItems}
endpointListItems={totalEndpointItems}
onFilterChange={handleFilterChange}
@ -374,6 +386,7 @@ const ExceptionsViewerComponent = ({
/>
<ExceptionsViewerItems
disableActions={!canUserCRUD || !hasIndexWrite}
showEmpty={showEmpty}
showNoResults={showNoResults}
isInitLoading={isInitLoading}

View file

@ -35,25 +35,28 @@ export const useExceptionActions = ({
const disabledAddException = !canUserCRUD || !hasIndexWrite;
const exceptionActionItems = useMemo(
() => [
<EuiContextMenuItem
key="add-endpoint-exception-menu-item"
data-test-subj="add-endpoint-exception-menu-item"
disabled={disabledAddEndpointException}
onClick={handleEndpointExceptionModal}
>
{ACTION_ADD_ENDPOINT_EXCEPTION}
</EuiContextMenuItem>,
() =>
disabledAddException
? []
: [
<EuiContextMenuItem
key="add-endpoint-exception-menu-item"
data-test-subj="add-endpoint-exception-menu-item"
disabled={disabledAddEndpointException}
onClick={handleEndpointExceptionModal}
>
{ACTION_ADD_ENDPOINT_EXCEPTION}
</EuiContextMenuItem>,
<EuiContextMenuItem
key="add-exception-menu-item"
data-test-subj="add-exception-menu-item"
disabled={disabledAddException}
onClick={handleDetectionExceptionModal}
>
{ACTION_ADD_EXCEPTION}
</EuiContextMenuItem>,
],
<EuiContextMenuItem
key="add-exception-menu-item"
data-test-subj="add-exception-menu-item"
disabled={disabledAddException}
onClick={handleDetectionExceptionModal}
>
{ACTION_ADD_EXCEPTION}
</EuiContextMenuItem>,
],
[
disabledAddEndpointException,
disabledAddException,

View file

@ -18,6 +18,9 @@ import { mockTimelines } from '../../../common/mock/mock_timelines_plugin';
import { createStartServicesMock } from '../../../common/lib/kibana/kibana_react.mock';
import { useKibana } from '../../../common/lib/kibana';
jest.mock('../user_info', () => ({
useUserData: jest.fn().mockReturnValue([{ canUserCRUD: true, hasIndexWrite: true }]),
}));
jest.mock('../../../common/hooks/endpoint/use_isolate_privileges', () => ({
useIsolationPrivileges: jest.fn().mockReturnValue({ isAllowed: true }),
}));

View file

@ -12,6 +12,10 @@ import { TestProviders, mockTimelineModel, mockTimelineData } from '../../../../
import { Actions } from '.';
import { mockTimelines } from '../../../../../common/mock/mock_timelines_plugin';
import { useIsExperimentalFeatureEnabled } from '../../../../../common/hooks/use_experimental_features';
jest.mock('../../../../../detections/components/user_info', () => ({
useUserData: jest.fn().mockReturnValue([{ canUserCRUD: true, hasIndexWrite: true }]),
}));
jest.mock('../../../../../common/hooks/use_experimental_features', () => ({
useIsExperimentalFeatureEnabled: jest.fn().mockReturnValue(false),
}));

View file

@ -166,8 +166,7 @@ export default ({ getService }: FtrProviderContext) => {
.expect(200);
});
// Tests in development
it.skip('should delete a single list referenced within an exception list item if ignoreReferences=true', async () => {
it('should delete a single list referenced within an exception list item if ignoreReferences=true', async () => {
// create a list
const { body: valueListBody } = await supertest
.post(LIST_URL)
@ -207,8 +206,7 @@ export default ({ getService }: FtrProviderContext) => {
.expect(409);
});
// Tests in development
it.skip('should delete a single list referenced within an exception list item and referenced exception list items if deleteReferences=true', async () => {
it('should delete a single list referenced within an exception list item and referenced exception list items if deleteReferences=true', async () => {
// create a list
const { body: valueListBody } = await supertest
.post(LIST_URL)
@ -241,6 +239,13 @@ export default ({ getService }: FtrProviderContext) => {
})
.expect(200);
// sanity check
await supertest
.get(`${LIST_ITEM_URL}/_find?list_id=${LIST_ID}`)
.set('kbn-xsrf', 'true')
.send()
.expect(200);
// delete that list by its auto-generated id and delete referenced list items
const deleteListBody = await supertest
.delete(`${LIST_URL}?id=${valueListBody.id}&ignoreReferences=true`)
@ -253,7 +258,7 @@ export default ({ getService }: FtrProviderContext) => {
.get(`${LIST_ITEM_URL}/_find?list_id=${LIST_ID}`)
.set('kbn-xsrf', 'true')
.send()
.expect(200);
.expect(404);
});
});
});

View file

@ -18,8 +18,7 @@ export default ({ getService }: FtrProviderContext) => {
const spacesService = getService('spaces');
const supertestWithoutAuth = getService('supertestWithoutAuth');
// FAILING ES PROMOTION: https://github.com/elastic/kibana/issues/88302
describe.skip('read_list_privileges', () => {
describe('read_list_privileges', () => {
const space1Id = 'space_1';
const user1 = {