Skip to content

Commit

Permalink
Move url state_hashing utils to kibana_utils
Browse files Browse the repository at this point in the history
Get back old error handling behaviour if hashed url was shared directly

add missing types

improve
  • Loading branch information
Dosant committed Dec 5, 2019
1 parent 05fd394 commit 283c1b1
Show file tree
Hide file tree
Showing 23 changed files with 158 additions and 49 deletions.
1 change: 1 addition & 0 deletions .i18nrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"kbnVislibVisTypes": "src/legacy/core_plugins/kbn_vislib_vis_types",
"kibana_react": "src/legacy/core_plugins/kibana_react",
"kibana-react": "src/plugins/kibana_react",
"kibana_utils": "src/plugins/kibana_utils",
"navigation": "src/legacy/core_plugins/navigation",
"newsfeed": "src/plugins/newsfeed",
"regionMap": "src/legacy/core_plugins/region_map",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ import {
KbnUrl,
SaveOptions,
SavedObjectFinder,
unhashUrl,
StateManagement,
} from './legacy_imports';
import { FilterStateManager, IndexPattern } from '../../../data/public';
import { Query, SavedQuery, IndexPatterns } from '../../../../../plugins/data/public';
Expand Down Expand Up @@ -747,7 +747,7 @@ export class DashboardAppController {
anchorElement,
allowEmbed: true,
allowShortUrl: !dashboardConfig.getHideWriteControls(),
shareableUrl: unhashUrl(window.location.href),
shareableUrl: StateManagement.Url.unhashUrl(window.location.href),
objectId: dash.id,
objectType: 'dashboard',
sharingData: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,6 @@ export { confirmModalFactory } from 'ui/modals/confirm_modal';
export { configureAppAngularModule } from 'ui/legacy_compat';
export { stateMonitorFactory, StateMonitor } from 'ui/state_management/state_monitor_factory';
export { ensureDefaultIndexPattern } from 'ui/legacy_compat';
export { unhashUrl } from 'ui/state_management/state_hashing';
export { StateManagement } from '../../../../../plugins/kibana_utils/public';
export { IInjector } from 'ui/chrome';
export { SavedObjectFinder } from 'ui/saved_objects/components/saved_object_finder';
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ import {
migrateLegacyQuery,
RequestAdapter,
showSaveModal,
unhashUrl,
StateManagement,
stateMonitorFactory,
subscribeWithScope,
tabifyAggResponse,
Expand Down Expand Up @@ -330,7 +330,7 @@ function discoverController(
anchorElement,
allowEmbed: false,
allowShortUrl: uiCapabilities.discover.createShortUrl,
shareableUrl: unhashUrl(window.location.href),
shareableUrl: StateManagement.Url.unhashUrl(window.location.href),
objectId: savedSearch.id,
objectType: 'search',
sharingData: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export { tabifyAggResponse } from 'ui/agg_response/tabify';
// @ts-ignore
export { vislibSeriesResponseHandlerProvider } from 'ui/vis/response_handlers/vislib';
export { ensureDefaultIndexPattern } from 'ui/legacy_compat';
export { unhashUrl } from 'ui/state_management/state_hashing';
export { StateManagement } from '../../../../../plugins/kibana_utils/public';

// EXPORT types
export { Vis } from 'ui/vis';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ import {
showSaveModal,
stateMonitorFactory,
subscribeWithScope,
unhashUrl,
StateManagement
} from '../kibana_services';

const {
Expand Down Expand Up @@ -248,7 +248,7 @@ function VisEditor(
anchorElement,
allowEmbed: true,
allowShortUrl: capabilities.visualize.createShortUrl,
shareableUrl: unhashUrl(window.location.href),
shareableUrl: StateManagement.Url.unhashUrl(window.location.href),
objectId: savedVis.id,
objectType: 'visualization',
sharingData: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ export { KibanaParsedUrl } from 'ui/url/kibana_parsed_url';
export { migrateLegacyQuery } from 'ui/utils/migrate_legacy_query';
export { subscribeWithScope } from 'ui/utils/subscribe_with_scope';
export { SavedObjectSaveModal } from 'ui/saved_objects/components/saved_object_save_modal';
export { unhashUrl } from 'ui/state_management/state_hashing';
export { StateManagement } from '../../../../../plugins/kibana_utils/public';
export {
Container,
Embeddable,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
*/

import chrome from 'ui/chrome';
import { hashUrl } from 'ui/state_management/state_hashing';
import { StateManagement } from '../../../../plugins/kibana_utils/public';
import uiRoutes from 'ui/routes';
import { fatalError } from 'ui/notify';

Expand All @@ -29,7 +29,7 @@ uiRoutes
url: function (AppState, globalState, $window) {
const redirectUrl = chrome.getInjected('redirectUrl');
try {
const hashedUrl = hashUrl(redirectUrl);
const hashedUrl = StateManagement.Url.hashUrl(redirectUrl);
const url = chrome.addBasePath(hashedUrl);

$window.location = url;
Expand Down
15 changes: 10 additions & 5 deletions src/legacy/ui/public/chrome/api/sub_url_hooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,23 @@

import url from 'url';

import {
unhashUrl,
} from '../../state_management/state_hashing';
import { StateManagement } from '../../../../../plugins/kibana_utils/public';
import { toastNotifications } from '../../notify/toasts';

export function registerSubUrlHooks(angularModule, internals) {
angularModule.run(($rootScope, Private, $location) => {
const subUrlRouteFilter = Private(SubUrlRouteFilterProvider);

function updateSubUrls() {
const urlWithHashes = window.location.href;
const urlWithStates = unhashUrl(urlWithHashes);
internals.trackPossibleSubUrl(urlWithStates);
let urlWithStates;
try {
urlWithStates = StateManagement.Url.unhashUrl(urlWithHashes);
} catch (e) {
toastNotifications.addDanger(e.message);
}

internals.trackPossibleSubUrl(urlWithStates || urlWithHashes);
}

function onRouteChange($event) {
Expand Down
20 changes: 9 additions & 11 deletions src/legacy/ui/public/state_management/__tests__/state.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,9 @@ import { toastNotifications } from '../../notify';
import * as FatalErrorNS from '../../notify/fatal_error';
import { StateProvider } from '../state';
import {
createStateHash,
isStateHash,
unhashQuery
} from '../state_hashing';
import { HashedItemStore } from '../../../../../plugins/kibana_utils/public';
StateManagement,
HashedItemStore
} from '../../../../../plugins/kibana_utils/public';
import { StubBrowserStorage } from 'test_utils/stub_browser_storage';
import { EventsProvider } from '../../events';

Expand Down Expand Up @@ -58,7 +56,7 @@ describe('State Management', () => {
const hashedItemStore = new HashedItemStore(store);
const state = new State(param, initial, hashedItemStore);

const getUnhashedSearch = () => unhashQuery($location.search());
const getUnhashedSearch = () => StateManagement.Url.unhashQuery($location.search());

return { store, hashedItemStore, state, getUnhashedSearch };
};
Expand Down Expand Up @@ -248,7 +246,7 @@ describe('State Management', () => {
state.save();
const urlVal = $location.search()[state.getQueryParamName()];

expect(isStateHash(urlVal)).to.be(true);
expect(StateManagement.StateHash.isStateHash(urlVal)).to.be(true);
expect(hashedItemStore.getItem(urlVal)).to.eql(JSON.stringify({ foo: 'bar' }));
});

Expand All @@ -262,7 +260,7 @@ describe('State Management', () => {

const urlVal = $location.search()._s;
expect(urlVal).to.not.be(rison);
expect(isStateHash(urlVal)).to.be(true);
expect(StateManagement.StateHash.isStateHash(urlVal)).to.be(true);
expect(hashedItemStore.getItem(urlVal)).to.eql(JSON.stringify(obj));
});

Expand All @@ -278,7 +276,7 @@ describe('State Management', () => {

const { state } = setup({ storeInHash: true });
const search = $location.search();
const badHash = createStateHash('{"a": "b"}', () => null);
const badHash = StateManagement.StateHash.createStateHash('{"a": "b"}', () => null);

search[state.getQueryParamName()] = badHash;
$location.search(search);
Expand Down Expand Up @@ -315,10 +313,10 @@ describe('State Management', () => {
expect(state.translateHashToRison('(a:b)')).to.be('(a:b)');
expect(state.translateHashToRison('')).to.be('');

const existingHash = createStateHash('{"a": "b"}', () => null);
const existingHash = StateManagement.StateHash.createStateHash('{"a": "b"}', () => null);
hashedItemStore.setItem(existingHash, '{"a": "b"}');

const nonExistingHash = createStateHash('{"b": "c"}', () => null);
const nonExistingHash = StateManagement.StateHash.createStateHash('{"b": "c"}', () => null);

expect(state.translateHashToRison(existingHash)).to.be('(a:b)');
expect(state.translateHashToRison(nonExistingHash)).to.be('!n');
Expand Down
12 changes: 4 additions & 8 deletions src/legacy/ui/public/state_management/state.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,7 @@ import { fatalError, toastNotifications } from '../notify';
import './config_provider';
import { createLegacyClass } from '../utils/legacy_class';
import { callEach } from '../utils/function';
import { hashedItemStore } from '../../../../plugins/kibana_utils/public';
import {
createStateHash,
isStateHash
} from './state_hashing';
import { hashedItemStore, StateManagement } from '../../../../plugins/kibana_utils/public';

export function StateProvider(Private, $rootScope, $location, stateManagementConfig, config, kbnUrl, $injector) {
const Events = Private(EventsProvider);
Expand Down Expand Up @@ -95,7 +91,7 @@ export function StateProvider(Private, $rootScope, $location, stateManagementCon
return null;
}

if (isStateHash(urlVal)) {
if (StateManagement.StateHash.isStateHash(urlVal)) {
return this._parseStateHash(urlVal);
}

Expand Down Expand Up @@ -269,7 +265,7 @@ export function StateProvider(Private, $rootScope, $location, stateManagementCon
* @return {string} rison
*/
State.prototype.translateHashToRison = function (stateHashOrRison) {
if (isStateHash(stateHashOrRison)) {
if (StateManagement.StateHash.isStateHash(stateHashOrRison)) {
return rison.encode(this._parseStateHash(stateHashOrRison));
}

Expand All @@ -292,7 +288,7 @@ export function StateProvider(Private, $rootScope, $location, stateManagementCon

// We need to strip out Angular-specific properties.
const json = angular.toJson(state);
const hash = createStateHash(json);
const hash = StateManagement.StateHash.createStateHash(json);
const isItemSet = this._hashedItemStore.setItem(hash, json);

if (isItemSet) {
Expand Down
2 changes: 2 additions & 0 deletions src/plugins/kibana_utils/public/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,5 @@ export * from './errors';
export * from './field_mapping';
export * from './storage';
export * from './storage/hashed_item_store';
import * as StateManagement from './state_management';
export { StateManagement };
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,7 @@
* under the License.
*/

export { hashUrl, unhashUrl, hashQuery, unhashQuery } from './hash_unhash_url';
export { createStateHash, isStateHash } from './state_hash';
import * as Url from './url';
import * as StateHash from './state_hash';

export { Url, StateHash };
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* 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.
*/

export * from './state_hash';
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,8 @@
*/

import { encode as encodeRison } from 'rison-node';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { mockStorage } from '../../../../../plugins/kibana_utils/public/storage/hashed_item_store/mock';
import { createStateHash, isStateHash } from '../state_hashing';
import { mockStorage } from '../../storage/hashed_item_store/mock';
import { createStateHash, isStateHash } from './state_hash';

describe('stateHash', () => {
beforeEach(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
*/

import { Sha256 } from '../../../../../core/public/utils';
import { hashedItemStore } from '../../../../../plugins/kibana_utils/public';
import { hashedItemStore } from '../../storage/hashed_item_store';

// This prefix is used to identify hash strings that have been encoded in the URL.
const HASH_PREFIX = 'h@';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,8 @@
* under the License.
*/

// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { mockStorage } from '../../../../../plugins/kibana_utils/public/storage/hashed_item_store/mock';
import { HashedItemStore } from '../../../../../plugins/kibana_utils/public';
import { mockStorage } from '../../storage/hashed_item_store/mock';
import { HashedItemStore } from '../../storage/hashed_item_store';
import { hashUrl, unhashUrl } from './hash_unhash_url';

describe('hash unhash url', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ import rison, { RisonObject } from 'rison-node';
import { stringify as stringifyQueryString } from 'querystring';
import encodeUriQuery from 'encode-uri-query';
import { format as formatUrl, parse as parseUrl } from 'url';
import { hashedItemStore } from '../../../../../plugins/kibana_utils/public';
import { createStateHash, isStateHash } from './state_hash';
import { hashedItemStore } from '../../storage/hashed_item_store';
import { createStateHash, isStateHash } from '../state_hash';

export type IParsedUrlQuery = Record<string, any>;

Expand Down Expand Up @@ -98,7 +98,7 @@ export function retrieveState(stateHash: string): RisonObject {
const json = hashedItemStore.getItem(stateHash);
const throwUnableToRestoreUrlError = () => {
throw new Error(
i18n.translate('common.ui.stateManagement.unableToRestoreUrlErrorMessage', {
i18n.translate('kibana_utils.stateManagement.url.unableToRestoreUrlErrorMessage', {
defaultMessage:
'Unable to completely restore the URL, be sure to use the share functionality.',
})
Expand All @@ -125,7 +125,7 @@ export function persistState(state: RisonObject): string {
if (isItemSet) return hash;
// If we ran out of space trying to persist the state, notify the user.
const message = i18n.translate(
'common.ui.stateManagement.unableToStoreHistoryInSessionErrorMessage',
'kibana_utils.stateManagement.url.unableToStoreHistoryInSessionErrorMessage',
{
defaultMessage:
'Kibana is unable to store history items in your session ' +
Expand Down
20 changes: 20 additions & 0 deletions src/plugins/kibana_utils/public/state_management/url/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* 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.
*/

export * from './hash_unhash_url';
24 changes: 24 additions & 0 deletions test/typings/encode_uri_query.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* 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.
*/

declare module 'encode-uri-query' {
function encodeUriQuery(query: string, usePercentageSpace?: boolean): string;
// eslint-disable-next-line import/no-default-export
export default encodeUriQuery;
}
Loading

0 comments on commit 283c1b1

Please sign in to comment.