Skip to content

Commit

Permalink
Merge branch 'master' into unskip-dataprovider
Browse files Browse the repository at this point in the history
  • Loading branch information
kibanamachine authored Jan 4, 2021
2 parents 4a9c9e6 + 8d2e51d commit 133e674
Show file tree
Hide file tree
Showing 38 changed files with 89 additions and 1,651 deletions.
2 changes: 1 addition & 1 deletion NOTICE.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Kibana source code with Kibana X-Pack source code
Copyright 2012-2020 Elasticsearch B.V.
Copyright 2012-2021 Elasticsearch B.V.

---
Pretty handling of logarithmic axes.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@
* under the License.
*/

import { validateObject } from './validate_object';
import { ensureNoUnsafeProperties } from './ensure_no_unsafe_properties';

test(`fails on circular references`, () => {
const foo: Record<string, any> = {};
foo.myself = foo;

expect(() =>
validateObject({
ensureNoUnsafeProperties({
payload: foo,
})
).toThrowErrorMatchingInlineSnapshot(`"circular reference detected"`);
Expand Down Expand Up @@ -57,7 +57,7 @@ test(`fails on circular references`, () => {
[property]: value,
};
test(`can submit ${JSON.stringify(obj)}`, () => {
expect(() => validateObject(obj)).not.toThrowError();
expect(() => ensureNoUnsafeProperties(obj)).not.toThrowError();
});
});
});
Expand All @@ -74,6 +74,6 @@ test(`fails on circular references`, () => {
JSON.parse(`{ "foo": { "bar": { "constructor": { "prototype" : null } } } }`),
].forEach((value) => {
test(`can't submit ${JSON.stringify(value)}`, () => {
expect(() => validateObject(value)).toThrowErrorMatchingSnapshot();
expect(() => ensureNoUnsafeProperties(value)).toThrowErrorMatchingSnapshot();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const hasOwnProperty = (obj: any, property: string) =>
const isObject = (obj: any) => typeof obj === 'object' && obj !== null;

// we're using a stack instead of recursion so we aren't limited by the call stack
export function validateObject(obj: any) {
export function ensureNoUnsafeProperties(obj: any) {
if (!isObject(obj)) {
return;
}
Expand Down
1 change: 1 addition & 0 deletions packages/kbn-std/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,5 @@ export { withTimeout } from './promise';
export { isRelativeUrl, modifyUrl, getUrlOrigin, URLMeaningfulParts } from './url';
export { unset } from './unset';
export { getFlattenedObject } from './get_flattened_object';
export { ensureNoUnsafeProperties } from './ensure_no_unsafe_properties';
export * from './rxjs_7';
4 changes: 2 additions & 2 deletions src/core/server/http/http_tools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ import Hoek from '@hapi/hoek';
import type { ServerOptions as TLSOptions } from 'https';
import type { ValidationError } from 'joi';
import uuid from 'uuid';
import { ensureNoUnsafeProperties } from '@kbn/std';
import { HttpConfig } from './http_config';
import { validateObject } from './prototype_pollution';

const corsAllowedHeaders = ['Accept', 'Authorization', 'Content-Type', 'If-None-Match', 'kbn-xsrf'];
/**
Expand Down Expand Up @@ -69,7 +69,7 @@ export function getServerOptions(config: HttpConfig, { configureTLS = true } = {
// This is a default payload validation which applies to all LP routes which do not specify their own
// `validate.payload` handler, in order to reduce the likelyhood of prototype pollution vulnerabilities.
// (All NP routes are already required to specify their own validation in order to access the payload)
payload: (value) => Promise.resolve(validateObject(value)),
payload: (value) => Promise.resolve(ensureNoUnsafeProperties(value)),
},
},
state: {
Expand Down
14 changes: 11 additions & 3 deletions src/plugins/data/public/ui/filter_bar/filter_item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,19 +71,27 @@ export function FilterItem(props: Props) {

useEffect(() => {
const index = props.filter.meta.index;
let isSubscribed = true;
if (index) {
getIndexPatterns()
.get(index)
.then((indexPattern) => {
setIndexPatternExists(!!indexPattern);
if (isSubscribed) {
setIndexPatternExists(!!indexPattern);
}
})
.catch(() => {
setIndexPatternExists(false);
if (isSubscribed) {
setIndexPatternExists(false);
}
});
} else {
} else if (isSubscribed) {
// Allow filters without an index pattern and don't validate them.
setIndexPatternExists(true);
}
return () => {
isSubscribed = false;
};
}, [props.filter.meta.index]);

function handleBadgeClick(e: MouseEvent<HTMLInputElement>) {
Expand Down
13 changes: 1 addition & 12 deletions src/plugins/discover/public/application/angular/context_app.html
Original file line number Diff line number Diff line change
@@ -1,15 +1,3 @@
<kbn-top-nav
app-name="'context'"
show-search-bar="true"
show-filter-bar="true"
show-query-bar="false"
show-save-query="false"
show-date-picker="false"
index-patterns="[contextApp.indexPattern]"
use-default-behaviors="true"
>
</kbn-top-nav>

<!-- Context App Legacy -->
<context-app-legacy
filter="contextApp.actions.addFilter"
Expand All @@ -29,4 +17,5 @@
successor-available="contextApp.state.rows.successors.length"
successor-status="contextApp.state.loadingStatus.successors.status"
on-change-successor-count="contextApp.actions.fetchGivenSuccessorRows"
top-nav-menu="contextApp.topNavMenu"
></context-app-legacy>
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,14 @@ getAngularModule().directive('contextApp', function ContextApp() {
});

function ContextAppController($scope, Private) {
const { filterManager, indexPatterns, uiSettings } = getServices();
const { filterManager, indexPatterns, uiSettings, navigation } = getServices();
const queryParameterActions = getQueryParameterActions(filterManager, indexPatterns);
const queryActions = Private(QueryActionsProvider);
this.state = createInitialState(
parseInt(uiSettings.get(CONTEXT_STEP_SETTING), 10),
getFirstSortableField(this.indexPattern, uiSettings.get(CONTEXT_TIE_BREAKER_FIELDS_SETTING))
);
this.topNavMenu = navigation.ui.TopNavMenu;

this.actions = _.mapValues(
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,6 @@
* under the License.
*/

export { validateObject } from './validate_object';
import React from 'react';

export const TopNavMenuMock = () => <div>Hello World</div>;
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { DocTableLegacy } from '../../angular/doc_table/create_doc_table_react';
import { findTestSubject } from '@elastic/eui/lib/test';
import { ActionBar } from '../../angular/context/components/action_bar/action_bar';
import { ContextErrorMessage } from '../context_error_message';
import { TopNavMenuMock } from './__mocks__/top_nav_menu';

describe('ContextAppLegacy test', () => {
const hit = {
Expand Down Expand Up @@ -64,6 +65,17 @@ describe('ContextAppLegacy test', () => {
onChangeSuccessorCount: jest.fn(),
predecessorStatus: 'loaded',
successorStatus: 'loaded',
topNavMenu: TopNavMenuMock,
};
const topNavProps = {
appName: 'context',
showSearchBar: true,
showQueryBar: false,
showFilterBar: true,
showSaveQuery: false,
showDatePicker: false,
indexPatterns: [indexPattern],
useDefaultBehaviors: true,
};

it('renders correctly', () => {
Expand All @@ -72,6 +84,9 @@ describe('ContextAppLegacy test', () => {
const loadingIndicator = findTestSubject(component, 'contextApp_loadingIndicator');
expect(loadingIndicator.length).toBe(0);
expect(component.find(ActionBar).length).toBe(2);
const topNavMenu = component.find(TopNavMenuMock);
expect(topNavMenu.length).toBe(1);
expect(topNavMenu.props()).toStrictEqual(topNavProps);
});

it('renders loading indicator', () => {
Expand All @@ -82,6 +97,7 @@ describe('ContextAppLegacy test', () => {
const loadingIndicator = findTestSubject(component, 'contextApp_loadingIndicator');
expect(loadingIndicator.length).toBe(1);
expect(component.find(ActionBar).length).toBe(2);
expect(component.find(TopNavMenuMock).length).toBe(1);
});

it('renders error message', () => {
Expand All @@ -90,6 +106,7 @@ describe('ContextAppLegacy test', () => {
props.reason = 'something went wrong';
const component = mountWithIntl(<ContextAppLegacy {...props} />);
expect(component.find(DocTableLegacy).length).toBe(0);
expect(component.find(TopNavMenuMock).length).toBe(0);
const errorMessage = component.find(ContextErrorMessage);
expect(errorMessage.length).toBe(1);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,10 @@ import {
import { IIndexPattern, IndexPatternField } from '../../../../../data/common/index_patterns';
import { LOADING_STATUS } from './constants';
import { ActionBar, ActionBarProps } from '../../angular/context/components/action_bar/action_bar';
import { TopNavMenuProps } from '../../../../../navigation/public';

export interface ContextAppProps {
topNavMenu: React.ComponentType<TopNavMenuProps>;
columns: string[];
hits: Array<Record<string, unknown>>;
indexPattern: IIndexPattern;
Expand Down Expand Up @@ -96,6 +98,20 @@ export function ContextAppLegacy(renderProps: ContextAppProps) {
} as DocTableLegacyProps;
};

const TopNavMenu = renderProps.topNavMenu;
const getNavBarProps = () => {
return {
appName: 'context',
showSearchBar: true,
showQueryBar: false,
showFilterBar: true,
showSaveQuery: false,
showDatePicker: false,
indexPatterns: [renderProps.indexPattern],
useDefaultBehaviors: true,
};
};

const loadingFeedback = () => {
if (status === LOADING_STATUS.UNINITIALIZED || status === LOADING_STATUS.LOADING) {
return (
Expand All @@ -112,20 +128,23 @@ export function ContextAppLegacy(renderProps: ContextAppProps) {
{isFailed ? (
<ContextErrorMessage status={status} reason={renderProps.reason} />
) : (
<EuiPage>
<EuiPageContent paddingSize="s" className="dscCxtAppContent">
<ActionBar {...actionBarProps(PREDECESSOR_TYPE)} />
{loadingFeedback()}
<EuiHorizontalRule margin="xs" />
{isLoaded ? (
<div className="discover-table">
<DocTableLegacy {...docTableProps()} />
</div>
) : null}
<EuiHorizontalRule margin="xs" />
<ActionBar {...actionBarProps(SUCCESSOR_TYPE)} />
</EuiPageContent>
</EuiPage>
<div>
<TopNavMenu {...getNavBarProps()} />
<EuiPage>
<EuiPageContent paddingSize="s" className="dscCxtAppContent">
<ActionBar {...actionBarProps(PREDECESSOR_TYPE)} />
{loadingFeedback()}
<EuiHorizontalRule margin="xs" />
{isLoaded ? (
<div className="discover-table">
<DocTableLegacy {...docTableProps()} />
</div>
) : null}
<EuiHorizontalRule margin="xs" />
<ActionBar {...actionBarProps(SUCCESSOR_TYPE)} />
</EuiPageContent>
</EuiPage>
</div>
)}
</I18nProvider>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,6 @@ export function createContextAppLegacy(reactDirective: any) {
['successorAvailable', { watchDepth: 'reference' }],
['successorStatus', { watchDepth: 'reference' }],
['onChangeSuccessorCount', { watchDepth: 'reference' }],
['topNavMenu', { watchDepth: 'reference' }],
]);
}
11 changes: 0 additions & 11 deletions src/plugins/discover/public/get_inner_angular.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,6 @@ import {
PromiseServiceCreator,
registerListenEventListener,
watchMultiDecorator,
createTopNavDirective,
createTopNavHelper,
} from '../../kibana_legacy/public';
import { DiscoverStartPlugins } from './plugin';
import { getScopedHistory } from './kibana_services';
Expand Down Expand Up @@ -98,7 +96,6 @@ export function initializeInnerAngularModule(
createLocalI18nModule();
createLocalPrivateModule();
createLocalPromiseModule();
createLocalTopNavModule(navigation);
createLocalStorageModule();
createPagerFactoryModule();
createDocTableModule();
Expand Down Expand Up @@ -131,7 +128,6 @@ export function initializeInnerAngularModule(
'discoverI18n',
'discoverPrivate',
'discoverPromise',
'discoverTopNav',
'discoverLocalStorageProvider',
'discoverDocTable',
'discoverPagerFactory',
Expand All @@ -151,13 +147,6 @@ function createLocalPrivateModule() {
angular.module('discoverPrivate', []).provider('Private', PrivateProvider);
}

function createLocalTopNavModule(navigation: NavigationStart) {
angular
.module('discoverTopNav', ['react'])
.directive('kbnTopNav', createTopNavDirective)
.directive('kbnTopNavHelper', createTopNavHelper(navigation.ui));
}

function createLocalI18nModule() {
angular
.module('discoverI18n', [])
Expand Down
2 changes: 1 addition & 1 deletion src/plugins/navigation/public/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export function plugin(initializerContext: PluginInitializerContext) {
return new NavigationPublicPlugin(initializerContext);
}

export { TopNavMenuData, TopNavMenu } from './top_nav_menu';
export { TopNavMenuData, TopNavMenu, TopNavMenuProps } from './top_nav_menu';

export { NavigationPublicPluginSetup, NavigationPublicPluginStart } from './types';

Expand Down
9 changes: 9 additions & 0 deletions src/plugins/vis_type_timeseries/server/routes/vis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

import { IRouter, KibanaRequest } from 'kibana/server';
import { schema } from '@kbn/config-schema';
import { ensureNoUnsafeProperties } from '@kbn/std';
import { getVisData, GetVisDataOptions } from '../lib/get_vis_data';
import { visPayloadSchema } from '../../common/vis_schema';
import { ROUTES } from '../../common/constants';
Expand All @@ -40,6 +41,14 @@ export const visDataRoutes = (
},
},
async (requestContext, request, response) => {
try {
ensureNoUnsafeProperties(request.body);
} catch (error) {
return response.badRequest({
body: error.message,
});
}

try {
visPayloadSchema.validate(request.body);
} catch (error) {
Expand Down
Loading

0 comments on commit 133e674

Please sign in to comment.