Validate incoming url timerange (#70948)

* validate incoming url timerange

* adjust discover test

* fix tests

* stabilize tests

* oops

Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
This commit is contained in:
Liza Katz 2020-07-13 13:47:12 +03:00 committed by GitHub
parent 639f8b7ca2
commit 3fc8c7af25
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 98 additions and 14 deletions

View file

@ -1991,7 +1991,7 @@ export const UI_SETTINGS: {
// src/plugins/data/public/index.ts:393:1 - (ae-forgotten-export) The symbol "parseInterval" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:394:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:397:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/query/state_sync/connect_to_query_state.ts:40:60 - (ae-forgotten-export) The symbol "FilterStateStore" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/query/state_sync/connect_to_query_state.ts:41:60 - (ae-forgotten-export) The symbol "FilterStateStore" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/types.ts:52:5 - (ae-forgotten-export) The symbol "createFiltersFromValueClickAction" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/types.ts:53:5 - (ae-forgotten-export) The symbol "createFiltersFromRangeSelectAction" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/types.ts:61:5 - (ae-forgotten-export) The symbol "IndexPatternSelectProps" needs to be exported by the entry point index.d.ts

View file

@ -24,6 +24,7 @@ import { BaseStateContainer } from '../../../../kibana_utils/public';
import { QuerySetup, QueryStart } from '../query_service';
import { QueryState, QueryStateChange } from './types';
import { FilterStateStore, COMPARE_ALL_OPTIONS, compareFilters } from '../../../common';
import { validateTimeRange } from '../timefilter';
/**
* Helper to setup two-way syncing of global data and a state container
@ -159,9 +160,9 @@ export const connectToQueryState = <S extends QueryState>(
// cloneDeep is required because services are mutating passed objects
// and state in state container is frozen
if (syncConfig.time) {
const time = state.time || timefilter.getTimeDefaults();
const time = validateTimeRange(state.time) ? state.time : timefilter.getTimeDefaults();
if (!_.isEqual(time, timefilter.getTime())) {
timefilter.setTime(_.cloneDeep(time));
timefilter.setTime(_.cloneDeep(time!));
}
}

View file

@ -24,3 +24,4 @@ export { Timefilter, TimefilterContract } from './timefilter';
export { TimeHistory, TimeHistoryContract } from './time_history';
export { changeTimeFilter, convertRangeFilterToTimeRangeString } from './lib/change_time_filter';
export { extractTimeFilter } from './lib/extract_time_filter';
export { validateTimeRange } from './lib/validate_timerange';

View file

@ -0,0 +1,52 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { validateTimeRange } from './validate_timerange';
describe('Validate timerange', () => {
test('Validate no range', () => {
const ok = validateTimeRange();
expect(ok).toBe(false);
});
test('normal range', () => {
const ok = validateTimeRange({
to: 'now',
from: 'now-7d',
});
expect(ok).toBe(true);
});
test('bad from time', () => {
const ok = validateTimeRange({
to: 'nowa',
from: 'now-7d',
});
expect(ok).toBe(false);
});
test('bad to time', () => {
const ok = validateTimeRange({
to: 'now',
from: 'nowa-7d',
});
expect(ok).toBe(false);
});
});

View file

@ -0,0 +1,28 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import dateMath from '@elastic/datemath';
import { TimeRange } from '../../../../common';
export function validateTimeRange(time?: TimeRange): boolean {
if (!time) return false;
const momentDateFrom = dateMath.parse(time.from);
const momentDateTo = dateMath.parse(time.to);
return !!(momentDateFrom && momentDateFrom.isValid() && momentDateTo && momentDateTo.isValid());
}

View file

@ -254,6 +254,19 @@ export default function ({ getService, getPageObjects }) {
});
});
describe('invalid time range in URL', function () {
it('should get the default timerange', async function () {
const prevTime = await PageObjects.timePicker.getTimeConfig();
await PageObjects.common.navigateToUrl('discover', '#/?_g=(time:(from:now-15m,to:null))', {
useActualUrl: true,
});
await PageObjects.header.awaitKibanaChrome();
const time = await PageObjects.timePicker.getTimeConfig();
expect(time.start).to.be(prevTime.start);
expect(time.end).to.be(prevTime.end);
});
});
describe('empty query', function () {
it('should update the histogram timerange when the query is resubmitted', async function () {
await kibanaServer.uiSettings.update({
@ -268,17 +281,6 @@ export default function ({ getService, getPageObjects }) {
});
});
describe('invalid time range in URL', function () {
it('should display a "Invalid time range toast"', async function () {
await PageObjects.common.navigateToUrl('discover', '#/?_g=(time:(from:now-15m,to:null))', {
useActualUrl: true,
});
await PageObjects.header.awaitKibanaChrome();
const toastMessage = await PageObjects.common.closeToast();
expect(toastMessage).to.be('Invalid time range');
});
});
describe('managing fields', function () {
it('should add a field, sort by it, remove it and also sorting by it', async function () {
await PageObjects.timePicker.setDefaultAbsoluteRangeViaUiSettings();