[Security into Core] expose userProfile service from Core (#180372)

## Summary

Fix https://github.com/elastic/kibana/issues/178932

- Introduce the new `userProfile` core service, both on the browser and
server-side.

- Have the security plugin register its API to Core for re-exposition

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Pierre Gayvallet 2024-04-24 10:20:05 +02:00 committed by GitHub
parent b3b665bfc8
commit 0f3ecf739e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
159 changed files with 2279 additions and 357 deletions

7
.github/CODEOWNERS vendored
View file

@ -313,6 +313,13 @@ packages/core/usage-data/core-usage-data-base-server-internal @elastic/kibana-co
packages/core/usage-data/core-usage-data-server @elastic/kibana-core
packages/core/usage-data/core-usage-data-server-internal @elastic/kibana-core
packages/core/usage-data/core-usage-data-server-mocks @elastic/kibana-core
packages/core/user-profile/core-user-profile-browser @elastic/kibana-core
packages/core/user-profile/core-user-profile-browser-internal @elastic/kibana-core
packages/core/user-profile/core-user-profile-browser-mocks @elastic/kibana-core
packages/core/user-profile/core-user-profile-common @elastic/kibana-core
packages/core/user-profile/core-user-profile-server @elastic/kibana-core
packages/core/user-profile/core-user-profile-server-internal @elastic/kibana-core
packages/core/user-profile/core-user-profile-server-mocks @elastic/kibana-core
packages/core/user-settings/core-user-settings-server @elastic/kibana-security
packages/core/user-settings/core-user-settings-server-internal @elastic/kibana-security
packages/core/user-settings/core-user-settings-server-mocks @elastic/kibana-security

View file

@ -368,6 +368,13 @@
"@kbn/core-usage-data-base-server-internal": "link:packages/core/usage-data/core-usage-data-base-server-internal",
"@kbn/core-usage-data-server": "link:packages/core/usage-data/core-usage-data-server",
"@kbn/core-usage-data-server-internal": "link:packages/core/usage-data/core-usage-data-server-internal",
"@kbn/core-user-profile-browser": "link:packages/core/user-profile/core-user-profile-browser",
"@kbn/core-user-profile-browser-internal": "link:packages/core/user-profile/core-user-profile-browser-internal",
"@kbn/core-user-profile-browser-mocks": "link:packages/core/user-profile/core-user-profile-browser-mocks",
"@kbn/core-user-profile-common": "link:packages/core/user-profile/core-user-profile-common",
"@kbn/core-user-profile-server": "link:packages/core/user-profile/core-user-profile-server",
"@kbn/core-user-profile-server-internal": "link:packages/core/user-profile/core-user-profile-server-internal",
"@kbn/core-user-profile-server-mocks": "link:packages/core/user-profile/core-user-profile-server-mocks",
"@kbn/core-user-settings-server": "link:packages/core/user-settings/core-user-settings-server",
"@kbn/core-user-settings-server-internal": "link:packages/core/user-settings/core-user-settings-server-internal",
"@kbn/core-user-settings-server-mocks": "link:packages/core/user-settings/core-user-settings-server-mocks",

View file

@ -232,3 +232,32 @@ describe('#security', () => {
});
});
});
describe('#userProfile', () => {
describe('getCurrent', () => {
test('calls coreStart.userProfile.getCurrent with the correct parameters', () => {
const request = httpServerMock.createKibanaRequest();
const coreStart = createCoreRouteHandlerContextParamsMock();
const context = new CoreRouteHandlerContext(coreStart, request);
context.userProfile?.getCurrent({ dataPath: '/data-path' });
expect(coreStart.userProfile.getCurrent).toHaveBeenCalledTimes(1);
expect(coreStart.userProfile.getCurrent).toHaveBeenCalledWith({
request,
dataPath: '/data-path',
});
});
test('returns the result of coreStart.userProfile.getCurrent', () => {
const request = httpServerMock.createKibanaRequest();
const coreStart = createCoreRouteHandlerContextParamsMock();
const context = new CoreRouteHandlerContext(coreStart, request);
const stubProfile: any = Symbol.for('stubProfile');
coreStart.userProfile.getCurrent.mockReturnValue(stubProfile);
const profile = context.userProfile?.getCurrent();
expect(profile).toBe(stubProfile);
});
});
});

View file

@ -28,6 +28,10 @@ import {
CoreSecurityRouteHandlerContext,
type InternalSecurityServiceStart,
} from '@kbn/core-security-server-internal';
import {
CoreUserProfileRouteHandlerContext,
type InternalUserProfileServiceStart,
} from '@kbn/core-user-profile-server-internal';
/**
* Subset of `InternalCoreStart` used by {@link CoreRouteHandlerContext}
@ -39,6 +43,7 @@ export interface CoreRouteHandlerContextParams {
uiSettings: InternalUiSettingsServiceStart;
deprecations: InternalDeprecationsServiceStart;
security: InternalSecurityServiceStart;
userProfile: InternalUserProfileServiceStart;
}
/**
@ -52,6 +57,7 @@ export class CoreRouteHandlerContext implements CoreRequestHandlerContext {
#uiSettings?: CoreUiSettingsRouteHandlerContext;
#deprecations?: CoreDeprecationsRouteHandlerContext;
#security?: CoreSecurityRouteHandlerContext;
#userProfile?: CoreUserProfileRouteHandlerContext;
constructor(
private readonly coreStart: CoreRouteHandlerContextParams,
@ -105,4 +111,14 @@ export class CoreRouteHandlerContext implements CoreRequestHandlerContext {
}
return this.#security;
}
public get userProfile() {
if (!this.#userProfile) {
this.#userProfile = new CoreUserProfileRouteHandlerContext(
this.coreStart.userProfile,
this.request
);
}
return this.#userProfile;
}
}

View file

@ -11,6 +11,7 @@ import { savedObjectsServiceMock } from '@kbn/core-saved-objects-server-mocks';
import { uiSettingsServiceMock } from '@kbn/core-ui-settings-server-mocks';
import { deprecationsServiceMock } from '@kbn/core-deprecations-server-mocks';
import { securityServiceMock } from '@kbn/core-security-server-mocks';
import { userProfileServiceMock } from '@kbn/core-user-profile-server-mocks';
export const createCoreRouteHandlerContextParamsMock = () => {
return {
@ -19,5 +20,6 @@ export const createCoreRouteHandlerContextParamsMock = () => {
uiSettings: uiSettingsServiceMock.createStartContract(),
deprecations: deprecationsServiceMock.createInternalStartContract(),
security: securityServiceMock.createInternalStart(),
userProfile: userProfileServiceMock.createInternalStart(),
};
};

View file

@ -25,6 +25,8 @@
"@kbn/core-deprecations-server-mocks",
"@kbn/core-security-server-internal",
"@kbn/core-security-server-mocks",
"@kbn/core-user-profile-server-internal",
"@kbn/core-user-profile-server-mocks",
],
"exclude": [
"target/**/*",

View file

@ -12,6 +12,7 @@ import type { SavedObjectsRequestHandlerContext } from '@kbn/core-saved-objects-
import type { DeprecationsRequestHandlerContext } from '@kbn/core-deprecations-server';
import type { UiSettingsRequestHandlerContext } from '@kbn/core-ui-settings-server';
import type { SecurityRequestHandlerContext } from '@kbn/core-security-server';
import type { UserProfileRequestHandlerContext } from '@kbn/core-user-profile-server';
/**
* The `core` context provided to route handler.
@ -33,6 +34,7 @@ export interface CoreRequestHandlerContext {
uiSettings: UiSettingsRequestHandlerContext;
deprecations: DeprecationsRequestHandlerContext;
security: SecurityRequestHandlerContext;
userProfile: UserProfileRequestHandlerContext;
}
/**

View file

@ -16,7 +16,8 @@
"@kbn/core-saved-objects-server",
"@kbn/core-deprecations-server",
"@kbn/core-ui-settings-server",
"@kbn/core-security-server"
"@kbn/core-security-server",
"@kbn/core-user-profile-server"
],
"exclude": [
"target/**/*",

View file

@ -11,12 +11,17 @@ import type { InternalApplicationSetup } from '@kbn/core-application-browser-int
import type { InternalInjectedMetadataSetup } from '@kbn/core-injected-metadata-browser-internal';
import type { InternalHttpSetup } from '@kbn/core-http-browser-internal';
import type { InternalSecurityServiceSetup } from '@kbn/core-security-browser-internal';
import type { InternalUserProfileServiceSetup } from '@kbn/core-user-profile-browser-internal';
/** @internal */
export interface InternalCoreSetup
extends Omit<CoreSetup, 'application' | 'plugins' | 'getStartServices' | 'http' | 'security'> {
extends Omit<
CoreSetup,
'application' | 'plugins' | 'getStartServices' | 'http' | 'security' | 'userProfile'
> {
application: InternalApplicationSetup;
injectedMetadata: InternalInjectedMetadataSetup;
http: InternalHttpSetup;
security: InternalSecurityServiceSetup;
userProfile: InternalUserProfileServiceSetup;
}

View file

@ -11,12 +11,14 @@ import type { InternalApplicationStart } from '@kbn/core-application-browser-int
import type { InternalInjectedMetadataStart } from '@kbn/core-injected-metadata-browser-internal';
import type { InternalHttpStart } from '@kbn/core-http-browser-internal';
import type { InternalSecurityServiceStart } from '@kbn/core-security-browser-internal';
import type { InternalUserProfileServiceStart } from '@kbn/core-user-profile-browser-internal';
/** @internal */
export interface InternalCoreStart
extends Omit<CoreStart, 'application' | 'plugins' | 'http' | 'security'> {
extends Omit<CoreStart, 'application' | 'plugins' | 'http' | 'security' | 'userProfile'> {
application: InternalApplicationStart;
injectedMetadata: InternalInjectedMetadataStart;
http: InternalHttpStart;
security: InternalSecurityServiceStart;
userProfile: InternalUserProfileServiceStart;
}

View file

@ -16,7 +16,8 @@
"@kbn/core-application-browser-internal",
"@kbn/core-injected-metadata-browser-internal",
"@kbn/core-http-browser-internal",
"@kbn/core-security-browser-internal"
"@kbn/core-security-browser-internal",
"@kbn/core-user-profile-browser-internal"
],
"exclude": [
"target/**/*",

View file

@ -18,6 +18,7 @@ import { notificationServiceMock } from '@kbn/core-notifications-browser-mocks';
import { applicationServiceMock } from '@kbn/core-application-browser-mocks';
import { customBrandingServiceMock } from '@kbn/core-custom-branding-browser-mocks';
import { securityServiceMock } from '@kbn/core-security-browser-mocks';
import { userProfileServiceMock } from '@kbn/core-user-profile-browser-mocks';
import { createCoreStartMock } from './core_start.mock';
export function createCoreSetupMock({
@ -46,6 +47,7 @@ export function createCoreSetupMock({
deprecations: deprecationsServiceMock.createSetupContract(),
theme: themeServiceMock.createSetupContract(),
security: securityServiceMock.createSetup(),
userProfile: userProfileServiceMock.createSetup(),
plugins: {
onSetup: jest.fn(),
onStart: jest.fn(),

View file

@ -22,6 +22,7 @@ import { applicationServiceMock } from '@kbn/core-application-browser-mocks';
import { chromeServiceMock } from '@kbn/core-chrome-browser-mocks';
import { customBrandingServiceMock } from '@kbn/core-custom-branding-browser-mocks';
import { securityServiceMock } from '@kbn/core-security-browser-mocks';
import { userProfileServiceMock } from '@kbn/core-user-profile-browser-mocks';
export function createCoreStartMock({ basePath = '' } = {}) {
const mock = {
@ -42,6 +43,7 @@ export function createCoreStartMock({ basePath = '' } = {}) {
theme: themeServiceMock.createStartContract(),
fatalErrors: fatalErrorsServiceMock.createStartContract(),
security: securityServiceMock.createStart(),
userProfile: userProfileServiceMock.createStart(),
plugins: {
onStart: jest.fn(),
},

View file

@ -27,7 +27,8 @@
"@kbn/core-application-browser-mocks",
"@kbn/core-chrome-browser-mocks",
"@kbn/core-custom-branding-browser-mocks",
"@kbn/core-security-browser-mocks"
"@kbn/core-security-browser-mocks",
"@kbn/core-user-profile-browser-mocks"
],
"exclude": [
"target/**/*",

View file

@ -17,6 +17,7 @@ import type { ApplicationSetup } from '@kbn/core-application-browser';
import type { CustomBrandingSetup } from '@kbn/core-custom-branding-browser';
import type { PluginsServiceSetup } from '@kbn/core-plugins-contracts-browser';
import type { SecurityServiceSetup } from '@kbn/core-security-browser';
import type { UserProfileServiceSetup } from '@kbn/core-user-profile-browser';
import type { CoreStart } from './core_start';
/**
@ -59,6 +60,8 @@ export interface CoreSetup<TPluginsStart extends object = object, TStart = unkno
plugins: PluginsServiceSetup;
/** {@link SecurityServiceSetup} */
security: SecurityServiceSetup;
/** {@link UserProfileServiceSetup} */
userProfile: UserProfileServiceSetup;
/** {@link StartServicesAccessor} */
getStartServices: StartServicesAccessor<TPluginsStart, TStart>;
}

View file

@ -23,6 +23,7 @@ import type { ChromeStart } from '@kbn/core-chrome-browser';
import type { CustomBrandingStart } from '@kbn/core-custom-branding-browser';
import type { PluginsServiceStart } from '@kbn/core-plugins-contracts-browser';
import type { SecurityServiceStart } from '@kbn/core-security-browser';
import type { UserProfileServiceStart } from '@kbn/core-user-profile-browser';
/**
* Core services exposed to the `Plugin` start lifecycle
@ -74,4 +75,6 @@ export interface CoreStart {
plugins: PluginsServiceStart;
/** {@link SecurityServiceStart} */
security: SecurityServiceStart;
/** {@link UserProfileServiceStart} */
userProfile: UserProfileServiceStart;
}

View file

@ -28,7 +28,8 @@
"@kbn/core-chrome-browser",
"@kbn/core-custom-branding-browser",
"@kbn/core-plugins-contracts-browser",
"@kbn/core-security-browser"
"@kbn/core-security-browser",
"@kbn/core-user-profile-browser"
],
"exclude": [
"target/**/*",

View file

@ -27,6 +27,7 @@ import type { InternalCoreUsageDataSetup } from '@kbn/core-usage-data-base-serve
import type { InternalCustomBrandingSetup } from '@kbn/core-custom-branding-server-internal';
import type { InternalUserSettingsServiceSetup } from '@kbn/core-user-settings-server-internal';
import type { InternalSecurityServiceSetup } from '@kbn/core-security-server-internal';
import type { InternalUserProfileServiceSetup } from '@kbn/core-user-profile-server-internal';
/** @internal */
export interface InternalCoreSetup {
@ -51,4 +52,5 @@ export interface InternalCoreSetup {
customBranding: InternalCustomBrandingSetup;
userSettings: InternalUserSettingsServiceSetup;
security: InternalSecurityServiceSetup;
userProfile: InternalUserProfileServiceSetup;
}

View file

@ -19,6 +19,7 @@ import type { InternalUiSettingsServiceStart } from '@kbn/core-ui-settings-serve
import type { CoreUsageDataStart } from '@kbn/core-usage-data-server';
import type { CustomBrandingStart } from '@kbn/core-custom-branding-server';
import type { InternalSecurityServiceStart } from '@kbn/core-security-server-internal';
import type { InternalUserProfileServiceStart } from '@kbn/core-user-profile-server-internal';
/**
* @internal
@ -37,4 +38,5 @@ export interface InternalCoreStart {
deprecations: InternalDeprecationsServiceStart;
customBranding: CustomBrandingStart;
security: InternalSecurityServiceStart;
userProfile: InternalUserProfileServiceStart;
}

View file

@ -34,7 +34,8 @@
"@kbn/core-custom-branding-server-internal",
"@kbn/core-custom-branding-server",
"@kbn/core-user-settings-server-internal",
"@kbn/core-security-server-internal"
"@kbn/core-security-server-internal",
"@kbn/core-user-profile-server-internal"
],
"exclude": [
"target/**/*",

View file

@ -27,6 +27,7 @@ import { coreUsageDataServiceMock } from '@kbn/core-usage-data-server-mocks';
import { customBrandingServiceMock } from '@kbn/core-custom-branding-server-mocks';
import { userSettingsServiceMock } from '@kbn/core-user-settings-server-mocks';
import { securityServiceMock } from '@kbn/core-security-server-mocks';
import { userProfileServiceMock } from '@kbn/core-user-profile-server-mocks';
import { createCoreStartMock } from './core_start.mock';
type CoreSetupMockType = MockedKeys<CoreSetup> & {
@ -69,6 +70,7 @@ export function createCoreSetupMock({
deprecations: deprecationsServiceMock.createSetupContract(),
executionContext: executionContextServiceMock.createInternalSetupContract(),
security: securityServiceMock.createSetup(),
userProfile: userProfileServiceMock.createSetup(),
coreUsageData: {
registerUsageCounter: coreUsageDataServiceMock.createSetupContract().registerUsageCounter,
},

View file

@ -20,6 +20,7 @@ import { uiSettingsServiceMock } from '@kbn/core-ui-settings-server-mocks';
import { coreUsageDataServiceMock } from '@kbn/core-usage-data-server-mocks';
import { customBrandingServiceMock } from '@kbn/core-custom-branding-server-mocks';
import { securityServiceMock } from '@kbn/core-security-server-mocks';
import { userProfileServiceMock } from '@kbn/core-user-profile-server-mocks';
export function createCoreStartMock() {
const mock: MockedKeys<CoreStart> = {
@ -35,6 +36,7 @@ export function createCoreStartMock() {
executionContext: executionContextServiceMock.createInternalStartContract(),
customBranding: customBrandingServiceMock.createStartContract(),
security: securityServiceMock.createStart(),
userProfile: userProfileServiceMock.createStart(),
plugins: {
onStart: jest.fn(),
},

View file

@ -27,6 +27,7 @@ import { coreUsageDataServiceMock } from '@kbn/core-usage-data-server-mocks';
import { customBrandingServiceMock } from '@kbn/core-custom-branding-server-mocks';
import { userSettingsServiceMock } from '@kbn/core-user-settings-server-mocks';
import { securityServiceMock } from '@kbn/core-security-server-mocks';
import { userProfileServiceMock } from '@kbn/core-user-profile-server-mocks';
export function createInternalCoreSetupMock() {
const setupDeps = {
@ -51,6 +52,7 @@ export function createInternalCoreSetupMock() {
customBranding: customBrandingServiceMock.createSetupContract(),
userSettings: userSettingsServiceMock.createSetupContract(),
security: securityServiceMock.createInternalSetup(),
userProfile: userProfileServiceMock.createInternalSetup(),
};
return setupDeps;
}

View file

@ -19,6 +19,7 @@ import { uiSettingsServiceMock } from '@kbn/core-ui-settings-server-mocks';
import { coreUsageDataServiceMock } from '@kbn/core-usage-data-server-mocks';
import { customBrandingServiceMock } from '@kbn/core-custom-branding-server-mocks';
import { securityServiceMock } from '@kbn/core-security-server-mocks';
import { userProfileServiceMock } from '@kbn/core-user-profile-server-mocks';
export function createInternalCoreStartMock() {
const startDeps = {
@ -35,6 +36,7 @@ export function createInternalCoreStartMock() {
deprecations: deprecationsServiceMock.createInternalStartContract(),
customBranding: customBrandingServiceMock.createStartContract(),
security: securityServiceMock.createInternalStart(),
userProfile: userProfileServiceMock.createInternalStart(),
};
return startDeps;
}

View file

@ -36,6 +36,7 @@
"@kbn/core-custom-branding-server-mocks",
"@kbn/core-user-settings-server-mocks",
"@kbn/core-security-server-mocks",
"@kbn/core-user-profile-server-mocks",
],
"exclude": [
"target/**/*",

View file

@ -26,6 +26,7 @@ import type { CustomBrandingSetup } from '@kbn/core-custom-branding-server';
import type { UserSettingsServiceSetup } from '@kbn/core-user-settings-server';
import type { PluginsServiceSetup } from '@kbn/core-plugins-contracts-server';
import type { SecurityServiceSetup } from '@kbn/core-security-server';
import type { UserProfileServiceSetup } from '@kbn/core-user-profile-server';
import type { CoreStart } from './core_start';
/**
@ -79,6 +80,8 @@ export interface CoreSetup<TPluginsStart extends object = object, TStart = unkno
plugins: PluginsServiceSetup;
/** {@link SecurityServiceSetup} */
security: SecurityServiceSetup;
/** {@link UserProfileServiceSetup} */
userProfile: UserProfileServiceSetup;
}
/**

View file

@ -19,6 +19,7 @@ import type { CoreUsageDataStart } from '@kbn/core-usage-data-server';
import type { CustomBrandingStart } from '@kbn/core-custom-branding-server';
import type { PluginsServiceStart } from '@kbn/core-plugins-contracts-server';
import type { SecurityServiceStart } from '@kbn/core-security-server';
import type { UserProfileServiceStart } from '@kbn/core-user-profile-server';
/**
* Context passed to the plugins `start` method.
@ -52,4 +53,6 @@ export interface CoreStart {
plugins: PluginsServiceStart;
/** {@link SecurityServiceStart} */
security: SecurityServiceStart;
/** {@link UserProfileServiceStart} */
userProfile: UserProfileServiceStart;
}

View file

@ -31,7 +31,8 @@
"@kbn/core-custom-branding-server",
"@kbn/core-user-settings-server",
"@kbn/core-plugins-contracts-server",
"@kbn/core-security-server"
"@kbn/core-security-server",
"@kbn/core-user-profile-server"
],
"exclude": [
"target/**/*",

View file

@ -94,7 +94,11 @@ export function createPluginSetupContext<
settings: deps.settings,
theme: deps.theme,
security: {
registerSecurityApi: (api) => deps.security.registerSecurityApi(api),
registerSecurityDelegate: (api) => deps.security.registerSecurityDelegate(api),
},
userProfile: {
registerUserProfileDelegate: (delegate) =>
deps.userProfile.registerUserProfileDelegate(delegate),
},
plugins: {
onSetup: (...dependencyNames) => runtimeResolver.onSetup(plugin.name, dependencyNames),
@ -162,6 +166,7 @@ export function createPluginStartContext<
security: {
authc: deps.security.authc,
},
userProfile: deps.userProfile,
plugins: {
onStart: (...dependencyNames) => runtimeResolver.onStart(plugin.name, dependencyNames),
},

View file

@ -42,6 +42,7 @@ import type { CoreSetup, CoreStart } from '@kbn/core-lifecycle-browser';
import { savedObjectsServiceMock } from '@kbn/core-saved-objects-browser-mocks';
import { deprecationsServiceMock } from '@kbn/core-deprecations-browser-mocks';
import { securityServiceMock } from '@kbn/core-security-browser-mocks';
import { userProfileServiceMock } from '@kbn/core-user-profile-browser-mocks';
export let mockPluginInitializers: Map<PluginName, MockedPluginInitializer>;
@ -100,6 +101,7 @@ describe('PluginsService', () => {
uiSettings: uiSettingsServiceMock.createSetupContract(),
theme: themeServiceMock.createSetupContract(),
security: securityServiceMock.createInternalSetup(),
userProfile: userProfileServiceMock.createInternalSetup(),
};
mockSetupContext = {
...omit(mockSetupDeps, 'injectedMetadata'),
@ -107,6 +109,7 @@ describe('PluginsService', () => {
plugins: expect.any(Object),
getStartServices: expect.any(Function),
security: expect.any(Object),
userProfile: expect.any(Object),
http: {
...mockSetupDeps.http,
staticAssets: expect.any(Object),
@ -130,6 +133,7 @@ describe('PluginsService', () => {
deprecations: deprecationsServiceMock.createStartContract(),
theme: themeServiceMock.createStartContract(),
security: securityServiceMock.createInternalStart(),
userProfile: userProfileServiceMock.createInternalStart(),
};
mockStartContext = {
...omit(mockStartDeps, 'injectedMetadata'),
@ -137,6 +141,7 @@ describe('PluginsService', () => {
plugins: expect.any(Object),
chrome: omit(mockStartDeps.chrome, 'getComponent'),
security: expect.any(Object),
userProfile: expect.any(Object),
http: {
...mockStartDeps.http,
staticAssets: expect.any(Object),

View file

@ -38,6 +38,7 @@
"@kbn/utility-types",
"@kbn/core-plugins-contracts-browser",
"@kbn/core-security-browser-mocks",
"@kbn/core-user-profile-browser-mocks",
],
"exclude": [
"target/**/*",

View file

@ -285,7 +285,11 @@ export function createPluginSetupContext<TPlugin, TPluginDependencies>({
onStart: (...dependencyNames) => runtimeResolver.onStart(plugin.name, dependencyNames),
},
security: {
registerSecurityApi: (api) => deps.security.registerSecurityApi(api),
registerSecurityDelegate: (api) => deps.security.registerSecurityDelegate(api),
},
userProfile: {
registerUserProfileDelegate: (delegate) =>
deps.userProfile.registerUserProfileDelegate(delegate),
},
};
}
@ -366,5 +370,6 @@ export function createPluginStartContext<TPlugin, TPluginDependencies>({
security: {
authc: deps.security.authc,
},
userProfile: deps.userProfile,
};
}

View file

@ -26,6 +26,7 @@ import { coreAppsMock } from '@kbn/core-apps-browser-mocks';
import { loggingSystemMock } from '@kbn/core-logging-browser-mocks';
import { customBrandingServiceMock } from '@kbn/core-custom-branding-browser-mocks';
import { securityServiceMock } from '@kbn/core-security-browser-mocks';
import { userProfileServiceMock } from '@kbn/core-user-profile-browser-mocks';
export const analyticsServiceStartMock = analyticsServiceMock.createAnalyticsServiceStart();
export const MockAnalyticsService = analyticsServiceMock.create();
@ -163,3 +164,11 @@ export const SecurityServiceConstructor = jest.fn().mockImplementation(() => Moc
jest.doMock('@kbn/core-security-browser-internal', () => ({
SecurityService: SecurityServiceConstructor,
}));
export const MockUserProfileService = userProfileServiceMock.create();
export const UserProfileServiceConstructor = jest
.fn()
.mockImplementation(() => MockUserProfileService);
jest.doMock('@kbn/core-user-profile-browser-internal', () => ({
UserProfileService: UserProfileServiceConstructor,
}));

View file

@ -46,6 +46,8 @@ import {
CustomBrandingServiceConstructor,
MockSecurityService,
SecurityServiceConstructor,
MockUserProfileService,
UserProfileServiceConstructor,
} from './core_system.test.mocks';
import type { EnvironmentMode } from '@kbn/config';
import { CoreSystem } from './core_system';
@ -153,6 +155,7 @@ describe('constructor', () => {
expect(LoggingSystemConstructor).toHaveBeenCalledTimes(1);
expect(CustomBrandingServiceConstructor).toHaveBeenCalledTimes(1);
expect(SecurityServiceConstructor).toHaveBeenCalledTimes(1);
expect(UserProfileServiceConstructor).toHaveBeenCalledTimes(1);
});
it('passes injectedMetadata param to InjectedMetadataService', () => {
@ -317,6 +320,11 @@ describe('#setup()', () => {
await setupCore();
expect(MockSecurityService.setup).toHaveBeenCalledTimes(1);
});
it('calls userProfile#setup()', async () => {
await setupCore();
expect(MockUserProfileService.setup).toHaveBeenCalledTimes(1);
});
});
describe('#start()', () => {
@ -508,6 +516,11 @@ describe('#start()', () => {
await startCore();
expect(MockSecurityService.start).toHaveBeenCalledTimes(1);
});
it('calls userProfile#start()', async () => {
await startCore();
expect(MockUserProfileService.start).toHaveBeenCalledTimes(1);
});
});
describe('#stop()', () => {

View file

@ -37,6 +37,7 @@ import type { InternalCoreSetup, InternalCoreStart } from '@kbn/core-lifecycle-b
import { PluginsService } from '@kbn/core-plugins-browser-internal';
import { CustomBrandingService } from '@kbn/core-custom-branding-browser-internal';
import { SecurityService } from '@kbn/core-security-browser-internal';
import { UserProfileService } from '@kbn/core-user-profile-browser-internal';
import { KBN_LOAD_MARKS } from './events';
import { fetchOptionalMemoryInfo } from './fetch_optional_memory_info';
import {
@ -105,6 +106,7 @@ export class CoreSystem {
private readonly executionContext: ExecutionContextService;
private readonly customBranding: CustomBrandingService;
private readonly security: SecurityService;
private readonly userProfile: UserProfileService;
private fatalErrorsSetup: FatalErrorsSetup | null = null;
constructor(params: CoreSystemParams) {
@ -130,6 +132,7 @@ export class CoreSystem {
this.stop();
});
this.security = new SecurityService(this.coreContext);
this.userProfile = new UserProfileService(this.coreContext);
this.theme = new ThemeService();
this.notifications = new NotificationsService();
this.http = new HttpService();
@ -238,6 +241,7 @@ export class CoreSystem {
executionContext,
});
const security = this.security.setup();
const userProfile = this.userProfile.setup();
this.chrome.setup({ analytics });
const uiSettings = this.uiSettings.setup({ http, injectedMetadata });
const settings = this.settings.setup({ http, injectedMetadata });
@ -260,6 +264,7 @@ export class CoreSystem {
executionContext,
customBranding,
security,
userProfile,
};
// Services that do not expose contracts at setup
@ -285,6 +290,7 @@ export class CoreSystem {
try {
const analytics = this.analytics.start();
const security = this.security.start();
const userProfile = this.userProfile.start();
const injectedMetadata = await this.injectedMetadata.start();
const uiSettings = await this.uiSettings.start();
const settings = await this.settings.start();
@ -360,6 +366,7 @@ export class CoreSystem {
deprecations,
customBranding,
security,
userProfile,
};
await this.plugins.start(core);
@ -423,6 +430,7 @@ export class CoreSystem {
this.theme.stop();
this.analytics.stop();
this.security.stop();
this.userProfile.stop();
this.rootDomElement.textContent = '';
}

View file

@ -64,6 +64,8 @@
"@kbn/core-custom-branding-browser-mocks",
"@kbn/core-security-browser-mocks",
"@kbn/core-security-browser-internal",
"@kbn/core-user-profile-browser-mocks",
"@kbn/core-user-profile-browser-internal",
],
"exclude": [
"target/**/*",

View file

@ -23,6 +23,7 @@ import { deprecationsServiceMock } from '@kbn/core-deprecations-server-mocks';
import { docLinksServiceMock } from '@kbn/core-doc-links-server-mocks';
import { userSettingsServiceMock } from '@kbn/core-user-settings-server-mocks';
import { securityServiceMock } from '@kbn/core-security-server-mocks';
import { userProfileServiceMock } from '@kbn/core-user-profile-server-mocks';
export const mockHttpService = httpServiceMock.create();
jest.doMock('@kbn/core-http-server-internal', () => ({
@ -140,6 +141,11 @@ jest.doMock('@kbn/core-security-server-internal', () => ({
SecurityService: jest.fn(() => mockSecurityService),
}));
export const mockUserProfileService = userProfileServiceMock.create();
jest.doMock('@kbn/core-user-profile-server-internal', () => ({
UserProfileService: jest.fn(() => mockUserProfileService),
}));
export const mockUsageDataService = coreUsageDataServiceMock.create();
jest.doMock('@kbn/core-usage-data-server-internal', () => ({
CoreUsageDataService: jest.fn(() => mockUsageDataService),

View file

@ -28,6 +28,7 @@ import {
mockCustomBrandingService,
mockUserSettingsService,
mockSecurityService,
mockUserProfileService,
} from './server.test.mocks';
import { BehaviorSubject } from 'rxjs';
@ -129,6 +130,8 @@ test('sets up services on "setup"', async () => {
expect(mockCustomBrandingService.setup).not.toHaveBeenCalled();
expect(mockUserSettingsService.setup).not.toHaveBeenCalled();
expect(mockSecurityService.setup).not.toHaveBeenCalled();
expect(mockSecurityService.setup).not.toHaveBeenCalled();
expect(mockUserProfileService.setup).not.toHaveBeenCalled();
await server.setup();
@ -148,6 +151,7 @@ test('sets up services on "setup"', async () => {
expect(mockCustomBrandingService.setup).toHaveBeenCalledTimes(1);
expect(mockUserSettingsService.setup).toHaveBeenCalledTimes(1);
expect(mockSecurityService.setup).toHaveBeenCalledTimes(1);
expect(mockUserProfileService.setup).toHaveBeenCalledTimes(1);
});
test('injects legacy dependency to context#setup()', async () => {
@ -201,6 +205,7 @@ test('runs services on "start"', async () => {
expect(mockDocLinksService.start).not.toHaveBeenCalled();
expect(mockCustomBrandingService.start).not.toHaveBeenCalled();
expect(mockSecurityService.start).not.toHaveBeenCalled();
expect(mockUserProfileService.start).not.toHaveBeenCalled();
await server.start();
@ -213,6 +218,7 @@ test('runs services on "start"', async () => {
expect(mockDocLinksService.start).toHaveBeenCalledTimes(1);
expect(mockCustomBrandingService.start).toHaveBeenCalledTimes(1);
expect(mockSecurityService.start).toHaveBeenCalledTimes(1);
expect(mockUserProfileService.start).toHaveBeenCalledTimes(1);
});
test('does not fail on "setup" if there are unused paths detected', async () => {
@ -241,6 +247,7 @@ test('stops services on "stop"', async () => {
expect(mockLoggingService.stop).not.toHaveBeenCalled();
expect(mockCustomBrandingService.stop).not.toHaveBeenCalled();
expect(mockSecurityService.stop).not.toHaveBeenCalled();
expect(mockUserProfileService.stop).not.toHaveBeenCalled();
await server.stop();
@ -255,6 +262,7 @@ test('stops services on "stop"', async () => {
expect(mockLoggingService.stop).toHaveBeenCalledTimes(1);
expect(mockCustomBrandingService.stop).toHaveBeenCalledTimes(1);
expect(mockSecurityService.stop).toHaveBeenCalledTimes(1);
expect(mockUserProfileService.stop).toHaveBeenCalledTimes(1);
});
test(`doesn't preboot core services if config validation fails`, async () => {

View file

@ -52,6 +52,7 @@ import type {
import { DiscoveredPlugins, PluginsService } from '@kbn/core-plugins-server-internal';
import { CoreAppsService } from '@kbn/core-apps-server-internal';
import { SecurityService } from '@kbn/core-security-server-internal';
import { UserProfileService } from '@kbn/core-user-profile-server-internal';
import { registerServiceConfig } from './register_service_config';
import { MIGRATION_EXCEPTION_CODE } from './constants';
import { coreConfig, type CoreConfigType } from './core_config';
@ -89,6 +90,7 @@ export class Server {
private readonly customBranding: CustomBrandingService;
private readonly userSettingsService: UserSettingsService;
private readonly security: SecurityService;
private readonly userProfile: UserProfileService;
private readonly savedObjectsStartPromise: Promise<SavedObjectsServiceStart>;
private resolveSavedObjectsStartPromise?: (value: SavedObjectsServiceStart) => void;
@ -138,6 +140,7 @@ export class Server {
this.customBranding = new CustomBrandingService(core);
this.userSettingsService = new UserSettingsService(core);
this.security = new SecurityService(core);
this.userProfile = new UserProfileService(core);
this.savedObjectsStartPromise = new Promise((resolve) => {
this.resolveSavedObjectsStartPromise = resolve;
@ -258,6 +261,7 @@ export class Server {
const executionContextSetup = this.executionContext.setup();
const docLinksSetup = this.docLinks.setup();
const securitySetup = this.security.setup();
const userProfileSetup = this.userProfile.setup();
const httpSetup = await this.http.setup({
context: contextServiceSetup,
@ -355,6 +359,7 @@ export class Server {
coreUsageData: coreUsageDataSetup,
userSettings: userSettingsServiceSetup,
security: securitySetup,
userProfile: userProfileSetup,
};
const pluginsSetup = await this.plugins.setup(coreSetup);
@ -375,6 +380,7 @@ export class Server {
const analyticsStart = this.analytics.start();
const securityStart = this.security.start();
const userProfileStart = this.userProfile.start();
const executionContextStart = this.executionContext.start();
const docLinkStart = this.docLinks.start();
@ -435,6 +441,7 @@ export class Server {
coreUsageData: coreUsageDataStart,
deprecations: deprecationsStart,
security: securityStart,
userProfile: userProfileStart,
};
await this.plugins.start(this.coreStart);
@ -470,6 +477,7 @@ export class Server {
this.node.stop();
this.deprecations.stop();
this.security.stop();
this.userProfile.stop();
}
private registerCoreContext(coreSetup: InternalCoreSetup) {

View file

@ -74,6 +74,8 @@
"@kbn/core-security-server-mocks",
"@kbn/core-security-server-internal",
"@kbn/core-usage-data-server-mocks",
"@kbn/core-user-profile-server-mocks",
"@kbn/core-user-profile-server-internal",
],
"exclude": [
"target/**/*",

View file

@ -13,11 +13,11 @@ import {
import { loggerMock } from '@kbn/logging-mocks';
import { coreContextMock } from '@kbn/core-base-browser-mocks';
import type { CoreSecurityContract } from '@kbn/core-security-browser';
import type { CoreSecurityDelegateContract } from '@kbn/core-security-browser';
import { SecurityService } from './security_service';
const createStubInternalContract = (): CoreSecurityContract => {
return Symbol('stubContract') as unknown as CoreSecurityContract;
const createStubInternalContract = (): CoreSecurityDelegateContract => {
return Symbol('stubContract') as unknown as CoreSecurityDelegateContract;
};
describe('SecurityService', () => {
@ -33,14 +33,14 @@ describe('SecurityService', () => {
});
describe('#setup', () => {
describe('#registerSecurityApi', () => {
describe('#registerSecurityDelegate', () => {
it('throws if called more than once', () => {
const { registerSecurityApi } = service.setup();
const { registerSecurityDelegate } = service.setup();
const contract = createStubInternalContract();
registerSecurityApi(contract);
registerSecurityDelegate(contract);
expect(() => registerSecurityApi(contract)).toThrowErrorMatchingInlineSnapshot(
expect(() => registerSecurityDelegate(contract)).toThrowErrorMatchingInlineSnapshot(
`"security API can only be registered once"`
);
});
@ -62,10 +62,10 @@ describe('SecurityService', () => {
});
it('calls convertSecurityApi with the registered API', () => {
const { registerSecurityApi } = service.setup();
const { registerSecurityDelegate } = service.setup();
const contract = createStubInternalContract();
registerSecurityApi(contract);
registerSecurityDelegate(contract);
service.start();

View file

@ -8,7 +8,7 @@
import type { Logger } from '@kbn/logging';
import type { CoreContext, CoreService } from '@kbn/core-base-browser-internal';
import type { CoreSecurityContract } from '@kbn/core-security-browser';
import type { CoreSecurityDelegateContract } from '@kbn/core-security-browser';
import type {
InternalSecurityServiceSetup,
InternalSecurityServiceStart,
@ -19,7 +19,7 @@ export class SecurityService
implements CoreService<InternalSecurityServiceSetup, InternalSecurityServiceStart>
{
private readonly log: Logger;
private securityApi?: CoreSecurityContract;
private securityApi?: CoreSecurityDelegateContract;
constructor(coreContext: CoreContext) {
this.log = coreContext.logger.get('security-service');
@ -27,7 +27,7 @@ export class SecurityService
public setup(): InternalSecurityServiceSetup {
return {
registerSecurityApi: (api) => {
registerSecurityDelegate: (api) => {
if (this.securityApi) {
throw new Error('security API can only be registered once');
}

View file

@ -6,12 +6,12 @@
* Side Public License, v 1.
*/
import type { CoreSecurityContract } from '@kbn/core-security-browser';
import type { CoreSecurityDelegateContract } from '@kbn/core-security-browser';
import { convertSecurityApi } from './convert_security_api';
describe('convertSecurityApi', () => {
it('returns the API from the source', () => {
const source: CoreSecurityContract = { authc: { getCurrentUser: jest.fn() } };
const source: CoreSecurityDelegateContract = { authc: { getCurrentUser: jest.fn() } };
const output = convertSecurityApi(source);
expect(output.authc.getCurrentUser).toBe(source.authc.getCurrentUser);
});

View file

@ -6,11 +6,11 @@
* Side Public License, v 1.
*/
import type { CoreSecurityContract } from '@kbn/core-security-browser';
import type { CoreSecurityDelegateContract } from '@kbn/core-security-browser';
import type { InternalSecurityServiceStart } from '../internal_contracts';
export const convertSecurityApi = (
privateApi: CoreSecurityContract
privateApi: CoreSecurityDelegateContract
): InternalSecurityServiceStart => {
// shapes are the same for now given we only have one API exposed.
return privateApi;

View file

@ -6,11 +6,11 @@
* Side Public License, v 1.
*/
import type { CoreSecurityContract } from '@kbn/core-security-browser';
import type { CoreSecurityDelegateContract } from '@kbn/core-security-browser';
import { getDefaultSecurityImplementation } from './default_implementation';
describe('getDefaultSecurityImplementation', () => {
let implementation: CoreSecurityContract;
let implementation: CoreSecurityDelegateContract;
beforeEach(() => {
implementation = getDefaultSecurityImplementation();

View file

@ -6,9 +6,9 @@
* Side Public License, v 1.
*/
import type { CoreSecurityContract } from '@kbn/core-security-browser';
import type { CoreSecurityDelegateContract } from '@kbn/core-security-browser';
export const getDefaultSecurityImplementation = (): CoreSecurityContract => {
export const getDefaultSecurityImplementation = (): CoreSecurityDelegateContract => {
return {
authc: {
getCurrentUser: () => {

View file

@ -14,7 +14,7 @@ import type {
const createSetupMock = () => {
const mock: jest.Mocked<SecurityServiceSetup> = {
registerSecurityApi: jest.fn(),
registerSecurityDelegate: jest.fn(),
};
return mock;
@ -32,7 +32,7 @@ const createStartMock = () => {
const createInternalSetupMock = () => {
const mock: jest.Mocked<InternalSecurityServiceSetup> = {
registerSecurityApi: jest.fn(),
registerSecurityDelegate: jest.fn(),
};
return mock;

View file

@ -8,4 +8,7 @@
export type { SecurityServiceSetup, SecurityServiceStart } from './src/contracts';
export type { CoreAuthenticationService } from './src/authc';
export type { CoreSecurityContract, AuthenticationServiceContract } from './src/api_provider';
export type {
CoreSecurityDelegateContract,
AuthenticationServiceContract,
} from './src/api_provider';

View file

@ -14,7 +14,7 @@ import type { CoreAuthenticationService } from './authc';
*
* @public
*/
export interface CoreSecurityContract {
export interface CoreSecurityDelegateContract {
authc: AuthenticationServiceContract;
}

View file

@ -7,7 +7,7 @@
*/
import type { CoreAuthenticationService } from './authc';
import type { CoreSecurityContract } from './api_provider';
import type { CoreSecurityDelegateContract } from './api_provider';
/**
* Setup contract for Core's security service.
@ -20,7 +20,7 @@ export interface SecurityServiceSetup {
*
* @remark this should **exclusively** be used by the security plugin.
*/
registerSecurityApi(api: CoreSecurityContract): void;
registerSecurityDelegate(api: CoreSecurityDelegateContract): void;
}
/**

View file

@ -13,11 +13,11 @@ import {
import { loggerMock, MockedLogger } from '@kbn/logging-mocks';
import { mockCoreContext } from '@kbn/core-base-server-mocks';
import type { CoreSecurityContract } from '@kbn/core-security-server';
import type { CoreSecurityDelegateContract } from '@kbn/core-security-server';
import { SecurityService } from './security_service';
const createStubInternalContract = (): CoreSecurityContract => {
return Symbol('stubContract') as unknown as CoreSecurityContract;
const createStubInternalContract = (): CoreSecurityDelegateContract => {
return Symbol('stubContract') as unknown as CoreSecurityDelegateContract;
};
describe('SecurityService', () => {
@ -33,14 +33,14 @@ describe('SecurityService', () => {
});
describe('#setup', () => {
describe('#registerSecurityApi', () => {
describe('#registerSecurityDelegate', () => {
it('throws if called more than once', () => {
const { registerSecurityApi } = service.setup();
const { registerSecurityDelegate } = service.setup();
const contract = createStubInternalContract();
registerSecurityApi(contract);
registerSecurityDelegate(contract);
expect(() => registerSecurityApi(contract)).toThrowErrorMatchingInlineSnapshot(
expect(() => registerSecurityDelegate(contract)).toThrowErrorMatchingInlineSnapshot(
`"security API can only be registered once"`
);
});
@ -62,10 +62,10 @@ describe('SecurityService', () => {
});
it('calls convertSecurityApi with the registered API', () => {
const { registerSecurityApi } = service.setup();
const { registerSecurityDelegate } = service.setup();
const contract = createStubInternalContract();
registerSecurityApi(contract);
registerSecurityDelegate(contract);
service.start();

View file

@ -8,7 +8,7 @@
import type { Logger } from '@kbn/logging';
import type { CoreContext, CoreService } from '@kbn/core-base-server-internal';
import type { CoreSecurityContract } from '@kbn/core-security-server';
import type { CoreSecurityDelegateContract } from '@kbn/core-security-server';
import type {
InternalSecurityServiceSetup,
InternalSecurityServiceStart,
@ -19,7 +19,7 @@ export class SecurityService
implements CoreService<InternalSecurityServiceSetup, InternalSecurityServiceStart>
{
private readonly log: Logger;
private securityApi?: CoreSecurityContract;
private securityApi?: CoreSecurityDelegateContract;
constructor(coreContext: CoreContext) {
this.log = coreContext.logger.get('security-service');
@ -27,7 +27,7 @@ export class SecurityService
public setup(): InternalSecurityServiceSetup {
return {
registerSecurityApi: (api) => {
registerSecurityDelegate: (api) => {
if (this.securityApi) {
throw new Error('security API can only be registered once');
}

View file

@ -6,12 +6,12 @@
* Side Public License, v 1.
*/
import type { CoreSecurityContract } from '@kbn/core-security-server';
import type { CoreSecurityDelegateContract } from '@kbn/core-security-server';
import { convertSecurityApi } from './convert_security_api';
describe('convertSecurityApi', () => {
it('returns the API from the source', () => {
const source: CoreSecurityContract = { authc: { getCurrentUser: jest.fn() } };
const source: CoreSecurityDelegateContract = { authc: { getCurrentUser: jest.fn() } };
const output = convertSecurityApi(source);
expect(output.authc.getCurrentUser).toBe(source.authc.getCurrentUser);
});

View file

@ -6,11 +6,11 @@
* Side Public License, v 1.
*/
import type { CoreSecurityContract } from '@kbn/core-security-server';
import type { CoreSecurityDelegateContract } from '@kbn/core-security-server';
import type { InternalSecurityServiceStart } from '../internal_contracts';
export const convertSecurityApi = (
privateApi: CoreSecurityContract
privateApi: CoreSecurityDelegateContract
): InternalSecurityServiceStart => {
// shapes are the same for now given we only have one API exposed.
return privateApi;

View file

@ -6,11 +6,11 @@
* Side Public License, v 1.
*/
import type { CoreSecurityContract } from '@kbn/core-security-server';
import type { CoreSecurityDelegateContract } from '@kbn/core-security-server';
import { getDefaultSecurityImplementation } from './default_implementation';
describe('getDefaultSecurityImplementation', () => {
let implementation: CoreSecurityContract;
let implementation: CoreSecurityDelegateContract;
beforeEach(() => {
implementation = getDefaultSecurityImplementation();

View file

@ -6,9 +6,9 @@
* Side Public License, v 1.
*/
import type { CoreSecurityContract } from '@kbn/core-security-server';
import type { CoreSecurityDelegateContract } from '@kbn/core-security-server';
export const getDefaultSecurityImplementation = (): CoreSecurityContract => {
export const getDefaultSecurityImplementation = (): CoreSecurityDelegateContract => {
return {
authc: {
getCurrentUser: () => null,

View file

@ -18,7 +18,7 @@ import type {
const createSetupMock = () => {
const mock: jest.Mocked<SecurityServiceSetup> = {
registerSecurityApi: jest.fn(),
registerSecurityDelegate: jest.fn(),
};
return mock;
@ -36,7 +36,7 @@ const createStartMock = () => {
const createInternalSetupMock = () => {
const mock: jest.Mocked<InternalSecurityServiceSetup> = {
registerSecurityApi: jest.fn(),
registerSecurityDelegate: jest.fn(),
};
return mock;

View file

@ -8,7 +8,10 @@
export type { SecurityServiceSetup, SecurityServiceStart } from './src/contracts';
export type { CoreAuthenticationService } from './src/authc';
export type { CoreSecurityContract, AuthenticationServiceContract } from './src/api_provider';
export type {
CoreSecurityDelegateContract,
AuthenticationServiceContract,
} from './src/api_provider';
export type {
SecurityRequestHandlerContext,
AuthcRequestHandlerContext,

View file

@ -14,7 +14,7 @@ import type { CoreAuthenticationService } from './authc';
*
* @public
*/
export interface CoreSecurityContract {
export interface CoreSecurityDelegateContract {
authc: AuthenticationServiceContract;
}

View file

@ -7,7 +7,7 @@
*/
import type { CoreAuthenticationService } from './authc';
import type { CoreSecurityContract } from './api_provider';
import type { CoreSecurityDelegateContract } from './api_provider';
/**
* Setup contract for Core's security service.
@ -20,7 +20,7 @@ export interface SecurityServiceSetup {
*
* @remark this should **exclusively** be used by the security plugin.
*/
registerSecurityApi(api: CoreSecurityContract): void;
registerSecurityDelegate(api: CoreSecurityDelegateContract): void;
}
/**

View file

@ -0,0 +1,3 @@
# @kbn/core-user-profile-browser-internal
This package contains the internal types and implementation for Core's browser-side `userProfile` service.

View file

@ -0,0 +1,12 @@
/*
* 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.
*/
export { UserProfileService } from './src/user_profile_service';
export type {
InternalUserProfileServiceSetup,
InternalUserProfileServiceStart,
} from './src/internal_contracts';

View file

@ -0,0 +1,13 @@
/*
* 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.
*/
module.exports = {
preset: '@kbn/test',
rootDir: '../../../..',
roots: ['<rootDir>/packages/core/user-profile/core-user-profile-browser-internal'],
};

View file

@ -0,0 +1,5 @@
{
"type": "shared-common",
"id": "@kbn/core-user-profile-browser-internal",
"owner": "@elastic/kibana-core"
}

View file

@ -0,0 +1,6 @@
{
"name": "@kbn/core-user-profile-browser-internal",
"private": true,
"version": "1.0.0",
"license": "SSPL-1.0 OR Elastic License 2.0"
}

View file

@ -0,0 +1,15 @@
/*
* 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 {
UserProfileServiceSetup,
UserProfileServiceStart,
} from '@kbn/core-user-profile-browser';
export type InternalUserProfileServiceSetup = UserProfileServiceSetup;
export type InternalUserProfileServiceStart = UserProfileServiceStart;

View file

@ -0,0 +1,19 @@
/*
* 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.
*/
export const getDefaultUserProfileImplementationMock = jest.fn();
export const convertUserProfileAPIMock = jest.fn();
jest.doMock('./utils', () => {
const actual = jest.requireActual('./utils');
return {
...actual,
getDefaultUserProfileImplementation: getDefaultUserProfileImplementationMock,
convertUserProfileAPI: convertUserProfileAPIMock,
};
});

View file

@ -0,0 +1,97 @@
/*
* 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 {
convertUserProfileAPIMock,
getDefaultUserProfileImplementationMock,
} from './user_profile_service.test.mocks';
import { loggerMock, MockedLogger } from '@kbn/logging-mocks';
import { mockCoreContext } from '@kbn/core-base-server-mocks';
import type { CoreUserProfileDelegateContract } from '@kbn/core-user-profile-browser';
import { UserProfileService } from './user_profile_service';
const createStubContract = (): CoreUserProfileDelegateContract => {
return Symbol('stubContract') as unknown as CoreUserProfileDelegateContract;
};
describe('UserProfileService', () => {
let coreContext: ReturnType<typeof mockCoreContext.create>;
let service: UserProfileService;
beforeEach(() => {
coreContext = mockCoreContext.create();
service = new UserProfileService(coreContext);
convertUserProfileAPIMock.mockReset();
getDefaultUserProfileImplementationMock.mockReset();
});
describe('#setup', () => {
describe('#registerUserProfileDelegate', () => {
it('throws if called more than once', () => {
const { registerUserProfileDelegate } = service.setup();
const contract = createStubContract();
registerUserProfileDelegate(contract);
expect(() => registerUserProfileDelegate(contract)).toThrowErrorMatchingInlineSnapshot(
`"userProfile API can only be registered once"`
);
});
});
});
describe('#start', () => {
it('logs a warning if the userProfile API was not registered', () => {
service.setup();
service.start();
expect(loggerMock.collect(coreContext.logger as MockedLogger).warn).toMatchInlineSnapshot(`
Array [
Array [
"userProfile API was not registered, using default implementation",
],
]
`);
});
it('calls convertUserProfileAPI with the registered API', () => {
const { registerUserProfileDelegate } = service.setup();
const contract = createStubContract();
registerUserProfileDelegate(contract);
service.start();
expect(convertUserProfileAPIMock).toHaveBeenCalledTimes(1);
expect(convertUserProfileAPIMock).toHaveBeenCalledWith(contract);
});
it('calls convertUserProfileAPI with the default implementation when no API was registered', () => {
const contract = createStubContract();
getDefaultUserProfileImplementationMock.mockReturnValue(contract);
service.setup();
service.start();
expect(convertUserProfileAPIMock).toHaveBeenCalledTimes(1);
expect(convertUserProfileAPIMock).toHaveBeenCalledWith(contract);
});
it('returns the result of convertUserProfileAPI as contract', () => {
const convertedContract = { stub: true };
convertUserProfileAPIMock.mockReturnValue(convertedContract);
service.setup();
const startContract = service.start();
expect(startContract).toEqual(convertedContract);
});
});
});

View file

@ -0,0 +1,48 @@
/*
* 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 { Logger } from '@kbn/logging';
import type { CoreContext, CoreService } from '@kbn/core-base-browser-internal';
import type { CoreUserProfileDelegateContract } from '@kbn/core-user-profile-browser';
import type {
InternalUserProfileServiceSetup,
InternalUserProfileServiceStart,
} from './internal_contracts';
import { getDefaultUserProfileImplementation, convertUserProfileAPI } from './utils';
export class UserProfileService
implements CoreService<InternalUserProfileServiceSetup, InternalUserProfileServiceStart>
{
private readonly log: Logger;
private delegate?: CoreUserProfileDelegateContract;
constructor(coreContext: CoreContext) {
this.log = coreContext.logger.get('user-profile-service');
}
public setup(): InternalUserProfileServiceSetup {
return {
registerUserProfileDelegate: (delegate) => {
if (this.delegate) {
throw new Error('userProfile API can only be registered once');
}
this.delegate = delegate;
},
};
}
public start(): InternalUserProfileServiceStart {
if (!this.delegate) {
this.log.warn('userProfile API was not registered, using default implementation');
}
const apiContract = this.delegate ?? getDefaultUserProfileImplementation();
return convertUserProfileAPI(apiContract);
}
public stop() {}
}

View file

@ -0,0 +1,76 @@
/*
* 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 { of } from 'rxjs';
import type { CoreUserProfileDelegateContract } from '@kbn/core-user-profile-browser';
import type { InternalUserProfileServiceStart } from '../internal_contracts';
import { convertUserProfileAPI } from './convert_api';
describe('convertUserProfileAPI', () => {
let source: jest.Mocked<CoreUserProfileDelegateContract>;
let output: InternalUserProfileServiceStart;
beforeEach(() => {
source = {
userProfile$: of(null),
getCurrent: jest.fn(),
bulkGet: jest.fn(),
suggest: jest.fn(),
update: jest.fn(),
partialUpdate: jest.fn(),
};
output = convertUserProfileAPI(source);
});
describe('getUserProfile$', () => {
it('returns the observable from the source', () => {
expect(output.getUserProfile$()).toBe(source.userProfile$);
});
});
describe('getCurrent', () => {
it('calls the API from the source with the correct parameters', () => {
output.getCurrent();
expect(source.getCurrent).toHaveBeenCalledTimes(1);
expect(source.getCurrent).toHaveBeenCalledWith();
});
});
describe('bulkGet', () => {
it('calls the API from the source with the correct parameters', () => {
const params = { uids: new Set<string>(['fake-uid-1', 'fake-uid-2', 'fake-uid-3']) };
output.bulkGet(params);
expect(source.bulkGet).toHaveBeenCalledTimes(1);
expect(source.bulkGet).toHaveBeenCalledWith(params);
});
});
describe('suggest', () => {
it('calls the API from the source with the correct parameters', () => {
output.suggest('path', { name: 'foo' });
expect(source.suggest).toHaveBeenCalledTimes(1);
expect(source.suggest).toHaveBeenCalledWith('path', { name: 'foo' });
});
});
describe('update', () => {
it('calls the API from the source with the correct parameters', () => {
output.update({ foo: 'dolly' });
expect(source.update).toHaveBeenCalledTimes(1);
expect(source.update).toHaveBeenCalledWith({ foo: 'dolly' });
});
});
describe('partialUpdate', () => {
it('calls the API from the source with the correct parameters', () => {
output.partialUpdate({ foo: 'dolly' });
expect(source.partialUpdate).toHaveBeenCalledTimes(1);
expect(source.partialUpdate).toHaveBeenCalledWith({ foo: 'dolly' });
});
});
});

View file

@ -0,0 +1,23 @@
/*
* 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 { CoreUserProfileDelegateContract } from '@kbn/core-user-profile-browser';
import type { InternalUserProfileServiceStart } from '../internal_contracts';
export const convertUserProfileAPI = (
delegate: CoreUserProfileDelegateContract
): InternalUserProfileServiceStart => {
return {
getUserProfile$: () => delegate.userProfile$,
getCurrent: delegate.getCurrent.bind(delegate),
bulkGet: delegate.bulkGet.bind(delegate),
suggest: delegate.suggest.bind(delegate),
update: delegate.update.bind(delegate),
partialUpdate: delegate.partialUpdate.bind(delegate),
};
};

View file

@ -0,0 +1,34 @@
/*
* 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 { CoreUserProfileDelegateContract } from '@kbn/core-user-profile-browser';
import { getDefaultUserProfileImplementation } from './default_implementation';
describe('getDefaultUserProfileImplementation', () => {
let implementation: CoreUserProfileDelegateContract;
beforeEach(() => {
implementation = getDefaultUserProfileImplementation();
});
it('getCurrent resolves to null', async () => {
expect(await implementation.getCurrent({ dataPath: '/data-path' })).toBeNull();
});
it('bulkGet resolves to empty list', async () => {
expect(await implementation.bulkGet({ uids: new Set() })).toEqual([]);
});
it('suggest resolves to empty list', async () => {
expect(await implementation.suggest('/suggest', { name: 'foo' })).toEqual([]);
});
it('update resolves to undefined', async () => {
expect(await implementation.update({})).toBeUndefined();
});
it('partialUpdate resolves to undefined', async () => {
expect(await implementation.update({})).toBeUndefined();
});
});

View file

@ -0,0 +1,26 @@
/*
* 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 { of } from 'rxjs';
import type {
CoreUserProfileDelegateContract,
GetUserProfileResponse,
} from '@kbn/core-user-profile-browser';
import { UserProfileData } from '@kbn/core-user-profile-common';
export const getDefaultUserProfileImplementation = (): CoreUserProfileDelegateContract => {
return {
userProfile$: of(null),
getCurrent: <D extends UserProfileData>() =>
Promise.resolve(null as unknown as GetUserProfileResponse<D>),
bulkGet: () => Promise.resolve([]),
suggest: () => Promise.resolve([]),
update: () => Promise.resolve(),
partialUpdate: () => Promise.resolve(),
};
};

View file

@ -0,0 +1,10 @@
/*
* 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.
*/
export { convertUserProfileAPI } from './convert_api';
export { getDefaultUserProfileImplementation } from './default_implementation';

View file

@ -0,0 +1,26 @@
{
"extends": "../../../../tsconfig.base.json",
"compilerOptions": {
"outDir": "target/types",
"types": [
"jest",
"node",
"react"
]
},
"include": [
"**/*.ts",
"**/*.tsx",
],
"exclude": [
"target/**/*"
],
"kbn_references": [
"@kbn/core-user-profile-browser",
"@kbn/logging-mocks",
"@kbn/core-base-server-mocks",
"@kbn/logging",
"@kbn/core-base-browser-internal",
"@kbn/core-user-profile-common",
]
}

View file

@ -0,0 +1,3 @@
# @kbn/core-user-profile-browser-mocks
This package contains mocks types for Core's browser-side `userProfile` service.

View file

@ -0,0 +1,9 @@
/*
* 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.
*/
export { userProfileServiceMock } from './src/user_profile_service.mock';

View file

@ -0,0 +1,13 @@
/*
* 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.
*/
module.exports = {
preset: '@kbn/test',
rootDir: '../../../..',
roots: ['<rootDir>/packages/core/user-profile/core-user-profile-browser-mocks'],
};

View file

@ -0,0 +1,5 @@
{
"type": "shared-common",
"id": "@kbn/core-user-profile-browser-mocks",
"owner": "@elastic/kibana-core"
}

View file

@ -0,0 +1,6 @@
{
"name": "@kbn/core-user-profile-browser-mocks",
"private": true,
"version": "1.0.0",
"license": "SSPL-1.0 OR Elastic License 2.0"
}

View file

@ -0,0 +1,76 @@
/*
* 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 {
UserProfileServiceSetup,
UserProfileServiceStart,
} from '@kbn/core-user-profile-browser';
import type {
InternalUserProfileServiceSetup,
InternalUserProfileServiceStart,
} from '@kbn/core-user-profile-browser-internal';
const createSetupMock = () => {
const mock: jest.Mocked<UserProfileServiceSetup> = {
registerUserProfileDelegate: jest.fn(),
};
return mock;
};
const createStartMock = () => {
const mock: jest.Mocked<UserProfileServiceStart> = {
getUserProfile$: jest.fn(),
getCurrent: jest.fn(),
bulkGet: jest.fn(),
suggest: jest.fn(),
update: jest.fn(),
partialUpdate: jest.fn(),
};
return mock;
};
const createInternalSetupMock = () => {
const mock: jest.Mocked<InternalUserProfileServiceSetup> = {
registerUserProfileDelegate: jest.fn(),
};
return mock;
};
const createInternalStartMock = () => {
const mock: jest.Mocked<InternalUserProfileServiceStart> = {
getUserProfile$: jest.fn(),
getCurrent: jest.fn(),
bulkGet: jest.fn(),
suggest: jest.fn(),
update: jest.fn(),
partialUpdate: jest.fn(),
};
return mock;
};
const createServiceMock = () => {
const mock = {
setup: jest.fn().mockReturnValue(createSetupMock()),
start: jest.fn().mockReturnValue(createStartMock()),
stop: jest.fn(),
};
return mock;
};
export const userProfileServiceMock = {
create: createServiceMock,
createSetup: createSetupMock,
createStart: createStartMock,
createInternalSetup: createInternalSetupMock,
createInternalStart: createInternalStartMock,
};

View file

@ -0,0 +1,22 @@
{
"extends": "../../../../tsconfig.base.json",
"compilerOptions": {
"outDir": "target/types",
"types": [
"jest",
"node",
"react"
]
},
"include": [
"**/*.ts",
"**/*.tsx",
],
"exclude": [
"target/**/*"
],
"kbn_references": [
"@kbn/core-user-profile-browser",
"@kbn/core-user-profile-browser-internal",
]
}

View file

@ -0,0 +1,3 @@
# @kbn/core-user-profile-browser
This package contains the public types for Core's browser-side `userProfile` service.

View file

@ -0,0 +1,17 @@
/*
* 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.
*/
export type { UserProfileServiceSetup, UserProfileServiceStart } from './src/contracts';
export type { CoreUserProfileDelegateContract } from './src/api_provider';
export type {
UserProfileService,
UserProfileSuggestParams,
UserProfileBulkGetParams,
GetUserProfileResponse,
UserProfileGetCurrentParams,
} from './src/service';

View file

@ -0,0 +1,13 @@
/*
* 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.
*/
module.exports = {
preset: '@kbn/test',
rootDir: '../../../..',
roots: ['<rootDir>/packages/core/user-profile/core-user-profile-browser'],
};

View file

@ -0,0 +1,5 @@
{
"type": "shared-common",
"id": "@kbn/core-user-profile-browser",
"owner": "@elastic/kibana-core"
}

View file

@ -0,0 +1,6 @@
{
"name": "@kbn/core-user-profile-browser",
"private": true,
"version": "1.0.0",
"license": "SSPL-1.0 OR Elastic License 2.0"
}

View file

@ -0,0 +1,14 @@
/*
* 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 { Observable } from 'rxjs';
import type { UserProfileData } from '@kbn/core-user-profile-common';
import type { UserProfileService } from './service';
export type CoreUserProfileDelegateContract = Omit<UserProfileService, 'getUserProfile$'> & {
userProfile$: Observable<UserProfileData | null>;
};

View file

@ -0,0 +1,31 @@
/*
* 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 { UserProfileService } from './service';
import type { CoreUserProfileDelegateContract } from './api_provider';
/**
* Setup contract for Core's userProfile service.
*
* @public
*/
export interface UserProfileServiceSetup {
/**
* Register the userProfile implementation that will be used and re-exposed by Core.
*
* @remark this should **exclusively** be used by the security plugin.
*/
registerUserProfileDelegate(delegate: CoreUserProfileDelegateContract): void;
}
/**
* Start contract for Core's userProfile service.
*
* @public
*/
export type UserProfileServiceStart = UserProfileService;

View file

@ -0,0 +1,135 @@
/*
* 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 { Observable } from 'rxjs';
import type { AuthenticatedUser } from '@kbn/core-security-common';
import type {
UserProfileData,
UserProfileWithSecurity,
UserProfile,
} from '@kbn/core-user-profile-common';
export interface UserProfileService {
/**
* Retrieve an observable emitting when the user profile is loaded.
*/
getUserProfile$(): Observable<UserProfileData | null>;
/**
* Retrieves the user profile of the current user. If the profile isn't available, e.g. for the anonymous users or
* users authenticated via authenticating proxies, the `null` value is returned.
* @param [params] Get current user profile operation parameters.
* @param params.dataPath By default `getCurrent()` returns user information, but does not return any user data. The
* optional "dataPath" parameter can be used to return personal data for this user (within `kibana` namespace only).
*/
getCurrent<D extends UserProfileData>(
params?: UserProfileGetCurrentParams
): Promise<GetUserProfileResponse<D>>;
/**
* Retrieves multiple user profiles by their identifiers.
* @param params Bulk get operation parameters.
* @param params.uids List of user profile identifiers.
* @param params.dataPath By default Elasticsearch returns user information, but does not return any user data. The
* optional "dataPath" parameter can be used to return personal data for the requested user
* profiles (within `kibana` namespace only).
*/
bulkGet<D extends UserProfileData>(
params: UserProfileBulkGetParams
): Promise<Array<UserProfile<D>>>;
/**
* Suggests multiple user profiles by search criteria.
*
* Note: This endpoint is not provided out-of-the-box by the platform. You need to expose your own
* version within your app. An example of how to do this can be found in:
* `examples/user_profile_examples/server/plugin.ts`
*
* @param path Path to your app's suggest endpoint.
* @param params Suggest operation parameters.
* @param params.name Query string used to match name-related fields in user profiles. The
* following fields are treated as name-related: username, full_name and email.
* @param params.size Desired number of suggestions to return. The default value is 10.
* @param params.dataPath By default, suggest API returns user information, but does not return
* any user data. The optional "dataPath" parameter can be used to return personal data for this
* user (within `kibana` namespace only).
*/
suggest<D extends UserProfileData>(
path: string,
params: UserProfileSuggestParams
): Promise<Array<UserProfile<D>>>;
/**
* Updates user profile data of the current user.
* @param data Application data to be written (merged with existing data).
*/
update<D extends UserProfileData>(data: D): Promise<void>;
/**
* Partially updates user profile data of the current user, merging the previous data with the provided data.
* @param data Application data to be merged with existing data.
*/
partialUpdate<D extends Partial<UserProfileData>>(data: D): Promise<void>;
}
/**
* Parameters for the get user profile for the current user API.
*/
export interface UserProfileGetCurrentParams {
/**
* By default, get API returns user information, but does not return any user data. The optional "dataPath"
* parameter can be used to return personal data for this user (within `kibana` namespace only).
*/
dataPath: string;
}
export interface GetUserProfileResponse<D extends UserProfileData = UserProfileData>
extends UserProfileWithSecurity<D> {
/**
* Information about the currently authenticated user that owns the profile.
*/
user: UserProfileWithSecurity['user'] & Pick<AuthenticatedUser, 'authentication_provider'>;
}
/**
* Parameters for the bulk get API.
*/
export interface UserProfileBulkGetParams {
/**
* List of user profile identifiers.
*/
uids: Set<string>;
/**
* By default, suggest API returns user information, but does not return any user data. The optional "dataPath"
* parameter can be used to return personal data for this user (within `kibana` namespace only).
*/
dataPath?: string;
}
/**
* Parameters for the suggest API.
*/
export interface UserProfileSuggestParams {
/**
* Query string used to match name-related fields in user profiles. The following fields are treated as
* name-related: username, full_name and email.
*/
name: string;
/**
* Desired number of suggestions to return. The default value is 10.
*/
size?: number;
/**
* By default, suggest API returns user information, but does not return any user data. The optional "dataPath"
* parameter can be used to return personal data for this user (within `kibana` namespace only).
*/
dataPath?: string;
}

View file

@ -0,0 +1,22 @@
{
"extends": "../../../../tsconfig.base.json",
"compilerOptions": {
"outDir": "target/types",
"types": [
"jest",
"node",
"react"
]
},
"include": [
"**/*.ts",
"**/*.tsx",
],
"exclude": [
"target/**/*"
],
"kbn_references": [
"@kbn/core-user-profile-common",
"@kbn/core-security-common",
]
}

View file

@ -0,0 +1,3 @@
# @kbn/core-user-profile-common
This package contains the common public types for Core's `userProfile` domain.

View file

@ -0,0 +1,16 @@
/*
* 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.
*/
export type {
UserProfileData,
UserProfileLabels,
UserProfileWithSecurity,
UserProfile,
UserProfileUserInfoWithSecurity,
UserProfileUserInfo,
} from './src/user_profile';

View file

@ -0,0 +1,13 @@
/*
* 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.
*/
module.exports = {
preset: '@kbn/test',
rootDir: '../../../..',
roots: ['<rootDir>/packages/core/user-profile/core-user-profile-common'],
};

View file

@ -0,0 +1,5 @@
{
"type": "shared-common",
"id": "@kbn/core-user-profile-common",
"owner": "@elastic/kibana-core"
}

View file

@ -0,0 +1,6 @@
{
"name": "@kbn/core-user-profile-common",
"private": true,
"version": "1.0.0",
"license": "SSPL-1.0 OR Elastic License 2.0"
}

View file

@ -1,8 +1,9 @@
/*
* 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.
* 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.
*/
/**

View file

@ -0,0 +1,19 @@
{
"extends": "../../../../tsconfig.base.json",
"compilerOptions": {
"outDir": "target/types",
"types": [
"jest",
"node",
"react"
]
},
"include": [
"**/*.ts",
"**/*.tsx",
],
"exclude": [
"target/**/*"
],
"kbn_references": []
}

View file

@ -0,0 +1,3 @@
# @kbn/core-user-profile-server-internal
This package contains the internal types and implementation for Core's server-side `userProfile` service.

View file

@ -0,0 +1,14 @@
/*
* 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.
*/
export { UserProfileService } from './src/user_profile_service';
export { CoreUserProfileRouteHandlerContext } from './src/user_profile_route_handler_context';
export type {
InternalUserProfileServiceSetup,
InternalUserProfileServiceStart,
} from './src/internal_contracts';

Some files were not shown because too many files have changed in this diff Show more