Skip to content

Commit

Permalink
Merge branch 'main' into sharedux/services-exit
Browse files Browse the repository at this point in the history
  • Loading branch information
kibanamachine authored Jan 9, 2022
2 parents 4d6cd93 + 526367c commit 63e482a
Show file tree
Hide file tree
Showing 15 changed files with 232 additions and 74 deletions.
3 changes: 2 additions & 1 deletion .backportrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,6 @@
"^v(\\d+).(\\d+).\\d+$": "$1.$2"
},
"autoMerge": true,
"autoMergeMethod": "squash"
"autoMergeMethod": "squash",
"backportBinary": "node scripts/backport"
}
1 change: 0 additions & 1 deletion .github/workflows/backport.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,3 @@ jobs:
commit_email: [email protected]
auto_merge: 'true'
auto_merge_method: 'squash'
manual_backport_command_template: 'node scripts/backport --pr %pullNumber%'
7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@
"**/istanbul-lib-coverage": "^3.2.0",
"**/json-schema": "^0.4.0",
"**/minimist": "^1.2.5",
"**/node-forge": "^1.1.0",
"**/pdfkit/crypto-js": "4.0.0",
"**/react-syntax-highlighter": "^15.3.1",
"**/react-syntax-highlighter/**/highlight.js": "^10.4.1",
Expand Down Expand Up @@ -299,7 +300,7 @@
"mustache": "^2.3.2",
"nock": "12.0.3",
"node-fetch": "^2.6.1",
"node-forge": "^0.10.0",
"node-forge": "^1.1.0",
"nodemailer": "^6.6.2",
"normalize-path": "^3.0.0",
"object-hash": "^1.3.1",
Expand Down Expand Up @@ -623,7 +624,7 @@
"@types/nock": "^10.0.3",
"@types/node": "16.10.2",
"@types/node-fetch": "^2.5.7",
"@types/node-forge": "^0.10.10",
"@types/node-forge": "^1.0.0",
"@types/nodemailer": "^6.4.0",
"@types/normalize-path": "^3.0.0",
"@types/object-hash": "^1.3.0",
Expand Down Expand Up @@ -711,7 +712,7 @@
"babel-plugin-require-context-hook": "^1.0.0",
"babel-plugin-styled-components": "^2.0.2",
"babel-plugin-transform-react-remove-prop-types": "^0.4.24",
"backport": "^6.1.1",
"backport": "^6.1.3",
"callsites": "^3.1.0",
"chai": "3.5.0",
"chance": "1.0.18",
Expand Down
48 changes: 25 additions & 23 deletions x-pack/plugins/osquery/public/application.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { ThemeProvider } from 'styled-components';
import { QueryClientProvider } from 'react-query';
import { ReactQueryDevtools } from 'react-query/devtools';

import { useUiSetting$ } from '../../../../src/plugins/kibana_react/public';
import { useUiSetting$, KibanaThemeProvider } from './shared_imports';
import { Storage } from '../../../../src/plugins/kibana_utils/public';
import { AppMountParameters, CoreStart } from '../../../../src/core/public';
import { AppPluginStartDependencies } from './types';
Expand Down Expand Up @@ -44,32 +44,34 @@ const OsqueryAppContext = () => {
export const renderApp = (
core: CoreStart,
services: AppPluginStartDependencies,
{ element, history }: AppMountParameters,
{ element, history, theme$ }: AppMountParameters,
storage: Storage,
kibanaVersion: string
) => {
ReactDOM.render(
<KibanaContextProvider
// eslint-disable-next-line react-perf/jsx-no-new-object-as-prop
services={{
appName: PLUGIN_NAME,
kibanaVersion,
...core,
...services,
storage,
}}
>
<EuiErrorBoundary>
<Router history={history}>
<I18nProvider>
<QueryClientProvider client={queryClient}>
<OsqueryAppContext />
<ReactQueryDevtools initialIsOpen={false} />
</QueryClientProvider>
</I18nProvider>
</Router>
</EuiErrorBoundary>
</KibanaContextProvider>,
<KibanaThemeProvider theme$={theme$}>
<KibanaContextProvider
// eslint-disable-next-line react-perf/jsx-no-new-object-as-prop
services={{
appName: PLUGIN_NAME,
kibanaVersion,
...core,
...services,
storage,
}}
>
<EuiErrorBoundary>
<Router history={history}>
<I18nProvider>
<QueryClientProvider client={queryClient}>
<OsqueryAppContext />
<ReactQueryDevtools initialIsOpen={false} />
</QueryClientProvider>
</I18nProvider>
</Router>
</EuiErrorBoundary>
</KibanaContextProvider>
</KibanaThemeProvider>,
element
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { KibanaContextProvider, useKibana } from '../../common/lib/kibana';
import { LiveQuery } from '../../live_queries';
import { queryClient } from '../../query_client';
import { OsqueryIcon } from '../../components/osquery_icon';
import { KibanaThemeProvider } from '../../shared_imports';

interface OsqueryActionProps {
metadata?: {
Expand Down Expand Up @@ -134,13 +135,15 @@ export const OsqueryAction = React.memo(OsqueryActionComponent);

// @ts-expect-error update types
const OsqueryActionWrapperComponent = ({ services, ...props }) => (
<KibanaContextProvider services={services}>
<EuiErrorBoundary>
<QueryClientProvider client={queryClient}>
<OsqueryAction {...props} />
</QueryClientProvider>
</EuiErrorBoundary>
</KibanaContextProvider>
<KibanaThemeProvider theme$={services.theme.theme$}>
<KibanaContextProvider services={services}>
<EuiErrorBoundary>
<QueryClientProvider client={queryClient}>
<OsqueryAction {...props} />
</QueryClientProvider>
</EuiErrorBoundary>
</KibanaContextProvider>
</KibanaThemeProvider>
);

const OsqueryActionWrapper = React.memo(OsqueryActionWrapperComponent);
Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/osquery/public/shared_imports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,4 @@ export type { ERROR_CODE } from '../../../../src/plugins/es_ui_shared/static/for

export { EuiCodeEditor } from '../../../../src/plugins/es_ui_shared/public';
export type { EuiCodeEditorProps } from '../../../../src/plugins/es_ui_shared/public';
export { useUiSetting$, KibanaThemeProvider } from '../../../../src/plugins/kibana_react/public';
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/*
* 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 {
TIMELINES_OVERVIEW_TABLE,
TIMELINES_OVERVIEW_ONLY_FAVORITES,
TIMELINES_OVERVIEW_SEARCH,
} from '../../screens/timelines';

import {
getTimeline,
getFavoritedTimeline,
sharedTimelineTitleFragment,
} from '../../objects/timeline';

import { cleanKibana } from '../../tasks/common';

import { loginAndWaitForPageWithoutDateRange } from '../../tasks/login';
import { createTimeline, favoriteTimeline } from '../../tasks/api_calls/timelines';

import { TIMELINES_URL } from '../../urls/navigation';

describe('timeline overview search', () => {
before(() => {
cleanKibana();

createTimeline(getFavoritedTimeline())
.then((response) => response.body.data.persistTimeline.timeline.savedObjectId)
.then((timelineId) => favoriteTimeline({ timelineId, timelineType: 'default' }));
createTimeline(getTimeline());

loginAndWaitForPageWithoutDateRange(TIMELINES_URL);
});

beforeEach(() => {
cy.get(TIMELINES_OVERVIEW_SEARCH).clear();
});

it('should show all timelines when no search term was entered', () => {
cy.get(TIMELINES_OVERVIEW_TABLE).contains(getTimeline().title);
cy.get(TIMELINES_OVERVIEW_TABLE).contains(getFavoritedTimeline().title);
});

it('should show the correct favorite count without search', () => {
cy.get(TIMELINES_OVERVIEW_ONLY_FAVORITES).contains(1);
});

it('should show the correct timelines when the favorite filter is activated', () => {
cy.get(TIMELINES_OVERVIEW_ONLY_FAVORITES).click(); // enable the filter

cy.get(TIMELINES_OVERVIEW_TABLE).contains(getTimeline().title).should('not.exist');
cy.get(TIMELINES_OVERVIEW_TABLE).contains(getFavoritedTimeline().title);
cy.get(TIMELINES_OVERVIEW_ONLY_FAVORITES).contains(1);

cy.get(TIMELINES_OVERVIEW_ONLY_FAVORITES).click(); // disable the filter
});

it('should find the correct timeline and have the correct favorite count when searching by timeline title', () => {
cy.get(TIMELINES_OVERVIEW_SEARCH).type(`"${getTimeline().title}"{enter}`);

cy.get(TIMELINES_OVERVIEW_TABLE).contains(getFavoritedTimeline().title).should('not.exist');
cy.get(TIMELINES_OVERVIEW_TABLE).contains(getTimeline().title);
cy.get(TIMELINES_OVERVIEW_ONLY_FAVORITES).contains(0);
});

it('should find the correct timelines when searching for favorited timelines', () => {
cy.get(TIMELINES_OVERVIEW_ONLY_FAVORITES).click(); // enable the filter
cy.get(TIMELINES_OVERVIEW_SEARCH).type(`"${getFavoritedTimeline().title}"{enter}`);

cy.get(TIMELINES_OVERVIEW_TABLE).contains(getTimeline().title).should('not.exist');
cy.get(TIMELINES_OVERVIEW_TABLE).contains(getFavoritedTimeline().title);
cy.get(TIMELINES_OVERVIEW_ONLY_FAVORITES).contains(1);

cy.get(TIMELINES_OVERVIEW_ONLY_FAVORITES).click(); // disable the filter
});

it('should find the correct timelines when both favorited and non-favorited timelines match', () => {
cy.get(TIMELINES_OVERVIEW_SEARCH).type(`"${sharedTimelineTitleFragment}"{enter}`);

cy.get(TIMELINES_OVERVIEW_TABLE).contains(getTimeline().title);
cy.get(TIMELINES_OVERVIEW_TABLE).contains(getFavoritedTimeline().title);
cy.get(TIMELINES_OVERVIEW_ONLY_FAVORITES).contains(1);
});
});
12 changes: 11 additions & 1 deletion x-pack/plugins/security_solution/cypress/objects/timeline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,24 @@ export const getFilter = (): TimelineFilter => ({
value: 'exists',
});

export const sharedTimelineTitleFragment = 'Timeline';

export const getTimeline = (): CompleteTimeline => ({
title: 'Security Timeline',
title: `Security ${sharedTimelineTitleFragment}`,
description: 'This is the best timeline',
query: 'host.name: *',
notes: 'Yes, the best timeline',
filter: getFilter(),
});

export const getFavoritedTimeline = (): CompleteTimeline => ({
title: `Darkest ${sharedTimelineTitleFragment}`,
description: 'This is the darkest timeline',
query: 'host.name: *',
notes: 'Yes, the darkest timeline, you heard me right',
filter: getFilter(),
});

export const getIndicatorMatchTimelineTemplate = (): CompleteTimeline => ({
...getTimeline(),
title: 'Generic Threat Match Timeline',
Expand Down
8 changes: 8 additions & 0 deletions x-pack/plugins/security_solution/cypress/screens/timelines.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,11 @@ export const TIMELINES_TABLE = '[data-test-subj="timelines-table"]';
export const TIMELINES_USERNAME = '[data-test-subj="username"]';

export const REFRESH_BUTTON = '[data-test-subj="refreshButton-linkIcon"]';

export const TIMELINES_OVERVIEW = '[data-test-subj="timelines-container"]';

export const TIMELINES_OVERVIEW_ONLY_FAVORITES = `${TIMELINES_OVERVIEW} [data-test-subj="only-favorites-toggle"]`;

export const TIMELINES_OVERVIEW_SEARCH = `${TIMELINES_OVERVIEW} [data-test-subj="search-bar"]`;

export const TIMELINES_OVERVIEW_TABLE = `${TIMELINES_OVERVIEW} [data-test-subj="timelines-table"]`;
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,26 @@ import { useKibana } from '../../../common/lib/kibana';
import type { DataView } from '../../../../../../../src/plugins/data/common';
import { TimelineId } from '../../../../common/types';

const useKibanaMock = useKibana as jest.Mocked<typeof useKibana>;

let mockIndexPatternFieldEditor: Start;
jest.mock('../../../common/lib/kibana');
const useKibanaMock = useKibana as jest.Mocked<typeof useKibana>;

const runAllPromises = () => new Promise(setImmediate);

describe('CreateFieldButton', () => {
beforeEach(() => {
mockIndexPatternFieldEditor = indexPatternFieldEditorPluginMock.createStartContract();
mockIndexPatternFieldEditor.userPermissions.editIndexPattern = () => true;
useKibanaMock().services.dataViewFieldEditor = mockIndexPatternFieldEditor;
useKibanaMock().services.data.dataViews.get = () => new Promise(() => undefined);
});

it('displays the button when user has permissions', () => {
mockIndexPatternFieldEditor.userPermissions.editIndexPattern = () => true;

useKibanaMock().services.application.capabilities = {
...useKibanaMock().services.application.capabilities,
indexPatterns: { save: true },
};
});
// refactor below tests once resolved: https://github.com/elastic/kibana/issues/122462
it('displays the button when user has read permissions and write permissions', () => {
render(
<CreateFieldButton
selectedDataViewId={'dataViewId'}
Expand All @@ -49,7 +52,7 @@ describe('CreateFieldButton', () => {
expect(screen.getByRole('button')).toBeInTheDocument();
});

it("doesn't display the button when user doesn't have permissions", () => {
it("doesn't display the button when user doesn't have read permissions", () => {
mockIndexPatternFieldEditor.userPermissions.editIndexPattern = () => false;
render(
<CreateFieldButton
Expand All @@ -65,8 +68,26 @@ describe('CreateFieldButton', () => {
expect(screen.queryByRole('button')).not.toBeInTheDocument();
});

it("doesn't display the button when user doesn't have write permissions", () => {
useKibanaMock().services.application.capabilities = {
...useKibanaMock().services.application.capabilities,
indexPatterns: { save: false },
};
render(
<CreateFieldButton
selectedDataViewId={'dataViewId'}
onClick={() => undefined}
timelineId={TimelineId.detectionsPage}
/>,
{
wrapper: TestProviders,
}
);

expect(screen.queryByRole('button')).not.toBeInTheDocument();
});

it("calls 'onClick' param when the button is clicked", async () => {
mockIndexPatternFieldEditor.userPermissions.editIndexPattern = () => true;
useKibanaMock().services.data.dataViews.get = () => Promise.resolve({} as DataView);

const onClickParam = jest.fn();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export const CreateFieldButton = React.memo<CreateFieldButtonProps>(
const {
dataViewFieldEditor,
data: { dataViews },
application: { capabilities },
} = useKibana().services;

useEffect(() => {
Expand Down Expand Up @@ -83,7 +84,11 @@ export const CreateFieldButton = React.memo<CreateFieldButtonProps>(
timelineId,
]);

if (!dataViewFieldEditor?.userPermissions.editIndexPattern()) {
if (
!dataViewFieldEditor?.userPermissions.editIndexPattern() ||
// remove below check once resolved: https://github.com/elastic/kibana/issues/122462
!capabilities.indexPatterns.save
) {
return null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ export const TimelinesPageComponent: React.FC = () => {
</EuiFlexGroup>
</HeaderPage>

<TimelinesContainer>
<TimelinesContainer data-test-subj="timelines-container">
<StatefulOpenTimeline
defaultPageSize={DEFAULT_SEARCH_RESULTS_PER_PAGE}
isModal={false}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -222,11 +222,10 @@ describe('saved_object', () => {
test('should send correct options for counts of favorite timeline', async () => {
expect(mockFindSavedObject.mock.calls[5][0]).toEqual({
filter:
'not siem-ui-timeline.attributes.status: draft and not siem-ui-timeline.attributes.status: immutable',
'not siem-ui-timeline.attributes.status: draft and not siem-ui-timeline.attributes.status: immutable and siem-ui-timeline.attributes.favorite.keySearch: dXNlcm5hbWU=',
page: 1,
perPage: 1,
search: ' dXNlcm5hbWU=',
searchFields: ['title', 'description', 'favorite.keySearch'],
searchFields: ['title', 'description'],
type: 'siem-ui-timeline',
});
});
Expand Down
Loading

0 comments on commit 63e482a

Please sign in to comment.