From ef5af172336d76cc553ae72cbcf289327c2ea428 Mon Sep 17 00:00:00 2001 From: Tim Sullivan Date: Thu, 18 Apr 2024 06:03:43 -0700 Subject: [PATCH] [Security] Remove usage of deprecated React rendering utilities (#180517) ## Summary Partially addresses https://github.com/elastic/kibana-team/issues/805 Follows https://github.com/elastic/kibana/pull/180003 These changes come up from searching in the code and finding where certain kinds of deprecated AppEx-SharedUX modules are imported. **Reviewers: Please interact with critical paths through the UI components touched in this PR, ESPECIALLY in terms of testing dark mode and i18n.** This focuses on code within Security. image Note: this also makes inclusion of `i18n` and `analytics` dependencies consistent. Analytics is an optional dependency for the SharedUX modules, which wrap `KibanaErrorBoundaryProvider` and is designed to capture telemetry about errors that are caught in the error boundary. ### Checklist Delete any items that are not applicable to this PR. - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - [ ] This renders correctly on smaller devices using a responsive layout. (You can test this [in your browser](https://www.browserstack.com/guide/responsive-testing-on-local-server)) - [ ] This was checked for [cross-browser compatibility](https://www.elastic.co/support/matrix#matrix_browsers) --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .../src/services.tsx | 4 +- .../public/cluster_address_form.test.tsx | 8 +- .../cluster_configuration_form.test.tsx | 10 +- .../public/enrollment_token_form.test.tsx | 8 +- .../interactive_setup/public/plugin.tsx | 26 ++--- .../interactive_setup/public/theme/index.tsx | 24 ---- .../public/verification_code_form.test.tsx | 8 +- src/plugins/interactive_setup/tsconfig.json | 3 +- .../account_management_app.tsx | 47 ++++---- .../access_agreement_app.test.ts | 4 +- .../access_agreement/access_agreement_app.ts | 6 +- .../access_agreement_page.tsx | 16 ++- .../logged_out/logged_out_app.test.ts | 4 +- .../logged_out/logged_out_app.ts | 6 +- .../logged_out/logged_out_page.tsx | 22 ++-- .../authentication/login/login_app.test.ts | 4 +- .../public/authentication/login/login_app.ts | 6 +- .../authentication/login/login_page.tsx | 16 ++- .../overwritten_session_app.test.ts | 4 +- .../overwritten_session_app.ts | 6 +- .../overwritten_session_page.tsx | 17 ++- x-pack/plugins/security/public/index.ts | 5 +- .../api_keys_grid/api_keys_grid_page.test.tsx | 15 ++- .../api_keys/api_keys_management_app.tsx | 44 +++---- .../role_mappings_management_app.tsx | 85 +++++++------- .../roles/edit_role/edit_role_page.test.tsx | 5 +- .../roles/edit_role/edit_role_page.tsx | 21 ++-- .../confirm_delete/confirm_delete.tsx | 13 +-- .../roles/roles_grid/roles_grid_page.tsx | 20 ++-- .../roles/roles_management_app.test.tsx | 110 ++++++++++++++++-- .../management/roles/roles_management_app.tsx | 96 +++++++-------- .../users/edit_user/create_user_page.test.tsx | 9 +- .../users/edit_user/edit_user_page.test.tsx | 13 +-- .../management/users/users_management_app.tsx | 32 +++-- .../nav_control/nav_control_service.tsx | 39 +++---- x-pack/plugins/security/public/plugin.tsx | 2 +- .../session/session_expiration_toast.test.tsx | 4 +- .../session/session_expiration_toast.tsx | 7 +- .../public/session/session_timeout.test.ts | 5 +- .../public/session/session_timeout.ts | 9 +- x-pack/plugins/security/tsconfig.json | 4 +- .../management/spaces_management_app.tsx | 47 ++++---- .../spaces/public/nav_control/nav_control.tsx | 30 +++-- .../public/space_selector/space_selector.tsx | 14 +-- .../space_selector/space_selector_app.tsx | 6 +- x-pack/plugins/spaces/tsconfig.json | 1 + 46 files changed, 435 insertions(+), 450 deletions(-) delete mode 100644 src/plugins/interactive_setup/public/theme/index.tsx diff --git a/packages/kbn-user-profile-components/src/services.tsx b/packages/kbn-user-profile-components/src/services.tsx index 683b9ac0ce01e2..71ce5a0ff844fe 100644 --- a/packages/kbn-user-profile-components/src/services.tsx +++ b/packages/kbn-user-profile-components/src/services.tsx @@ -48,10 +48,10 @@ export interface UserProfilesKibanaDependencies { userProfiles: UserProfileAPIClient; }; /** - * Handler from the '@kbn/kibana-react-plugin/public' Plugin + * Handler from the '@kbn/react-kibana-mount' Package * * ``` - * import { toMountPoint } from '@kbn/kibana-react-plugin/public'; + * import { toMountPoint } from '@kbn/react-kibana-mount'; * ``` */ toMountPoint: typeof toMountPoint; diff --git a/src/plugins/interactive_setup/public/cluster_address_form.test.tsx b/src/plugins/interactive_setup/public/cluster_address_form.test.tsx index 51ca8dd830c3f8..a532a81deac343 100644 --- a/src/plugins/interactive_setup/public/cluster_address_form.test.tsx +++ b/src/plugins/interactive_setup/public/cluster_address_form.test.tsx @@ -9,7 +9,7 @@ import { fireEvent, render, waitFor } from '@testing-library/react'; import React from 'react'; -import { coreMock, themeServiceMock } from '@kbn/core/public/mocks'; +import { coreMock } from '@kbn/core/public/mocks'; import { ClusterAddressForm } from './cluster_address_form'; import { Providers } from './plugin'; @@ -21,8 +21,6 @@ jest.mock('@elastic/eui/lib/services/accessibility/html_id_generator', () => ({ describe('ClusterAddressForm', () => { jest.setTimeout(20_000); - const theme$ = themeServiceMock.createTheme$(); - it('calls enrollment API when submitting form', async () => { const coreStart = coreMock.createStart(); coreStart.http.post.mockResolvedValue({}); @@ -30,7 +28,7 @@ describe('ClusterAddressForm', () => { const onSuccess = jest.fn(); const { findByRole, findByLabelText } = render( - + ); @@ -54,7 +52,7 @@ describe('ClusterAddressForm', () => { const onSuccess = jest.fn(); const { findAllByText, findByRole, findByLabelText } = render( - + ); diff --git a/src/plugins/interactive_setup/public/cluster_configuration_form.test.tsx b/src/plugins/interactive_setup/public/cluster_configuration_form.test.tsx index 2e66d9b4f125ec..01512cee06cf21 100644 --- a/src/plugins/interactive_setup/public/cluster_configuration_form.test.tsx +++ b/src/plugins/interactive_setup/public/cluster_configuration_form.test.tsx @@ -9,7 +9,7 @@ import { fireEvent, render, waitFor } from '@testing-library/react'; import React from 'react'; -import { coreMock, themeServiceMock } from '@kbn/core/public/mocks'; +import { coreMock } from '@kbn/core/public/mocks'; import { ClusterConfigurationForm } from './cluster_configuration_form'; import { Providers } from './plugin'; @@ -21,8 +21,6 @@ jest.mock('@elastic/eui/lib/services/accessibility/html_id_generator', () => ({ describe('ClusterConfigurationForm', () => { jest.setTimeout(20_000); - const theme$ = themeServiceMock.createTheme$(); - it('calls enrollment API for https addresses when submitting form', async () => { const coreStart = coreMock.createStart(); coreStart.http.post.mockResolvedValue({}); @@ -30,7 +28,7 @@ describe('ClusterConfigurationForm', () => { const onSuccess = jest.fn(); const { findByRole, findByLabelText } = render( - + { const onSuccess = jest.fn(); const { findByRole } = render( - + { const onSuccess = jest.fn(); const { findAllByText, findByRole, findByLabelText } = render( - + { jest.setTimeout(20_000); - const theme$ = themeServiceMock.createTheme$(); - it('calls enrollment API when submitting form', async () => { const coreStart = coreMock.createStart(); coreStart.http.post.mockResolvedValue({}); @@ -38,7 +36,7 @@ describe('EnrollmentTokenForm', () => { const onSuccess = jest.fn(); const { findByRole, findByLabelText } = render( - + ); @@ -64,7 +62,7 @@ describe('EnrollmentTokenForm', () => { const onSuccess = jest.fn(); const { findAllByText, findByRole, findByLabelText } = render( - + ); diff --git a/src/plugins/interactive_setup/public/plugin.tsx b/src/plugins/interactive_setup/public/plugin.tsx index aa688cd0e53b51..84c581fe44a9a8 100644 --- a/src/plugins/interactive_setup/public/plugin.tsx +++ b/src/plugins/interactive_setup/public/plugin.tsx @@ -9,13 +9,11 @@ import type { FunctionComponent } from 'react'; import React from 'react'; import ReactDOM from 'react-dom'; -import type { Observable } from 'rxjs'; -import type { CoreSetup, CoreStart, CoreTheme, Plugin } from '@kbn/core/public'; -import { I18nProvider } from '@kbn/i18n-react'; +import type { CoreSetup, CoreStart, Plugin } from '@kbn/core/public'; +import { KibanaRenderContextProvider } from '@kbn/react-kibana-context-render'; import { App } from './app'; -import { KibanaThemeProvider } from './theme'; // TODO: replace this with the one exported from `kibana_react` after https://github.com/elastic/kibana/issues/119204 is implemented. import { KibanaProvider } from './use_kibana'; import { VerificationProvider } from './use_verification'; @@ -26,7 +24,7 @@ export class InteractiveSetupPlugin implements Plugin { title: 'Configure Elastic to get started', appRoute: '/', chromeless: true, - mount: async ({ element, theme$ }) => { + mount: async ({ element }) => { const url = new URL(window.location.href); const defaultCode = url.searchParams.get('code') || undefined; const onSuccess = () => { @@ -36,7 +34,7 @@ export class InteractiveSetupPlugin implements Plugin { const [services] = await core.getStartServices(); ReactDOM.render( - + , element @@ -46,26 +44,22 @@ export class InteractiveSetupPlugin implements Plugin { }); } - public start(core: CoreStart) {} + public start(_core: CoreStart) {} } export interface ProvidersProps { services: CoreStart; - theme$: Observable; defaultCode?: string; } export const Providers: FunctionComponent = ({ defaultCode, services, - theme$, children, }) => ( - - - - {children} - - - + + + {children} + + ); diff --git a/src/plugins/interactive_setup/public/theme/index.tsx b/src/plugins/interactive_setup/public/theme/index.tsx deleted file mode 100644 index 8007d392a071db..00000000000000 --- a/src/plugins/interactive_setup/public/theme/index.tsx +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import type { EuiProviderProps } from '@elastic/eui'; -import React, { type FC } from 'react'; -import type { Observable } from 'rxjs'; - -import type { CoreTheme } from '@kbn/core-theme-browser'; -import { KibanaThemeProvider as KbnThemeProvider } from '@kbn/react-kibana-context-theme'; - -export interface KibanaThemeProviderProps { - theme$: Observable; - modify?: EuiProviderProps<{}>['modify']; -} - -/** @deprecated use `KibanaThemeProvider` from `@kbn/react-kibana-context-theme */ -export const KibanaThemeProvider: FC = ({ theme$, modify, children }) => ( - {children} -); diff --git a/src/plugins/interactive_setup/public/verification_code_form.test.tsx b/src/plugins/interactive_setup/public/verification_code_form.test.tsx index efa5721c8d5b86..c7329396c0cd1b 100644 --- a/src/plugins/interactive_setup/public/verification_code_form.test.tsx +++ b/src/plugins/interactive_setup/public/verification_code_form.test.tsx @@ -9,7 +9,7 @@ import { fireEvent, render, waitFor } from '@testing-library/react'; import React from 'react'; -import { coreMock, themeServiceMock } from '@kbn/core/public/mocks'; +import { coreMock } from '@kbn/core/public/mocks'; import { Providers } from './plugin'; import { VerificationCodeForm } from './verification_code_form'; @@ -21,8 +21,6 @@ jest.mock('@elastic/eui/lib/services/accessibility/html_id_generator', () => ({ describe('VerificationCodeForm', () => { jest.setTimeout(20_000); - const theme$ = themeServiceMock.createTheme$(); - it('calls enrollment API when submitting form', async () => { const coreStart = coreMock.createStart(); coreStart.http.post.mockResolvedValue({}); @@ -30,7 +28,7 @@ describe('VerificationCodeForm', () => { const onSuccess = jest.fn(); const { findByRole, findByLabelText } = render( - + ); @@ -67,7 +65,7 @@ describe('VerificationCodeForm', () => { const onSuccess = jest.fn(); const { findAllByText, findByRole, findByLabelText } = render( - + ); diff --git a/src/plugins/interactive_setup/tsconfig.json b/src/plugins/interactive_setup/tsconfig.json index c8ae9dc8fdfb6f..51fff541980cc2 100644 --- a/src/plugins/interactive_setup/tsconfig.json +++ b/src/plugins/interactive_setup/tsconfig.json @@ -23,9 +23,8 @@ "@kbn/utils", "@kbn/core-logging-server-mocks", "@kbn/core-preboot-server", - "@kbn/react-kibana-context-theme", - "@kbn/core-theme-browser", "@kbn/security-hardening", + "@kbn/react-kibana-context-render", ], "exclude": [ "target/**/*", diff --git a/x-pack/plugins/security/public/account_management/account_management_app.tsx b/x-pack/plugins/security/public/account_management/account_management_app.tsx index e7a41e49f3cb5a..e648e6409536a5 100644 --- a/x-pack/plugins/security/public/account_management/account_management_app.tsx +++ b/x-pack/plugins/security/public/account_management/account_management_app.tsx @@ -17,9 +17,8 @@ import type { StartServicesAccessor, } from '@kbn/core/public'; import { i18n } from '@kbn/i18n'; -import { I18nProvider } from '@kbn/i18n-react'; import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; -import { KibanaThemeProvider } from '@kbn/react-kibana-context-theme'; +import { KibanaRenderContextProvider } from '@kbn/react-kibana-context-render'; import { toMountPoint } from '@kbn/react-kibana-mount'; import type { AuthenticationServiceSetup } from '@kbn/security-plugin-types-public'; import { Router } from '@kbn/shared-ux-router'; @@ -87,27 +86,25 @@ export const Providers: FunctionComponent = ({ onChange, children, }) => ( - - - - - - - - - {children} - - - - - - - - + + + + + + + + {children} + + + + + + + ); diff --git a/x-pack/plugins/security/public/authentication/access_agreement/access_agreement_app.test.ts b/x-pack/plugins/security/public/authentication/access_agreement/access_agreement_app.test.ts index 40f667996e590c..eb008293c0f1de 100644 --- a/x-pack/plugins/security/public/authentication/access_agreement/access_agreement_app.test.ts +++ b/x-pack/plugins/security/public/authentication/access_agreement/access_agreement_app.test.ts @@ -57,8 +57,8 @@ describe('accessAgreementApp', () => { const mockRenderApp = jest.requireMock('./access_agreement_page').renderAccessAgreementPage; expect(mockRenderApp).toHaveBeenCalledTimes(1); expect(mockRenderApp).toHaveBeenCalledWith( - coreStartMock.i18n, - { element: appMountParams.element, theme$: appMountParams.theme$ }, + coreStartMock, + { element: appMountParams.element }, { http: coreStartMock.http, notifications: coreStartMock.notifications, diff --git a/x-pack/plugins/security/public/authentication/access_agreement/access_agreement_app.ts b/x-pack/plugins/security/public/authentication/access_agreement/access_agreement_app.ts index b32056094cd7f6..f429b5782a816a 100644 --- a/x-pack/plugins/security/public/authentication/access_agreement/access_agreement_app.ts +++ b/x-pack/plugins/security/public/authentication/access_agreement/access_agreement_app.ts @@ -23,14 +23,14 @@ export const accessAgreementApp = Object.freeze({ }), chromeless: true, appRoute: '/security/access_agreement', - async mount({ element, theme$ }: AppMountParameters) { + async mount({ element }: AppMountParameters) { const [[coreStart], { renderAccessAgreementPage }] = await Promise.all([ getStartServices(), import('./access_agreement_page'), ]); return renderAccessAgreementPage( - coreStart.i18n, - { element, theme$ }, + coreStart, + { element }, { http: coreStart.http, notifications: coreStart.notifications, diff --git a/x-pack/plugins/security/public/authentication/access_agreement/access_agreement_page.tsx b/x-pack/plugins/security/public/authentication/access_agreement/access_agreement_page.tsx index ba96ee16a03bd3..c4c3c51d94d6f7 100644 --- a/x-pack/plugins/security/public/authentication/access_agreement/access_agreement_page.tsx +++ b/x-pack/plugins/security/public/authentication/access_agreement/access_agreement_page.tsx @@ -23,15 +23,15 @@ import ReactMarkdown from 'react-markdown'; import type { AppMountParameters, - CoreStart, FatalErrorsStart, HttpStart, NotificationsStart, } from '@kbn/core/public'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; -import { KibanaThemeProvider } from '@kbn/kibana-react-plugin/public'; +import { KibanaRenderContextProvider } from '@kbn/react-kibana-context-render'; +import type { StartServices } from '../..'; import { parseNext } from '../../../common/parse_next'; import { AuthenticationStatePage } from '../components'; @@ -128,16 +128,14 @@ export function AccessAgreementPage({ http, fatalErrors, notifications }: Props) } export function renderAccessAgreementPage( - i18nStart: CoreStart['i18n'], - { element, theme$ }: Pick, + services: StartServices, + { element }: Pick, props: Props ) { ReactDOM.render( - - - - - , + + + , element ); diff --git a/x-pack/plugins/security/public/authentication/logged_out/logged_out_app.test.ts b/x-pack/plugins/security/public/authentication/logged_out/logged_out_app.test.ts index 966efccf0c3ba9..0b68d63985652e 100644 --- a/x-pack/plugins/security/public/authentication/logged_out/logged_out_app.test.ts +++ b/x-pack/plugins/security/public/authentication/logged_out/logged_out_app.test.ts @@ -53,8 +53,8 @@ describe('loggedOutApp', () => { const mockRenderApp = jest.requireMock('./logged_out_page').renderLoggedOutPage; expect(mockRenderApp).toHaveBeenCalledTimes(1); expect(mockRenderApp).toHaveBeenCalledWith( - coreStartMock.i18n, - { element: appMountParams.element, theme$: appMountParams.theme$ }, + coreStartMock, + { element: appMountParams.element }, { basePath: coreStartMock.http.basePath, customBranding: coreStartMock.customBranding } ); }); diff --git a/x-pack/plugins/security/public/authentication/logged_out/logged_out_app.ts b/x-pack/plugins/security/public/authentication/logged_out/logged_out_app.ts index 1141a9b3ffacaa..291630c634cf27 100644 --- a/x-pack/plugins/security/public/authentication/logged_out/logged_out_app.ts +++ b/x-pack/plugins/security/public/authentication/logged_out/logged_out_app.ts @@ -28,14 +28,14 @@ export const loggedOutApp = Object.freeze({ title: i18n.translate('xpack.security.loggedOutAppTitle', { defaultMessage: 'Logged out' }), chromeless: true, appRoute: '/security/logged_out', - async mount({ element, theme$ }: AppMountParameters) { + async mount({ element }: AppMountParameters) { const [[coreStart], { renderLoggedOutPage }] = await Promise.all([ getStartServices(), import('./logged_out_page'), ]); return renderLoggedOutPage( - coreStart.i18n, - { element, theme$ }, + coreStart, + { element }, { basePath: coreStart.http.basePath, customBranding: coreStart.customBranding } ); }, diff --git a/x-pack/plugins/security/public/authentication/logged_out/logged_out_page.tsx b/x-pack/plugins/security/public/authentication/logged_out/logged_out_page.tsx index 7b077f60cc1e0d..c380bfa11c2b98 100644 --- a/x-pack/plugins/security/public/authentication/logged_out/logged_out_page.tsx +++ b/x-pack/plugins/security/public/authentication/logged_out/logged_out_page.tsx @@ -10,15 +10,11 @@ import React from 'react'; import ReactDOM from 'react-dom'; import useObservable from 'react-use/lib/useObservable'; -import type { - AppMountParameters, - CoreStart, - CustomBrandingStart, - IBasePath, -} from '@kbn/core/public'; +import type { AppMountParameters, CustomBrandingStart, IBasePath } from '@kbn/core/public'; import { FormattedMessage } from '@kbn/i18n-react'; -import { KibanaThemeProvider } from '@kbn/kibana-react-plugin/public'; +import { KibanaRenderContextProvider } from '@kbn/react-kibana-context-render'; +import type { StartServices } from '../..'; import { parseNext } from '../../../common/parse_next'; import { AuthenticationStatePage } from '../components'; @@ -47,16 +43,14 @@ export function LoggedOutPage({ basePath, customBranding }: Props) { } export function renderLoggedOutPage( - i18nStart: CoreStart['i18n'], - { element, theme$ }: Pick, + services: StartServices, + { element }: Pick, props: Props ) { ReactDOM.render( - - - - - , + + + , element ); diff --git a/x-pack/plugins/security/public/authentication/login/login_app.test.ts b/x-pack/plugins/security/public/authentication/login/login_app.test.ts index fd62978aa98b18..dee1086c35aa3e 100644 --- a/x-pack/plugins/security/public/authentication/login/login_app.test.ts +++ b/x-pack/plugins/security/public/authentication/login/login_app.test.ts @@ -60,8 +60,8 @@ describe('loginApp', () => { const mockRenderApp = jest.requireMock('./login_page').renderLoginPage; expect(mockRenderApp).toHaveBeenCalledTimes(1); expect(mockRenderApp).toHaveBeenCalledWith( - coreStartMock.i18n, - { element: appMountParams.element, theme$: appMountParams.theme$ }, + coreStartMock, + { element: appMountParams.element }, { http: coreStartMock.http, customBranding: coreStartMock.customBranding, diff --git a/x-pack/plugins/security/public/authentication/login/login_app.ts b/x-pack/plugins/security/public/authentication/login/login_app.ts index df944a259e4d74..495bd8d1037c89 100644 --- a/x-pack/plugins/security/public/authentication/login/login_app.ts +++ b/x-pack/plugins/security/public/authentication/login/login_app.ts @@ -31,14 +31,14 @@ export const loginApp = Object.freeze({ title: i18n.translate('xpack.security.loginAppTitle', { defaultMessage: 'Login' }), chromeless: true, appRoute: '/login', - async mount({ element, theme$ }: AppMountParameters) { + async mount({ element }: AppMountParameters) { const [[coreStart], { renderLoginPage }] = await Promise.all([ getStartServices(), import('./login_page'), ]); return renderLoginPage( - coreStart.i18n, - { element, theme$ }, + coreStart, + { element }, { customBranding: coreStart.customBranding, http: coreStart.http, diff --git a/x-pack/plugins/security/public/authentication/login/login_page.tsx b/x-pack/plugins/security/public/authentication/login/login_page.tsx index a645ab70a540f4..741f61016928c0 100644 --- a/x-pack/plugins/security/public/authentication/login/login_page.tsx +++ b/x-pack/plugins/security/public/authentication/login/login_page.tsx @@ -25,7 +25,6 @@ import { BehaviorSubject } from 'rxjs'; import type { AppMountParameters, - CoreStart, CustomBrandingStart, FatalErrorsStart, HttpStart, @@ -34,10 +33,11 @@ import type { import type { CustomBranding } from '@kbn/core-custom-branding-common'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; -import { KibanaThemeProvider } from '@kbn/kibana-react-plugin/public'; +import { KibanaRenderContextProvider } from '@kbn/react-kibana-context-render'; import type { LoginFormProps } from './components'; import { DisabledLoginForm, LoginForm, LoginFormMessageType } from './components'; +import type { StartServices } from '../..'; import { AUTH_PROVIDER_HINT_QUERY_STRING_PARAMETER, LOGOUT_REASON_QUERY_STRING_PARAMETER, @@ -368,16 +368,14 @@ export class LoginPage extends Component { } export function renderLoginPage( - i18nStart: CoreStart['i18n'], - { element, theme$ }: Pick, + services: StartServices, + { element }: Pick, props: Props ) { ReactDOM.render( - - - - - , + + + , element ); diff --git a/x-pack/plugins/security/public/authentication/overwritten_session/overwritten_session_app.test.ts b/x-pack/plugins/security/public/authentication/overwritten_session/overwritten_session_app.test.ts index dee4149b085071..f81dc8f4f27ca6 100644 --- a/x-pack/plugins/security/public/authentication/overwritten_session/overwritten_session_app.test.ts +++ b/x-pack/plugins/security/public/authentication/overwritten_session/overwritten_session_app.test.ts @@ -63,8 +63,8 @@ describe('overwrittenSessionApp', () => { ).renderOverwrittenSessionPage; expect(mockRenderApp).toHaveBeenCalledTimes(1); expect(mockRenderApp).toHaveBeenCalledWith( - coreStartMock.i18n, - { element: appMountParams.element, theme$: appMountParams.theme$ }, + coreStartMock, + { element: appMountParams.element }, { authc: authcMock, basePath: coreStartMock.http.basePath } ); }); diff --git a/x-pack/plugins/security/public/authentication/overwritten_session/overwritten_session_app.ts b/x-pack/plugins/security/public/authentication/overwritten_session/overwritten_session_app.ts index b0f3f1059dfb4f..a121377a5f3fc3 100644 --- a/x-pack/plugins/security/public/authentication/overwritten_session/overwritten_session_app.ts +++ b/x-pack/plugins/security/public/authentication/overwritten_session/overwritten_session_app.ts @@ -25,14 +25,14 @@ export const overwrittenSessionApp = Object.freeze({ }), chromeless: true, appRoute: '/security/overwritten_session', - async mount({ element, theme$ }: AppMountParameters) { + async mount({ element }: AppMountParameters) { const [[coreStart], { renderOverwrittenSessionPage }] = await Promise.all([ getStartServices(), import('./overwritten_session_page'), ]); return renderOverwrittenSessionPage( - coreStart.i18n, - { element, theme$ }, + coreStart, + { element }, { authc, basePath: coreStart.http.basePath, diff --git a/x-pack/plugins/security/public/authentication/overwritten_session/overwritten_session_page.tsx b/x-pack/plugins/security/public/authentication/overwritten_session/overwritten_session_page.tsx index 6f39a2608e1cd1..42ef361bc1fd9b 100644 --- a/x-pack/plugins/security/public/authentication/overwritten_session/overwritten_session_page.tsx +++ b/x-pack/plugins/security/public/authentication/overwritten_session/overwritten_session_page.tsx @@ -9,11 +9,12 @@ import { EuiButton } from '@elastic/eui'; import React, { useEffect, useState } from 'react'; import ReactDOM from 'react-dom'; -import type { AppMountParameters, CoreStart, IBasePath } from '@kbn/core/public'; +import type { AppMountParameters, IBasePath } from '@kbn/core/public'; import { FormattedMessage } from '@kbn/i18n-react'; -import { KibanaThemeProvider } from '@kbn/kibana-react-plugin/public'; +import { KibanaRenderContextProvider } from '@kbn/react-kibana-context-render'; import type { AuthenticationServiceSetup } from '@kbn/security-plugin-types-public'; +import type { StartServices } from '../..'; import { parseNext } from '../../../common/parse_next'; import { AuthenticationStatePage } from '../components'; @@ -53,16 +54,14 @@ export function OverwrittenSessionPage({ authc, basePath }: Props) { } export function renderOverwrittenSessionPage( - i18nStart: CoreStart['i18n'], - { element, theme$ }: Pick, + services: StartServices, + { element }: Pick, props: Props ) { ReactDOM.render( - - - - - , + + + , element ); diff --git a/x-pack/plugins/security/public/index.ts b/x-pack/plugins/security/public/index.ts index 66f0c08521d528..7db535b030f3b9 100644 --- a/x-pack/plugins/security/public/index.ts +++ b/x-pack/plugins/security/public/index.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { PluginInitializer, PluginInitializerContext } from '@kbn/core/public'; +import type { CoreStart, PluginInitializer, PluginInitializerContext } from '@kbn/core/public'; import type { SecurityPluginSetup } from '@kbn/security-plugin-types-public'; import type { @@ -40,3 +40,6 @@ export const plugin: PluginInitializer< PluginSetupDependencies, PluginStartDependencies > = (initializerContext: PluginInitializerContext) => new SecurityPlugin(initializerContext); + +// services needed for rendering React using shared modules +export type StartServices = Pick; diff --git a/x-pack/plugins/security/public/management/api_keys/api_keys_grid/api_keys_grid_page.test.tsx b/x-pack/plugins/security/public/management/api_keys/api_keys_grid/api_keys_grid_page.test.tsx index b10a1eaeaacda7..159495b67400c2 100644 --- a/x-pack/plugins/security/public/management/api_keys/api_keys_grid/api_keys_grid_page.test.tsx +++ b/x-pack/plugins/security/public/management/api_keys/api_keys_grid/api_keys_grid_page.test.tsx @@ -9,7 +9,7 @@ import { render } from '@testing-library/react'; import { createMemoryHistory } from 'history'; import React from 'react'; -import { coreMock, themeServiceMock } from '@kbn/core/public/mocks'; +import { coreMock } from '@kbn/core/public/mocks'; import { APIKeysGridPage } from './api_keys_grid_page'; import { mockAuthenticatedUser } from '../../../../common/model/authenticated_user.mock'; @@ -33,7 +33,6 @@ describe('APIKeysGridPage', () => { const consoleWarnMock = jest.spyOn(console, 'error').mockImplementation(); let coreStart: ReturnType; - const theme$ = themeServiceMock.createTheme$(); const { authc } = securityMock.createSetup(); beforeEach(() => { @@ -102,12 +101,12 @@ describe('APIKeysGridPage', () => { }; const { findByText, queryByTestId, getByText } = render( - + ); - expect(await queryByTestId('apiKeysCreateTableButton')).not.toBeInTheDocument(); + expect(queryByTestId('apiKeysCreateTableButton')).not.toBeInTheDocument(); expect(await findByText(/Loading API keys/)).not.toBeInTheDocument(); @@ -134,7 +133,7 @@ describe('APIKeysGridPage', () => { }; const { findByText } = render( - + ); @@ -158,7 +157,7 @@ describe('APIKeysGridPage', () => { }; const { findByText } = render( - + ); @@ -185,7 +184,7 @@ describe('APIKeysGridPage', () => { }; const { findByText } = render( - + ); @@ -215,7 +214,7 @@ describe('APIKeysGridPage', () => { }; const { findByText, queryByText } = render( - + ); diff --git a/x-pack/plugins/security/public/management/api_keys/api_keys_management_app.tsx b/x-pack/plugins/security/public/management/api_keys/api_keys_management_app.tsx index c15ea9d9e731ee..08fcbaac520e32 100644 --- a/x-pack/plugins/security/public/management/api_keys/api_keys_management_app.tsx +++ b/x-pack/plugins/security/public/management/api_keys/api_keys_management_app.tsx @@ -9,13 +9,12 @@ import type { History } from 'history'; import type { FunctionComponent } from 'react'; import React from 'react'; import { render, unmountComponentAtNode } from 'react-dom'; -import type { Observable } from 'rxjs'; -import type { CoreStart, CoreTheme, StartServicesAccessor } from '@kbn/core/public'; +import type { CoreStart, StartServicesAccessor } from '@kbn/core/public'; import { i18n } from '@kbn/i18n'; -import { I18nProvider } from '@kbn/i18n-react'; -import { KibanaContextProvider, KibanaThemeProvider } from '@kbn/kibana-react-plugin/public'; +import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; import type { RegisterManagementAppArgs } from '@kbn/management-plugin/public'; +import { KibanaRenderContextProvider } from '@kbn/react-kibana-context-render'; import type { AuthenticationServiceSetup } from '@kbn/security-plugin-types-public'; import { Router } from '@kbn/shared-ux-router'; @@ -43,7 +42,7 @@ export const apiKeysManagementApp = Object.freeze({ title: i18n.translate('xpack.security.management.apiKeysTitle', { defaultMessage: 'API keys', }), - async mount({ element, theme$, setBreadcrumbs, history }) { + async mount({ element, setBreadcrumbs, history }) { const [[coreStart], { APIKeysGridPage }] = await Promise.all([ getStartServices(), import('./api_keys_grid'), @@ -52,7 +51,6 @@ export const apiKeysManagementApp = Object.freeze({ render( ; history: History; authc: AuthenticationServiceSetup; onChange?: BreadcrumbsChangeHandler; @@ -87,27 +84,24 @@ export interface ProvidersProps { export const Providers: FunctionComponent = ({ services, - theme$, history, authc, onChange, children, }) => ( - - - - - - - {children} - - - - - + + + + + + {children} + + + + ); diff --git a/x-pack/plugins/security/public/management/role_mappings/role_mappings_management_app.tsx b/x-pack/plugins/security/public/management/role_mappings/role_mappings_management_app.tsx index c44ddbdc8ac835..b3fc8ec71b8909 100644 --- a/x-pack/plugins/security/public/management/role_mappings/role_mappings_management_app.tsx +++ b/x-pack/plugins/security/public/management/role_mappings/role_mappings_management_app.tsx @@ -11,8 +11,9 @@ import { useParams } from 'react-router-dom'; import type { StartServicesAccessor } from '@kbn/core/public'; import { i18n } from '@kbn/i18n'; -import { KibanaContextProvider, KibanaThemeProvider } from '@kbn/kibana-react-plugin/public'; +import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; import type { RegisterManagementAppArgs } from '@kbn/management-plugin/public'; +import { KibanaRenderContextProvider } from '@kbn/react-kibana-context-render'; import { Route, Router } from '@kbn/shared-ux-router'; import { @@ -39,7 +40,7 @@ export const roleMappingsManagementApp = Object.freeze({ id: this.id, order: 40, title, - async mount({ element, theme$, setBreadcrumbs, history }) { + async mount({ element, setBreadcrumbs, history }) { const [ [core], { RoleMappingsGridPage }, @@ -91,47 +92,45 @@ export const roleMappingsManagementApp = Object.freeze({ }; render( - - - - - - - - - - - - - - - - - - - - - - , + + + + + + + + + + + + + + + + + + + + , element ); diff --git a/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.test.tsx b/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.test.tsx index 846818e540dcc0..622d10a4faab34 100644 --- a/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.test.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.test.tsx @@ -12,6 +12,7 @@ import React from 'react'; import type { BuildFlavor } from '@kbn/config'; import type { Capabilities } from '@kbn/core/public'; import { coreMock, scopedHistoryMock } from '@kbn/core/public/mocks'; +import { analyticsServiceMock } from '@kbn/core-analytics-browser-mocks'; import { i18nServiceMock } from '@kbn/core-i18n-browser-mocks'; import { themeServiceMock } from '@kbn/core-theme-browser-mocks'; import { dataViewPluginMocks } from '@kbn/data-views-plugin/public/mocks'; @@ -192,6 +193,7 @@ function getProps({ return []; } }); + const analyticsMock = analyticsServiceMock.createAnalyticsServiceStart(); const i18nMock = i18nServiceMock.createStartContract(); const themeMock = themeServiceMock.createStartContract(); return { @@ -213,7 +215,8 @@ function getProps({ spacesApiUi, buildFlavor, theme: themeMock, - i18nStart: i18nMock, + i18n: i18nMock, + analytics: analyticsMock, }; } diff --git a/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.tsx b/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.tsx index 8e0cb5f0cf0658..745cb2d68ab07e 100644 --- a/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.tsx @@ -30,10 +30,8 @@ import type { DocLinksStart, FatalErrorsSetup, HttpStart, - I18nStart, NotificationsStart, ScopedHistory, - ThemeServiceStart, } from '@kbn/core/public'; import type { IHttpFetchError } from '@kbn/core-http-browser'; import type { DataViewsContract } from '@kbn/data-views-plugin/public'; @@ -53,6 +51,7 @@ import { ElasticsearchPrivileges, KibanaPrivilegesRegion } from './privileges'; import { ReservedRoleBadge } from './reserved_role_badge'; import type { RoleValidationResult } from './validate_role'; import { RoleValidator } from './validate_role'; +import type { StartServices } from '../../..'; import type { BuiltinESPrivileges, RawKibanaPrivileges, @@ -76,7 +75,7 @@ import { KibanaPrivileges } from '../model'; import type { PrivilegesAPIClient } from '../privileges_api_client'; import type { RolesAPIClient } from '../roles_api_client'; -interface Props { +export interface Props extends StartServices { action: 'edit' | 'clone'; roleName?: string; dataViews?: DataViewsContract; @@ -94,8 +93,6 @@ interface Props { history: ScopedHistory; spacesApiUi?: SpacesApiUi; buildFlavor: BuildFlavor; - i18nStart: I18nStart; - theme: ThemeServiceStart; cloudOrgUrl?: string; } @@ -336,9 +333,8 @@ export const EditRolePage: FunctionComponent = ({ history, spacesApiUi, buildFlavor, - i18nStart, - theme, cloudOrgUrl, + ...startServices }) => { const isDarkMode = useDarkMode(); @@ -402,7 +398,7 @@ export const EditRolePage: FunctionComponent = ({ const [kibanaPrivileges, builtInESPrivileges] = privileges; const getFormTitle = () => { - let titleText; + let titleText: JSX.Element; const props: HTMLProps = { tabIndex: 0, }; @@ -505,7 +501,7 @@ export const EditRolePage: FunctionComponent = ({ name: e.target.value, }); - const onNameBlur = (e: FocusEvent) => { + const onNameBlur = (_e: FocusEvent) => { if (!isEditingExistingRole && previousName !== role.name) { setPreviousName(role.name); doesRoleExist().then((roleExists) => { @@ -676,7 +672,7 @@ export const EditRolePage: FunctionComponent = ({ , - { i18n: i18nStart, theme } + startServices ), }); } else { @@ -738,10 +734,7 @@ export const EditRolePage: FunctionComponent = ({ , - { - i18n: i18nStart, - theme, - } + startServices ), }); } else { diff --git a/x-pack/plugins/security/public/management/roles/roles_grid/confirm_delete/confirm_delete.tsx b/x-pack/plugins/security/public/management/roles/roles_grid/confirm_delete/confirm_delete.tsx index 35aea7c9b99ca2..bc434f61dab0d2 100644 --- a/x-pack/plugins/security/public/management/roles/roles_grid/confirm_delete/confirm_delete.tsx +++ b/x-pack/plugins/security/public/management/roles/roles_grid/confirm_delete/confirm_delete.tsx @@ -20,24 +20,22 @@ import { import React, { Component, Fragment } from 'react'; import type { BuildFlavor } from '@kbn/config'; -import type { I18nStart, NotificationsStart } from '@kbn/core/public'; +import type { NotificationsStart } from '@kbn/core/public'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; -import type { ThemeServiceStart } from '@kbn/react-kibana-context-common'; import { toMountPoint } from '@kbn/react-kibana-mount'; import type { PublicMethodsOf } from '@kbn/utility-types'; +import type { StartServices } from '../../../..'; import type { RolesAPIClient } from '../../roles_api_client'; -interface Props { +interface Props extends StartServices { rolesToDelete: string[]; callback: (rolesToDelete: string[], errors: string[]) => void; onCancel: () => void; notifications: NotificationsStart; rolesAPIClient: PublicMethodsOf; buildFlavor: BuildFlavor; - theme: ThemeServiceStart; - i18nStart: I18nStart; cloudOrgUrl?: string; } @@ -213,10 +211,7 @@ export class ConfirmDelete extends Component { , - { - i18n: this.props.i18nStart, - theme: this.props.theme, - } + this.props ), }); } diff --git a/x-pack/plugins/security/public/management/roles/roles_grid/roles_grid_page.tsx b/x-pack/plugins/security/public/management/roles/roles_grid/roles_grid_page.tsx index 2dc2628d23030b..4273a31e207c9c 100644 --- a/x-pack/plugins/security/public/management/roles/roles_grid/roles_grid_page.tsx +++ b/x-pack/plugins/security/public/management/roles/roles_grid/roles_grid_page.tsx @@ -23,15 +23,15 @@ import _ from 'lodash'; import React, { Component } from 'react'; import type { BuildFlavor } from '@kbn/config'; -import type { I18nStart, NotificationsStart, ScopedHistory } from '@kbn/core/public'; +import type { NotificationsStart, ScopedHistory } from '@kbn/core/public'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import { reactRouterNavigate } from '@kbn/kibana-react-plugin/public'; -import type { ThemeServiceStart } from '@kbn/react-kibana-context-common'; import type { PublicMethodsOf } from '@kbn/utility-types'; import { ConfirmDelete } from './confirm_delete'; import { PermissionDenied } from './permission_denied'; +import type { StartServices } from '../../..'; import type { Role } from '../../../../common'; import { getExtendedRoleDeprecationNotice, @@ -44,14 +44,12 @@ import { DeprecatedBadge, DisabledBadge, ReservedBadge } from '../../badges'; import { ActionsEuiTableFormatting } from '../../table_utils'; import type { RolesAPIClient } from '../roles_api_client'; -interface Props { +export interface Props extends StartServices { notifications: NotificationsStart; rolesAPIClient: PublicMethodsOf; history: ScopedHistory; readOnly?: boolean; buildFlavor: BuildFlavor; - theme: ThemeServiceStart; - i18nStart: I18nStart; cloudOrgUrl?: string; } @@ -180,12 +178,8 @@ export class RolesGridPage extends Component { onCancel={this.onCancelDelete} rolesToDelete={this.state.selection.map((role) => role.name)} callback={this.handleDelete} - notifications={this.props.notifications} - rolesAPIClient={this.props.rolesAPIClient} - buildFlavor={this.props.buildFlavor} - theme={this.props.theme} - i18nStart={this.props.i18nStart} cloudOrgUrl={this.props.cloudOrgUrl} + {...this.props} /> ) : null} @@ -237,7 +231,7 @@ export class RolesGridPage extends Component { direction: 'asc', }, }} - rowProps={(role: Role) => { + rowProps={(_role: Role) => { return { 'data-test-subj': `roleRow`, }; @@ -257,7 +251,7 @@ export class RolesGridPage extends Component { defaultMessage: 'Role', }), sortable: true, - render: (name: string, record: Role) => { + render: (name: string, _record: Role) => { return ( { defaultMessage: 'Status', }), sortable: (role: Role) => isRoleEnabled(role) && !isRoleDeprecated(role), - render: (metadata: Role['metadata'], record: Role) => { + render: (_metadata: Role['metadata'], record: Role) => { return this.getRoleStatusBadges(record); }, }); diff --git a/x-pack/plugins/security/public/management/roles/roles_management_app.test.tsx b/x-pack/plugins/security/public/management/roles/roles_management_app.test.tsx index 19bdb6d41c2ad3..1c417a977b856c 100644 --- a/x-pack/plugins/security/public/management/roles/roles_management_app.test.tsx +++ b/x-pack/plugins/security/public/management/roles/roles_management_app.test.tsx @@ -13,17 +13,55 @@ import { coreMock, scopedHistoryMock, themeServiceMock } from '@kbn/core/public/ import { featuresPluginMock } from '@kbn/features-plugin/public/mocks'; import type { Unmount } from '@kbn/management-plugin/public/types'; +import type { Props as EditRolePageProps } from './edit_role/edit_role_page'; +import type { Props as RolesGridPageProps } from './roles_grid/roles_grid_page'; import { rolesManagementApp } from './roles_management_app'; import { licenseMock } from '../../../common/licensing/index.mock'; jest.mock('./roles_grid', () => ({ - RolesGridPage: (props: any) => `Roles Page: ${JSON.stringify(props)}`, + RolesGridPage: ({ + // props object is too big to include into test snapshot, so we just check for existence of fields we care about + buildFlavor, + cloudOrgUrl, + readOnly, + rolesAPIClient, + }: RolesGridPageProps) => + `Roles Page: ${JSON.stringify( + { + buildFlavor, + cloudOrgUrl, + readOnly, + rolesAPIClient: rolesAPIClient ? 'rolesAPIClient' : undefined, + }, + null, + ' ' + )}`, })); jest.mock('./edit_role', () => ({ - // `docLinks` object is too big to include into test snapshot, so we just check its existence. - EditRolePage: (props: any) => - `Role Edit Page: ${JSON.stringify({ ...props, docLinks: props.docLinks ? {} : undefined })}`, + EditRolePage: ({ + // props object is too big to include into test snapshot, so we just check for existence of fields we care about + buildFlavor, + cloudOrgUrl, + roleName, + indicesAPIClient, + privilegesAPIClient, + rolesAPIClient, + userAPIClient, + }: EditRolePageProps) => + `Role Edit Page: ${JSON.stringify( + { + buildFlavor, + cloudOrgUrl, + roleName, + indicesAPIClient: indicesAPIClient ? 'indicesAPIClient' : undefined, + privilegesAPIClient: privilegesAPIClient ? 'privilegesAPIClient' : undefined, + rolesAPIClient: rolesAPIClient ? 'rolesAPIClient' : undefined, + userAPIClient: userAPIClient ? 'userAPIClient' : undefined, + }, + null, + ' ' + )}`, })); async function mountApp(basePath: string, pathname: string, buildFlavor?: BuildFlavor) { @@ -94,7 +132,11 @@ describe('rolesManagementApp', () => { expect(docTitle.reset).not.toHaveBeenCalled(); expect(container).toMatchInlineSnapshot(`
- Roles Page: {"notifications":{"toasts":{}},"rolesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"history":{"action":"PUSH","length":1,"location":{"pathname":"/","search":"","hash":""}},"readOnly":false,"buildFlavor":"traditional","i18nStart":{},"theme":{"theme$":{}}} + Roles Page: { + "buildFlavor": "traditional", + "readOnly": false, + "rolesAPIClient": "rolesAPIClient" + }
`); @@ -116,7 +158,13 @@ describe('rolesManagementApp', () => { expect(docTitle.reset).not.toHaveBeenCalled(); expect(container).toMatchInlineSnapshot(`
- Role Edit Page: {"action":"edit","rolesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"userAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"indicesAPIClient":{"fieldCache":{},"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"privilegesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}},"notifications":{"toasts":{}},"fatalErrors":{},"license":{"features$":{}},"docLinks":{},"uiCapabilities":{"catalogue":{},"management":{},"navLinks":{},"roles":{"save":true}},"history":{"action":"PUSH","length":1,"location":{"pathname":"/edit","search":"","hash":""}},"buildFlavor":"traditional","i18nStart":{},"theme":{"theme$":{}}} + Role Edit Page: { + "buildFlavor": "traditional", + "indicesAPIClient": "indicesAPIClient", + "privilegesAPIClient": "privilegesAPIClient", + "rolesAPIClient": "rolesAPIClient", + "userAPIClient": "userAPIClient" + }
`); @@ -143,7 +191,14 @@ describe('rolesManagementApp', () => { expect(docTitle.reset).not.toHaveBeenCalled(); expect(container).toMatchInlineSnapshot(`
- Role Edit Page: {"action":"edit","roleName":"role@name","rolesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"userAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"indicesAPIClient":{"fieldCache":{},"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"privilegesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}},"notifications":{"toasts":{}},"fatalErrors":{},"license":{"features$":{}},"docLinks":{},"uiCapabilities":{"catalogue":{},"management":{},"navLinks":{},"roles":{"save":true}},"history":{"action":"PUSH","length":1,"location":{"pathname":"/edit/role@name","search":"","hash":""}},"buildFlavor":"traditional","i18nStart":{},"theme":{"theme$":{}}} + Role Edit Page: { + "buildFlavor": "traditional", + "roleName": "role@name", + "indicesAPIClient": "indicesAPIClient", + "privilegesAPIClient": "privilegesAPIClient", + "rolesAPIClient": "rolesAPIClient", + "userAPIClient": "userAPIClient" + }
`); @@ -170,7 +225,14 @@ describe('rolesManagementApp', () => { expect(docTitle.reset).not.toHaveBeenCalled(); expect(container).toMatchInlineSnapshot(`
- Role Edit Page: {"action":"clone","roleName":"someRoleName","rolesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"userAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"indicesAPIClient":{"fieldCache":{},"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"privilegesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}},"notifications":{"toasts":{}},"fatalErrors":{},"license":{"features$":{}},"docLinks":{},"uiCapabilities":{"catalogue":{},"management":{},"navLinks":{},"roles":{"save":true}},"history":{"action":"PUSH","length":1,"location":{"pathname":"/clone/someRoleName","search":"","hash":""}},"buildFlavor":"traditional","i18nStart":{},"theme":{"theme$":{}}} + Role Edit Page: { + "buildFlavor": "traditional", + "roleName": "someRoleName", + "indicesAPIClient": "indicesAPIClient", + "privilegesAPIClient": "privilegesAPIClient", + "rolesAPIClient": "rolesAPIClient", + "userAPIClient": "userAPIClient" + }
`); @@ -228,7 +290,11 @@ describe('rolesManagementApp - serverless', () => { expect(docTitle.reset).not.toHaveBeenCalled(); expect(container).toMatchInlineSnapshot(`
- Roles Page: {"notifications":{"toasts":{}},"rolesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"history":{"action":"PUSH","length":1,"location":{"pathname":"/","search":"","hash":""}},"readOnly":false,"buildFlavor":"serverless","i18nStart":{},"theme":{"theme$":{}}} + Roles Page: { + "buildFlavor": "serverless", + "readOnly": false, + "rolesAPIClient": "rolesAPIClient" + }
`); @@ -257,7 +323,13 @@ describe('rolesManagementApp - serverless', () => { expect(docTitle.reset).not.toHaveBeenCalled(); expect(container).toMatchInlineSnapshot(`
- Role Edit Page: {"action":"edit","rolesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"userAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"indicesAPIClient":{"fieldCache":{},"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"privilegesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}},"notifications":{"toasts":{}},"fatalErrors":{},"license":{"features$":{}},"docLinks":{},"uiCapabilities":{"catalogue":{},"management":{},"navLinks":{},"roles":{"save":true}},"history":{"action":"PUSH","length":1,"location":{"pathname":"/edit","search":"","hash":""}},"buildFlavor":"serverless","i18nStart":{},"theme":{"theme$":{}}} + Role Edit Page: { + "buildFlavor": "serverless", + "indicesAPIClient": "indicesAPIClient", + "privilegesAPIClient": "privilegesAPIClient", + "rolesAPIClient": "rolesAPIClient", + "userAPIClient": "userAPIClient" + }
`); @@ -288,7 +360,14 @@ describe('rolesManagementApp - serverless', () => { expect(docTitle.reset).not.toHaveBeenCalled(); expect(container).toMatchInlineSnapshot(`
- Role Edit Page: {"action":"edit","roleName":"role@name","rolesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"userAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"indicesAPIClient":{"fieldCache":{},"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"privilegesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}},"notifications":{"toasts":{}},"fatalErrors":{},"license":{"features$":{}},"docLinks":{},"uiCapabilities":{"catalogue":{},"management":{},"navLinks":{},"roles":{"save":true}},"history":{"action":"PUSH","length":1,"location":{"pathname":"/edit/role@name","search":"","hash":""}},"buildFlavor":"serverless","i18nStart":{},"theme":{"theme$":{}}} + Role Edit Page: { + "buildFlavor": "serverless", + "roleName": "role@name", + "indicesAPIClient": "indicesAPIClient", + "privilegesAPIClient": "privilegesAPIClient", + "rolesAPIClient": "rolesAPIClient", + "userAPIClient": "userAPIClient" + }
`); @@ -319,7 +398,14 @@ describe('rolesManagementApp - serverless', () => { expect(docTitle.reset).not.toHaveBeenCalled(); expect(container).toMatchInlineSnapshot(`
- Role Edit Page: {"action":"clone","roleName":"someRoleName","rolesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"userAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"indicesAPIClient":{"fieldCache":{},"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"privilegesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}},"notifications":{"toasts":{}},"fatalErrors":{},"license":{"features$":{}},"docLinks":{},"uiCapabilities":{"catalogue":{},"management":{},"navLinks":{},"roles":{"save":true}},"history":{"action":"PUSH","length":1,"location":{"pathname":"/clone/someRoleName","search":"","hash":""}},"buildFlavor":"serverless","i18nStart":{},"theme":{"theme$":{}}} + Role Edit Page: { + "buildFlavor": "serverless", + "roleName": "someRoleName", + "indicesAPIClient": "indicesAPIClient", + "privilegesAPIClient": "privilegesAPIClient", + "rolesAPIClient": "rolesAPIClient", + "userAPIClient": "userAPIClient" + }
`); diff --git a/x-pack/plugins/security/public/management/roles/roles_management_app.tsx b/x-pack/plugins/security/public/management/roles/roles_management_app.tsx index f82548f89b3525..3a5d9f57b432a2 100644 --- a/x-pack/plugins/security/public/management/roles/roles_management_app.tsx +++ b/x-pack/plugins/security/public/management/roles/roles_management_app.tsx @@ -12,8 +12,9 @@ import { useParams } from 'react-router-dom'; import type { BuildFlavor } from '@kbn/config'; import type { FatalErrorsSetup, StartServicesAccessor } from '@kbn/core/public'; import { i18n } from '@kbn/i18n'; -import { KibanaContextProvider, KibanaThemeProvider } from '@kbn/kibana-react-plugin/public'; +import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; import type { RegisterManagementAppArgs } from '@kbn/management-plugin/public'; +import { KibanaRenderContextProvider } from '@kbn/react-kibana-context-render'; import { Route, Router } from '@kbn/shared-ux-router'; import type { SecurityLicense } from '../../../common'; @@ -35,7 +36,7 @@ interface CreateParams { export const rolesManagementApp = Object.freeze({ id: 'roles', - create({ license, fatalErrors, getStartServices, buildFlavor }: CreateParams) { + create({ license, getStartServices, buildFlavor }: CreateParams) { const title = buildFlavor === 'serverless' ? i18n.translate('xpack.security.management.rolesTitleServerless', { @@ -48,7 +49,7 @@ export const rolesManagementApp = Object.freeze({ id: this.id, order: 20, title, - async mount({ element, theme$, setBreadcrumbs, history }) { + async mount({ element, setBreadcrumbs, history }) { const [ [startServices, { dataViews, features, spaces, cloud }], { RolesGridPage }, @@ -67,15 +68,7 @@ export const rolesManagementApp = Object.freeze({ import('../users'), ]); - const { - application, - docLinks, - http, - i18n: i18nStart, - notifications, - chrome, - theme: themeServiceStart, - } = startServices; + const { application, http, chrome } = startServices; chrome.docTitle.change(title); @@ -109,63 +102,54 @@ export const rolesManagementApp = Object.freeze({ indicesAPIClient={new IndicesAPIClient(http)} privilegesAPIClient={new PrivilegesAPIClient(http)} getFeatures={features.getFeatures} - http={http} - notifications={notifications} - fatalErrors={fatalErrors} license={license} - docLinks={docLinks} uiCapabilities={application.capabilities} dataViews={dataViews} history={history} spacesApiUi={spacesApiUi} buildFlavor={buildFlavor} - i18nStart={i18nStart} - theme={themeServiceStart} cloudOrgUrl={cloud?.organizationUrl} + {...startServices} /> ); }; render( - - - - - - - - - - - - - - - - - - - - - - , + + + + + + + + + + + + + + + + + + + + , element ); diff --git a/x-pack/plugins/security/public/management/users/edit_user/create_user_page.test.tsx b/x-pack/plugins/security/public/management/users/edit_user/create_user_page.test.tsx index ef41ba92c78502..7771560826f6fc 100644 --- a/x-pack/plugins/security/public/management/users/edit_user/create_user_page.test.tsx +++ b/x-pack/plugins/security/public/management/users/edit_user/create_user_page.test.tsx @@ -9,7 +9,7 @@ import { fireEvent, render, waitFor, within } from '@testing-library/react'; import { createMemoryHistory } from 'history'; import React from 'react'; -import { coreMock, themeServiceMock } from '@kbn/core/public/mocks'; +import { coreMock } from '@kbn/core/public/mocks'; import { CreateUserPage } from './create_user_page'; import { securityMock } from '../../../mocks'; @@ -23,7 +23,6 @@ describe('CreateUserPage', () => { jest.setTimeout(15_000); const coreStart = coreMock.createStart(); - const theme$ = themeServiceMock.createTheme$(); let history = createMemoryHistory({ initialEntries: ['/create'] }); const authc = securityMock.createSetup().authc; @@ -45,7 +44,7 @@ describe('CreateUserPage', () => { coreStart.http.post.mockResolvedValue({}); const { findByRole, findByLabelText } = render( - + ); @@ -80,7 +79,7 @@ describe('CreateUserPage', () => { }; render( - + ); @@ -103,7 +102,7 @@ describe('CreateUserPage', () => { ]); const { findAllByText, findByRole, findByLabelText } = render( - + ); diff --git a/x-pack/plugins/security/public/management/users/edit_user/edit_user_page.test.tsx b/x-pack/plugins/security/public/management/users/edit_user/edit_user_page.test.tsx index 673fd2e89599a4..badc5990d91b2b 100644 --- a/x-pack/plugins/security/public/management/users/edit_user/edit_user_page.test.tsx +++ b/x-pack/plugins/security/public/management/users/edit_user/edit_user_page.test.tsx @@ -9,7 +9,7 @@ import { fireEvent, render } from '@testing-library/react'; import { createMemoryHistory } from 'history'; import React from 'react'; -import { coreMock, themeServiceMock } from '@kbn/core/public/mocks'; +import { coreMock } from '@kbn/core/public/mocks'; import { EditUserPage } from './edit_user_page'; import { securityMock } from '../../../mocks'; @@ -25,7 +25,6 @@ const userMock = { describe('EditUserPage', () => { const coreStart = coreMock.createStart(); - const theme$ = themeServiceMock.createTheme$(); let history = createMemoryHistory({ initialEntries: ['/edit/jdoe'] }); const authc = securityMock.createSetup().authc; @@ -53,7 +52,7 @@ describe('EditUserPage', () => { coreStart.http.get.mockResolvedValueOnce([]); const { findByText } = render( - + ); @@ -73,7 +72,7 @@ describe('EditUserPage', () => { coreStart.http.get.mockResolvedValueOnce([]); const { findByRole, findByText } = render( - + ); @@ -94,7 +93,7 @@ describe('EditUserPage', () => { coreStart.http.get.mockResolvedValueOnce([]); const { findByRole, findByText } = render( - + ); @@ -124,7 +123,7 @@ describe('EditUserPage', () => { ]); const { findByText } = render( - + ); @@ -143,7 +142,7 @@ describe('EditUserPage', () => { }; const { findByRole, findAllByRole } = render( - + ); diff --git a/x-pack/plugins/security/public/management/users/users_management_app.tsx b/x-pack/plugins/security/public/management/users/users_management_app.tsx index ffb7d1e5618d93..4935db6273bb67 100644 --- a/x-pack/plugins/security/public/management/users/users_management_app.tsx +++ b/x-pack/plugins/security/public/management/users/users_management_app.tsx @@ -10,13 +10,12 @@ import type { FunctionComponent } from 'react'; import React from 'react'; import { render, unmountComponentAtNode } from 'react-dom'; import { Redirect } from 'react-router-dom'; -import type { Observable } from 'rxjs'; -import type { CoreStart, CoreTheme, StartServicesAccessor } from '@kbn/core/public'; +import type { CoreStart, StartServicesAccessor } from '@kbn/core/public'; import { i18n } from '@kbn/i18n'; -import { I18nProvider } from '@kbn/i18n-react'; -import { KibanaContextProvider, KibanaThemeProvider } from '@kbn/kibana-react-plugin/public'; +import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; import type { RegisterManagementAppArgs } from '@kbn/management-plugin/public'; +import { KibanaRenderContextProvider } from '@kbn/react-kibana-context-render'; import type { AuthenticationServiceSetup } from '@kbn/security-plugin-types-public'; import { Route, Router, Routes } from '@kbn/shared-ux-router'; @@ -46,7 +45,7 @@ export const usersManagementApp = Object.freeze({ id: this.id, order: 10, title, - async mount({ element, theme$, setBreadcrumbs, history }) { + async mount({ element, setBreadcrumbs, history }) { const [ [coreStart], { UsersGridPage }, @@ -64,7 +63,6 @@ export const usersManagementApp = Object.freeze({ render( ; history: History; authc: AuthenticationServiceSetup; onChange?: BreadcrumbsChangeHandler; @@ -142,21 +139,18 @@ export interface ProvidersProps { export const Providers: FunctionComponent = ({ services, - theme$, history, authc, onChange, children, }) => ( - - - - - - {children} - - - - - + + + + + {children} + + + + ); diff --git a/x-pack/plugins/security/public/nav_control/nav_control_service.tsx b/x-pack/plugins/security/public/nav_control/nav_control_service.tsx index a9098396bd1891..ebfe41aeafc0c7 100644 --- a/x-pack/plugins/security/public/nav_control/nav_control_service.tsx +++ b/x-pack/plugins/security/public/nav_control/nav_control_service.tsx @@ -9,13 +9,13 @@ import { sortBy } from 'lodash'; import type { FunctionComponent } from 'react'; import React from 'react'; import ReactDOM from 'react-dom'; -import type { Observable, Subscription } from 'rxjs'; +import type { Subscription } from 'rxjs'; import { BehaviorSubject, map, ReplaySubject, takeUntil } from 'rxjs'; import type { BuildFlavor } from '@kbn/config/src/types'; -import type { CoreStart, CoreTheme } from '@kbn/core/public'; -import { I18nProvider } from '@kbn/i18n-react'; -import { KibanaContextProvider, KibanaThemeProvider } from '@kbn/kibana-react-plugin/public'; +import type { CoreStart } from '@kbn/core/public'; +import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; +import { KibanaRenderContextProvider } from '@kbn/react-kibana-context-render'; import type { AuthenticationServiceSetup, SecurityNavControlServiceStart, @@ -110,18 +110,11 @@ export class SecurityNavControlService { } private registerSecurityNavControl(core: CoreStart, authc: AuthenticationServiceSetup) { - const { theme$ } = core.theme; - core.chrome.navControls.registerRight({ order: 4000, mount: (element: HTMLElement) => { ReactDOM.render( - + ; } export const Providers: FunctionComponent = ({ authc, services, - theme$, securityApiClients, children, }) => ( - - - - - - {children} - - - - - + + + + + {children} + + + + ); diff --git a/x-pack/plugins/security/public/plugin.tsx b/x-pack/plugins/security/public/plugin.tsx index 1aaf7a882d6a28..333f8736731ac2 100644 --- a/x-pack/plugins/security/public/plugin.tsx +++ b/x-pack/plugins/security/public/plugin.tsx @@ -196,7 +196,7 @@ export class SecurityPlugin const sessionExpired = new SessionExpired(application, logoutUrl, tenant); http.intercept(new UnauthorizedResponseHttpInterceptor(sessionExpired, anonymousPaths)); - this.sessionTimeout = new SessionTimeout(notifications, sessionExpired, http, tenant); + this.sessionTimeout = new SessionTimeout(core, notifications, sessionExpired, http, tenant); this.sessionTimeout.start(); this.securityCheckupService.start({ http, notifications, docLinks }); diff --git a/x-pack/plugins/security/public/session/session_expiration_toast.test.tsx b/x-pack/plugins/security/public/session/session_expiration_toast.test.tsx index 0cec3b1848008d..f2f1f6ff92f792 100644 --- a/x-pack/plugins/security/public/session/session_expiration_toast.test.tsx +++ b/x-pack/plugins/security/public/session/session_expiration_toast.test.tsx @@ -8,6 +8,7 @@ import { fireEvent, render } from '@testing-library/react'; import React from 'react'; import { of } from 'rxjs'; +import { coreMock } from '@kbn/core/public/mocks'; import { I18nProvider } from '@kbn/i18n-react'; import { createSessionExpirationToast, SessionExpirationToast } from './session_expiration_toast'; @@ -15,6 +16,7 @@ import type { SessionState } from './session_timeout'; describe('createSessionExpirationToast', () => { it('creates a toast', () => { + const coreStart = coreMock.createStart(); const sessionState$ = of({ lastExtensionTime: Date.now(), expiresInMs: 60 * 1000, @@ -22,7 +24,7 @@ describe('createSessionExpirationToast', () => { }); const onExtend = jest.fn(); const onClose = jest.fn(); - const toast = createSessionExpirationToast(sessionState$, onExtend, onClose); + const toast = createSessionExpirationToast(coreStart, sessionState$, onExtend, onClose); expect(toast).toEqual( expect.objectContaining({ diff --git a/x-pack/plugins/security/public/session/session_expiration_toast.tsx b/x-pack/plugins/security/public/session/session_expiration_toast.tsx index b5aa984a5ce1f7..03e82d06b64da0 100644 --- a/x-pack/plugins/security/public/session/session_expiration_toast.tsx +++ b/x-pack/plugins/security/public/session/session_expiration_toast.tsx @@ -15,9 +15,10 @@ import type { Observable } from 'rxjs'; import type { ToastInput } from '@kbn/core/public'; import { i18n } from '@kbn/i18n'; import { FormattedMessage, FormattedRelative } from '@kbn/i18n-react'; -import { toMountPoint } from '@kbn/kibana-react-plugin/public'; +import { toMountPoint } from '@kbn/react-kibana-mount'; import type { SessionState } from './session_timeout'; +import type { StartServices } from '..'; import { SESSION_GRACE_PERIOD_MS } from '../../common/constants'; export interface SessionExpirationToastProps { @@ -74,6 +75,7 @@ export const SessionExpirationToast: FunctionComponent, onExtend: () => Promise, onClose: () => void @@ -85,7 +87,8 @@ export const createSessionExpirationToast = ( defaultMessage: 'Session timeout', }), text: toMountPoint( - + , + services ), onClose, toastLifeTimeMs: 0x7fffffff, // Toast is hidden based on observable so using maximum possible timeout diff --git a/x-pack/plugins/security/public/session/session_timeout.test.ts b/x-pack/plugins/security/public/session/session_timeout.test.ts index fa0bcffc66b015..71180a83a8cbe9 100644 --- a/x-pack/plugins/security/public/session/session_timeout.test.ts +++ b/x-pack/plugins/security/public/session/session_timeout.test.ts @@ -38,11 +38,12 @@ const visibilityStateMock = jest.spyOn(document, 'visibilityState', 'get'); function createSessionTimeout(expiresInMs: number | null = 60 * 60 * 1000, canBeExtended = true) { const { notifications, http } = coreMock.createSetup(); + const coreStart = coreMock.createStart(); const toast = Symbol(); notifications.toasts.add.mockReturnValue(toast as any); const sessionExpired = createSessionExpiredMock(); const tenant = 'test'; - const sessionTimeout = new SessionTimeout(notifications, sessionExpired, http, tenant); + const sessionTimeout = new SessionTimeout(coreStart, notifications, sessionExpired, http, tenant); http.fetch.mockResolvedValue({ expiresInMs, @@ -294,7 +295,7 @@ describe('SessionTimeout', () => { const [toast] = notifications.toasts.add.mock.calls[0] as [ToastInputFields]; - await toast.onClose!(); + toast.onClose!(); expect(http.fetch).toHaveBeenCalledTimes(3); expect(http.fetch).toHaveBeenLastCalledWith( diff --git a/x-pack/plugins/security/public/session/session_timeout.ts b/x-pack/plugins/security/public/session/session_timeout.ts index 34255657857c98..e119e43db1b728 100644 --- a/x-pack/plugins/security/public/session/session_timeout.ts +++ b/x-pack/plugins/security/public/session/session_timeout.ts @@ -17,6 +17,7 @@ import type { import { createSessionExpirationToast } from './session_expiration_toast'; import type { SessionExpired } from './session_expired'; +import type { StartServices } from '..'; import { SESSION_CHECK_MS, SESSION_EXPIRATION_WARNING_MS, @@ -57,6 +58,7 @@ export class SessionTimeout { private stopLogoutTimer?: Function; constructor( + private startServices: StartServices, private notifications: NotificationsSetup, private sessionExpired: Pick, private http: HttpSetup, @@ -265,7 +267,12 @@ export class SessionTimeout { this.hideWarning(true); return onExtend(); }; - const toast = createSessionExpirationToast(this.sessionState$, onExtend, onClose); + const toast = createSessionExpirationToast( + this.startServices, + this.sessionState$, + onExtend, + onClose + ); this.warningToast = this.notifications.toasts.add(toast); } }; diff --git a/x-pack/plugins/security/tsconfig.json b/x-pack/plugins/security/tsconfig.json index 2e0430de3b5496..3dde17effc7109 100644 --- a/x-pack/plugins/security/tsconfig.json +++ b/x-pack/plugins/security/tsconfig.json @@ -77,11 +77,11 @@ "@kbn/core-security-server", "@kbn/core-http-router-server-internal", "@kbn/react-kibana-mount", - "@kbn/react-kibana-context-theme", "@kbn/core-security-common", - "@kbn/react-kibana-context-common", + "@kbn/react-kibana-context-render", "@kbn/core-i18n-browser-mocks", "@kbn/core-theme-browser-mocks", + "@kbn/core-analytics-browser-mocks", ], "exclude": [ "target/**/*", diff --git a/x-pack/plugins/spaces/public/management/spaces_management_app.tsx b/x-pack/plugins/spaces/public/management/spaces_management_app.tsx index ba63168875d758..1819b22cb7f3b7 100644 --- a/x-pack/plugins/spaces/public/management/spaces_management_app.tsx +++ b/x-pack/plugins/spaces/public/management/spaces_management_app.tsx @@ -11,8 +11,9 @@ import { useParams } from 'react-router-dom'; import type { StartServicesAccessor } from '@kbn/core/public'; import { i18n } from '@kbn/i18n'; -import { KibanaContextProvider, KibanaThemeProvider } from '@kbn/kibana-react-plugin/public'; +import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; import type { RegisterManagementAppArgs } from '@kbn/management-plugin/public'; +import { KibanaRenderContextProvider } from '@kbn/react-kibana-context-render'; import { RedirectAppLinks } from '@kbn/shared-ux-link-redirect-app'; import { Route, Router, Routes } from '@kbn/shared-ux-router'; @@ -39,7 +40,7 @@ export const spacesManagementApp = Object.freeze({ order: 2, title, - async mount({ element, theme$, setBreadcrumbs, history }) { + async mount({ element, setBreadcrumbs, history }) { const [[coreStart, { features }], { SpacesGridPage }, { ManageSpacePage }] = await Promise.all([getStartServices(), import('./spaces_grid'), import('./edit_space')]); @@ -47,7 +48,7 @@ export const spacesManagementApp = Object.freeze({ text: title, href: `/`, }; - const { notifications, i18n: i18nStart, application, chrome } = coreStart; + const { notifications, application, chrome } = coreStart; chrome.docTitle.change(title); @@ -115,27 +116,25 @@ export const spacesManagementApp = Object.freeze({ }; render( - - - - - - - - - - - - - - - - - - - - - , + + + + + + + + + + + + + + + + + + + , element ); diff --git a/x-pack/plugins/spaces/public/nav_control/nav_control.tsx b/x-pack/plugins/spaces/public/nav_control/nav_control.tsx index 80b08bdd5f8f89..732be89eacd7b1 100644 --- a/x-pack/plugins/spaces/public/nav_control/nav_control.tsx +++ b/x-pack/plugins/spaces/public/nav_control/nav_control.tsx @@ -10,13 +10,11 @@ import React, { lazy, Suspense } from 'react'; import ReactDOM from 'react-dom'; import type { CoreStart } from '@kbn/core/public'; -import { KibanaThemeProvider } from '@kbn/kibana-react-plugin/public'; +import { KibanaRenderContextProvider } from '@kbn/react-kibana-context-render'; import type { SpacesManager } from '../spaces_manager'; export function initSpacesNavControl(spacesManager: SpacesManager, core: CoreStart) { - const I18nContext = core.i18n.Context; - const { theme$ } = core.theme; core.chrome.navControls.registerLeft({ order: 1000, mount(targetDomElement: HTMLElement) { @@ -31,20 +29,18 @@ export function initSpacesNavControl(spacesManager: SpacesManager, core: CoreSta ); ReactDOM.render( - - - }> - - - - , + + }> + + + , targetDomElement ); diff --git a/x-pack/plugins/spaces/public/space_selector/space_selector.tsx b/x-pack/plugins/spaces/public/space_selector/space_selector.tsx index ee7d320ead7ccd..e90d1c4a10954c 100644 --- a/x-pack/plugins/spaces/public/space_selector/space_selector.tsx +++ b/x-pack/plugins/spaces/public/space_selector/space_selector.tsx @@ -26,7 +26,7 @@ import type { AppMountParameters, CoreStart } from '@kbn/core/public'; import type { CustomBranding } from '@kbn/core-custom-branding-common'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; -import { KibanaThemeProvider } from '@kbn/kibana-react-plugin/public'; +import { KibanaRenderContextProvider } from '@kbn/react-kibana-context-render'; import { KibanaSolutionAvatar } from '@kbn/shared-ux-avatar-solution'; import { KibanaPageTemplate } from '@kbn/shared-ux-page-kibana-template'; @@ -250,16 +250,14 @@ export class SpaceSelector extends Component { } export const renderSpaceSelectorApp = ( - i18nStart: CoreStart['i18n'], - { element, theme$ }: Pick, + services: Pick, + { element }: Pick, props: Props ) => { ReactDOM.render( - - - - - , + + + , element ); return () => ReactDOM.unmountComponentAtNode(element); diff --git a/x-pack/plugins/spaces/public/space_selector/space_selector_app.tsx b/x-pack/plugins/spaces/public/space_selector/space_selector_app.tsx index 45fb334c2b8643..61f19595e31771 100644 --- a/x-pack/plugins/spaces/public/space_selector/space_selector_app.tsx +++ b/x-pack/plugins/spaces/public/space_selector/space_selector_app.tsx @@ -26,14 +26,14 @@ export const spaceSelectorApp = Object.freeze({ }), chromeless: true, appRoute: '/spaces/space_selector', - mount: async ({ element, theme$ }: AppMountParameters) => { + mount: async ({ element }: AppMountParameters) => { const [[coreStart], { renderSpaceSelectorApp }] = await Promise.all([ getStartServices(), import('./space_selector'), ]); return renderSpaceSelectorApp( - coreStart.i18n, - { element, theme$ }, + coreStart, + { element }, { spacesManager, serverBasePath: coreStart.http.basePath.serverBasePath, diff --git a/x-pack/plugins/spaces/tsconfig.json b/x-pack/plugins/spaces/tsconfig.json index 9e89c8c2055ee8..863027b3825102 100644 --- a/x-pack/plugins/spaces/tsconfig.json +++ b/x-pack/plugins/spaces/tsconfig.json @@ -33,6 +33,7 @@ "@kbn/config", "@kbn/shared-ux-avatar-solution", "@kbn/core-http-server", + "@kbn/react-kibana-context-render", ], "exclude": [ "target/**/*",