Skip to content

Commit

Permalink
[SIEM] Import timeline schema update (#61622) (#61828)
Browse files Browse the repository at this point in the history
* 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 <[email protected]>

Co-authored-by: Elastic Machine <[email protected]>
  • Loading branch information
angorayc and elasticmachine authored Mar 30, 2020
1 parent 1f332fb commit c9de902
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 31 deletions.
Original file line number Diff line number Diff line change
@@ -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);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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>
)}
Expand All @@ -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>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -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,
Expand Down Expand Up @@ -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),
Expand All @@ -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),
Expand All @@ -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)
);
Expand All @@ -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;

0 comments on commit c9de902

Please sign in to comment.