mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
adapt Core userSettings
service to no longer depends on the security
plugin (#181538)
## Summary Part of https://github.com/elastic/kibana/issues/174578 Adapt Core's `userSettings` service to leverage Core's `userProfile` service instead of the `security` plugin --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
2f5897a70c
commit
8bf0c419cc
22 changed files with 201 additions and 496 deletions
|
@ -272,9 +272,7 @@ export function createPluginSetupContext<TPlugin, TPluginDependencies>({
|
|||
registerGlobal: deps.uiSettings.registerGlobal,
|
||||
setAllowlist: deps.uiSettings.setAllowlist,
|
||||
},
|
||||
userSettings: {
|
||||
setUserProfileSettings: deps.userSettings.setUserProfileSettings,
|
||||
},
|
||||
userSettings: {},
|
||||
getStartServices: () => plugin.startDependencies,
|
||||
deprecations: deps.deprecations.getRegistry(plugin.name),
|
||||
coreUsageData: {
|
||||
|
|
|
@ -129,7 +129,7 @@ describe('bootstrapRenderer', () => {
|
|||
});
|
||||
|
||||
it('calls getThemeTag with values (true/dark) from the UserSettingsService when provided', async () => {
|
||||
userSettingsService.getUserSettingDarkMode.mockReturnValueOnce(true);
|
||||
userSettingsService.getUserSettingDarkMode.mockResolvedValueOnce(true);
|
||||
|
||||
renderer = bootstrapRendererFactory({
|
||||
auth,
|
||||
|
@ -155,7 +155,7 @@ describe('bootstrapRenderer', () => {
|
|||
});
|
||||
|
||||
it('calls getThemeTag with values (false/light) from the UserSettingsService when provided', async () => {
|
||||
userSettingsService.getUserSettingDarkMode.mockReturnValueOnce(false);
|
||||
userSettingsService.getUserSettingDarkMode.mockResolvedValueOnce(false);
|
||||
|
||||
renderer = bootstrapRendererFactory({
|
||||
auth,
|
||||
|
@ -181,7 +181,7 @@ describe('bootstrapRenderer', () => {
|
|||
});
|
||||
|
||||
it('calls getThemeTag with values from the UiSettingsClient when values (false/light) from UserSettingsService are `undefined`', async () => {
|
||||
userSettingsService.getUserSettingDarkMode.mockReturnValueOnce(undefined);
|
||||
userSettingsService.getUserSettingDarkMode.mockResolvedValueOnce(undefined);
|
||||
|
||||
renderer = bootstrapRendererFactory({
|
||||
auth,
|
||||
|
@ -207,7 +207,7 @@ describe('bootstrapRenderer', () => {
|
|||
});
|
||||
|
||||
it('calls getThemeTag with values from the UiSettingsClient when values (true/dark) from UserSettingsService are `undefined`', async () => {
|
||||
userSettingsService.getUserSettingDarkMode.mockReturnValueOnce(undefined);
|
||||
userSettingsService.getUserSettingDarkMode.mockResolvedValueOnce(undefined);
|
||||
|
||||
renderer = bootstrapRendererFactory({
|
||||
auth,
|
||||
|
|
|
@ -219,6 +219,7 @@ test('runs services on "start"', async () => {
|
|||
expect(mockCustomBrandingService.start).toHaveBeenCalledTimes(1);
|
||||
expect(mockSecurityService.start).toHaveBeenCalledTimes(1);
|
||||
expect(mockUserProfileService.start).toHaveBeenCalledTimes(1);
|
||||
expect(mockUserSettingsService.start).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
test('does not fail on "setup" if there are unused paths detected', async () => {
|
||||
|
|
|
@ -386,6 +386,7 @@ export class Server {
|
|||
const analyticsStart = this.analytics.start();
|
||||
const securityStart = this.security.start();
|
||||
const userProfileStart = this.userProfile.start();
|
||||
this.userSettingsService.start({ userProfile: userProfileStart });
|
||||
const executionContextStart = this.executionContext.start();
|
||||
const docLinkStart = this.docLinks.start();
|
||||
|
||||
|
|
|
@ -6,5 +6,5 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
export { UserSettingsService } from './user_settings_service';
|
||||
export type { InternalUserSettingsServiceSetup } from './user_settings_service';
|
||||
export { UserSettingsService } from './src/user_settings_service';
|
||||
export type { InternalUserSettingsServiceSetup } from './src/user_settings_service';
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { mockCoreContext } from '@kbn/core-base-server-mocks';
|
||||
import { httpServerMock } from '@kbn/core-http-server-mocks';
|
||||
import { userProfileServiceMock } from '@kbn/core-user-profile-server-mocks';
|
||||
import type { UserProfileWithSecurity } from '@kbn/core-user-profile-common';
|
||||
import { UserSettingsService } from './user_settings_service';
|
||||
|
||||
describe('#setup', () => {
|
||||
let coreContext: ReturnType<typeof mockCoreContext.create>;
|
||||
let service: UserSettingsService;
|
||||
let startDeps: { userProfile: ReturnType<typeof userProfileServiceMock.createInternalStart> };
|
||||
|
||||
beforeEach(() => {
|
||||
coreContext = mockCoreContext.create();
|
||||
service = new UserSettingsService(coreContext);
|
||||
startDeps = {
|
||||
userProfile: userProfileServiceMock.createInternalStart(),
|
||||
};
|
||||
});
|
||||
|
||||
const createUserProfile = (darkMode: string | undefined): UserProfileWithSecurity => {
|
||||
return {
|
||||
data: {
|
||||
userSettings: {
|
||||
darkMode,
|
||||
},
|
||||
},
|
||||
} as unknown as UserProfileWithSecurity;
|
||||
};
|
||||
|
||||
it('fetches userSettings when client is set and returns `true` when `darkMode` is set to `dark`', async () => {
|
||||
startDeps.userProfile.getCurrent.mockResolvedValue(createUserProfile('dark'));
|
||||
|
||||
const { getUserSettingDarkMode } = service.setup();
|
||||
service.start(startDeps);
|
||||
|
||||
const kibanaRequest = httpServerMock.createKibanaRequest();
|
||||
const darkMode = await getUserSettingDarkMode(kibanaRequest);
|
||||
|
||||
expect(darkMode).toEqual(true);
|
||||
expect(startDeps.userProfile.getCurrent).toHaveBeenCalledTimes(1);
|
||||
expect(startDeps.userProfile.getCurrent).toHaveBeenCalledWith({
|
||||
request: kibanaRequest,
|
||||
dataPath: 'userSettings',
|
||||
});
|
||||
});
|
||||
|
||||
it('fetches userSettings when client is set and returns `false` when `darkMode` is set to `light`', async () => {
|
||||
startDeps.userProfile.getCurrent.mockResolvedValue(createUserProfile('light'));
|
||||
|
||||
const { getUserSettingDarkMode } = service.setup();
|
||||
service.start(startDeps);
|
||||
|
||||
const kibanaRequest = httpServerMock.createKibanaRequest();
|
||||
const darkMode = await getUserSettingDarkMode(kibanaRequest);
|
||||
|
||||
expect(darkMode).toEqual(false);
|
||||
expect(startDeps.userProfile.getCurrent).toHaveBeenCalledTimes(1);
|
||||
expect(startDeps.userProfile.getCurrent).toHaveBeenCalledWith({
|
||||
request: kibanaRequest,
|
||||
dataPath: 'userSettings',
|
||||
});
|
||||
});
|
||||
|
||||
it('fetches userSettings when client is set and returns `undefined` when `darkMode` is set to `` (the default value)', async () => {
|
||||
startDeps.userProfile.getCurrent.mockResolvedValue(createUserProfile(''));
|
||||
|
||||
const { getUserSettingDarkMode } = service.setup();
|
||||
service.start(startDeps);
|
||||
|
||||
const kibanaRequest = httpServerMock.createKibanaRequest();
|
||||
const darkMode = await getUserSettingDarkMode(kibanaRequest);
|
||||
|
||||
expect(darkMode).toEqual(undefined);
|
||||
expect(startDeps.userProfile.getCurrent).toHaveBeenCalledTimes(1);
|
||||
expect(startDeps.userProfile.getCurrent).toHaveBeenCalledWith({
|
||||
request: kibanaRequest,
|
||||
dataPath: 'userSettings',
|
||||
});
|
||||
});
|
||||
|
||||
it('does not fetch userSettings when client is not set, returns `undefined`, and logs a debug statement', async () => {
|
||||
const { getUserSettingDarkMode } = service.setup();
|
||||
|
||||
const kibanaRequest = httpServerMock.createKibanaRequest();
|
||||
const darkMode = await getUserSettingDarkMode(kibanaRequest);
|
||||
|
||||
expect(darkMode).toEqual(undefined);
|
||||
expect(coreContext.logger.get().debug).toHaveBeenCalledWith('userProfile not set');
|
||||
});
|
||||
});
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import type { CoreContext } from '@kbn/core-base-server-internal';
|
||||
import type { Logger } from '@kbn/logging';
|
||||
import type { KibanaRequest } from '@kbn/core-http-server';
|
||||
import type { DarkModeValue } from '@kbn/core-ui-settings-common';
|
||||
import type { InternalUserProfileServiceStart } from '@kbn/core-user-profile-server-internal';
|
||||
|
||||
export interface UserSettingsServiceStartDeps {
|
||||
userProfile: InternalUserProfileServiceStart;
|
||||
}
|
||||
|
||||
const userSettingsDataPath = 'userSettings';
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export interface InternalUserSettingsServiceSetup {
|
||||
getUserSettingDarkMode: (request: KibanaRequest) => Promise<DarkModeValue | undefined>;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export class UserSettingsService {
|
||||
private logger: Logger;
|
||||
private userProfile?: InternalUserProfileServiceStart;
|
||||
|
||||
constructor(coreContext: CoreContext) {
|
||||
this.logger = coreContext.logger.get('user-settings-service');
|
||||
}
|
||||
|
||||
public setup(): InternalUserSettingsServiceSetup {
|
||||
return {
|
||||
getUserSettingDarkMode: async (request: KibanaRequest) => {
|
||||
const userSettings = await this.getSettings(request);
|
||||
return getUserSettingDarkMode(userSettings);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
public start(deps: UserSettingsServiceStartDeps) {
|
||||
this.userProfile = deps.userProfile;
|
||||
}
|
||||
|
||||
private async getSettings(request: KibanaRequest): Promise<Record<string, string>> {
|
||||
if (this.userProfile) {
|
||||
const userProfile = await this.userProfile.getCurrent({
|
||||
request,
|
||||
dataPath: userSettingsDataPath,
|
||||
});
|
||||
return (userProfile?.data?.[userSettingsDataPath] ?? {}) as Record<string, string>;
|
||||
} else {
|
||||
this.logger.debug('userProfile not set');
|
||||
return {};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const getUserSettingDarkMode = (
|
||||
userSettings: Record<string, string>
|
||||
): DarkModeValue | undefined => {
|
||||
if (userSettings?.darkMode) {
|
||||
return userSettings.darkMode.toUpperCase() === 'DARK';
|
||||
}
|
||||
return undefined;
|
||||
};
|
|
@ -13,8 +13,10 @@
|
|||
"@kbn/core-base-server-internal",
|
||||
"@kbn/logging",
|
||||
"@kbn/core-http-server-mocks",
|
||||
"@kbn/core-user-settings-server",
|
||||
"@kbn/core-ui-settings-common",
|
||||
"@kbn/core-user-profile-server-mocks",
|
||||
"@kbn/core-user-profile-common",
|
||||
"@kbn/core-user-profile-server-internal",
|
||||
],
|
||||
"include": [
|
||||
"**/*.ts",
|
||||
|
|
|
@ -1,82 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { mockCoreContext } from '@kbn/core-base-server-mocks';
|
||||
import { UserSettingsService } from './user_settings_service';
|
||||
import { httpServerMock } from '@kbn/core-http-server-mocks';
|
||||
|
||||
describe('#setup', () => {
|
||||
const coreContext: ReturnType<typeof mockCoreContext.create> = mockCoreContext.create();
|
||||
const { createKibanaRequest } = httpServerMock;
|
||||
|
||||
it('fetches userSettings when client is set and returns `true` when `darkMode` is set to `dark`', async () => {
|
||||
const service = new UserSettingsService(coreContext);
|
||||
const { setUserProfileSettings, getUserSettingDarkMode } = service.setup();
|
||||
|
||||
const userProfileContract = {
|
||||
get: jest.fn().mockReturnValueOnce(Promise.resolve({ darkMode: 'dark' })),
|
||||
};
|
||||
|
||||
setUserProfileSettings(userProfileContract);
|
||||
|
||||
const kibanaRequest = createKibanaRequest();
|
||||
const darkMode = await getUserSettingDarkMode(kibanaRequest);
|
||||
|
||||
expect(darkMode).toEqual(true);
|
||||
expect(userProfileContract.get).toHaveBeenCalledTimes(1);
|
||||
expect(userProfileContract.get).toHaveBeenCalledWith(kibanaRequest);
|
||||
});
|
||||
|
||||
it('fetches userSettings when client is set and returns `false` when `darkMode` is set to `light`', async () => {
|
||||
const service = new UserSettingsService(coreContext);
|
||||
const { setUserProfileSettings, getUserSettingDarkMode } = service.setup();
|
||||
|
||||
const userProfileContract = {
|
||||
get: jest.fn().mockReturnValueOnce(Promise.resolve({ darkMode: 'light' })),
|
||||
};
|
||||
|
||||
setUserProfileSettings(userProfileContract);
|
||||
|
||||
const kibanaRequest = createKibanaRequest();
|
||||
const darkMode = await getUserSettingDarkMode(kibanaRequest);
|
||||
|
||||
expect(darkMode).toEqual(false);
|
||||
expect(userProfileContract.get).toHaveBeenCalledTimes(1);
|
||||
expect(userProfileContract.get).toHaveBeenCalledWith(kibanaRequest);
|
||||
});
|
||||
|
||||
it('fetches userSettings when client is set and returns `undefined` when `darkMode` is set to `` (the default value)', async () => {
|
||||
const service = new UserSettingsService(coreContext);
|
||||
const { setUserProfileSettings, getUserSettingDarkMode } = service.setup();
|
||||
|
||||
const userProfileContract = {
|
||||
get: jest.fn().mockReturnValueOnce(Promise.resolve({ darkMode: '' })),
|
||||
};
|
||||
|
||||
setUserProfileSettings(userProfileContract);
|
||||
|
||||
const kibanaRequest = createKibanaRequest();
|
||||
const darkMode = await getUserSettingDarkMode(kibanaRequest);
|
||||
|
||||
expect(darkMode).toEqual(undefined);
|
||||
expect(userProfileContract.get).toHaveBeenCalledTimes(1);
|
||||
expect(userProfileContract.get).toHaveBeenCalledWith(kibanaRequest);
|
||||
});
|
||||
|
||||
it('does not fetch userSettings when client is not set, returns `undefined`, and logs a debug statement', async () => {
|
||||
const service = new UserSettingsService(coreContext);
|
||||
const { getUserSettingDarkMode } = service.setup();
|
||||
const kibanaRequest = createKibanaRequest();
|
||||
const darkMode = await getUserSettingDarkMode(kibanaRequest);
|
||||
|
||||
expect(darkMode).toEqual(undefined);
|
||||
expect(coreContext.logger.get().debug).toHaveBeenCalledWith(
|
||||
'UserProfileSettingsClient not set'
|
||||
);
|
||||
});
|
||||
});
|
|
@ -1,65 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { CoreContext } from '@kbn/core-base-server-internal';
|
||||
import { Logger } from '@kbn/logging';
|
||||
import { KibanaRequest } from '@kbn/core-http-server';
|
||||
import { DarkModeValue } from '@kbn/core-ui-settings-common';
|
||||
import { UserProfileSettingsClientContract } from '@kbn/core-user-settings-server';
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export interface InternalUserSettingsServiceSetup {
|
||||
setUserProfileSettings: (client: UserProfileSettingsClientContract) => void;
|
||||
getUserSettingDarkMode: (request: KibanaRequest) => Promise<DarkModeValue | undefined>;
|
||||
}
|
||||
|
||||
export class UserSettingsService {
|
||||
private logger: Logger;
|
||||
private client?: UserProfileSettingsClientContract;
|
||||
|
||||
constructor(coreContext: CoreContext) {
|
||||
this.logger = coreContext.logger.get('user-settings-service');
|
||||
}
|
||||
|
||||
public setup(): InternalUserSettingsServiceSetup {
|
||||
return {
|
||||
setUserProfileSettings: (client: UserProfileSettingsClientContract) => {
|
||||
this.client = client;
|
||||
},
|
||||
getUserSettingDarkMode: async (request: KibanaRequest) => {
|
||||
const userSettings = await this.getSettings(request);
|
||||
return this.getUserSettingDarkMode(userSettings);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
private async getSettings(request: KibanaRequest): Promise<Record<string, string>> {
|
||||
let result = {};
|
||||
if (this.client) {
|
||||
result = (await this.client.get(request)) as Record<string, string>;
|
||||
} else {
|
||||
this.logger.debug('UserProfileSettingsClient not set');
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private async getUserSettingDarkMode(
|
||||
userSettings: Record<string, string>
|
||||
): Promise<DarkModeValue | undefined> {
|
||||
let result;
|
||||
|
||||
if (userSettings?.darkMode) {
|
||||
result = userSettings.darkMode.toUpperCase() === 'DARK';
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
import { UserSettingsService } from '@kbn/core-user-settings-server-internal';
|
||||
|
||||
export const serviceContractMock = (): jest.Mocked<UserSettingsService> => {
|
||||
return {
|
||||
setup: jest.fn(),
|
||||
} as unknown as jest.Mocked<UserSettingsService>;
|
||||
};
|
|
@ -6,20 +6,25 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { serviceContractMock } from './service_contract.mock';
|
||||
import type { PublicMethodsOf } from '@kbn/utility-types';
|
||||
import type {
|
||||
UserSettingsService,
|
||||
InternalUserSettingsServiceSetup,
|
||||
} from '@kbn/core-user-settings-server-internal';
|
||||
|
||||
const createSetupContractMock = () => {
|
||||
const createSetupContractMock = (): jest.Mocked<InternalUserSettingsServiceSetup> => {
|
||||
return {
|
||||
setUserProfileSettings: jest.fn(),
|
||||
getUserSettingDarkMode: jest.fn(),
|
||||
};
|
||||
};
|
||||
|
||||
const createMock = () => {
|
||||
const mocked = serviceContractMock();
|
||||
mocked.setup.mockReturnValue(createSetupContractMock());
|
||||
// mocked.start.mockReturnValue(createStartContractMock());
|
||||
return mocked;
|
||||
const createMock = (): jest.Mocked<PublicMethodsOf<UserSettingsService>> => {
|
||||
const mock = {
|
||||
setup: jest.fn(),
|
||||
start: jest.fn(),
|
||||
};
|
||||
mock.setup.mockReturnValue(createSetupContractMock());
|
||||
return mock;
|
||||
};
|
||||
|
||||
export const userSettingsServiceMock = {
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
},
|
||||
"kbn_references": [
|
||||
"@kbn/core-user-settings-server-internal",
|
||||
"@kbn/utility-types",
|
||||
],
|
||||
"include": [
|
||||
"**/*.ts",
|
||||
|
|
|
@ -6,4 +6,4 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
export type { UserSettingsServiceSetup, UserProfileSettingsClientContract } from './types';
|
||||
export type { UserSettingsServiceSetup } from './types';
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
]
|
||||
},
|
||||
"kbn_references": [
|
||||
"@kbn/core-http-server",
|
||||
],
|
||||
"include": [
|
||||
"**/*.ts",
|
||||
|
|
|
@ -5,13 +5,8 @@
|
|||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
import { KibanaRequest } from '@kbn/core-http-server';
|
||||
|
||||
/** @public */
|
||||
export interface UserSettingsServiceSetup {
|
||||
setUserProfileSettings: (client: UserProfileSettingsClientContract) => void;
|
||||
}
|
||||
|
||||
export interface UserProfileSettingsClientContract {
|
||||
get: (request: KibanaRequest) => Promise<Record<string, string>>;
|
||||
}
|
||||
// keeping the empty service contract for now as we might re-use it very soon
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
||||
export interface UserSettingsServiceSetup {}
|
||||
|
|
|
@ -60,9 +60,6 @@ import { setupSpacesClient } from './spaces';
|
|||
import { registerSecurityUsageCollector } from './usage_collector';
|
||||
import { UserProfileService } from './user_profile';
|
||||
import type { UserProfileServiceStartInternal } from './user_profile';
|
||||
import { UserProfileSettingsClient } from './user_profile/user_profile_settings_client';
|
||||
import type { UserSettingServiceStart } from './user_profile/user_setting_service';
|
||||
import { UserSettingService } from './user_profile/user_setting_service';
|
||||
import type { AuthenticatedUser, SecurityLicense } from '../common';
|
||||
import { SecurityLicenseService } from '../common/licensing';
|
||||
|
||||
|
@ -172,9 +169,6 @@ export class SecurityPlugin
|
|||
private readonly userProfileService: UserProfileService;
|
||||
private userProfileStart?: UserProfileServiceStartInternal;
|
||||
|
||||
private readonly userSettingService: UserSettingService;
|
||||
private userSettingServiceStart?: UserSettingServiceStart;
|
||||
private userProfileSettingsClient: UserProfileSettingsClient;
|
||||
private readonly getUserProfileService = () => {
|
||||
if (!this.userProfileStart) {
|
||||
throw new Error(`userProfileStart is not registered!`);
|
||||
|
@ -202,15 +196,8 @@ export class SecurityPlugin
|
|||
this.userProfileService = new UserProfileService(
|
||||
this.initializerContext.logger.get('user-profile')
|
||||
);
|
||||
this.userSettingService = new UserSettingService(
|
||||
this.initializerContext.logger.get('user-settings')
|
||||
);
|
||||
|
||||
this.analyticsService = new AnalyticsService(this.initializerContext.logger.get('analytics'));
|
||||
|
||||
this.userProfileSettingsClient = new UserProfileSettingsClient(
|
||||
this.initializerContext.logger.get('user-settings-client')
|
||||
);
|
||||
}
|
||||
|
||||
public setup(
|
||||
|
@ -238,8 +225,6 @@ export class SecurityPlugin
|
|||
features: depsServices.features,
|
||||
}));
|
||||
|
||||
core.userSettings.setUserProfileSettings(this.userProfileSettingsClient);
|
||||
|
||||
const { license } = this.securityLicenseService.setup({
|
||||
license$: licensing.license$,
|
||||
});
|
||||
|
@ -386,8 +371,6 @@ export class SecurityPlugin
|
|||
this.session = session;
|
||||
|
||||
this.userProfileStart = this.userProfileService.start({ clusterClient, session });
|
||||
this.userSettingServiceStart = this.userSettingService.start(this.userProfileStart);
|
||||
this.userProfileSettingsClient.setUserSettingsServiceStart(this.userSettingServiceStart);
|
||||
|
||||
// In serverless, we want to redirect users to the list of projects instead of standard "Logged Out" page.
|
||||
const customLogoutURL =
|
||||
|
|
|
@ -1,46 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { loggingSystemMock } from '@kbn/core/server/mocks';
|
||||
import type { httpServerMock } from '@kbn/core-http-server-mocks';
|
||||
import type { Logger } from '@kbn/logging';
|
||||
|
||||
import { UserProfileSettingsClient } from './user_profile_settings_client';
|
||||
import type { UserSettingServiceStart } from './user_setting_service';
|
||||
|
||||
describe('UserProfileSettingsClient', () => {
|
||||
let mockRequest: ReturnType<typeof httpServerMock.createKibanaRequest>;
|
||||
let client: UserProfileSettingsClient;
|
||||
let logger: Logger;
|
||||
let userSettingServiceStart: jest.Mocked<UserSettingServiceStart>;
|
||||
|
||||
beforeEach(() => {
|
||||
userSettingServiceStart = {
|
||||
getCurrentUserProfileSettings: jest.fn(),
|
||||
};
|
||||
|
||||
userSettingServiceStart.getCurrentUserProfileSettings.mockResolvedValue({ darkMode: 'dark' });
|
||||
|
||||
logger = loggingSystemMock.createLogger();
|
||||
client = new UserProfileSettingsClient(logger);
|
||||
});
|
||||
|
||||
describe('#get', () => {
|
||||
it('should return empty before UserSettingServiceStart is set', async () => {
|
||||
const userSettings = await client.get(mockRequest);
|
||||
expect(userSettings).toEqual({});
|
||||
expect(logger.debug).toHaveBeenCalledWith('UserSettingsServiceStart has not been set yet');
|
||||
});
|
||||
|
||||
it('should return user settings after UserSettingServiceStart is set', async () => {
|
||||
client.setUserSettingsServiceStart(userSettingServiceStart);
|
||||
const userSettings = await client.get(mockRequest);
|
||||
|
||||
expect(userSettings).toEqual({ darkMode: 'dark' });
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,45 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
import type { Logger } from '@kbn/core/server';
|
||||
import type { KibanaRequest } from '@kbn/core-http-server';
|
||||
import type { UserProfileSettingsClientContract } from '@kbn/core-user-settings-server';
|
||||
|
||||
import type { UserSettingServiceStart } from './user_setting_service';
|
||||
/**
|
||||
* A wrapper client around {@link UserSettingServiceStart} that exposes a method to get the current user's profile
|
||||
*/
|
||||
export class UserProfileSettingsClient implements UserProfileSettingsClientContract {
|
||||
private userSettingServiceStart: UserSettingServiceStart | undefined;
|
||||
private logger: Logger;
|
||||
|
||||
constructor(logger: Logger) {
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current user's user profile settings
|
||||
*
|
||||
* @param request the KibanaRequest that is required to get the current user and their settings
|
||||
* @return the User Settings values retrieved from the UserSettingsServiceStart, if it has been set, otherwise,
|
||||
* default to an empty Record
|
||||
*/
|
||||
async get(request: KibanaRequest): Promise<Record<string, string>> {
|
||||
let result: Record<string, string> = {} as Record<string, string>;
|
||||
|
||||
if (this.userSettingServiceStart) {
|
||||
result = await this.userSettingServiceStart.getCurrentUserProfileSettings(request);
|
||||
} else {
|
||||
this.logger.debug('UserSettingsServiceStart has not been set yet');
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
setUserSettingsServiceStart(userSettingServiceStart: UserSettingServiceStart) {
|
||||
this.userSettingServiceStart = userSettingServiceStart;
|
||||
}
|
||||
}
|
|
@ -1,55 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import type { KibanaRequest } from '@kbn/core-http-server';
|
||||
import type { Logger } from '@kbn/logging';
|
||||
import type {
|
||||
UserProfileGetCurrentParams,
|
||||
UserProfileServiceStart,
|
||||
} from '@kbn/security-plugin-types-server';
|
||||
|
||||
export interface UserSettingServiceStart {
|
||||
/**
|
||||
* Returns the currently signed-in user's settings from their User Profile
|
||||
*
|
||||
* @param request the KibanaRequest that is required to get the current user and their settings
|
||||
*/
|
||||
getCurrentUserProfileSettings(request: KibanaRequest): Promise<Record<string, string>>;
|
||||
}
|
||||
|
||||
/**
|
||||
* A service that wraps the {@link UserProfileServiceStart} so that only the 'getCurrent' method is made available
|
||||
*/
|
||||
export class UserSettingService {
|
||||
private readonly logger: Logger;
|
||||
|
||||
constructor(logger: Logger) {
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
start(userProfileServiceStart: UserProfileServiceStart): UserSettingServiceStart {
|
||||
return {
|
||||
getCurrentUserProfileSettings: async (request) => {
|
||||
const params: UserProfileGetCurrentParams = {
|
||||
request,
|
||||
dataPath: 'userSettings',
|
||||
};
|
||||
|
||||
const currentUserProfile = await userProfileServiceStart.getCurrent(params);
|
||||
|
||||
let result = {} as Record<string, string>;
|
||||
|
||||
if (currentUserProfile?.data?.userSettings) {
|
||||
result = currentUserProfile?.data?.userSettings as Record<string, string>;
|
||||
} else {
|
||||
this.logger.debug('User Settings not found.');
|
||||
}
|
||||
return result;
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
|
@ -1,143 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import type { SecurityGetUserProfileResponse } from '@elastic/elasticsearch/lib/api/types';
|
||||
|
||||
import {
|
||||
elasticsearchServiceMock,
|
||||
httpServerMock,
|
||||
loggingSystemMock,
|
||||
} from '@kbn/core/server/mocks';
|
||||
import type { UserProfileServiceStart } from '@kbn/security-plugin-types-server';
|
||||
|
||||
import { UserProfileService } from './user_profile_service';
|
||||
import { UserSettingService } from './user_setting_service';
|
||||
import type { UserProfileWithSecurity } from '../../common';
|
||||
import { licenseMock } from '../../common/licensing/index.mock';
|
||||
import { userProfileMock } from '../../common/model/user_profile.mock';
|
||||
import { authorizationMock } from '../authorization/index.mock';
|
||||
import { sessionMock } from '../session_management/session.mock';
|
||||
|
||||
const logger = loggingSystemMock.createLogger();
|
||||
describe('UserSettingService', () => {
|
||||
let mockStartParams: {
|
||||
clusterClient: ReturnType<typeof elasticsearchServiceMock.createClusterClient>;
|
||||
session: ReturnType<typeof sessionMock.create>;
|
||||
};
|
||||
|
||||
let mockAuthz: ReturnType<typeof authorizationMock.create>;
|
||||
let userProfileService: UserProfileService;
|
||||
let userSettingsService: UserSettingService;
|
||||
let userProfileServiceStart: UserProfileServiceStart;
|
||||
|
||||
beforeEach(() => {
|
||||
mockStartParams = {
|
||||
clusterClient: elasticsearchServiceMock.createClusterClient(),
|
||||
session: sessionMock.create(),
|
||||
};
|
||||
|
||||
mockAuthz = authorizationMock.create();
|
||||
|
||||
userProfileService = new UserProfileService(logger);
|
||||
userSettingsService = new UserSettingService(logger);
|
||||
|
||||
userProfileService.setup({
|
||||
authz: mockAuthz,
|
||||
license: licenseMock.create({ allowUserProfileCollaboration: true }),
|
||||
});
|
||||
|
||||
userProfileServiceStart = userProfileService.start(mockStartParams);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
logger.error.mockClear();
|
||||
});
|
||||
|
||||
it('should expose correct start contract', () => {
|
||||
const userSettingServiceStart = userSettingsService.start(userProfileServiceStart);
|
||||
expect(userSettingServiceStart).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"getCurrentUserProfileSettings": [Function],
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
describe('#getCurrentUserProfileSettings', () => {
|
||||
let mockUserProfile: UserProfileWithSecurity;
|
||||
let mockRequest: ReturnType<typeof httpServerMock.createKibanaRequest>;
|
||||
beforeEach(() => {
|
||||
mockRequest = httpServerMock.createKibanaRequest();
|
||||
});
|
||||
|
||||
it('returns user settings data', async () => {
|
||||
mockUserProfile = userProfileMock.createWithSecurity({
|
||||
uid: 'UID',
|
||||
user: {
|
||||
username: 'user-1',
|
||||
full_name: 'full-name-1',
|
||||
realm_name: 'some-realm',
|
||||
realm_domain: 'some-domain',
|
||||
roles: ['role-1'],
|
||||
},
|
||||
data: {
|
||||
kibana: {
|
||||
userSettings: {
|
||||
darkMode: 'dark',
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
mockStartParams.clusterClient.asInternalUser.security.getUserProfile.mockResolvedValue({
|
||||
profiles: [mockUserProfile],
|
||||
} as unknown as SecurityGetUserProfileResponse);
|
||||
|
||||
mockStartParams.session.get.mockResolvedValue({
|
||||
error: null,
|
||||
value: sessionMock.createValue({ userProfileId: mockUserProfile.uid }),
|
||||
});
|
||||
|
||||
userProfileServiceStart = userProfileService.start(mockStartParams);
|
||||
const userSettingServiceStart = userSettingsService.start(userProfileServiceStart);
|
||||
await expect(
|
||||
userSettingServiceStart.getCurrentUserProfileSettings(mockRequest)
|
||||
).resolves.toEqual({ darkMode: 'dark' });
|
||||
});
|
||||
|
||||
it('logs a warning and returns ', async () => {
|
||||
mockUserProfile = userProfileMock.createWithSecurity({
|
||||
uid: 'UID',
|
||||
user: {
|
||||
username: 'user-1',
|
||||
full_name: 'full-name-1',
|
||||
realm_name: 'some-realm',
|
||||
realm_domain: 'some-domain',
|
||||
roles: ['role-1'],
|
||||
},
|
||||
data: {},
|
||||
});
|
||||
|
||||
mockStartParams.clusterClient.asInternalUser.security.getUserProfile.mockResolvedValue({
|
||||
profiles: [mockUserProfile],
|
||||
} as unknown as SecurityGetUserProfileResponse);
|
||||
|
||||
mockStartParams.session.get.mockResolvedValue({
|
||||
error: null,
|
||||
value: sessionMock.createValue({ userProfileId: mockUserProfile.uid }),
|
||||
});
|
||||
|
||||
userProfileServiceStart = userProfileService.start(mockStartParams);
|
||||
const userSettingServiceStart = userSettingsService.start(userProfileServiceStart);
|
||||
|
||||
await expect(
|
||||
userSettingServiceStart.getCurrentUserProfileSettings(mockRequest)
|
||||
).resolves.toEqual({});
|
||||
|
||||
expect(logger.debug).toHaveBeenCalledWith('User Settings not found.');
|
||||
});
|
||||
});
|
||||
});
|
|
@ -64,7 +64,6 @@
|
|||
"@kbn/shared-ux-router",
|
||||
"@kbn/core-http-server",
|
||||
"@kbn/core-http-server-mocks",
|
||||
"@kbn/core-user-settings-server",
|
||||
"@kbn/remote-clusters-plugin",
|
||||
"@kbn/analytics-client",
|
||||
"@kbn/security-plugin-types-common",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue