): void;
+}
+
// @public
export interface IRouter {
delete: (route: RouteConfig
, handler: RequestHandler
) => void;
@@ -751,6 +759,22 @@ export type IsAuthenticated = (request: KibanaRequest | LegacyRequest) => boolea
// @public
export type IScopedClusterClient = Pick;
+// @public
+export interface IUiSettingsClient {
+ get: (key: string) => Promise;
+ getAll: () => Promise>;
+ getDefaults: () => Record;
+ getUserProvided: () => Promise>;
+ isOverridden: (key: string) => boolean;
+ remove: (key: string) => Promise;
+ removeMany: (keys: string[]) => Promise;
+ set: (key: string, value: T) => Promise;
+ setMany: (changes: Record) => Promise;
+}
+
// @public
export class KibanaRequest {
// @internal (undocumented)
@@ -1545,6 +1569,22 @@ export interface SessionStorageFactory {
asScoped: (request: KibanaRequest) => SessionStorage;
}
+// @public
+export interface UiSettingsParams {
+ category: string[];
+ description: string;
+ name: string;
+ optionLabels?: Record;
+ options?: string[];
+ readonly?: boolean;
+ requiresPageReload?: boolean;
+ type?: UiSettingsType;
+ value: SavedObjectAttribute;
+}
+
+// @public
+export type UiSettingsType = 'json' | 'markdown' | 'number' | 'select' | 'boolean' | 'string';
+
// Warnings were encountered during analysis:
//
diff --git a/src/core/server/server.ts b/src/core/server/server.ts
index 455bb97d47b57..3e4f5c2e5a813 100644
--- a/src/core/server/server.ts
+++ b/src/core/server/server.ts
@@ -25,6 +25,7 @@ import { ElasticsearchService, ElasticsearchServiceSetup } from './elasticsearch
import { HttpService, InternalHttpServiceSetup } from './http';
import { LegacyService } from './legacy';
import { Logger, LoggerFactory } from './logging';
+import { UiSettingsService } from './ui_settings';
import { PluginsService, config as pluginsConfig } from './plugins';
import { SavedObjectsService } from '../server/saved_objects';
@@ -34,6 +35,7 @@ import { config as loggingConfig } from './logging';
import { config as devConfig } from './dev';
import { config as kibanaConfig } from './kibana_config';
import { config as savedObjectsConfig } from './saved_objects';
+import { config as uiSettingsConfig } from './ui_settings';
import { mapToObject } from '../utils/';
import { ContextService } from './context';
import { SavedObjectsServiceSetup } from './saved_objects/saved_objects_service';
@@ -50,6 +52,7 @@ export class Server {
private readonly log: Logger;
private readonly plugins: PluginsService;
private readonly savedObjects: SavedObjectsService;
+ private readonly uiSettings: UiSettingsService;
constructor(
readonly config$: Observable,
@@ -66,6 +69,7 @@ export class Server {
this.legacy = new LegacyService(core);
this.elasticsearch = new ElasticsearchService(core);
this.savedObjects = new SavedObjectsService(core);
+ this.uiSettings = new UiSettingsService(core);
}
public async setup() {
@@ -89,10 +93,15 @@ export class Server {
http: httpSetup,
});
+ const uiSettingsSetup = await this.uiSettings.setup({
+ http: httpSetup,
+ });
+
const coreSetup = {
context: contextServiceSetup,
elasticsearch: elasticsearchServiceSetup,
http: httpSetup,
+ uiSettings: uiSettingsSetup,
};
const pluginsSetup = await this.plugins.setup(coreSetup);
@@ -184,6 +193,7 @@ export class Server {
[devConfig.path, devConfig.schema],
[kibanaConfig.path, kibanaConfig.schema],
[savedObjectsConfig.path, savedObjectsConfig.schema],
+ [uiSettingsConfig.path, uiSettingsConfig.schema],
];
for (const [path, schema] of schemas) {
diff --git a/src/legacy/ui/ui_settings/create_objects_client_stub.ts b/src/core/server/ui_settings/create_objects_client_stub.ts
similarity index 96%
rename from src/legacy/ui/ui_settings/create_objects_client_stub.ts
rename to src/core/server/ui_settings/create_objects_client_stub.ts
index ad19b5c8bc7cf..d52ec58fa7e37 100644
--- a/src/legacy/ui/ui_settings/create_objects_client_stub.ts
+++ b/src/core/server/ui_settings/create_objects_client_stub.ts
@@ -18,7 +18,7 @@
*/
import sinon from 'sinon';
-import { SavedObjectsClient } from '../../../../src/core/server';
+import { SavedObjectsClient } from '../saved_objects';
export const savedObjectsClientErrors = SavedObjectsClient.errors;
diff --git a/src/legacy/ui/ui_settings/create_or_upgrade_saved_config/create_or_upgrade_saved_config.test.ts b/src/core/server/ui_settings/create_or_upgrade_saved_config/create_or_upgrade_saved_config.test.ts
similarity index 87%
rename from src/legacy/ui/ui_settings/create_or_upgrade_saved_config/create_or_upgrade_saved_config.test.ts
rename to src/core/server/ui_settings/create_or_upgrade_saved_config/create_or_upgrade_saved_config.test.ts
index 654c0fbb66c8b..5f7e915365873 100644
--- a/src/legacy/ui/ui_settings/create_or_upgrade_saved_config/create_or_upgrade_saved_config.test.ts
+++ b/src/core/server/ui_settings/create_or_upgrade_saved_config/create_or_upgrade_saved_config.test.ts
@@ -18,14 +18,13 @@
*/
import sinon from 'sinon';
-import expect from '@kbn/expect';
import Chance from 'chance';
+import { loggingServiceMock } from '../../logging/logging_service.mock';
import * as getUpgradeableConfigNS from './get_upgradeable_config';
import { createOrUpgradeSavedConfig } from './create_or_upgrade_saved_config';
const chance = new Chance();
-
describe('uiSettings/createOrUpgradeSavedConfig', function() {
const sandbox = sinon.createSandbox();
afterEach(() => sandbox.restore());
@@ -35,7 +34,7 @@ describe('uiSettings/createOrUpgradeSavedConfig', function() {
const buildNum = chance.integer({ min: 1000, max: 5000 });
function setup() {
- const logWithMetadata = sinon.stub();
+ const logger = loggingServiceMock.create();
const getUpgradeableConfig = sandbox.stub(getUpgradeableConfigNS, 'getUpgradeableConfig');
const savedObjectsClient = {
create: sinon.stub().callsFake(async (type, attributes, options = {}) => ({
@@ -50,7 +49,7 @@ describe('uiSettings/createOrUpgradeSavedConfig', function() {
savedObjectsClient,
version,
buildNum,
- logWithMetadata,
+ log: logger.get(),
...options,
});
@@ -62,7 +61,7 @@ describe('uiSettings/createOrUpgradeSavedConfig', function() {
return {
buildNum,
- logWithMetadata,
+ logger,
run,
version,
savedObjectsClient,
@@ -126,7 +125,7 @@ describe('uiSettings/createOrUpgradeSavedConfig', function() {
});
it('should log a message for upgrades', async () => {
- const { getUpgradeableConfig, logWithMetadata, run } = setup();
+ const { getUpgradeableConfig, logger, run } = setup();
getUpgradeableConfig.resolves({
id: prevVersion,
@@ -136,20 +135,21 @@ describe('uiSettings/createOrUpgradeSavedConfig', function() {
});
await run();
- sinon.assert.calledOnce(logWithMetadata);
- sinon.assert.calledWithExactly(
- logWithMetadata,
- ['plugin', 'elasticsearch'],
- sinon.match('Upgrade'),
- sinon.match({
- prevVersion,
- newVersion: version,
- })
- );
+ expect(loggingServiceMock.collect(logger).debug).toMatchInlineSnapshot(`
+ Array [
+ Array [
+ "Upgrade config from 4.0.0 to 4.0.1",
+ Object {
+ "newVersion": "4.0.1",
+ "prevVersion": "4.0.0",
+ },
+ ],
+ ]
+ `);
});
it('does not log when upgrade fails', async () => {
- const { getUpgradeableConfig, logWithMetadata, run, savedObjectsClient } = setup();
+ const { getUpgradeableConfig, logger, run, savedObjectsClient } = setup();
getUpgradeableConfig.resolves({
id: prevVersion,
@@ -166,10 +166,10 @@ describe('uiSettings/createOrUpgradeSavedConfig', function() {
await run();
throw new Error('Expected run() to throw an error');
} catch (error) {
- expect(error.message).to.be('foo');
+ expect(error.message).toBe('foo');
}
- sinon.assert.notCalled(logWithMetadata);
+ expect(loggingServiceMock.collect(logger).debug).toHaveLength(0);
});
});
@@ -198,7 +198,7 @@ describe('uiSettings/createOrUpgradeSavedConfig', function() {
});
const result = await run({ onWriteError: () => 123 });
- expect(result).to.be(123);
+ expect(result).toBe(123);
});
it('rejects with the error from onWriteError() if it rejects', async () => {
@@ -214,7 +214,7 @@ describe('uiSettings/createOrUpgradeSavedConfig', function() {
});
throw new Error('expected run() to reject');
} catch (error) {
- expect(error.message).to.be('foo bar');
+ expect(error.message).toBe('foo bar');
}
});
@@ -233,7 +233,7 @@ describe('uiSettings/createOrUpgradeSavedConfig', function() {
});
throw new Error('expected run() to reject');
} catch (error) {
- expect(error.message).to.be('foo bar');
+ expect(error.message).toBe('foo bar');
}
});
@@ -250,7 +250,7 @@ describe('uiSettings/createOrUpgradeSavedConfig', function() {
});
throw new Error('expected run() to reject');
} catch (error) {
- expect(error.message).to.be('foo');
+ expect(error.message).toBe('foo');
}
});
});
diff --git a/src/legacy/ui/ui_settings/create_or_upgrade_saved_config/create_or_upgrade_saved_config.ts b/src/core/server/ui_settings/create_or_upgrade_saved_config/create_or_upgrade_saved_config.ts
similarity index 82%
rename from src/legacy/ui/ui_settings/create_or_upgrade_saved_config/create_or_upgrade_saved_config.ts
rename to src/core/server/ui_settings/create_or_upgrade_saved_config/create_or_upgrade_saved_config.ts
index 0dc3d5f50e97e..1655297adb6c9 100644
--- a/src/legacy/ui/ui_settings/create_or_upgrade_saved_config/create_or_upgrade_saved_config.ts
+++ b/src/core/server/ui_settings/create_or_upgrade_saved_config/create_or_upgrade_saved_config.ts
@@ -18,8 +18,9 @@
*/
import { defaults } from 'lodash';
-import { SavedObjectsClientContract, SavedObjectAttribute } from 'src/core/server';
-import { Legacy } from 'kibana';
+
+import { SavedObjectsClientContract, SavedObjectAttribute } from '../../saved_objects/types';
+import { Logger } from '../../logging';
import { getUpgradeableConfig } from './get_upgradeable_config';
@@ -27,7 +28,7 @@ interface Options {
savedObjectsClient: SavedObjectsClientContract;
version: string;
buildNum: number;
- logWithMetadata: Legacy.Server['logWithMetadata'];
+ log: Logger;
onWriteError?: (
error: Error,
attributes: Record
@@ -36,7 +37,7 @@ interface Options {
export async function createOrUpgradeSavedConfig(
options: Options
): Promise | undefined> {
- const { savedObjectsClient, version, buildNum, logWithMetadata, onWriteError } = options;
+ const { savedObjectsClient, version, buildNum, log, onWriteError } = options;
// try to find an older config we can upgrade
const upgradeableConfig = await getUpgradeableConfig({
@@ -59,13 +60,9 @@ export async function createOrUpgradeSavedConfig {
let savedObjectsClient: SavedObjectsClientContract;
let kbnServer: KbnServer;
@@ -88,7 +89,7 @@ describe('createOrUpgradeSavedConfig()', () => {
savedObjectsClient,
version: '5.4.0',
buildNum: 54099,
- logWithMetadata: sinon.stub(),
+ log: logger,
});
const config540 = await savedObjectsClient.get('config', '5.4.0');
@@ -114,7 +115,7 @@ describe('createOrUpgradeSavedConfig()', () => {
savedObjectsClient,
version: '5.4.1',
buildNum: 54199,
- logWithMetadata: sinon.stub(),
+ log: logger,
});
const config541 = await savedObjectsClient.get('config', '5.4.1');
@@ -140,7 +141,7 @@ describe('createOrUpgradeSavedConfig()', () => {
savedObjectsClient,
version: '7.0.0-rc1',
buildNum: 70010,
- logWithMetadata: sinon.stub(),
+ log: logger,
});
const config700rc1 = await savedObjectsClient.get('config', '7.0.0-rc1');
@@ -167,7 +168,7 @@ describe('createOrUpgradeSavedConfig()', () => {
savedObjectsClient,
version: '7.0.0',
buildNum: 70099,
- logWithMetadata: sinon.stub(),
+ log: logger,
});
const config700 = await savedObjectsClient.get('config', '7.0.0');
@@ -195,7 +196,7 @@ describe('createOrUpgradeSavedConfig()', () => {
savedObjectsClient,
version: '6.2.3-rc1',
buildNum: 62310,
- logWithMetadata: sinon.stub(),
+ log: logger,
});
const config623rc1 = await savedObjectsClient.get('config', '6.2.3-rc1');
diff --git a/src/legacy/ui/ui_settings/create_or_upgrade_saved_config/is_config_version_upgradeable.test.ts b/src/core/server/ui_settings/create_or_upgrade_saved_config/is_config_version_upgradeable.test.ts
similarity index 86%
rename from src/legacy/ui/ui_settings/create_or_upgrade_saved_config/is_config_version_upgradeable.test.ts
rename to src/core/server/ui_settings/create_or_upgrade_saved_config/is_config_version_upgradeable.test.ts
index 6bb2cb3b87850..073a6961fdec4 100644
--- a/src/legacy/ui/ui_settings/create_or_upgrade_saved_config/is_config_version_upgradeable.test.ts
+++ b/src/core/server/ui_settings/create_or_upgrade_saved_config/is_config_version_upgradeable.test.ts
@@ -20,8 +20,6 @@
import expect from '@kbn/expect';
import { isConfigVersionUpgradeable } from './is_config_version_upgradeable';
-// @ts-ignore
-import { pkg } from '../../../utils';
describe('savedObjects/health_check/isConfigVersionUpgradeable', function() {
function isUpgradeableTest(savedVersion: string, kibanaVersion: string, expected: boolean) {
@@ -30,10 +28,10 @@ describe('savedObjects/health_check/isConfigVersionUpgradeable', function() {
});
}
- isUpgradeableTest('1.0.0-beta1', pkg.version, false);
- isUpgradeableTest('1.0.0-beta256', pkg.version, false);
+ isUpgradeableTest('1.0.0-beta1', '7.4.0', false);
+ isUpgradeableTest('1.0.0-beta256', '7.4.0', false);
isUpgradeableTest('10.100.1000-beta256', '10.100.1000-beta257', false);
- isUpgradeableTest(pkg.version, pkg.version, false);
+ isUpgradeableTest('7.4.0', '7.4.0', false);
isUpgradeableTest('4.0.0-RC1', '4.0.0-RC2', true);
isUpgradeableTest('10.100.1000-rc256', '10.100.1000-RC257', true);
isUpgradeableTest('4.0.0-rc2', '4.0.0-rc1', false);
@@ -48,6 +46,6 @@ describe('savedObjects/health_check/isConfigVersionUpgradeable', function() {
isUpgradeableTest('4.1.0-rc1-SNAPSHOT', '4.1.0-rc1', false);
isUpgradeableTest('5.0.0-alpha11', '5.0.0', false);
isUpgradeableTest('50.0.10-rc150-SNAPSHOT', '50.0.9', false);
- isUpgradeableTest(undefined as any, pkg.version, false);
- isUpgradeableTest('@@version', pkg.version, false);
+ isUpgradeableTest(undefined as any, '7.4.0', false);
+ isUpgradeableTest('@@version', '7.4.0', false);
});
diff --git a/src/legacy/ui/ui_settings/create_or_upgrade_saved_config/is_config_version_upgradeable.ts b/src/core/server/ui_settings/create_or_upgrade_saved_config/is_config_version_upgradeable.ts
similarity index 100%
rename from src/legacy/ui/ui_settings/create_or_upgrade_saved_config/is_config_version_upgradeable.ts
rename to src/core/server/ui_settings/create_or_upgrade_saved_config/is_config_version_upgradeable.ts
diff --git a/src/core/server/ui_settings/index.ts b/src/core/server/ui_settings/index.ts
new file mode 100644
index 0000000000000..edd0bfc4f3a89
--- /dev/null
+++ b/src/core/server/ui_settings/index.ts
@@ -0,0 +1,32 @@
+/*
+ * 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 {
+ IUiSettingsClient,
+ UiSettingsClient,
+ UiSettingsServiceOptions,
+} from './ui_settings_client';
+
+export { config } from './ui_settings_config';
+export {
+ UiSettingsParams,
+ UiSettingsService,
+ InternalUiSettingsServiceSetup,
+ UiSettingsType,
+} from './ui_settings_service';
diff --git a/src/legacy/ui/ui_settings/ui_settings_service.test.ts b/src/core/server/ui_settings/ui_settings_client.test.ts
similarity index 94%
rename from src/legacy/ui/ui_settings/ui_settings_service.test.ts
rename to src/core/server/ui_settings/ui_settings_client.test.ts
index f37076b27ad6f..59c13fbebee70 100644
--- a/src/legacy/ui/ui_settings/ui_settings_service.test.ts
+++ b/src/core/server/ui_settings/ui_settings_client.test.ts
@@ -21,17 +21,20 @@ import expect from '@kbn/expect';
import Chance from 'chance';
import sinon from 'sinon';
-import { UiSettingsService } from './ui_settings_service';
+import { loggingServiceMock } from '../logging/logging_service.mock';
+
+import { UiSettingsClient } from './ui_settings_client';
import * as createOrUpgradeSavedConfigNS from './create_or_upgrade_saved_config/create_or_upgrade_saved_config';
import { createObjectsClientStub, savedObjectsClientErrors } from './create_objects_client_stub';
+const logger = loggingServiceMock.create().get();
+
const TYPE = 'config';
const ID = 'kibana-version';
const BUILD_NUM = 1234;
const chance = new Chance();
interface SetupOptions {
- getDefaults?: () => Record;
defaults?: Record;
esDocSource?: Record;
overrides?: Record;
@@ -41,17 +44,18 @@ describe('ui settings', () => {
const sandbox = sinon.createSandbox();
function setup(options: SetupOptions = {}) {
- const { getDefaults, defaults = {}, overrides = {}, esDocSource = {} } = options;
+ const { defaults = {}, overrides = {}, esDocSource = {} } = options;
const savedObjectsClient = createObjectsClientStub(esDocSource);
- const uiSettings = new UiSettingsService({
+ const uiSettings = new UiSettingsClient({
type: TYPE,
id: ID,
buildNum: BUILD_NUM,
- getDefaults: getDefaults || (() => defaults),
+ defaults,
savedObjectsClient,
overrides,
+ log: logger,
});
const createOrUpgradeSavedConfig = sandbox.stub(
@@ -239,25 +243,10 @@ describe('ui settings', () => {
});
describe('#getDefaults()', () => {
- it('returns a promise for the defaults', async () => {
- const { uiSettings } = setup();
- const promise = uiSettings.getDefaults();
- expect(promise).to.be.a(Promise);
- expect(await promise).to.eql({});
- });
- });
-
- describe('getDefaults() argument', () => {
- it('casts sync `getDefaults()` to promise', () => {
- const getDefaults = () => ({ key: { value: chance.word() } });
- const { uiSettings } = setup({ getDefaults });
- expect(uiSettings.getDefaults()).to.be.a(Promise);
- });
-
- it('returns the defaults returned by getDefaults() argument', async () => {
+ it('returns the defaults passed to the constructor', () => {
const value = chance.word();
const { uiSettings } = setup({ defaults: { key: { value } } });
- expect(await uiSettings.getDefaults()).to.eql({
+ expect(uiSettings.getDefaults()).to.eql({
key: { value },
});
});
diff --git a/src/legacy/ui/ui_settings/ui_settings_service.ts b/src/core/server/ui_settings/ui_settings_client.ts
similarity index 63%
rename from src/legacy/ui/ui_settings/ui_settings_service.ts
rename to src/core/server/ui_settings/ui_settings_client.ts
index 57312140b16b3..c495d1b4c4567 100644
--- a/src/legacy/ui/ui_settings/ui_settings_service.ts
+++ b/src/core/server/ui_settings/ui_settings_client.ts
@@ -16,12 +16,13 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { Legacy } from 'kibana';
import { defaultsDeep } from 'lodash';
import Boom from 'boom';
-import { SavedObjectsClientContract, SavedObjectAttribute } from 'src/core/server';
+import { SavedObjectsClientContract, SavedObjectAttribute } from '../saved_objects/types';
+import { Logger } from '../logging';
import { createOrUpgradeSavedConfig } from './create_or_upgrade_saved_config';
+import { UiSettingsParams } from './ui_settings_service';
export interface UiSettingsServiceOptions {
type: string;
@@ -29,8 +30,8 @@ export interface UiSettingsServiceOptions {
buildNum: number;
savedObjectsClient: SavedObjectsClientContract;
overrides?: Record;
- getDefaults?: () => Record;
- logWithMetadata?: Legacy.Server['logWithMetadata'];
+ defaults?: Record;
+ log: Logger;
}
interface ReadOptions {
@@ -38,82 +39,87 @@ interface ReadOptions {
autoCreateOrUpgradeIfMissing?: boolean;
}
-interface UserProvidedValue {
- userValue?: SavedObjectAttribute;
+interface UserProvidedValue {
+ userValue?: T;
isOverridden?: boolean;
}
type UiSettingsRawValue = UiSettingsParams & UserProvidedValue;
-type UserProvided = Record;
+type UserProvided = Record>;
type UiSettingsRaw = Record;
-type UiSettingsType = 'json' | 'markdown' | 'number' | 'select' | 'boolean' | 'string';
-
-interface UiSettingsParams {
- name: string;
- value: SavedObjectAttribute;
- description: string;
- category: string[];
- options?: string[];
- optionLabels?: Record;
- requiresPageReload?: boolean;
- readonly?: boolean;
- type?: UiSettingsType;
-}
-
+/**
+ * Service that provides access to the UiSettings stored in elasticsearch.
+ *
+ * @public
+ */
export interface IUiSettingsClient {
- getDefaults: () => Promise>;
+ /**
+ * Returns uiSettings default values {@link UiSettingsParams}
+ */
+ getDefaults: () => Record;
+ /**
+ * Retrieves uiSettings values set by the user with fallbacks to default values if not specified.
+ */
get: (key: string) => Promise;
+ /**
+ * Retrieves a set of all uiSettings values set by the user with fallbacks to default values if not specified.
+ */
getAll: () => Promise>;
- getUserProvided: () => Promise;
+ /**
+ * Retrieves a set of all uiSettings values set by the user.
+ */
+ getUserProvided: () => Promise<
+ Record
+ >;
+ /**
+ * Writes multiple uiSettings values and marks them as set by the user.
+ */
setMany: (changes: Record) => Promise;
+ /**
+ * Writes uiSettings value and marks it as set by the user.
+ */
set: (key: string, value: T) => Promise;
+ /**
+ * Removes uiSettings value by key.
+ */
remove: (key: string) => Promise;
+ /**
+ * Removes multiple uiSettings values by keys.
+ */
removeMany: (keys: string[]) => Promise;
+ /**
+ * Shows whether the uiSettings value set by the user.
+ */
isOverridden: (key: string) => boolean;
}
-/**
- * Service that provides access to the UiSettings stored in elasticsearch.
- * @class UiSettingsService
- */
-export class UiSettingsService implements IUiSettingsClient {
- private readonly _type: UiSettingsServiceOptions['type'];
- private readonly _id: UiSettingsServiceOptions['id'];
- private readonly _buildNum: UiSettingsServiceOptions['buildNum'];
- private readonly _savedObjectsClient: UiSettingsServiceOptions['savedObjectsClient'];
- private readonly _overrides: NonNullable;
- private readonly _getDefaults: NonNullable;
- private readonly _logWithMetadata: NonNullable;
+
+export class UiSettingsClient implements IUiSettingsClient {
+ private readonly type: UiSettingsServiceOptions['type'];
+ private readonly id: UiSettingsServiceOptions['id'];
+ private readonly buildNum: UiSettingsServiceOptions['buildNum'];
+ private readonly savedObjectsClient: UiSettingsServiceOptions['savedObjectsClient'];
+ private readonly overrides: NonNullable;
+ private readonly defaults: NonNullable;
+ private readonly log: Logger;
constructor(options: UiSettingsServiceOptions) {
- const {
- type,
- id,
- buildNum,
- savedObjectsClient,
- // we use a function for getDefaults() so that defaults can be different in
- // different scenarios, and so they can change over time
- getDefaults = () => ({}),
- // function that accepts log messages in the same format as server.logWithMetadata
- logWithMetadata = () => {},
- overrides = {},
- } = options;
-
- this._type = type;
- this._id = id;
- this._buildNum = buildNum;
- this._savedObjectsClient = savedObjectsClient;
- this._getDefaults = getDefaults;
- this._overrides = overrides;
- this._logWithMetadata = logWithMetadata;
+ const { type, id, buildNum, savedObjectsClient, log, defaults = {}, overrides = {} } = options;
+
+ this.type = type;
+ this.id = id;
+ this.buildNum = buildNum;
+ this.savedObjectsClient = savedObjectsClient;
+ this.defaults = defaults;
+ this.overrides = overrides;
+ this.log = log;
}
- async getDefaults() {
- return await this._getDefaults();
+ getDefaults() {
+ return this.defaults;
}
- // returns a Promise for the value of the requested setting
async get(key: string): Promise {
const all = await this.getAll();
return all[key];
@@ -135,14 +141,16 @@ export class UiSettingsService implements IUiSettingsClient {
// NOTE: should be a private method
async getRaw(): Promise {
const userProvided = await this.getUserProvided();
- return defaultsDeep(userProvided, await this.getDefaults());
+ return defaultsDeep(userProvided, this.defaults);
}
- async getUserProvided(options: ReadOptions = {}): Promise {
+ async getUserProvided(
+ options: ReadOptions = {}
+ ): Promise> {
const userProvided: UserProvided = {};
// write the userValue for each key stored in the saved object that is not overridden
- for (const [key, userValue] of Object.entries(await this._read(options))) {
+ for (const [key, userValue] of Object.entries(await this.read(options))) {
if (userValue !== null && !this.isOverridden(key)) {
userProvided[key] = {
userValue,
@@ -152,7 +160,7 @@ export class UiSettingsService implements IUiSettingsClient {
// write all overridden keys, dropping the userValue is override is null and
// adding keys for overrides that are not in saved object
- for (const [key, userValue] of Object.entries(this._overrides)) {
+ for (const [key, userValue] of Object.entries(this.overrides)) {
userProvided[key] =
userValue === null ? { isOverridden: true } : { isOverridden: true, userValue };
}
@@ -161,7 +169,7 @@ export class UiSettingsService implements IUiSettingsClient {
}
async setMany(changes: Record) {
- await this._write({ changes });
+ await this.write({ changes });
}
async set(key: string, value: T) {
@@ -181,7 +189,7 @@ export class UiSettingsService implements IUiSettingsClient {
}
isOverridden(key: string) {
- return this._overrides.hasOwnProperty(key);
+ return this.overrides.hasOwnProperty(key);
}
// NOTE: should be private method
@@ -191,7 +199,7 @@ export class UiSettingsService implements IUiSettingsClient {
}
}
- private async _write({
+ private async write({
changes,
autoCreateOrUpgradeIfMissing = true,
}: {
@@ -203,28 +211,28 @@ export class UiSettingsService implements IUiSettingsClient {
}
try {
- await this._savedObjectsClient.update(this._type, this._id, changes);
+ await this.savedObjectsClient.update(this.type, this.id, changes);
} catch (error) {
- const { isNotFoundError } = this._savedObjectsClient.errors;
+ const { isNotFoundError } = this.savedObjectsClient.errors;
if (!isNotFoundError(error) || !autoCreateOrUpgradeIfMissing) {
throw error;
}
await createOrUpgradeSavedConfig({
- savedObjectsClient: this._savedObjectsClient,
- version: this._id,
- buildNum: this._buildNum,
- logWithMetadata: this._logWithMetadata,
+ savedObjectsClient: this.savedObjectsClient,
+ version: this.id,
+ buildNum: this.buildNum,
+ log: this.log,
});
- await this._write({
+ await this.write({
changes,
autoCreateOrUpgradeIfMissing: false,
});
}
}
- private async _read({
+ private async read({
ignore401Errors = false,
autoCreateOrUpgradeIfMissing = true,
}: ReadOptions = {}): Promise> {
@@ -233,18 +241,18 @@ export class UiSettingsService implements IUiSettingsClient {
isNotFoundError,
isForbiddenError,
isNotAuthorizedError,
- } = this._savedObjectsClient.errors;
+ } = this.savedObjectsClient.errors;
try {
- const resp = await this._savedObjectsClient.get(this._type, this._id);
+ const resp = await this.savedObjectsClient.get(this.type, this.id);
return resp.attributes;
} catch (error) {
if (isNotFoundError(error) && autoCreateOrUpgradeIfMissing) {
const failedUpgradeAttributes = await createOrUpgradeSavedConfig({
- savedObjectsClient: this._savedObjectsClient,
- version: this._id,
- buildNum: this._buildNum,
- logWithMetadata: this._logWithMetadata,
+ savedObjectsClient: this.savedObjectsClient,
+ version: this.id,
+ buildNum: this.buildNum,
+ log: this.log,
onWriteError(writeError, attributes) {
if (isConflictError(writeError)) {
// trigger `!failedUpgradeAttributes` check below, since another
@@ -262,7 +270,7 @@ export class UiSettingsService implements IUiSettingsClient {
});
if (!failedUpgradeAttributes) {
- return await this._read({
+ return await this.read({
ignore401Errors,
autoCreateOrUpgradeIfMissing: false,
});
@@ -284,7 +292,7 @@ export class UiSettingsService implements IUiSettingsClient {
isForbiddenError,
isEsUnavailableError,
isNotAuthorizedError,
- } = this._savedObjectsClient.errors;
+ } = this.savedObjectsClient.errors;
return (
isForbiddenError(error) ||
diff --git a/src/core/server/ui_settings/ui_settings_config.ts b/src/core/server/ui_settings/ui_settings_config.ts
new file mode 100644
index 0000000000000..702286f953ef1
--- /dev/null
+++ b/src/core/server/ui_settings/ui_settings_config.ts
@@ -0,0 +1,32 @@
+/*
+ * 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 { schema, TypeOf } from '@kbn/config-schema';
+
+export type UiSettingsConfigType = TypeOf;
+
+export const config = {
+ path: 'uiSettings',
+ schema: schema.object({
+ overrides: schema.object({}, { allowUnknowns: true }),
+ // Deprecation is implemented in LP.
+ // We define schema here not to fail on the validation step.
+ enabled: schema.maybe(schema.boolean()),
+ }),
+};
diff --git a/src/legacy/ui/ui_settings/ui_settings_service.mock.ts b/src/core/server/ui_settings/ui_settings_service.mock.ts
similarity index 71%
rename from src/legacy/ui/ui_settings/ui_settings_service.mock.ts
rename to src/core/server/ui_settings/ui_settings_service.mock.ts
index 7c1a17ebd447c..2127faf0d2029 100644
--- a/src/legacy/ui/ui_settings/ui_settings_service.mock.ts
+++ b/src/core/server/ui_settings/ui_settings_service.mock.ts
@@ -17,9 +17,10 @@
* under the License.
*/
-import { IUiSettingsClient } from './ui_settings_service';
+import { IUiSettingsClient } from './ui_settings_client';
+import { InternalUiSettingsServiceSetup } from './ui_settings_service';
-const createServiceMock = () => {
+const createClientMock = () => {
const mocked: jest.Mocked = {
getDefaults: jest.fn(),
get: jest.fn(),
@@ -35,6 +36,18 @@ const createServiceMock = () => {
return mocked;
};
+const createSetupMock = () => {
+ const mocked: jest.Mocked = {
+ setDefaults: jest.fn(),
+ asScopedToClient: jest.fn(),
+ };
+
+ mocked.asScopedToClient.mockReturnValue(createClientMock());
+
+ return mocked;
+};
+
export const uiSettingsServiceMock = {
- create: createServiceMock,
+ createSetup: createSetupMock,
+ createClient: createClientMock,
};
diff --git a/src/core/server/ui_settings/ui_settings_service.test.mock.ts b/src/core/server/ui_settings/ui_settings_service.test.mock.ts
new file mode 100644
index 0000000000000..586ad3049ed6a
--- /dev/null
+++ b/src/core/server/ui_settings/ui_settings_service.test.mock.ts
@@ -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.
+ */
+
+export const MockUiSettingsClientConstructor = jest.fn();
+
+jest.doMock('./ui_settings_client', () => ({
+ UiSettingsClient: MockUiSettingsClientConstructor,
+}));
diff --git a/src/core/server/ui_settings/ui_settings_service.test.ts b/src/core/server/ui_settings/ui_settings_service.test.ts
new file mode 100644
index 0000000000000..832d61bdb4137
--- /dev/null
+++ b/src/core/server/ui_settings/ui_settings_service.test.ts
@@ -0,0 +1,109 @@
+/*
+ * 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 { BehaviorSubject } from 'rxjs';
+
+import { MockUiSettingsClientConstructor } from './ui_settings_service.test.mock';
+
+import { UiSettingsService } from './ui_settings_service';
+import { httpServiceMock } from '../http/http_service.mock';
+import { loggingServiceMock } from '../logging/logging_service.mock';
+import { SavedObjectsClientMock } from '../mocks';
+import { mockCoreContext } from '../core_context.mock';
+
+const overrides = {
+ overrideBaz: 'baz',
+};
+
+const defaults = {
+ foo: {
+ name: 'foo',
+ value: 'bar',
+ category: [],
+ description: '',
+ },
+};
+
+const coreContext = mockCoreContext.create();
+coreContext.configService.atPath.mockReturnValue(new BehaviorSubject({ overrides }));
+const httpSetup = httpServiceMock.createSetupContract();
+const setupDeps = { http: httpSetup };
+const savedObjectsClient = SavedObjectsClientMock.create();
+
+afterEach(() => {
+ MockUiSettingsClientConstructor.mockClear();
+});
+
+describe('uiSettings', () => {
+ describe('#setup', () => {
+ describe('#asScopedToClient', () => {
+ it('passes overrides to UiSettingsClient', async () => {
+ const service = new UiSettingsService(coreContext);
+ const setup = await service.setup(setupDeps);
+ setup.asScopedToClient(savedObjectsClient);
+ expect(MockUiSettingsClientConstructor).toBeCalledTimes(1);
+ expect(MockUiSettingsClientConstructor.mock.calls[0][0].overrides).toBe(overrides);
+ expect(MockUiSettingsClientConstructor.mock.calls[0][0].overrides).toEqual(overrides);
+ });
+
+ it('passes overrides with deprecated "server.defaultRoute"', async () => {
+ const service = new UiSettingsService(coreContext);
+ const httpSetupWithDefaultRoute = httpServiceMock.createSetupContract();
+ httpSetupWithDefaultRoute.config.defaultRoute = '/defaultRoute';
+ const setup = await service.setup({ http: httpSetupWithDefaultRoute });
+ setup.asScopedToClient(savedObjectsClient);
+
+ expect(MockUiSettingsClientConstructor.mock.calls[0][0].overrides).toEqual({
+ ...overrides,
+ defaultRoute: '/defaultRoute',
+ });
+
+ expect(loggingServiceMock.collect(coreContext.logger).warn).toMatchInlineSnapshot(`
+ Array [
+ Array [
+ "Config key \\"server.defaultRoute\\" is deprecated. It has been replaced with \\"uiSettings.overrides.defaultRoute\\"",
+ ],
+ ]
+ `);
+ });
+
+ it('passes a copy of set defaults to UiSettingsClient', async () => {
+ const service = new UiSettingsService(coreContext);
+ const setup = await service.setup(setupDeps);
+
+ setup.setDefaults(defaults);
+ setup.asScopedToClient(savedObjectsClient);
+ expect(MockUiSettingsClientConstructor).toBeCalledTimes(1);
+
+ expect(MockUiSettingsClientConstructor.mock.calls[0][0].defaults).toEqual(defaults);
+ expect(MockUiSettingsClientConstructor.mock.calls[0][0].defaults).not.toBe(defaults);
+ });
+ });
+
+ describe('#setDefaults', () => {
+ it('throws if set defaults for the same key twice', async () => {
+ const service = new UiSettingsService(coreContext);
+ const setup = await service.setup(setupDeps);
+ setup.setDefaults(defaults);
+ expect(() => setup.setDefaults(defaults)).toThrowErrorMatchingInlineSnapshot(
+ `"uiSettings defaults for key [foo] has been already set"`
+ );
+ });
+ });
+ });
+});
diff --git a/src/core/server/ui_settings/ui_settings_service.ts b/src/core/server/ui_settings/ui_settings_service.ts
new file mode 100644
index 0000000000000..746fa514c5d4b
--- /dev/null
+++ b/src/core/server/ui_settings/ui_settings_service.ts
@@ -0,0 +1,140 @@
+/*
+ * 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 { Observable } from 'rxjs';
+import { first } from 'rxjs/operators';
+import { CoreService } from '../../types';
+import { CoreContext } from '../core_context';
+import { Logger } from '../logging';
+
+import { SavedObjectsClientContract, SavedObjectAttribute } from '../saved_objects/types';
+import { InternalHttpServiceSetup } from '../http';
+import { UiSettingsConfigType } from './ui_settings_config';
+import { IUiSettingsClient, UiSettingsClient } from './ui_settings_client';
+import { mapToObject } from '../../utils/';
+
+interface SetupDeps {
+ http: InternalHttpServiceSetup;
+}
+
+/**
+ * UI element type to represent the settings.
+ * @public
+ * */
+export type UiSettingsType = 'json' | 'markdown' | 'number' | 'select' | 'boolean' | 'string';
+
+/**
+ * UiSettings parameters defined by the plugins.
+ * @public
+ * */
+export interface UiSettingsParams {
+ /** title in the UI */
+ name: string;
+ /** default value to fall back to if a user doesn't provide any */
+ value: SavedObjectAttribute;
+ /** description provided to a user in UI */
+ description: string;
+ /** used to group the configured setting in the UI */
+ category: string[];
+ /** a range of valid values */
+ options?: string[];
+ /** text labels for 'select' type UI element */
+ optionLabels?: Record;
+ /** a flag indicating whether new value applying requires page reloading */
+ requiresPageReload?: boolean;
+ /** a flag indicating that value cannot be changed */
+ readonly?: boolean;
+ /** defines a type of UI element {@link UiSettingsType} */
+ type?: UiSettingsType;
+}
+
+/** @internal */
+export interface InternalUiSettingsServiceSetup {
+ /**
+ * Sets the parameters with default values for the uiSettings.
+ * @param values
+ */
+ setDefaults(values: Record): void;
+ /**
+ * Creates uiSettings client with provided *scoped* saved objects client {@link IUiSettingsClient}
+ * @param values
+ */
+ asScopedToClient(savedObjectsClient: SavedObjectsClientContract): IUiSettingsClient;
+}
+
+/** @internal */
+export class UiSettingsService implements CoreService {
+ private readonly log: Logger;
+ private readonly config$: Observable;
+ private readonly uiSettingsDefaults = new Map();
+
+ constructor(private readonly coreContext: CoreContext) {
+ this.log = coreContext.logger.get('ui-settings-service');
+ this.config$ = coreContext.configService.atPath('uiSettings');
+ }
+
+ public async setup(deps: SetupDeps): Promise {
+ this.log.debug('Setting up ui settings service');
+ const overrides = await this.getOverrides(deps);
+ const { version, buildNum } = this.coreContext.env.packageInfo;
+
+ return {
+ setDefaults: this.setDefaults.bind(this),
+ asScopedToClient: (savedObjectsClient: SavedObjectsClientContract) => {
+ return new UiSettingsClient({
+ type: 'config',
+ id: version,
+ buildNum,
+ savedObjectsClient,
+ defaults: mapToObject(this.uiSettingsDefaults),
+ overrides,
+ log: this.log,
+ });
+ },
+ };
+ }
+
+ public async start() {}
+
+ public async stop() {}
+
+ private setDefaults(values: Record = {}) {
+ Object.entries(values).forEach(([key, value]) => {
+ if (this.uiSettingsDefaults.has(key)) {
+ throw new Error(`uiSettings defaults for key [${key}] has been already set`);
+ }
+ this.uiSettingsDefaults.set(key, value);
+ });
+ }
+
+ private async getOverrides(deps: SetupDeps) {
+ const config = await this.config$.pipe(first()).toPromise();
+ const overrides: Record = config.overrides;
+ // manually implemented deprecation until New platform Config service
+ // supports them https://github.com/elastic/kibana/issues/40255
+ if (typeof deps.http.config.defaultRoute !== 'undefined') {
+ overrides.defaultRoute = deps.http.config.defaultRoute;
+ this.log.warn(
+ 'Config key "server.defaultRoute" is deprecated. It has been replaced with "uiSettings.overrides.defaultRoute"'
+ );
+ }
+
+ return overrides;
+ }
+}
diff --git a/src/legacy/server/config/schema.js b/src/legacy/server/config/schema.js
index 1d74fc63bcc0f..3f9b897730f51 100644
--- a/src/legacy/server/config/schema.js
+++ b/src/legacy/server/config/schema.js
@@ -108,9 +108,7 @@ export default () => Joi.object({
ssl: HANDLED_IN_NEW_PLATFORM,
}).default(),
- uiSettings: Joi.object().keys({
- overrides: Joi.object().unknown(true).default()
- }).default(),
+ uiSettings: HANDLED_IN_NEW_PLATFORM,
logging: Joi.object().keys({
silent: Joi.boolean().default(false),
diff --git a/src/legacy/server/config/transform_deprecations.js b/src/legacy/server/config/transform_deprecations.js
index 8be880074f9fd..7cac17a88fe64 100644
--- a/src/legacy/server/config/transform_deprecations.js
+++ b/src/legacy/server/config/transform_deprecations.js
@@ -95,7 +95,6 @@ const cspRules = (settings, log) => {
const deprecations = [
//server
- rename('server.defaultRoute', 'uiSettings.overrides.defaultRoute'),
unused('server.xsrf.token'),
unused('uiSettings.enabled'),
rename('optimize.lazy', 'optimize.watch'),
diff --git a/src/legacy/server/config/transform_deprecations.test.js b/src/legacy/server/config/transform_deprecations.test.js
index 4094443ac0006..f8cf38efc8bd8 100644
--- a/src/legacy/server/config/transform_deprecations.test.js
+++ b/src/legacy/server/config/transform_deprecations.test.js
@@ -62,24 +62,6 @@ describe('server/config', function () {
});
});
- describe('server.defaultRoute', () => {
- it('renames to uiSettings.overrides.defaultRoute when specified', () => {
- const settings = {
- server: {
- defaultRoute: '/app/foo',
- },
- };
-
- expect(transformDeprecations(settings)).toEqual({
- uiSettings: {
- overrides: {
- defaultRoute: '/app/foo'
- }
- }
- });
- });
- });
-
describe('csp.rules', () => {
describe('with nonce source', () => {
it('logs a warning', () => {
diff --git a/src/legacy/server/http/integration_tests/default_route_provider.test.ts b/src/legacy/server/http/integration_tests/default_route_provider.test.ts
index fe8c464965132..d74be851a3535 100644
--- a/src/legacy/server/http/integration_tests/default_route_provider.test.ts
+++ b/src/legacy/server/http/integration_tests/default_route_provider.test.ts
@@ -45,11 +45,11 @@ describe('default route provider', () => {
throw Error(`unsupported ui setting: ${key}`);
},
getDefaults: () => {
- return Promise.resolve({
+ return {
defaultRoute: {
value: '/app/kibana',
},
- });
+ };
},
};
});
diff --git a/src/legacy/server/http/setup_default_route_provider.ts b/src/legacy/server/http/setup_default_route_provider.ts
index 07ff61015a187..f627cf30a3cff 100644
--- a/src/legacy/server/http/setup_default_route_provider.ts
+++ b/src/legacy/server/http/setup_default_route_provider.ts
@@ -40,7 +40,7 @@ export function setupDefaultRouteProvider(server: Legacy.Server) {
`Ignoring configured default route of '${defaultRoute}', as it is malformed.`
);
- const fallbackRoute = (await uiSettings.getDefaults()).defaultRoute.value;
+ const fallbackRoute = uiSettings.getDefaults().defaultRoute.value;
const qualifiedFallbackRoute = `${request.getBasePath()}${fallbackRoute}`;
return qualifiedFallbackRoute;
diff --git a/src/legacy/server/kbn_server.d.ts b/src/legacy/server/kbn_server.d.ts
index f5771c6b86d9a..e7f2f4c85435f 100644
--- a/src/legacy/server/kbn_server.d.ts
+++ b/src/legacy/server/kbn_server.d.ts
@@ -28,6 +28,7 @@ import {
LoggerFactory,
SavedObjectsClientContract,
SavedObjectsLegacyService,
+ IUiSettingsClient,
PackageInfo,
} from '../../core/server';
@@ -41,7 +42,6 @@ import { CallClusterWithRequest, ElasticsearchPlugin } from '../core_plugins/ela
import { CapabilitiesModifier } from './capabilities';
import { IndexPatternsServiceFactory } from './index_patterns';
import { Capabilities } from '../../core/public';
-import { IUiSettingsClient } from '../../legacy/ui/ui_settings/ui_settings_service';
import { UiSettingsServiceFactoryOptions } from '../../legacy/ui/ui_settings/ui_settings_service_factory';
export interface KibanaConfig {
@@ -104,6 +104,13 @@ type KbnMixinFunc = (kbnServer: KbnServer, server: Server, config: any) => Promi
// eslint-disable-next-line import/no-default-export
export default class KbnServer {
public readonly newPlatform: {
+ __internals: {
+ hapiServer: LegacyServiceSetupDeps['core']['http']['server'];
+ uiPlugins: LegacyServiceSetupDeps['core']['plugins']['uiPlugins'];
+ elasticsearch: LegacyServiceSetupDeps['core']['elasticsearch'];
+ uiSettings: LegacyServiceSetupDeps['core']['uiSettings'];
+ kibanaMigrator: LegacyServiceStartDeps['core']['savedObjects']['migrator'];
+ };
env: {
mode: Readonly;
packageInfo: Readonly;
diff --git a/src/legacy/ui/field_formats/mixin/field_formats_mixin.ts b/src/legacy/ui/field_formats/mixin/field_formats_mixin.ts
index 3720677ec17d2..f9a5c25878322 100644
--- a/src/legacy/ui/field_formats/mixin/field_formats_mixin.ts
+++ b/src/legacy/ui/field_formats/mixin/field_formats_mixin.ts
@@ -28,7 +28,7 @@ export function fieldFormatsMixin(kbnServer: any, server: Legacy.Server) {
// for use outside of the request context, for special cases
server.decorate('server', 'fieldFormatServiceFactory', async function(uiSettings) {
const uiConfigs = await uiSettings.getAll();
- const uiSettingDefaults = await uiSettings.getDefaults();
+ const uiSettingDefaults = uiSettings.getDefaults();
Object.keys(uiSettingDefaults).forEach(key => {
if (has(uiConfigs, key) && uiSettingDefaults[key].type === 'json') {
uiConfigs[key] = JSON.parse(uiConfigs[key]);
diff --git a/src/legacy/ui/ui_settings/integration_tests/ui_settings_mixin.test.ts b/src/legacy/ui/ui_settings/integration_tests/ui_settings_mixin.test.ts
index f43c6436d1c33..9f553b37935d7 100644
--- a/src/legacy/ui/ui_settings/integration_tests/ui_settings_mixin.test.ts
+++ b/src/legacy/ui/ui_settings/integration_tests/ui_settings_mixin.test.ts
@@ -20,9 +20,7 @@
import sinon from 'sinon';
import expect from '@kbn/expect';
-// @ts-ignore
-import { Config } from '../../../server/config';
-
+import { SavedObjectsClientMock } from '../../../../core/server/mocks';
import * as uiSettingsServiceFactoryNS from '../ui_settings_service_factory';
import * as getUiSettingsServiceForRequestNS from '../ui_settings_service_for_request';
// @ts-ignore
@@ -33,18 +31,16 @@ interface Decorators {
request: { [name: string]: any };
}
+const uiSettingDefaults = {
+ application: {
+ defaultProperty1: 'value1',
+ },
+};
+
describe('uiSettingsMixin()', () => {
const sandbox = sinon.createSandbox();
function setup() {
- const config = Config.withDefaultSchema({
- uiSettings: {
- overrides: {
- foo: 'bar',
- },
- },
- });
-
// maps of decorations passed to `server.decorate()`
const decorations: Decorators = {
server: {},
@@ -55,7 +51,6 @@ describe('uiSettingsMixin()', () => {
const server = {
log: sinon.stub(),
route: sinon.stub(),
- config: () => config,
addMemoizedFactoryToRequest(name: string, factory: (...args: any[]) => any) {
this.decorate('request', name, function(this: typeof server) {
return factory(this);
@@ -73,12 +68,18 @@ describe('uiSettingsMixin()', () => {
const kbnServer = {
server,
- config,
- uiExports: { addConsumer: sinon.stub() },
+ uiExports: { uiSettingDefaults },
ready: sinon.stub().returns(readyPromise),
+ newPlatform: {
+ __internals: {
+ uiSettings: {
+ setDefaults: sinon.stub(),
+ },
+ },
+ },
};
- uiSettingsMixin(kbnServer, server, config);
+ uiSettingsMixin(kbnServer, server);
return {
kbnServer,
@@ -90,6 +91,15 @@ describe('uiSettingsMixin()', () => {
afterEach(() => sandbox.restore());
+ it('passes uiSettingsDefaults to the new platform', () => {
+ const { kbnServer } = setup();
+ sinon.assert.calledOnce(kbnServer.newPlatform.__internals.uiSettings.setDefaults);
+ sinon.assert.calledWithExactly(
+ kbnServer.newPlatform.__internals.uiSettings.setDefaults,
+ uiSettingDefaults
+ );
+ });
+
describe('server.uiSettingsServiceFactory()', () => {
it('decorates server with "uiSettingsServiceFactory"', () => {
const { decorations } = setup();
@@ -116,18 +126,16 @@ describe('uiSettingsMixin()', () => {
uiSettingsServiceFactoryNS,
'uiSettingsServiceFactory'
);
+
sinon.assert.notCalled(uiSettingsServiceFactoryStub);
+
+ const savedObjectsClient = SavedObjectsClientMock.create();
decorations.server.uiSettingsServiceFactory({
- foo: 'bar',
+ savedObjectsClient,
});
sinon.assert.calledOnce(uiSettingsServiceFactoryStub);
sinon.assert.calledWithExactly(uiSettingsServiceFactoryStub, server as any, {
- // @ts-ignore foo doesn't exist on Hapi.Server
- foo: 'bar',
- overrides: {
- foo: 'bar',
- },
- getDefaults: sinon.match.func,
+ savedObjectsClient,
});
});
});
@@ -161,12 +169,7 @@ describe('uiSettingsMixin()', () => {
sinon.assert.notCalled(getUiSettingsServiceForRequestStub);
const request = {};
decorations.request.getUiSettingsService.call(request);
- sinon.assert.calledWith(getUiSettingsServiceForRequestStub, server as any, request as any, {
- overrides: {
- foo: 'bar',
- },
- getDefaults: sinon.match.func,
- });
+ sinon.assert.calledWith(getUiSettingsServiceForRequestStub, server as any, request as any);
});
});
diff --git a/src/legacy/ui/ui_settings/routes/integration_tests/lib/servers.ts b/src/legacy/ui/ui_settings/routes/integration_tests/lib/servers.ts
index b076a2a86e166..ae0ef1c91411e 100644
--- a/src/legacy/ui/ui_settings/routes/integration_tests/lib/servers.ts
+++ b/src/legacy/ui/ui_settings/routes/integration_tests/lib/servers.ts
@@ -18,12 +18,11 @@
*/
import { UnwrapPromise } from '@kbn/utility-types';
-import { SavedObjectsClientContract } from 'src/core/server';
+import { SavedObjectsClientContract, IUiSettingsClient } from 'src/core/server';
import KbnServer from '../../../../../server/kbn_server';
import { createTestServers } from '../../../../../../test_utils/kbn_server';
import { CallCluster } from '../../../../../../legacy/core_plugins/elasticsearch';
-import { IUiSettingsClient } from '../../../ui_settings_service';
let kbnServer: KbnServer;
let servers: ReturnType;
diff --git a/src/legacy/ui/ui_settings/ui_settings_mixin.js b/src/legacy/ui/ui_settings/ui_settings_mixin.js
index 3683ba5dd265e..8c7ef25c6f8d7 100644
--- a/src/legacy/ui/ui_settings/ui_settings_mixin.js
+++ b/src/legacy/ui/ui_settings/ui_settings_mixin.js
@@ -42,22 +42,15 @@ export function uiSettingsMixin(kbnServer, server) {
acc[currentKey] = updatedDefaultSetting;
return acc;
}, {});
- const getDefaults = () => mergedUiSettingDefaults;
- const overrides = kbnServer.config.get('uiSettings.overrides');
+
+ kbnServer.newPlatform.__internals.uiSettings.setDefaults(mergedUiSettingDefaults);
server.decorate('server', 'uiSettingsServiceFactory', (options = {}) => {
- return uiSettingsServiceFactory(server, {
- getDefaults,
- overrides,
- ...options
- });
+ return uiSettingsServiceFactory(server, options);
});
server.addMemoizedFactoryToRequest('getUiSettingsService', request => {
- return getUiSettingsServiceForRequest(server, request, {
- getDefaults,
- overrides,
- });
+ return getUiSettingsServiceForRequest(server, request);
});
server.decorate('server', 'uiSettings', () => {
diff --git a/src/legacy/ui/ui_settings/ui_settings_service_factory.ts b/src/legacy/ui/ui_settings/ui_settings_service_factory.ts
index 9e1384494161c..ab4eb75e4b703 100644
--- a/src/legacy/ui/ui_settings/ui_settings_service_factory.ts
+++ b/src/legacy/ui/ui_settings/ui_settings_service_factory.ts
@@ -17,18 +17,13 @@
* under the License.
*/
import { Legacy } from 'kibana';
-import {
- IUiSettingsClient,
- UiSettingsService,
- UiSettingsServiceOptions,
-} from './ui_settings_service';
+import { IUiSettingsClient, SavedObjectsClientContract } from 'src/core/server';
-export type UiSettingsServiceFactoryOptions = Pick<
- UiSettingsServiceOptions,
- 'savedObjectsClient' | 'getDefaults' | 'overrides'
->;
+export interface UiSettingsServiceFactoryOptions {
+ savedObjectsClient: SavedObjectsClientContract;
+}
/**
- * Create an instance of UiSettingsService that will use the
+ * Create an instance of UiSettingsClient that will use the
* passed `savedObjectsClient` to communicate with elasticsearch
*
* @return {IUiSettingsClient}
@@ -37,17 +32,5 @@ export function uiSettingsServiceFactory(
server: Legacy.Server,
options: UiSettingsServiceFactoryOptions
): IUiSettingsClient {
- const config = server.config();
-
- const { savedObjectsClient, getDefaults, overrides } = options;
-
- return new UiSettingsService({
- type: 'config',
- id: config.get('pkg.version'),
- buildNum: config.get('pkg.buildNum'),
- savedObjectsClient,
- getDefaults,
- overrides,
- logWithMetadata: server.logWithMetadata,
- });
+ return server.newPlatform.__internals.uiSettings.asScopedToClient(options.savedObjectsClient);
}
diff --git a/src/legacy/ui/ui_settings/ui_settings_service_for_request.ts b/src/legacy/ui/ui_settings/ui_settings_service_for_request.ts
index e265ad5f1e115..057fc64c9ebd7 100644
--- a/src/legacy/ui/ui_settings/ui_settings_service_for_request.ts
+++ b/src/legacy/ui/ui_settings/ui_settings_service_for_request.ts
@@ -18,10 +18,9 @@
*/
import { Legacy } from 'kibana';
+import { IUiSettingsClient } from 'src/core/server';
import { uiSettingsServiceFactory } from './ui_settings_service_factory';
-import { IUiSettingsClient, UiSettingsServiceOptions } from './ui_settings_service';
-type Options = Pick;
/**
* Get/create an instance of UiSettingsService bound to a specific request.
* Each call is cached (keyed on the request object itself) and subsequent
@@ -36,16 +35,8 @@ type Options = Pick;
*/
export function getUiSettingsServiceForRequest(
server: Legacy.Server,
- request: Legacy.Request,
- options: Options
+ request: Legacy.Request
): IUiSettingsClient {
- const { getDefaults, overrides } = options;
-
- const uiSettingsService = uiSettingsServiceFactory(server, {
- getDefaults,
- overrides,
- savedObjectsClient: request.getSavedObjectsClient(),
- });
-
- return uiSettingsService;
+ const savedObjectsClient = request.getSavedObjectsClient();
+ return uiSettingsServiceFactory(server, { savedObjectsClient });
}
diff --git a/x-pack/legacy/plugins/apm/server/lib/helpers/setup_request.test.ts b/x-pack/legacy/plugins/apm/server/lib/helpers/setup_request.test.ts
index 6edac00b8a1ab..cfc33b4fad7ea 100644
--- a/x-pack/legacy/plugins/apm/server/lib/helpers/setup_request.test.ts
+++ b/x-pack/legacy/plugins/apm/server/lib/helpers/setup_request.test.ts
@@ -6,7 +6,7 @@
import { Legacy } from 'kibana';
import { setupRequest } from './setup_request';
-import { uiSettingsServiceMock } from '../../../../../../../src/legacy/ui/ui_settings/ui_settings_service.mock';
+import { uiSettingsServiceMock } from 'src/core/server/mocks';
function getMockRequest() {
const callWithRequestSpy = jest.fn();
@@ -125,7 +125,7 @@ describe('setupRequest', () => {
it('should set `ignore_throttled=true` if `includeFrozen=false`', async () => {
const { mockRequest, callWithRequestSpy } = getMockRequest();
- const uiSettingsService = uiSettingsServiceMock.create();
+ const uiSettingsService = uiSettingsServiceMock.createClient();
// mock includeFrozen to return false
uiSettingsService.get.mockResolvedValue(false);
mockRequest.getUiSettingsService = () => uiSettingsService;
@@ -138,7 +138,7 @@ describe('setupRequest', () => {
it('should set `ignore_throttled=false` if `includeFrozen=true`', async () => {
const { mockRequest, callWithRequestSpy } = getMockRequest();
- const uiSettingsService = uiSettingsServiceMock.create();
+ const uiSettingsService = uiSettingsServiceMock.createClient();
// mock includeFrozen to return true
uiSettingsService.get.mockResolvedValue(true);
mockRequest.getUiSettingsService = () => uiSettingsService;
diff --git a/x-pack/legacy/plugins/ml/common/types/modules.ts b/x-pack/legacy/plugins/ml/common/types/modules.ts
index cb012c3641f3b..18879304d7c7f 100644
--- a/x-pack/legacy/plugins/ml/common/types/modules.ts
+++ b/x-pack/legacy/plugins/ml/common/types/modules.ts
@@ -3,9 +3,8 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
-
+import { SavedObjectAttributes } from 'src/core/server/types';
import { Datafeed, Job } from '../../public/jobs/new_job_new/common/job_creator/configs';
-import { SavedObjectAttributes } from '../../../../../../target/types/core/server';
export interface ModuleJob {
id: string;