mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
[SIEM] Import timeline schema update (#61622)
* allow users importing data if they are authorized * rename props * rename types * hide import timeline btn if unauthorized * unit test for TimelinesPageComponent * update schemas * update schema Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
This commit is contained in:
parent
1855d10d9d
commit
c0c9d98538
3 changed files with 117 additions and 31 deletions
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { TimelinesPageComponent } from './timelines_page';
|
||||
import { useKibana } from '../../lib/kibana';
|
||||
import { shallow, ShallowWrapper } from 'enzyme';
|
||||
import React from 'react';
|
||||
import ApolloClient from 'apollo-client';
|
||||
|
||||
jest.mock('../../lib/kibana', () => {
|
||||
return {
|
||||
useKibana: jest.fn(),
|
||||
};
|
||||
});
|
||||
describe('TimelinesPageComponent', () => {
|
||||
const mockAppollloClient = {} as ApolloClient<object>;
|
||||
let wrapper: ShallowWrapper;
|
||||
|
||||
describe('If the user is authorised', () => {
|
||||
beforeAll(() => {
|
||||
((useKibana as unknown) as jest.Mock).mockReturnValue({
|
||||
services: {
|
||||
application: {
|
||||
capabilities: {
|
||||
siem: {
|
||||
crud: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
wrapper = shallow(<TimelinesPageComponent apolloClient={mockAppollloClient} />);
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
((useKibana as unknown) as jest.Mock).mockReset();
|
||||
});
|
||||
|
||||
test('should not show the import timeline modal by default', () => {
|
||||
expect(
|
||||
wrapper.find('[data-test-subj="stateful-open-timeline"]').prop('importDataModalToggle')
|
||||
).toEqual(false);
|
||||
});
|
||||
|
||||
test('should show the import timeline button', () => {
|
||||
expect(wrapper.find('[data-test-subj="open-import-data-modal-btn"]').exists()).toEqual(true);
|
||||
});
|
||||
|
||||
test('should show the import timeline modal after user clicking on the button', () => {
|
||||
wrapper.find('[data-test-subj="open-import-data-modal-btn"]').simulate('click');
|
||||
expect(
|
||||
wrapper.find('[data-test-subj="stateful-open-timeline"]').prop('importDataModalToggle')
|
||||
).toEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('If the user is not authorised', () => {
|
||||
beforeAll(() => {
|
||||
((useKibana as unknown) as jest.Mock).mockReturnValue({
|
||||
services: {
|
||||
application: {
|
||||
capabilities: {
|
||||
siem: {
|
||||
crud: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
wrapper = shallow(<TimelinesPageComponent apolloClient={mockAppollloClient} />);
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
((useKibana as unknown) as jest.Mock).mockReset();
|
||||
});
|
||||
test('should not show the import timeline modal by default', () => {
|
||||
expect(
|
||||
wrapper.find('[data-test-subj="stateful-open-timeline"]').prop('importDataModalToggle')
|
||||
).toEqual(false);
|
||||
});
|
||||
|
||||
test('should not show the import timeline button', () => {
|
||||
expect(wrapper.find('[data-test-subj="open-import-data-modal-btn"]').exists()).toEqual(false);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -28,7 +28,7 @@ type OwnProps = TimelinesProps;
|
|||
|
||||
export const DEFAULT_SEARCH_RESULTS_PER_PAGE = 10;
|
||||
|
||||
const TimelinesPageComponent: React.FC<OwnProps> = ({ apolloClient }) => {
|
||||
export const TimelinesPageComponent: React.FC<OwnProps> = ({ apolloClient }) => {
|
||||
const [importDataModalToggle, setImportDataModalToggle] = useState<boolean>(false);
|
||||
const onImportTimelineBtnClick = useCallback(() => {
|
||||
setImportDataModalToggle(true);
|
||||
|
@ -43,7 +43,11 @@ const TimelinesPageComponent: React.FC<OwnProps> = ({ apolloClient }) => {
|
|||
<WrapperPage>
|
||||
<HeaderPage border title={i18n.PAGE_TITLE}>
|
||||
{capabilitiesCanUserCRUD && (
|
||||
<EuiButton iconType="indexOpen" onClick={onImportTimelineBtnClick}>
|
||||
<EuiButton
|
||||
iconType="indexOpen"
|
||||
onClick={onImportTimelineBtnClick}
|
||||
data-test-subj="open-import-data-modal-btn"
|
||||
>
|
||||
{i18n.ALL_TIMELINES_IMPORT_TIMELINE_TITLE}
|
||||
</EuiButton>
|
||||
)}
|
||||
|
@ -57,6 +61,7 @@ const TimelinesPageComponent: React.FC<OwnProps> = ({ apolloClient }) => {
|
|||
importDataModalToggle={importDataModalToggle && capabilitiesCanUserCRUD}
|
||||
setImportDataModalToggle={setImportDataModalToggle}
|
||||
title={i18n.ALL_TIMELINES_PANEL_TITLE}
|
||||
data-test-subj="stateful-open-timeline"
|
||||
/>
|
||||
</TimelinesContainer>
|
||||
</WrapperPage>
|
||||
|
|
|
@ -6,14 +6,14 @@
|
|||
import Joi from 'joi';
|
||||
|
||||
const allowEmptyString = Joi.string().allow([null, '']);
|
||||
const columnHeaderType = Joi.string();
|
||||
const columnHeaderType = allowEmptyString;
|
||||
export const created = Joi.number().allow(null);
|
||||
export const createdBy = Joi.string();
|
||||
export const createdBy = allowEmptyString;
|
||||
|
||||
export const description = allowEmptyString;
|
||||
export const end = Joi.number();
|
||||
export const eventId = allowEmptyString;
|
||||
export const eventType = Joi.string();
|
||||
export const eventType = allowEmptyString;
|
||||
|
||||
export const filters = Joi.array()
|
||||
.items(
|
||||
|
@ -24,19 +24,11 @@ export const filters = Joi.array()
|
|||
disabled: Joi.boolean().allow(null),
|
||||
field: allowEmptyString,
|
||||
formattedValue: allowEmptyString,
|
||||
index: {
|
||||
type: 'keyword',
|
||||
},
|
||||
key: {
|
||||
type: 'keyword',
|
||||
},
|
||||
negate: {
|
||||
type: 'boolean',
|
||||
},
|
||||
index: allowEmptyString,
|
||||
key: allowEmptyString,
|
||||
negate: Joi.boolean().allow(null),
|
||||
params: allowEmptyString,
|
||||
type: {
|
||||
type: 'keyword',
|
||||
},
|
||||
type: allowEmptyString,
|
||||
value: allowEmptyString,
|
||||
}),
|
||||
exists: allowEmptyString,
|
||||
|
@ -68,22 +60,22 @@ export const version = allowEmptyString;
|
|||
export const columns = Joi.array().items(
|
||||
Joi.object({
|
||||
aggregatable: Joi.boolean().allow(null),
|
||||
category: Joi.string(),
|
||||
category: allowEmptyString,
|
||||
columnHeaderType,
|
||||
description,
|
||||
example: allowEmptyString,
|
||||
indexes: allowEmptyString,
|
||||
id: Joi.string(),
|
||||
id: allowEmptyString,
|
||||
name,
|
||||
placeholder: allowEmptyString,
|
||||
searchable: Joi.boolean().allow(null),
|
||||
type: Joi.string(),
|
||||
type: allowEmptyString,
|
||||
}).required()
|
||||
);
|
||||
export const dataProviders = Joi.array()
|
||||
.items(
|
||||
Joi.object({
|
||||
id: Joi.string(),
|
||||
id: allowEmptyString,
|
||||
name: allowEmptyString,
|
||||
enabled: Joi.boolean().allow(null),
|
||||
excluded: Joi.boolean().allow(null),
|
||||
|
@ -98,7 +90,7 @@ export const dataProviders = Joi.array()
|
|||
and: Joi.array()
|
||||
.items(
|
||||
Joi.object({
|
||||
id: Joi.string(),
|
||||
id: allowEmptyString,
|
||||
name,
|
||||
enabled: Joi.boolean().allow(null),
|
||||
excluded: Joi.boolean().allow(null),
|
||||
|
@ -122,9 +114,9 @@ export const dateRange = Joi.object({
|
|||
});
|
||||
export const favorite = Joi.array().items(
|
||||
Joi.object({
|
||||
keySearch: Joi.string(),
|
||||
fullName: Joi.string(),
|
||||
userName: Joi.string(),
|
||||
keySearch: allowEmptyString,
|
||||
fullName: allowEmptyString,
|
||||
userName: allowEmptyString,
|
||||
favoriteDate: Joi.number(),
|
||||
}).allow(null)
|
||||
);
|
||||
|
@ -141,26 +133,26 @@ const noteItem = Joi.object({
|
|||
});
|
||||
export const eventNotes = Joi.array().items(noteItem);
|
||||
export const globalNotes = Joi.array().items(noteItem);
|
||||
export const kqlMode = Joi.string();
|
||||
export const kqlMode = allowEmptyString;
|
||||
export const kqlQuery = Joi.object({
|
||||
filterQuery: Joi.object({
|
||||
kuery: Joi.object({
|
||||
kind: Joi.string(),
|
||||
kind: allowEmptyString,
|
||||
expression: allowEmptyString,
|
||||
}),
|
||||
serializedQuery: allowEmptyString,
|
||||
}),
|
||||
});
|
||||
export const pinnedEventIds = Joi.array()
|
||||
.items(Joi.string())
|
||||
.items(allowEmptyString)
|
||||
.allow(null);
|
||||
export const sort = Joi.object({
|
||||
columnId: Joi.string(),
|
||||
sortDirection: Joi.string(),
|
||||
columnId: allowEmptyString,
|
||||
sortDirection: allowEmptyString,
|
||||
});
|
||||
/* eslint-disable @typescript-eslint/camelcase */
|
||||
|
||||
export const ids = Joi.array().items(Joi.string());
|
||||
export const ids = Joi.array().items(allowEmptyString);
|
||||
|
||||
export const exclude_export_details = Joi.boolean();
|
||||
export const file_name = allowEmptyString;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue