diff --git a/x-pack/plugins/security/server/plugin.ts b/x-pack/plugins/security/server/plugin.ts index d196dd9f41139..341ab79e97e5b 100644 --- a/x-pack/plugins/security/server/plugin.ts +++ b/x-pack/plugins/security/server/plugin.ts @@ -201,6 +201,7 @@ export class SecurityPlugin private readonly userSettingService: UserSettingService; private userSettingServiceStart?: UserSettingServiceStart; + private userProfileSettingsClient: UserProfileSettingsClient; private readonly getUserProfileService = () => { if (!this.userProfileStart) { throw new Error(`userProfileStart is not registered!`); @@ -233,6 +234,10 @@ export class SecurityPlugin ); this.analyticsService = new AnalyticsService(this.initializerContext.logger.get('analytics')); + + this.userProfileSettingsClient = new UserProfileSettingsClient( + this.initializerContext.logger.get('user-settings-client') + ); } public setup( @@ -255,25 +260,12 @@ export class SecurityPlugin const kibanaIndexName = this.getKibanaIndexName(); // A subset of `start` services we need during `setup`. - const startServicesPromise = core - .getStartServices() - .then(([coreServices, depsServices, startServices]) => ({ - elasticsearch: coreServices.elasticsearch, - features: depsServices.features, - userProfiles: startServices.userProfiles, - })); - - /** - * Once the UserProfileServiceStart is available, use it to start the SecurityPlugin > UserSettingService. - * - * Then the UserProfileSettingsClient is created with the SecurityPlugin > UserSettingServiceStart and set on - * the Core > UserSettingsServiceSetup - */ - startServicesPromise.then(({ userProfiles }) => { - this.userSettingServiceStart = this.userSettingService.start(userProfiles); - const client = new UserProfileSettingsClient(this.userSettingServiceStart); - core.userSettings.setUserProfileSettings(client); - }); + const startServicesPromise = core.getStartServices().then(([coreServices, depsServices]) => ({ + elasticsearch: coreServices.elasticsearch, + features: depsServices.features, + })); + + core.userSettings.setUserProfileSettings(this.userProfileSettingsClient); const { license } = this.securityLicenseService.setup({ license$: licensing.license$, @@ -408,6 +400,7 @@ export class SecurityPlugin 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 = diff --git a/x-pack/plugins/security/server/user_profile/user_profile_settings_client.test.ts b/x-pack/plugins/security/server/user_profile/user_profile_settings_client.test.ts index dfcc88c8ca5a1..46202d5a94ea2 100644 --- a/x-pack/plugins/security/server/user_profile/user_profile_settings_client.test.ts +++ b/x-pack/plugins/security/server/user_profile/user_profile_settings_client.test.ts @@ -5,7 +5,9 @@ * 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'; @@ -13,20 +15,31 @@ import type { UserSettingServiceStart } from './user_setting_service'; describe('UserProfileSettingsClient', () => { let mockRequest: ReturnType; let client: UserProfileSettingsClient; + let logger: Logger; + let userSettingServiceStart: jest.Mocked; beforeEach(() => { - const userSettingsServiceStart = { + userSettingServiceStart = { getCurrentUserProfileSettings: jest.fn(), - } as jest.Mocked; + }; - userSettingsServiceStart.getCurrentUserProfileSettings.mockResolvedValue({ darkMode: 'dark' }); + userSettingServiceStart.getCurrentUserProfileSettings.mockResolvedValue({ darkMode: 'dark' }); - client = new UserProfileSettingsClient(userSettingsServiceStart); + logger = loggingSystemMock.createLogger(); + client = new UserProfileSettingsClient(logger); }); describe('#get', () => { - it('should return user settings', async () => { + 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' }); }); }); diff --git a/x-pack/plugins/security/server/user_profile/user_profile_settings_client.ts b/x-pack/plugins/security/server/user_profile/user_profile_settings_client.ts index a888f22256acc..03bf4855cbc79 100644 --- a/x-pack/plugins/security/server/user_profile/user_profile_settings_client.ts +++ b/x-pack/plugins/security/server/user_profile/user_profile_settings_client.ts @@ -4,28 +4,42 @@ * 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 userSettingsServiceStart: UserSettingServiceStart; + private userSettingServiceStart: UserSettingServiceStart | undefined; + private logger: Logger; - constructor(userSettingsServiceStart: UserSettingServiceStart) { - this.userSettingsServiceStart = userSettingsServiceStart; + 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> { - return await this.userSettingsServiceStart.getCurrentUserProfileSettings(request); + let result: Record = {} as Record; + + 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; } }