From 4d7bb8a4c5ed6997d3141132fbe9b71043002f80 Mon Sep 17 00:00:00 2001 From: Vadim Yakhin Date: Tue, 1 Jun 2021 11:05:01 -0300 Subject: [PATCH 01/17] Copy lazy_wrapper and suspense_error_boundary from Spaces plugin These components are needed to enable async loading of Security components into Enterprise Search. The components are copied without any changes except for i18n ids, so it's easier to DRY out in the future if needed. --- .../public/suspense_error_boundary/index.ts | 8 +++ .../suspense_error_boundary.tsx | 54 +++++++++++++++++++ .../security/public/ui_api/lazy_wrapper.tsx | 42 +++++++++++++++ 3 files changed, 104 insertions(+) create mode 100644 x-pack/plugins/security/public/suspense_error_boundary/index.ts create mode 100644 x-pack/plugins/security/public/suspense_error_boundary/suspense_error_boundary.tsx create mode 100644 x-pack/plugins/security/public/ui_api/lazy_wrapper.tsx diff --git a/x-pack/plugins/security/public/suspense_error_boundary/index.ts b/x-pack/plugins/security/public/suspense_error_boundary/index.ts new file mode 100644 index 0000000000000..061923c8445c2 --- /dev/null +++ b/x-pack/plugins/security/public/suspense_error_boundary/index.ts @@ -0,0 +1,8 @@ +/* + * 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. + */ + +export { SuspenseErrorBoundary } from './suspense_error_boundary'; diff --git a/x-pack/plugins/security/public/suspense_error_boundary/suspense_error_boundary.tsx b/x-pack/plugins/security/public/suspense_error_boundary/suspense_error_boundary.tsx new file mode 100644 index 0000000000000..313401ff45bd9 --- /dev/null +++ b/x-pack/plugins/security/public/suspense_error_boundary/suspense_error_boundary.tsx @@ -0,0 +1,54 @@ +/* + * 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 { EuiLoadingSpinner } from '@elastic/eui'; +import type { PropsWithChildren } from 'react'; +import React, { Component, Suspense } from 'react'; + +import { i18n } from '@kbn/i18n'; +import type { NotificationsStart } from 'src/core/public'; + +interface Props { + notifications: NotificationsStart; +} + +interface State { + error: Error | null; +} + +export class SuspenseErrorBoundary extends Component, State> { + state: State = { + error: null, + }; + + static getDerivedStateFromError(error: Error) { + // Update state so next render shows fallback UI. + return { error }; + } + + public componentDidCatch(error: Error) { + const { notifications } = this.props; + if (notifications) { + const title = i18n.translate('xpack.security.uiApi.errorBoundaryToastTitle', { + defaultMessage: 'Failed to load Kibana asset', + }); + const toastMessage = i18n.translate('xpack.security.uiApi.errorBoundaryToastMessage', { + defaultMessage: 'Reload page to continue.', + }); + notifications.toasts.addError(error, { title, toastMessage }); + } + } + + render() { + const { children, notifications } = this.props; + const { error } = this.state; + if (!notifications || error) { + return null; + } + return }>{children}; + } +} diff --git a/x-pack/plugins/security/public/ui_api/lazy_wrapper.tsx b/x-pack/plugins/security/public/ui_api/lazy_wrapper.tsx new file mode 100644 index 0000000000000..a1d3d84b6c099 --- /dev/null +++ b/x-pack/plugins/security/public/ui_api/lazy_wrapper.tsx @@ -0,0 +1,42 @@ +/* + * 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 { FC, PropsWithChildren, PropsWithRef, ReactElement } from 'react'; +import React, { lazy, useMemo } from 'react'; +import useAsync from 'react-use/lib/useAsync'; + +import type { StartServicesAccessor } from 'src/core/public'; + +import type { PluginStartDependencies } from '../plugin'; +import { SuspenseErrorBoundary } from '../suspense_error_boundary'; + +interface InternalProps { + fn: () => Promise>; + getStartServices: StartServicesAccessor; + props: JSX.IntrinsicAttributes & PropsWithRef>; +} + +export const LazyWrapper: (props: InternalProps) => ReactElement | null = ({ + fn, + getStartServices, + props, +}) => { + const { value: startServices = [{ notifications: undefined }] } = useAsync(getStartServices); + const [{ notifications }] = startServices; + + const LazyComponent = useMemo(() => lazy(() => fn().then((x) => ({ default: x }))), [fn]); + + if (!notifications) { + return null; + } + + return ( + + + + ); +}; From c416ab95b13eff8621321a94e345dd10b56cfff5 Mon Sep 17 00:00:00 2001 From: Vadim Yakhin Date: Tue, 1 Jun 2021 11:10:30 -0300 Subject: [PATCH 02/17] Create async versions of personal_info and change_password components --- .../change_password/change_password.tsx | 4 ++-- .../change_password/change_password_async.tsx | 17 +++++++++++++++++ .../account_management/change_password/index.ts | 1 + .../account_management/personal_info/index.ts | 1 + .../personal_info/personal_info.tsx | 4 ++-- .../personal_info/personal_info_async.tsx | 17 +++++++++++++++++ 6 files changed, 40 insertions(+), 4 deletions(-) create mode 100644 x-pack/plugins/security/public/account_management/change_password/change_password_async.tsx create mode 100644 x-pack/plugins/security/public/account_management/personal_info/personal_info_async.tsx diff --git a/x-pack/plugins/security/public/account_management/change_password/change_password.tsx b/x-pack/plugins/security/public/account_management/change_password/change_password.tsx index 90d63d8b43bc7..8450541aa9fb0 100644 --- a/x-pack/plugins/security/public/account_management/change_password/change_password.tsx +++ b/x-pack/plugins/security/public/account_management/change_password/change_password.tsx @@ -17,13 +17,13 @@ import { canUserChangePassword } from '../../../common/model'; import type { UserAPIClient } from '../../management/users'; import { ChangePasswordForm } from '../../management/users/components/change_password_form'; -interface Props { +export interface ChangePasswordProps { user: AuthenticatedUser; userAPIClient: PublicMethodsOf; notifications: NotificationsSetup; } -export class ChangePassword extends Component { +export class ChangePassword extends Component { public render() { const canChangePassword = canUserChangePassword(this.props.user); diff --git a/x-pack/plugins/security/public/account_management/change_password/change_password_async.tsx b/x-pack/plugins/security/public/account_management/change_password/change_password_async.tsx new file mode 100644 index 0000000000000..628cfe701705a --- /dev/null +++ b/x-pack/plugins/security/public/account_management/change_password/change_password_async.tsx @@ -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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; + +import type { ChangePasswordProps } from './change_password'; + +export const getChangePasswordComponent = async (): Promise> => { + const { ChangePassword } = await import('./change_password'); + return (props: ChangePasswordProps) => { + return ; + }; +}; diff --git a/x-pack/plugins/security/public/account_management/change_password/index.ts b/x-pack/plugins/security/public/account_management/change_password/index.ts index c73b497512cdf..07fc9c1c0ec21 100644 --- a/x-pack/plugins/security/public/account_management/change_password/index.ts +++ b/x-pack/plugins/security/public/account_management/change_password/index.ts @@ -6,3 +6,4 @@ */ export { ChangePassword } from './change_password'; +export type { ChangePasswordProps } from './change_password'; diff --git a/x-pack/plugins/security/public/account_management/personal_info/index.ts b/x-pack/plugins/security/public/account_management/personal_info/index.ts index a7d2873e85391..1ede9b7864bd6 100644 --- a/x-pack/plugins/security/public/account_management/personal_info/index.ts +++ b/x-pack/plugins/security/public/account_management/personal_info/index.ts @@ -6,3 +6,4 @@ */ export { PersonalInfo } from './personal_info'; +export type { PersonalInfoProps } from './personal_info'; diff --git a/x-pack/plugins/security/public/account_management/personal_info/personal_info.tsx b/x-pack/plugins/security/public/account_management/personal_info/personal_info.tsx index e9de2b8a69bfa..20b21fc0c30ce 100644 --- a/x-pack/plugins/security/public/account_management/personal_info/personal_info.tsx +++ b/x-pack/plugins/security/public/account_management/personal_info/personal_info.tsx @@ -12,11 +12,11 @@ import { FormattedMessage } from '@kbn/i18n/react'; import type { AuthenticatedUser } from '../../../common/model'; -interface Props { +export interface PersonalInfoProps { user: AuthenticatedUser; } -export const PersonalInfo = (props: Props) => { +export const PersonalInfo = (props: PersonalInfoProps) => { return ( > => { + const { PersonalInfo } = await import('./personal_info'); + return (props: PersonalInfoProps) => { + return ; + }; +}; From f994ba5d8ffe8f07a43e25f5d0df95073f1deee4 Mon Sep 17 00:00:00 2001 From: Vadim Yakhin Date: Tue, 1 Jun 2021 17:32:17 -0300 Subject: [PATCH 03/17] Create ui_api that allows to load Security components asuncronously The patterns were mostly copied from Spaces plugin --- .../security/public/ui_api/components.tsx | 36 +++++++++++++++++ .../security/public/ui_api/index.mock.ts | 18 +++++++++ .../plugins/security/public/ui_api/index.ts | 39 +++++++++++++++++++ 3 files changed, 93 insertions(+) create mode 100644 x-pack/plugins/security/public/ui_api/components.tsx create mode 100644 x-pack/plugins/security/public/ui_api/index.mock.ts create mode 100644 x-pack/plugins/security/public/ui_api/index.ts diff --git a/x-pack/plugins/security/public/ui_api/components.tsx b/x-pack/plugins/security/public/ui_api/components.tsx new file mode 100644 index 0000000000000..51bf14404bfe0 --- /dev/null +++ b/x-pack/plugins/security/public/ui_api/components.tsx @@ -0,0 +1,36 @@ +/* + * 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 { FC, PropsWithChildren, PropsWithRef } from 'react'; +import React from 'react'; + +import type { StartServicesAccessor } from 'src/core/public'; + +import { getChangePasswordComponent } from '../account_management/change_password/change_password_async'; +import { getPersonalInfoComponent } from '../account_management/personal_info/personal_info_async'; +import type { PluginStartDependencies } from '../plugin'; +import { LazyWrapper } from './lazy_wrapper'; + +export interface GetComponentsOptions { + getStartServices: StartServicesAccessor; +} + +export const getComponents = ({ getStartServices }: GetComponentsOptions) => { + /** + * Returns a function that creates a lazy-loading version of a component. + */ + function wrapLazy(fn: () => Promise>) { + return (props: JSX.IntrinsicAttributes & PropsWithRef>) => ( + + ); + } + + return { + getPersonalInfo: wrapLazy(getPersonalInfoComponent), + getChangePassword: wrapLazy(getChangePasswordComponent), + }; +}; diff --git a/x-pack/plugins/security/public/ui_api/index.mock.ts b/x-pack/plugins/security/public/ui_api/index.mock.ts new file mode 100644 index 0000000000000..6d42f99af7c1b --- /dev/null +++ b/x-pack/plugins/security/public/ui_api/index.mock.ts @@ -0,0 +1,18 @@ +/* + * 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 { UiApi } from './'; + +export const getUiApiMock = { + createStart: (): jest.Mocked => ({ + components: { + getPersonalInfo: jest.fn(), + getChangePassword: jest.fn(), + }, + UserAPIClient: jest.fn(), + }), +}; diff --git a/x-pack/plugins/security/public/ui_api/index.ts b/x-pack/plugins/security/public/ui_api/index.ts new file mode 100644 index 0000000000000..d3521dd5f79a4 --- /dev/null +++ b/x-pack/plugins/security/public/ui_api/index.ts @@ -0,0 +1,39 @@ +/* + * 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 { ReactElement } from 'react'; + +import type { StartServicesAccessor } from 'src/core/public'; + +import type { ChangePasswordProps } from '../account_management/change_password'; +import type { PersonalInfoProps } from '../account_management/personal_info'; +import { UserAPIClient } from '../management'; +import type { PluginStartDependencies } from '../plugin'; +import { getComponents } from './components'; + +interface GetUiApiOptions { + getStartServices: StartServicesAccessor; +} + +type LazyComponentFn = (props: T) => ReactElement; + +export interface UiApi { + components: { + getPersonalInfo: LazyComponentFn; + getChangePassword: LazyComponentFn; + }; + UserAPIClient: typeof UserAPIClient; +} + +export const getUiApi = ({ getStartServices }: GetUiApiOptions): UiApi => { + const components = getComponents({ getStartServices }); + + return { + components, + UserAPIClient, + }; +}; From e09f42a4ad6c4d042e53457a3764ad5d3469e0d1 Mon Sep 17 00:00:00 2001 From: Vadim Yakhin Date: Tue, 1 Jun 2021 17:35:45 -0300 Subject: [PATCH 04/17] Make ui_api available through Security components's lifecycle methods --- x-pack/plugins/security/public/mocks.ts | 2 ++ x-pack/plugins/security/public/plugin.test.tsx | 7 +++++++ x-pack/plugins/security/public/plugin.tsx | 8 ++++++++ 3 files changed, 17 insertions(+) diff --git a/x-pack/plugins/security/public/mocks.ts b/x-pack/plugins/security/public/mocks.ts index 829c3ced9dddb..b936f8d01cfd5 100644 --- a/x-pack/plugins/security/public/mocks.ts +++ b/x-pack/plugins/security/public/mocks.ts @@ -11,6 +11,7 @@ import { mockAuthenticatedUser } from '../common/model/authenticated_user.mock'; import { authenticationMock } from './authentication/index.mock'; import { navControlServiceMock } from './nav_control/index.mock'; import { createSessionTimeoutMock } from './session/session_timeout.mock'; +import { getUiApiMock } from './ui_api/index.mock'; function createSetupMock() { return { @@ -23,6 +24,7 @@ function createStartMock() { return { authc: authenticationMock.createStart(), navControlService: navControlServiceMock.createStart(), + uiApi: getUiApiMock.createStart(), }; } diff --git a/x-pack/plugins/security/public/plugin.test.tsx b/x-pack/plugins/security/public/plugin.test.tsx index d3794ddbeb1a6..dbd28dbe4f474 100644 --- a/x-pack/plugins/security/public/plugin.test.tsx +++ b/x-pack/plugins/security/public/plugin.test.tsx @@ -103,6 +103,13 @@ describe('Security Plugin', () => { features: {} as FeaturesPluginStart, }) ).toEqual({ + uiApi: { + UserAPIClient: expect.any(Function), + components: { + getChangePassword: expect.any(Function), + getPersonalInfo: expect.any(Function), + }, + }, authc: { getCurrentUser: expect.any(Function), areAPIKeysEnabled: expect.any(Function), diff --git a/x-pack/plugins/security/public/plugin.tsx b/x-pack/plugins/security/public/plugin.tsx index 7d7ab36f1dadb..3bdbd3eff72c8 100644 --- a/x-pack/plugins/security/public/plugin.tsx +++ b/x-pack/plugins/security/public/plugin.tsx @@ -28,6 +28,8 @@ import { ManagementService } from './management'; import { SecurityNavControlService } from './nav_control'; import { SecurityCheckupService } from './security_checkup'; import { SessionExpired, SessionTimeout, UnauthorizedResponseHttpInterceptor } from './session'; +import { getUiApi } from './ui_api'; +import type { UiApi } from './ui_api'; export interface PluginSetupDependencies { licensing: LicensingPluginSetup; @@ -60,6 +62,7 @@ export class SecurityPlugin private readonly securityCheckupService = new SecurityCheckupService(); private authc!: AuthenticationServiceSetup; private readonly config: ConfigType; + private uiApi!: UiApi; constructor(private readonly initializerContext: PluginInitializerContext) { this.config = this.initializerContext.config.get(); @@ -97,6 +100,10 @@ export class SecurityPlugin logoutUrl, }); + this.uiApi = getUiApi({ + getStartServices: core.getStartServices, + }); + accountManagementApp.create({ authc: this.authc, application: core.application, @@ -147,6 +154,7 @@ export class SecurityPlugin } return { + uiApi: this.uiApi, navControlService: this.navControlService.start({ core }), authc: this.authc as AuthenticationServiceStart, }; From 897615a8a82140d8514d49e65be56e7eb4fdc3ea Mon Sep 17 00:00:00 2001 From: Vadim Yakhin Date: Tue, 1 Jun 2021 17:37:36 -0300 Subject: [PATCH 05/17] Import Security plugin into Enterprise Search --- .../enterprise_search/public/applications/index.test.tsx | 2 ++ x-pack/plugins/enterprise_search/public/plugin.ts | 3 +++ 2 files changed, 5 insertions(+) diff --git a/x-pack/plugins/enterprise_search/public/applications/index.test.tsx b/x-pack/plugins/enterprise_search/public/applications/index.test.tsx index 2e0940b9c4af2..cb73686eb4c5b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/index.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/index.test.tsx @@ -12,6 +12,7 @@ import { getContext } from 'kea'; import { coreMock } from '../../../../../src/core/public/mocks'; import { chartPluginMock } from '../../../../../src/plugins/charts/public/mocks'; import { licensingMock } from '../../../licensing/public/mocks'; +import { securityMock } from '../../../security/public/mocks'; import { AppSearch } from './app_search'; import { EnterpriseSearch } from './enterprise_search'; @@ -27,6 +28,7 @@ describe('renderApp', () => { plugins: { licensing: licensingMock.createStart(), charts: chartPluginMock.createStartContract(), + security: securityMock.createStart(), }, } as any; const pluginData = { diff --git a/x-pack/plugins/enterprise_search/public/plugin.ts b/x-pack/plugins/enterprise_search/public/plugin.ts index e402d233da58d..6e521efc369df 100644 --- a/x-pack/plugins/enterprise_search/public/plugin.ts +++ b/x-pack/plugins/enterprise_search/public/plugin.ts @@ -21,6 +21,7 @@ import { } from '../../../../src/plugins/home/public'; import { CloudSetup } from '../../cloud/public'; import { LicensingPluginStart } from '../../licensing/public'; +import { SecurityPluginSetup, SecurityPluginStart } from '../../security/public'; import { APP_SEARCH_PLUGIN, @@ -42,11 +43,13 @@ export interface ClientData extends InitialAppData { interface PluginsSetup { cloud?: CloudSetup; home?: HomePublicPluginSetup; + security?: SecurityPluginSetup; } export interface PluginsStart { cloud?: CloudSetup; licensing: LicensingPluginStart; charts: ChartsPluginStart; + security?: SecurityPluginStart; } export class EnterpriseSearchPlugin implements Plugin { From 3080c1c32811408a4001c141bc09e83a37d5c6e1 Mon Sep 17 00:00:00 2001 From: Vadim Yakhin Date: Tue, 1 Jun 2021 17:39:25 -0300 Subject: [PATCH 06/17] Add Security plugin and Notifications service to Kibana Logic file --- .../applications/__mocks__/kibana_logic.mock.ts | 4 ++++ .../enterprise_search/public/applications/index.tsx | 2 ++ .../public/applications/shared/kibana/kibana_logic.ts | 11 ++++++++++- 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/enterprise_search/public/applications/__mocks__/kibana_logic.mock.ts b/x-pack/plugins/enterprise_search/public/applications/__mocks__/kibana_logic.mock.ts index 1ebd61df388c5..525be080ca298 100644 --- a/x-pack/plugins/enterprise_search/public/applications/__mocks__/kibana_logic.mock.ts +++ b/x-pack/plugins/enterprise_search/public/applications/__mocks__/kibana_logic.mock.ts @@ -7,7 +7,9 @@ import { mockHistory } from './react_router_history.mock'; +import { notificationServiceMock } from '../../../../../../src/core/public/mocks'; import { chartPluginMock } from '../../../../../../src/plugins/charts/public/mocks'; +import { securityMock } from '../../../../security/public/mocks'; export const mockKibanaValues = { config: { host: 'http://localhost:3002' }, @@ -18,6 +20,8 @@ export const mockKibanaValues = { }, history: mockHistory, navigateToUrl: jest.fn(), + notifications: notificationServiceMock.createStartContract(), + security: securityMock.createStart(), setBreadcrumbs: jest.fn(), setChromeIsVisible: jest.fn(), setDocTitle: jest.fn(), diff --git a/x-pack/plugins/enterprise_search/public/applications/index.tsx b/x-pack/plugins/enterprise_search/public/applications/index.tsx index c2bf77751528a..773c82c6ee7f9 100644 --- a/x-pack/plugins/enterprise_search/public/applications/index.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/index.tsx @@ -48,6 +48,8 @@ export const renderApp = ( cloud: plugins.cloud || {}, history: params.history, navigateToUrl: core.application.navigateToUrl, + notifications: core.notifications, + security: plugins.security || {}, setBreadcrumbs: core.chrome.setBreadcrumbs, setChromeIsVisible: core.chrome.setIsVisible, setDocTitle: core.chrome.docTitle.change, diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/kibana/kibana_logic.ts b/x-pack/plugins/enterprise_search/public/applications/shared/kibana/kibana_logic.ts index 2bef7d373f160..412d7b35b1fdc 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/kibana/kibana_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/kibana/kibana_logic.ts @@ -10,9 +10,14 @@ import { FC } from 'react'; import { History } from 'history'; import { kea, MakeLogicType } from 'kea'; -import { ApplicationStart, ChromeBreadcrumb } from '../../../../../../../src/core/public'; +import { + ApplicationStart, + ChromeBreadcrumb, + NotificationsStart, +} from '../../../../../../../src/core/public'; import { ChartsPluginStart } from '../../../../../../../src/plugins/charts/public'; import { CloudSetup } from '../../../../../cloud/public'; +import { SecurityPluginStart } from '../../../../../security/public'; import { HttpLogic } from '../http'; import { createHref, CreateHrefOptions } from '../react_router_helpers'; @@ -23,6 +28,8 @@ interface KibanaLogicProps { cloud: Partial; charts: ChartsPluginStart; navigateToUrl: ApplicationStart['navigateToUrl']; + notifications: NotificationsStart; + security: Partial; setBreadcrumbs(crumbs: ChromeBreadcrumb[]): void; setChromeIsVisible(isVisible: boolean): void; setDocTitle(title: string): void; @@ -47,6 +54,8 @@ export const KibanaLogic = kea>({ }, {}, ], + notifications: [props.notifications, {}], + security: [props.security || {}, {}], setBreadcrumbs: [props.setBreadcrumbs, {}], setChromeIsVisible: [props.setChromeIsVisible, {}], setDocTitle: [props.setDocTitle, {}], From cfc13863161ffa0693d546692c654d5d89ca1c63 Mon Sep 17 00:00:00 2001 From: Vadim Yakhin Date: Tue, 1 Jun 2021 17:41:37 -0300 Subject: [PATCH 07/17] Export the required components from the Security plugin and use them in the new AccountSettings component --- .../applications/workplace_search/index.tsx | 7 +++ .../account_settings/account_settings.tsx | 46 +++++++++++++++++++ .../views/account_settings/index.ts | 8 ++++ 3 files changed, 61 insertions(+) create mode 100644 x-pack/plugins/enterprise_search/public/applications/workplace_search/views/account_settings/account_settings.tsx create mode 100644 x-pack/plugins/enterprise_search/public/applications/workplace_search/views/account_settings/index.ts diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/index.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/index.tsx index 54085a9cd4467..0fc55125b700e 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/index.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/index.tsx @@ -28,7 +28,9 @@ import { ORG_SETTINGS_PATH, ROLE_MAPPINGS_PATH, SECURITY_PATH, + PERSONAL_SETTINGS_PATH, } from './routes'; +import { AccountSettings } from './views/account_settings'; import { SourcesRouter } from './views/content_sources'; import { SourceAdded } from './views/content_sources/components/source_added'; import { SourceSubNav } from './views/content_sources/components/source_sub_nav'; @@ -103,6 +105,11 @@ export const WorkplaceSearchConfigured: React.FC = (props) => { + + + + + } />} diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/account_settings/account_settings.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/account_settings/account_settings.tsx new file mode 100644 index 0000000000000..3a23f8dadf70f --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/account_settings/account_settings.tsx @@ -0,0 +1,46 @@ +/* + * 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 React, { useState, useEffect, useMemo } from 'react'; + +import { useValues } from 'kea'; + +import type { AuthenticatedUser } from '../../../../../../security/public'; +import { HttpLogic } from '../../../shared/http/http_logic'; +import { KibanaLogic } from '../../../shared/kibana/kibana_logic'; + +export const AccountSettings: React.FC = () => { + const { security, notifications } = useValues(KibanaLogic); + const { http } = useValues(HttpLogic); + + const [currentUser, setCurrentUser] = useState(null); + + useEffect(() => { + security!.authc!.getCurrentUser().then(setCurrentUser); + }, [security.authc]); + + const UserAPIClient = security!.uiApi!.UserAPIClient; + const PersonalInfo = useMemo(() => security!.uiApi!.components.getPersonalInfo, [security.uiApi]); + const ChangePassword = useMemo(() => security!.uiApi!.components.getChangePassword, [ + security.uiApi, + ]); + + if (!currentUser) { + return null; + } + + return ( + <> + + + + ); +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/account_settings/index.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/account_settings/index.ts new file mode 100644 index 0000000000000..016b8f721aea4 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/account_settings/index.ts @@ -0,0 +1,8 @@ +/* + * 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. + */ + +export { AccountSettings } from './account_settings'; From efa7d683110ce4bd9b6533e1eddf7bf17f9a59ed Mon Sep 17 00:00:00 2001 From: Vadim Yakhin Date: Tue, 1 Jun 2021 17:42:59 -0300 Subject: [PATCH 08/17] Update link to the Account Settings page --- .../components/layout/account_header/account_header.tsx | 5 ++--- .../public/applications/workplace_search/routes.ts | 1 - 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/account_header/account_header.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/account_header/account_header.tsx index 92a936fcdbefe..b1e190edade2b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/account_header/account_header.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/account_header/account_header.tsx @@ -27,7 +27,7 @@ import { getWorkplaceSearchUrl } from '../../../../shared/enterprise_search_url' import { EuiButtonEmptyTo } from '../../../../shared/react_router_helpers'; import { AppLogic } from '../../../app_logic'; import { WORKPLACE_SEARCH_TITLE, ACCOUNT_NAV } from '../../../constants'; -import { PERSONAL_SOURCES_PATH, LOGOUT_ROUTE, KIBANA_ACCOUNT_ROUTE } from '../../../routes'; +import { PERSONAL_SOURCES_PATH, LOGOUT_ROUTE, PERSONAL_SETTINGS_PATH } from '../../../routes'; export const AccountHeader: React.FC = () => { const [isPopoverOpen, setPopover] = useState(false); @@ -44,8 +44,7 @@ export const AccountHeader: React.FC = () => { const accountNavItems = [ - {/* TODO: Once auth is completed, we need to have non-admins redirect to the self-hosted form */} - {ACCOUNT_NAV.SETTINGS} + {ACCOUNT_NAV.SETTINGS} , {ACCOUNT_NAV.LOGOUT} diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/routes.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/routes.ts index 0a6b6ef89b2a4..1562fb958479a 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/routes.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/routes.ts @@ -13,7 +13,6 @@ export const SETUP_GUIDE_PATH = '/setup_guide'; export const NOT_FOUND_PATH = '/404'; export const LOGOUT_ROUTE = '/logout'; -export const KIBANA_ACCOUNT_ROUTE = '/security/account'; export const LEAVE_FEEDBACK_EMAIL = 'support@elastic.co'; export const LEAVE_FEEDBACK_URL = `mailto:${LEAVE_FEEDBACK_EMAIL}?Subject=Elastic%20Workplace%20Search%20Feedback`; From 4f8f832880303c35490279e18c9d1cb715e46e03 Mon Sep 17 00:00:00 2001 From: Vadim Yakhin Date: Tue, 8 Jun 2021 11:48:12 -0300 Subject: [PATCH 09/17] Move getUiApi call to security start and pass core instead of getStartServices --- x-pack/plugins/security/public/plugin.tsx | 8 +------- x-pack/plugins/security/public/ui_api/components.tsx | 9 ++++----- x-pack/plugins/security/public/ui_api/index.ts | 9 ++++----- .../plugins/security/public/ui_api/lazy_wrapper.tsx | 11 ++++------- 4 files changed, 13 insertions(+), 24 deletions(-) diff --git a/x-pack/plugins/security/public/plugin.tsx b/x-pack/plugins/security/public/plugin.tsx index 3bdbd3eff72c8..6577b0b8526e3 100644 --- a/x-pack/plugins/security/public/plugin.tsx +++ b/x-pack/plugins/security/public/plugin.tsx @@ -29,7 +29,6 @@ import { SecurityNavControlService } from './nav_control'; import { SecurityCheckupService } from './security_checkup'; import { SessionExpired, SessionTimeout, UnauthorizedResponseHttpInterceptor } from './session'; import { getUiApi } from './ui_api'; -import type { UiApi } from './ui_api'; export interface PluginSetupDependencies { licensing: LicensingPluginSetup; @@ -62,7 +61,6 @@ export class SecurityPlugin private readonly securityCheckupService = new SecurityCheckupService(); private authc!: AuthenticationServiceSetup; private readonly config: ConfigType; - private uiApi!: UiApi; constructor(private readonly initializerContext: PluginInitializerContext) { this.config = this.initializerContext.config.get(); @@ -100,10 +98,6 @@ export class SecurityPlugin logoutUrl, }); - this.uiApi = getUiApi({ - getStartServices: core.getStartServices, - }); - accountManagementApp.create({ authc: this.authc, application: core.application, @@ -154,7 +148,7 @@ export class SecurityPlugin } return { - uiApi: this.uiApi, + uiApi: getUiApi({ core }), navControlService: this.navControlService.start({ core }), authc: this.authc as AuthenticationServiceStart, }; diff --git a/x-pack/plugins/security/public/ui_api/components.tsx b/x-pack/plugins/security/public/ui_api/components.tsx index 51bf14404bfe0..a595a361a04dd 100644 --- a/x-pack/plugins/security/public/ui_api/components.tsx +++ b/x-pack/plugins/security/public/ui_api/components.tsx @@ -8,24 +8,23 @@ import type { FC, PropsWithChildren, PropsWithRef } from 'react'; import React from 'react'; -import type { StartServicesAccessor } from 'src/core/public'; +import type { CoreStart } from 'src/core/public'; import { getChangePasswordComponent } from '../account_management/change_password/change_password_async'; import { getPersonalInfoComponent } from '../account_management/personal_info/personal_info_async'; -import type { PluginStartDependencies } from '../plugin'; import { LazyWrapper } from './lazy_wrapper'; export interface GetComponentsOptions { - getStartServices: StartServicesAccessor; + core: CoreStart; } -export const getComponents = ({ getStartServices }: GetComponentsOptions) => { +export const getComponents = ({ core }: GetComponentsOptions) => { /** * Returns a function that creates a lazy-loading version of a component. */ function wrapLazy(fn: () => Promise>) { return (props: JSX.IntrinsicAttributes & PropsWithRef>) => ( - + ); } diff --git a/x-pack/plugins/security/public/ui_api/index.ts b/x-pack/plugins/security/public/ui_api/index.ts index d3521dd5f79a4..1de70e584a512 100644 --- a/x-pack/plugins/security/public/ui_api/index.ts +++ b/x-pack/plugins/security/public/ui_api/index.ts @@ -7,16 +7,15 @@ import type { ReactElement } from 'react'; -import type { StartServicesAccessor } from 'src/core/public'; +import type { CoreStart } from 'src/core/public'; import type { ChangePasswordProps } from '../account_management/change_password'; import type { PersonalInfoProps } from '../account_management/personal_info'; import { UserAPIClient } from '../management'; -import type { PluginStartDependencies } from '../plugin'; import { getComponents } from './components'; interface GetUiApiOptions { - getStartServices: StartServicesAccessor; + core: CoreStart; } type LazyComponentFn = (props: T) => ReactElement; @@ -29,8 +28,8 @@ export interface UiApi { UserAPIClient: typeof UserAPIClient; } -export const getUiApi = ({ getStartServices }: GetUiApiOptions): UiApi => { - const components = getComponents({ getStartServices }); +export const getUiApi = ({ core }: GetUiApiOptions): UiApi => { + const components = getComponents({ core }); return { components, diff --git a/x-pack/plugins/security/public/ui_api/lazy_wrapper.tsx b/x-pack/plugins/security/public/ui_api/lazy_wrapper.tsx index a1d3d84b6c099..6a37b35df7327 100644 --- a/x-pack/plugins/security/public/ui_api/lazy_wrapper.tsx +++ b/x-pack/plugins/security/public/ui_api/lazy_wrapper.tsx @@ -7,26 +7,23 @@ import type { FC, PropsWithChildren, PropsWithRef, ReactElement } from 'react'; import React, { lazy, useMemo } from 'react'; -import useAsync from 'react-use/lib/useAsync'; -import type { StartServicesAccessor } from 'src/core/public'; +import type { CoreStart } from 'src/core/public'; -import type { PluginStartDependencies } from '../plugin'; import { SuspenseErrorBoundary } from '../suspense_error_boundary'; interface InternalProps { fn: () => Promise>; - getStartServices: StartServicesAccessor; + core: CoreStart; props: JSX.IntrinsicAttributes & PropsWithRef>; } export const LazyWrapper: (props: InternalProps) => ReactElement | null = ({ fn, - getStartServices, + core, props, }) => { - const { value: startServices = [{ notifications: undefined }] } = useAsync(getStartServices); - const [{ notifications }] = startServices; + const { notifications } = core; const LazyComponent = useMemo(() => lazy(() => fn().then((x) => ({ default: x }))), [fn]); From 9f18ea9db06e9bcbdbee51364b8987729bfe15d3 Mon Sep 17 00:00:00 2001 From: Vadim Yakhin Date: Tue, 8 Jun 2021 12:06:18 -0300 Subject: [PATCH 10/17] Simplify import of change_password_async component by providing... ... `notifications` and `userAPIClient` props in the security plugin --- .../account_settings/account_settings.tsx | 11 ++--------- .../change_password/change_password_async.tsx | 18 +++++++++++++++--- .../security/public/ui_api/components.tsx | 2 +- x-pack/plugins/security/public/ui_api/index.ts | 2 +- 4 files changed, 19 insertions(+), 14 deletions(-) diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/account_settings/account_settings.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/account_settings/account_settings.tsx index 3a23f8dadf70f..e28faaeec8993 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/account_settings/account_settings.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/account_settings/account_settings.tsx @@ -10,12 +10,10 @@ import React, { useState, useEffect, useMemo } from 'react'; import { useValues } from 'kea'; import type { AuthenticatedUser } from '../../../../../../security/public'; -import { HttpLogic } from '../../../shared/http/http_logic'; import { KibanaLogic } from '../../../shared/kibana/kibana_logic'; export const AccountSettings: React.FC = () => { - const { security, notifications } = useValues(KibanaLogic); - const { http } = useValues(HttpLogic); + const { security } = useValues(KibanaLogic); const [currentUser, setCurrentUser] = useState(null); @@ -23,7 +21,6 @@ export const AccountSettings: React.FC = () => { security!.authc!.getCurrentUser().then(setCurrentUser); }, [security.authc]); - const UserAPIClient = security!.uiApi!.UserAPIClient; const PersonalInfo = useMemo(() => security!.uiApi!.components.getPersonalInfo, [security.uiApi]); const ChangePassword = useMemo(() => security!.uiApi!.components.getChangePassword, [ security.uiApi, @@ -36,11 +33,7 @@ export const AccountSettings: React.FC = () => { return ( <> - + ); }; diff --git a/x-pack/plugins/security/public/account_management/change_password/change_password_async.tsx b/x-pack/plugins/security/public/account_management/change_password/change_password_async.tsx index 628cfe701705a..4dabd2f7b7942 100644 --- a/x-pack/plugins/security/public/account_management/change_password/change_password_async.tsx +++ b/x-pack/plugins/security/public/account_management/change_password/change_password_async.tsx @@ -7,11 +7,23 @@ import React from 'react'; +import type { CoreStart } from 'src/core/public'; + +import { UserAPIClient } from '../../management/users'; import type { ChangePasswordProps } from './change_password'; -export const getChangePasswordComponent = async (): Promise> => { +export const getChangePasswordComponent = async ( + core: CoreStart +): Promise>> => { const { ChangePassword } = await import('./change_password'); - return (props: ChangePasswordProps) => { - return ; + + return (props: Pick) => { + return ( + + ); }; }; diff --git a/x-pack/plugins/security/public/ui_api/components.tsx b/x-pack/plugins/security/public/ui_api/components.tsx index a595a361a04dd..eeee7946663b7 100644 --- a/x-pack/plugins/security/public/ui_api/components.tsx +++ b/x-pack/plugins/security/public/ui_api/components.tsx @@ -30,6 +30,6 @@ export const getComponents = ({ core }: GetComponentsOptions) => { return { getPersonalInfo: wrapLazy(getPersonalInfoComponent), - getChangePassword: wrapLazy(getChangePasswordComponent), + getChangePassword: wrapLazy(() => getChangePasswordComponent(core)), }; }; diff --git a/x-pack/plugins/security/public/ui_api/index.ts b/x-pack/plugins/security/public/ui_api/index.ts index 1de70e584a512..98c020e91e203 100644 --- a/x-pack/plugins/security/public/ui_api/index.ts +++ b/x-pack/plugins/security/public/ui_api/index.ts @@ -23,7 +23,7 @@ type LazyComponentFn = (props: T) => ReactElement; export interface UiApi { components: { getPersonalInfo: LazyComponentFn; - getChangePassword: LazyComponentFn; + getChangePassword: LazyComponentFn>; }; UserAPIClient: typeof UserAPIClient; } From 706ac2ebb455686bec1a201fd6706e66dd56f4aa Mon Sep 17 00:00:00 2001 From: Vadim Yakhin Date: Tue, 8 Jun 2021 12:11:59 -0300 Subject: [PATCH 11/17] Remove UserAPIClient from ui_api It's not needed anymore since the components are initiated with this prop already passed --- x-pack/plugins/security/public/plugin.test.tsx | 1 - x-pack/plugins/security/public/ui_api/index.mock.ts | 1 - x-pack/plugins/security/public/ui_api/index.ts | 3 --- 3 files changed, 5 deletions(-) diff --git a/x-pack/plugins/security/public/plugin.test.tsx b/x-pack/plugins/security/public/plugin.test.tsx index dbd28dbe4f474..1a0f183e258a6 100644 --- a/x-pack/plugins/security/public/plugin.test.tsx +++ b/x-pack/plugins/security/public/plugin.test.tsx @@ -104,7 +104,6 @@ describe('Security Plugin', () => { }) ).toEqual({ uiApi: { - UserAPIClient: expect.any(Function), components: { getChangePassword: expect.any(Function), getPersonalInfo: expect.any(Function), diff --git a/x-pack/plugins/security/public/ui_api/index.mock.ts b/x-pack/plugins/security/public/ui_api/index.mock.ts index 6d42f99af7c1b..c35f9342be6ca 100644 --- a/x-pack/plugins/security/public/ui_api/index.mock.ts +++ b/x-pack/plugins/security/public/ui_api/index.mock.ts @@ -13,6 +13,5 @@ export const getUiApiMock = { getPersonalInfo: jest.fn(), getChangePassword: jest.fn(), }, - UserAPIClient: jest.fn(), }), }; diff --git a/x-pack/plugins/security/public/ui_api/index.ts b/x-pack/plugins/security/public/ui_api/index.ts index 98c020e91e203..f146a6bd78fb6 100644 --- a/x-pack/plugins/security/public/ui_api/index.ts +++ b/x-pack/plugins/security/public/ui_api/index.ts @@ -11,7 +11,6 @@ import type { CoreStart } from 'src/core/public'; import type { ChangePasswordProps } from '../account_management/change_password'; import type { PersonalInfoProps } from '../account_management/personal_info'; -import { UserAPIClient } from '../management'; import { getComponents } from './components'; interface GetUiApiOptions { @@ -25,7 +24,6 @@ export interface UiApi { getPersonalInfo: LazyComponentFn; getChangePassword: LazyComponentFn>; }; - UserAPIClient: typeof UserAPIClient; } export const getUiApi = ({ core }: GetUiApiOptions): UiApi => { @@ -33,6 +31,5 @@ export const getUiApi = ({ core }: GetUiApiOptions): UiApi => { return { components, - UserAPIClient, }; }; From ebc2753855b37c9a8d4fa6660d9ffcf9b6ab3f6e Mon Sep 17 00:00:00 2001 From: Vadim Yakhin Date: Tue, 8 Jun 2021 12:19:56 -0300 Subject: [PATCH 12/17] Export ChangePasswordProps and PersonalInfoProps from account_management/index.ts This makes it easier to import these props from outside the account_management folder --- .../public/account_management/change_password/index.ts | 1 - x-pack/plugins/security/public/account_management/index.ts | 3 +++ .../security/public/account_management/personal_info/index.ts | 1 - x-pack/plugins/security/public/ui_api/index.ts | 3 +-- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/security/public/account_management/change_password/index.ts b/x-pack/plugins/security/public/account_management/change_password/index.ts index 07fc9c1c0ec21..c73b497512cdf 100644 --- a/x-pack/plugins/security/public/account_management/change_password/index.ts +++ b/x-pack/plugins/security/public/account_management/change_password/index.ts @@ -6,4 +6,3 @@ */ export { ChangePassword } from './change_password'; -export type { ChangePasswordProps } from './change_password'; diff --git a/x-pack/plugins/security/public/account_management/index.ts b/x-pack/plugins/security/public/account_management/index.ts index bfba213c632d0..9c107b7527937 100644 --- a/x-pack/plugins/security/public/account_management/index.ts +++ b/x-pack/plugins/security/public/account_management/index.ts @@ -6,3 +6,6 @@ */ export { accountManagementApp } from './account_management_app'; + +export type { ChangePasswordProps } from './change_password/change_password'; +export type { PersonalInfoProps } from './personal_info/personal_info'; diff --git a/x-pack/plugins/security/public/account_management/personal_info/index.ts b/x-pack/plugins/security/public/account_management/personal_info/index.ts index 1ede9b7864bd6..a7d2873e85391 100644 --- a/x-pack/plugins/security/public/account_management/personal_info/index.ts +++ b/x-pack/plugins/security/public/account_management/personal_info/index.ts @@ -6,4 +6,3 @@ */ export { PersonalInfo } from './personal_info'; -export type { PersonalInfoProps } from './personal_info'; diff --git a/x-pack/plugins/security/public/ui_api/index.ts b/x-pack/plugins/security/public/ui_api/index.ts index f146a6bd78fb6..b058c2a7f3f64 100644 --- a/x-pack/plugins/security/public/ui_api/index.ts +++ b/x-pack/plugins/security/public/ui_api/index.ts @@ -9,8 +9,7 @@ import type { ReactElement } from 'react'; import type { CoreStart } from 'src/core/public'; -import type { ChangePasswordProps } from '../account_management/change_password'; -import type { PersonalInfoProps } from '../account_management/personal_info'; +import type { ChangePasswordProps, PersonalInfoProps } from '../account_management'; import { getComponents } from './components'; interface GetUiApiOptions { From 140cd91fc7ea4717be957322a215833d0f9ba368 Mon Sep 17 00:00:00 2001 From: Vadim Yakhin Date: Tue, 8 Jun 2021 12:25:39 -0300 Subject: [PATCH 13/17] Remove notifications service from kibana_logic It is not needed anymore since we're initializing security components with notifications already provided --- .../public/applications/__mocks__/kibana_logic.mock.ts | 2 -- .../enterprise_search/public/applications/index.tsx | 1 - .../public/applications/shared/kibana/kibana_logic.ts | 8 +------- 3 files changed, 1 insertion(+), 10 deletions(-) diff --git a/x-pack/plugins/enterprise_search/public/applications/__mocks__/kibana_logic.mock.ts b/x-pack/plugins/enterprise_search/public/applications/__mocks__/kibana_logic.mock.ts index 525be080ca298..98d17e18bdf8e 100644 --- a/x-pack/plugins/enterprise_search/public/applications/__mocks__/kibana_logic.mock.ts +++ b/x-pack/plugins/enterprise_search/public/applications/__mocks__/kibana_logic.mock.ts @@ -7,7 +7,6 @@ import { mockHistory } from './react_router_history.mock'; -import { notificationServiceMock } from '../../../../../../src/core/public/mocks'; import { chartPluginMock } from '../../../../../../src/plugins/charts/public/mocks'; import { securityMock } from '../../../../security/public/mocks'; @@ -20,7 +19,6 @@ export const mockKibanaValues = { }, history: mockHistory, navigateToUrl: jest.fn(), - notifications: notificationServiceMock.createStartContract(), security: securityMock.createStart(), setBreadcrumbs: jest.fn(), setChromeIsVisible: jest.fn(), diff --git a/x-pack/plugins/enterprise_search/public/applications/index.tsx b/x-pack/plugins/enterprise_search/public/applications/index.tsx index 773c82c6ee7f9..ba2b28e64b9cf 100644 --- a/x-pack/plugins/enterprise_search/public/applications/index.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/index.tsx @@ -48,7 +48,6 @@ export const renderApp = ( cloud: plugins.cloud || {}, history: params.history, navigateToUrl: core.application.navigateToUrl, - notifications: core.notifications, security: plugins.security || {}, setBreadcrumbs: core.chrome.setBreadcrumbs, setChromeIsVisible: core.chrome.setIsVisible, diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/kibana/kibana_logic.ts b/x-pack/plugins/enterprise_search/public/applications/shared/kibana/kibana_logic.ts index 412d7b35b1fdc..9c6db7d09f72c 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/kibana/kibana_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/kibana/kibana_logic.ts @@ -10,11 +10,7 @@ import { FC } from 'react'; import { History } from 'history'; import { kea, MakeLogicType } from 'kea'; -import { - ApplicationStart, - ChromeBreadcrumb, - NotificationsStart, -} from '../../../../../../../src/core/public'; +import { ApplicationStart, ChromeBreadcrumb } from '../../../../../../../src/core/public'; import { ChartsPluginStart } from '../../../../../../../src/plugins/charts/public'; import { CloudSetup } from '../../../../../cloud/public'; import { SecurityPluginStart } from '../../../../../security/public'; @@ -28,7 +24,6 @@ interface KibanaLogicProps { cloud: Partial; charts: ChartsPluginStart; navigateToUrl: ApplicationStart['navigateToUrl']; - notifications: NotificationsStart; security: Partial; setBreadcrumbs(crumbs: ChromeBreadcrumb[]): void; setChromeIsVisible(isVisible: boolean): void; @@ -54,7 +49,6 @@ export const KibanaLogic = kea>({ }, {}, ], - notifications: [props.notifications, {}], security: [props.security || {}, {}], setBreadcrumbs: [props.setBreadcrumbs, {}], setChromeIsVisible: [props.setChromeIsVisible, {}], From 8ec937920b371e9be3ce5a7591f09d35136d85e1 Mon Sep 17 00:00:00 2001 From: Vadim Yakhin Date: Thu, 10 Jun 2021 10:29:32 -0300 Subject: [PATCH 14/17] Add UiApi to SecurityPluginStart interface --- x-pack/plugins/security/public/plugin.tsx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/x-pack/plugins/security/public/plugin.tsx b/x-pack/plugins/security/public/plugin.tsx index 6031d552e2384..fbb282ee246f9 100644 --- a/x-pack/plugins/security/public/plugin.tsx +++ b/x-pack/plugins/security/public/plugin.tsx @@ -30,6 +30,7 @@ import type { SecurityNavControlServiceStart } from './nav_control'; import { SecurityNavControlService } from './nav_control'; import { SecurityCheckupService } from './security_checkup'; import { SessionExpired, SessionTimeout, UnauthorizedResponseHttpInterceptor } from './session'; +import type { UiApi } from './ui_api'; import { getUiApi } from './ui_api'; export interface PluginSetupDependencies { @@ -186,4 +187,8 @@ export interface SecurityPluginStart { * Exposes authentication information about the currently logged in user. */ authc: AuthenticationServiceStart; + /** + * Exposes UI components that will be loaded asynchronously. + */ + uiApi: UiApi; } From 9b932dcf9ba0c4a2a65fe5ecd792f3db93cfebab Mon Sep 17 00:00:00 2001 From: Vadim Yakhin Date: Thu, 10 Jun 2021 10:38:19 -0300 Subject: [PATCH 15/17] Utilize index files for exporting Props types --- .../public/account_management/change_password/index.ts | 2 ++ x-pack/plugins/security/public/account_management/index.ts | 4 ++-- .../security/public/account_management/personal_info/index.ts | 2 ++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/security/public/account_management/change_password/index.ts b/x-pack/plugins/security/public/account_management/change_password/index.ts index c73b497512cdf..028d0f6cc7497 100644 --- a/x-pack/plugins/security/public/account_management/change_password/index.ts +++ b/x-pack/plugins/security/public/account_management/change_password/index.ts @@ -6,3 +6,5 @@ */ export { ChangePassword } from './change_password'; + +export type { ChangePasswordProps } from './change_password'; diff --git a/x-pack/plugins/security/public/account_management/index.ts b/x-pack/plugins/security/public/account_management/index.ts index 9c107b7527937..2d1045723a6e1 100644 --- a/x-pack/plugins/security/public/account_management/index.ts +++ b/x-pack/plugins/security/public/account_management/index.ts @@ -7,5 +7,5 @@ export { accountManagementApp } from './account_management_app'; -export type { ChangePasswordProps } from './change_password/change_password'; -export type { PersonalInfoProps } from './personal_info/personal_info'; +export type { ChangePasswordProps } from './change_password'; +export type { PersonalInfoProps } from './personal_info'; diff --git a/x-pack/plugins/security/public/account_management/personal_info/index.ts b/x-pack/plugins/security/public/account_management/personal_info/index.ts index a7d2873e85391..6dc6489afa8c5 100644 --- a/x-pack/plugins/security/public/account_management/personal_info/index.ts +++ b/x-pack/plugins/security/public/account_management/personal_info/index.ts @@ -6,3 +6,5 @@ */ export { PersonalInfo } from './personal_info'; + +export type { PersonalInfoProps } from './personal_info'; From 24258211021c0b995ff548521a172acaac11c636 Mon Sep 17 00:00:00 2001 From: Vadim Yakhin Date: Thu, 10 Jun 2021 11:15:27 -0300 Subject: [PATCH 16/17] Replace Pick<...> with two separate interfaces as it doesn't work well with our docs --- .../account_management/change_password/change_password.tsx | 5 ++++- .../change_password/change_password_async.tsx | 4 ++-- x-pack/plugins/security/public/ui_api/index.ts | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/security/public/account_management/change_password/change_password.tsx b/x-pack/plugins/security/public/account_management/change_password/change_password.tsx index 8450541aa9fb0..ac0e284c8b9ad 100644 --- a/x-pack/plugins/security/public/account_management/change_password/change_password.tsx +++ b/x-pack/plugins/security/public/account_management/change_password/change_password.tsx @@ -19,11 +19,14 @@ import { ChangePasswordForm } from '../../management/users/components/change_pas export interface ChangePasswordProps { user: AuthenticatedUser; +} + +export interface ChangePasswordPropsInternal extends ChangePasswordProps { userAPIClient: PublicMethodsOf; notifications: NotificationsSetup; } -export class ChangePassword extends Component { +export class ChangePassword extends Component { public render() { const canChangePassword = canUserChangePassword(this.props.user); diff --git a/x-pack/plugins/security/public/account_management/change_password/change_password_async.tsx b/x-pack/plugins/security/public/account_management/change_password/change_password_async.tsx index 4dabd2f7b7942..a4ad769146e59 100644 --- a/x-pack/plugins/security/public/account_management/change_password/change_password_async.tsx +++ b/x-pack/plugins/security/public/account_management/change_password/change_password_async.tsx @@ -14,10 +14,10 @@ import type { ChangePasswordProps } from './change_password'; export const getChangePasswordComponent = async ( core: CoreStart -): Promise>> => { +): Promise> => { const { ChangePassword } = await import('./change_password'); - return (props: Pick) => { + return (props: ChangePasswordProps) => { return ( = (props: T) => ReactElement; export interface UiApi { components: { getPersonalInfo: LazyComponentFn; - getChangePassword: LazyComponentFn>; + getChangePassword: LazyComponentFn; }; } From 1880755587bfed1c337da8cfc626999e52569041 Mon Sep 17 00:00:00 2001 From: Vadim Yakhin Date: Thu, 10 Jun 2021 11:59:52 -0300 Subject: [PATCH 17/17] Add a comment explaining why we're not loading async components through index file --- x-pack/plugins/security/public/ui_api/components.tsx | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/x-pack/plugins/security/public/ui_api/components.tsx b/x-pack/plugins/security/public/ui_api/components.tsx index eeee7946663b7..a488bc359b538 100644 --- a/x-pack/plugins/security/public/ui_api/components.tsx +++ b/x-pack/plugins/security/public/ui_api/components.tsx @@ -10,6 +10,14 @@ import React from 'react'; import type { CoreStart } from 'src/core/public'; +/** + * We're importing specific files here instead of passing them + * through the index file. It helps to keep the bundle size low. + * + * Importing async components through the index file increases the bundle size. + * It happens because the bundle starts to also include all the sync dependencies + * available through the index file. + */ import { getChangePasswordComponent } from '../account_management/change_password/change_password_async'; import { getPersonalInfoComponent } from '../account_management/personal_info/personal_info_async'; import { LazyWrapper } from './lazy_wrapper';