Skip to content

Commit

Permalink
[8.x] [Spaces] Read Security license to infer eligibility for sub fea…
Browse files Browse the repository at this point in the history
…ture customization (#195389) (#196925)

# Backport

This will backport the following commits from `main` to `8.x`:
- [[Spaces] Read Security license to infer eligibility for sub feature
customization (#195389)](#195389)

<!--- Backport version: 8.9.8 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sqren/backport)

<!--BACKPORT [{"author":{"name":"Eyo O.
Eyo","email":"[email protected]"},"sourceCommit":{"committedDate":"2024-10-16T10:02:51Z","message":"[Spaces]
Read Security license to infer eligibility for sub feature customization
(#195389)\n\n## Summary\r\n\r\nCloses
https://github.com/elastic/kibana/issues/195549\r\n\r\nThis PR adds
implementation such that eligibility to allow for the\r\ntoggling of the
switch for customization of sub features whilst defining\r\nprivileges
that would be assigned to a space is determined from
security\r\nlicense.\r\n\r\n\r\n###
Before\r\n![ScreenRecording2024-10-09at10 09
33-ezgif\r\ncom-video-to-gif-converter](https://github.com/user-attachments/assets/c80761c9-a45e-4784-835e-e6895d2fbed5)\r\n\r\n###
After\r\n\r\n![ScreenRecording2024-10-09at10 05
53-ezgif\r\ncom-video-to-gif-converter](https://github.com/user-attachments/assets/4e7d5724-42b0-4495-8fae-b47e7a97957c)\r\n\r\n<!--
### Checklist\r\n\r\nDelete any items that are not applicable to this
PR.\r\n\r\n- [ ] Any text added follows [EUI's
writing\r\nguidelines](https://elastic.github.io/eui/#/guidelines/writing),
uses\r\nsentence case text and includes
[i18n\r\nsupport](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md)\r\n-
[
]\r\n[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)\r\nwas
added for features that require explanation or tutorials\r\n- [ ] [Unit
or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common scenarios\r\n- [ ] [Flaky
Test\r\nRunner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1)
was\r\nused on any tests changed\r\n- [ ] Any UI touched in this PR is
usable by keyboard only (learn more\r\nabout [keyboard
accessibility](https://webaim.org/techniques/keyboard/))\r\n- [ ] Any UI
touched in this PR does not create any new axe failures\r\n(run axe in
browser:\r\n[FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/),\r\n[Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US))\r\n-
[ ] If a plugin configuration key changed, check if it needs to
be\r\nallowlisted in the cloud and added to the
[docker\r\nlist](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker)\r\n-
[ ] This renders correctly on smaller devices using a
responsive\r\nlayout. (You can test this [in
your\r\nbrowser](https://www.browserstack.com/guide/responsive-testing-on-local-server))\r\n-
[ ] This was checked for
[cross-browser\r\ncompatibility](https://www.elastic.co/support/matrix#matrix_browsers)\r\n\r\n\r\n###
Risk Matrix\r\n\r\nDelete this section if it is not applicable to this
PR.\r\n\r\nBefore closing this PR, invite QA, stakeholders, and other
developers to\r\nidentify risks that should be tested prior to the
change/feature\r\nrelease.\r\n\r\nWhen forming the risk matrix, consider
some of the following examples\r\nand how they may potentially impact
the change:\r\n\r\n| Risk | Probability | Severity | Mitigation/Notes
|\r\n\r\n|---------------------------|-------------|----------|-------------------------|\r\n|
Multiple Spaces&mdash;unexpected behavior in non-default Kibana
Space.\r\n| Low | High | Integration tests will verify that all features
are still\r\nsupported in non-default Kibana Space and when user
switches between\r\nspaces. |\r\n| Multiple nodes&mdash;Elasticsearch
polling might have race conditions\r\nwhen multiple Kibana nodes are
polling for the same tasks. | High | Low\r\n| Tasks are idempotent, so
executing them multiple times will not result\r\nin logical error, but
will degrade performance. To test for this case we\r\nadd plenty of unit
tests around this logic and document manual testing\r\nprocedure. |\r\n|
Code should gracefully handle cases when feature X or plugin Y
are\r\ndisabled. | Medium | High | Unit tests will verify that any
feature flag\r\nor plugin combination still results in our service
operational. |\r\n| [See more potential
risk\r\nexamples](https://github.com/elastic/kibana/blob/main/RISK_MATRIX.mdx)
|\r\n\r\n\r\n### For maintainers\r\n\r\n- [ ] This was checked for
breaking API changes and was
[labeled\r\nappropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)\r\n-->","sha":"e6e30c20215ce7cbb8bd25d6646edc5d0a8bc33e","branchLabelMapping":{"^v9.0.0$":"main","^v8.16.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["Team:Security","release_note:skip","backport
missing","v9.0.0","backport:prev-major"],"number":195389,"url":"https://github.com/elastic/kibana/pull/195389","mergeCommit":{"message":"[Spaces]
Read Security license to infer eligibility for sub feature customization
(#195389)\n\n## Summary\r\n\r\nCloses
https://github.com/elastic/kibana/issues/195549\r\n\r\nThis PR adds
implementation such that eligibility to allow for the\r\ntoggling of the
switch for customization of sub features whilst defining\r\nprivileges
that would be assigned to a space is determined from
security\r\nlicense.\r\n\r\n\r\n###
Before\r\n![ScreenRecording2024-10-09at10 09
33-ezgif\r\ncom-video-to-gif-converter](https://github.com/user-attachments/assets/c80761c9-a45e-4784-835e-e6895d2fbed5)\r\n\r\n###
After\r\n\r\n![ScreenRecording2024-10-09at10 05
53-ezgif\r\ncom-video-to-gif-converter](https://github.com/user-attachments/assets/4e7d5724-42b0-4495-8fae-b47e7a97957c)\r\n\r\n<!--
### Checklist\r\n\r\nDelete any items that are not applicable to this
PR.\r\n\r\n- [ ] Any text added follows [EUI's
writing\r\nguidelines](https://elastic.github.io/eui/#/guidelines/writing),
uses\r\nsentence case text and includes
[i18n\r\nsupport](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md)\r\n-
[
]\r\n[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)\r\nwas
added for features that require explanation or tutorials\r\n- [ ] [Unit
or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common scenarios\r\n- [ ] [Flaky
Test\r\nRunner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1)
was\r\nused on any tests changed\r\n- [ ] Any UI touched in this PR is
usable by keyboard only (learn more\r\nabout [keyboard
accessibility](https://webaim.org/techniques/keyboard/))\r\n- [ ] Any UI
touched in this PR does not create any new axe failures\r\n(run axe in
browser:\r\n[FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/),\r\n[Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US))\r\n-
[ ] If a plugin configuration key changed, check if it needs to
be\r\nallowlisted in the cloud and added to the
[docker\r\nlist](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker)\r\n-
[ ] This renders correctly on smaller devices using a
responsive\r\nlayout. (You can test this [in
your\r\nbrowser](https://www.browserstack.com/guide/responsive-testing-on-local-server))\r\n-
[ ] This was checked for
[cross-browser\r\ncompatibility](https://www.elastic.co/support/matrix#matrix_browsers)\r\n\r\n\r\n###
Risk Matrix\r\n\r\nDelete this section if it is not applicable to this
PR.\r\n\r\nBefore closing this PR, invite QA, stakeholders, and other
developers to\r\nidentify risks that should be tested prior to the
change/feature\r\nrelease.\r\n\r\nWhen forming the risk matrix, consider
some of the following examples\r\nand how they may potentially impact
the change:\r\n\r\n| Risk | Probability | Severity | Mitigation/Notes
|\r\n\r\n|---------------------------|-------------|----------|-------------------------|\r\n|
Multiple Spaces&mdash;unexpected behavior in non-default Kibana
Space.\r\n| Low | High | Integration tests will verify that all features
are still\r\nsupported in non-default Kibana Space and when user
switches between\r\nspaces. |\r\n| Multiple nodes&mdash;Elasticsearch
polling might have race conditions\r\nwhen multiple Kibana nodes are
polling for the same tasks. | High | Low\r\n| Tasks are idempotent, so
executing them multiple times will not result\r\nin logical error, but
will degrade performance. To test for this case we\r\nadd plenty of unit
tests around this logic and document manual testing\r\nprocedure. |\r\n|
Code should gracefully handle cases when feature X or plugin Y
are\r\ndisabled. | Medium | High | Unit tests will verify that any
feature flag\r\nor plugin combination still results in our service
operational. |\r\n| [See more potential
risk\r\nexamples](https://github.com/elastic/kibana/blob/main/RISK_MATRIX.mdx)
|\r\n\r\n\r\n### For maintainers\r\n\r\n- [ ] This was checked for
breaking API changes and was
[labeled\r\nappropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)\r\n-->","sha":"e6e30c20215ce7cbb8bd25d6646edc5d0a8bc33e"}},"sourceBranch":"main","suggestedTargetBranches":[],"targetPullRequestStates":[{"branch":"main","label":"v9.0.0","labelRegex":"^v9.0.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/195389","number":195389,"mergeCommit":{"message":"[Spaces]
Read Security license to infer eligibility for sub feature customization
(#195389)\n\n## Summary\r\n\r\nCloses
https://github.com/elastic/kibana/issues/195549\r\n\r\nThis PR adds
implementation such that eligibility to allow for the\r\ntoggling of the
switch for customization of sub features whilst defining\r\nprivileges
that would be assigned to a space is determined from
security\r\nlicense.\r\n\r\n\r\n###
Before\r\n![ScreenRecording2024-10-09at10 09
33-ezgif\r\ncom-video-to-gif-converter](https://github.com/user-attachments/assets/c80761c9-a45e-4784-835e-e6895d2fbed5)\r\n\r\n###
After\r\n\r\n![ScreenRecording2024-10-09at10 05
53-ezgif\r\ncom-video-to-gif-converter](https://github.com/user-attachments/assets/4e7d5724-42b0-4495-8fae-b47e7a97957c)\r\n\r\n<!--
### Checklist\r\n\r\nDelete any items that are not applicable to this
PR.\r\n\r\n- [ ] Any text added follows [EUI's
writing\r\nguidelines](https://elastic.github.io/eui/#/guidelines/writing),
uses\r\nsentence case text and includes
[i18n\r\nsupport](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md)\r\n-
[
]\r\n[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)\r\nwas
added for features that require explanation or tutorials\r\n- [ ] [Unit
or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common scenarios\r\n- [ ] [Flaky
Test\r\nRunner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1)
was\r\nused on any tests changed\r\n- [ ] Any UI touched in this PR is
usable by keyboard only (learn more\r\nabout [keyboard
accessibility](https://webaim.org/techniques/keyboard/))\r\n- [ ] Any UI
touched in this PR does not create any new axe failures\r\n(run axe in
browser:\r\n[FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/),\r\n[Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US))\r\n-
[ ] If a plugin configuration key changed, check if it needs to
be\r\nallowlisted in the cloud and added to the
[docker\r\nlist](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker)\r\n-
[ ] This renders correctly on smaller devices using a
responsive\r\nlayout. (You can test this [in
your\r\nbrowser](https://www.browserstack.com/guide/responsive-testing-on-local-server))\r\n-
[ ] This was checked for
[cross-browser\r\ncompatibility](https://www.elastic.co/support/matrix#matrix_browsers)\r\n\r\n\r\n###
Risk Matrix\r\n\r\nDelete this section if it is not applicable to this
PR.\r\n\r\nBefore closing this PR, invite QA, stakeholders, and other
developers to\r\nidentify risks that should be tested prior to the
change/feature\r\nrelease.\r\n\r\nWhen forming the risk matrix, consider
some of the following examples\r\nand how they may potentially impact
the change:\r\n\r\n| Risk | Probability | Severity | Mitigation/Notes
|\r\n\r\n|---------------------------|-------------|----------|-------------------------|\r\n|
Multiple Spaces&mdash;unexpected behavior in non-default Kibana
Space.\r\n| Low | High | Integration tests will verify that all features
are still\r\nsupported in non-default Kibana Space and when user
switches between\r\nspaces. |\r\n| Multiple nodes&mdash;Elasticsearch
polling might have race conditions\r\nwhen multiple Kibana nodes are
polling for the same tasks. | High | Low\r\n| Tasks are idempotent, so
executing them multiple times will not result\r\nin logical error, but
will degrade performance. To test for this case we\r\nadd plenty of unit
tests around this logic and document manual testing\r\nprocedure. |\r\n|
Code should gracefully handle cases when feature X or plugin Y
are\r\ndisabled. | Medium | High | Unit tests will verify that any
feature flag\r\nor plugin combination still results in our service
operational. |\r\n| [See more potential
risk\r\nexamples](https://github.com/elastic/kibana/blob/main/RISK_MATRIX.mdx)
|\r\n\r\n\r\n### For maintainers\r\n\r\n- [ ] This was checked for
breaking API changes and was
[labeled\r\nappropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)\r\n-->","sha":"e6e30c20215ce7cbb8bd25d6646edc5d0a8bc33e"}},{"url":"https://github.com/elastic/kibana/pull/196924","number":196924,"branch":"8.16","state":"OPEN"}]}]
BACKPORT-->

Co-authored-by: Eyo O. Eyo <[email protected]>
  • Loading branch information
tsullivan and eokoneyo authored Oct 18, 2024
1 parent 070ea62 commit ecf451f
Show file tree
Hide file tree
Showing 18 changed files with 334 additions and 95 deletions.
1 change: 1 addition & 0 deletions x-pack/packages/security/plugin_types_public/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,4 @@ export type {
} from './src/roles';
export { PrivilegesAPIClientPublicContract } from './src/privileges';
export type { PrivilegesAPIClientGetAllArgs } from './src/privileges';
export type { SecurityLicense } from './src/license';
10 changes: 10 additions & 0 deletions x-pack/packages/security/plugin_types_public/src/license/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import type { SecurityPluginSetup } from '../plugin';

export type SecurityLicense = SecurityPluginSetup['license'];
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,13 @@ import {
import { __IntlProvider as IntlProvider } from '@kbn/i18n-react';

import { EditSpaceContentTab } from './edit_space_content_tab';
import { EditSpaceProvider } from './provider';
import { EditSpaceProviderRoot } from './provider';
import type { Space } from '../../../common';
import { spacesManagerMock } from '../../spaces_manager/spaces_manager.mock';
import type { SpaceContentTypeSummaryItem } from '../../types';
import { getPrivilegeAPIClientMock } from '../privilege_api_client.mock';
import { getRolesAPIClientMock } from '../roles_api_client.mock';
import { getSecurityLicenseMock } from '../security_license.mock';

const getUrlForApp = (appId: string) => appId;
const navigateToUrl = jest.fn();
Expand All @@ -42,7 +43,7 @@ const logger = loggingSystemMock.createLogger();
const TestComponent: React.FC<React.PropsWithChildren> = ({ children }) => {
return (
<IntlProvider locale="en">
<EditSpaceProvider
<EditSpaceProviderRoot
capabilities={{
navLinks: {},
management: {},
Expand All @@ -58,12 +59,13 @@ const TestComponent: React.FC<React.PropsWithChildren> = ({ children }) => {
notifications={notifications}
overlays={overlays}
getPrivilegesAPIClient={getPrivilegeAPIClient}
getSecurityLicense={getSecurityLicenseMock}
theme={theme}
i18n={i18n}
logger={logger}
>
{children}
</EditSpaceProvider>
</EditSpaceProviderRoot>
</IntlProvider>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,13 @@ import { KibanaFeature } from '@kbn/features-plugin/common';
import { __IntlProvider as IntlProvider } from '@kbn/i18n-react';

import { EditSpaceSettingsTab } from './edit_space_general_tab';
import { EditSpaceProvider } from './provider/edit_space_provider';
import { EditSpaceProviderRoot } from './provider/edit_space_provider';
import type { SolutionView } from '../../../common';
import { SOLUTION_VIEW_CLASSIC } from '../../../common/constants';
import { spacesManagerMock } from '../../spaces_manager/spaces_manager.mock';
import { getPrivilegeAPIClientMock } from '../privilege_api_client.mock';
import { getRolesAPIClientMock } from '../roles_api_client.mock';
import { getSecurityLicenseMock } from '../security_license.mock';

const space = { id: 'default', name: 'Default', disabledFeatures: [], _reserved: true };
const history = scopedHistoryMock.create();
Expand Down Expand Up @@ -64,7 +65,7 @@ describe('EditSpaceSettings', () => {
const TestComponent: React.FC<React.PropsWithChildren> = ({ children }) => {
return (
<IntlProvider locale="en">
<EditSpaceProvider
<EditSpaceProviderRoot
capabilities={{
navLinks: {},
management: {},
Expand All @@ -80,12 +81,13 @@ describe('EditSpaceSettings', () => {
notifications={notifications}
overlays={overlays}
getPrivilegesAPIClient={getPrivilegeAPIClient}
getSecurityLicense={getSecurityLicenseMock}
theme={theme}
i18n={i18n}
logger={logger}
>
{children}
</EditSpaceProvider>
</EditSpaceProviderRoot>
</IntlProvider>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import React from 'react';
import type { ComponentProps, PropsWithChildren } from 'react';

import { EditSpace } from './edit_space';
import { EditSpaceProvider, type EditSpaceProviderProps } from './provider';
import { EditSpaceProviderRoot, type EditSpaceProviderRootProps } from './provider';

type EditSpacePageProps = ComponentProps<typeof EditSpace> & EditSpaceProviderProps;
type EditSpacePageProps = ComponentProps<typeof EditSpace> & EditSpaceProviderRootProps;

export function EditSpacePage({
spaceId,
Expand All @@ -25,7 +25,7 @@ export function EditSpacePage({
...editSpaceServicesProps
}: PropsWithChildren<EditSpacePageProps>) {
return (
<EditSpaceProvider {...editSpaceServicesProps}>
<EditSpaceProviderRoot {...editSpaceServicesProps}>
<EditSpace
spaceId={spaceId}
getFeatures={getFeatures}
Expand All @@ -35,6 +35,6 @@ export function EditSpacePage({
allowFeatureVisibility={allowFeatureVisibility}
allowSolutionVisibility={allowSolutionVisibility}
/>
</EditSpaceProvider>
</EditSpaceProviderRoot>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,11 @@ import {
import { __IntlProvider as IntlProvider } from '@kbn/i18n-react';

import { EditSpaceAssignedRolesTab } from './edit_space_roles_tab';
import { EditSpaceProvider } from './provider';
import { EditSpaceProviderRoot } from './provider';
import { spacesManagerMock } from '../../spaces_manager/spaces_manager.mock';
import { getPrivilegeAPIClientMock } from '../privilege_api_client.mock';
import { getRolesAPIClientMock } from '../roles_api_client.mock';
import { getSecurityLicenseMock } from '../security_license.mock';

const getUrlForApp = (appId: string) => appId;
const navigateToUrl = jest.fn();
Expand Down Expand Up @@ -51,7 +52,7 @@ describe('EditSpaceAssignedRolesTab', () => {
const TestComponent: React.FC<React.PropsWithChildren> = ({ children }) => {
return (
<IntlProvider locale="en">
<EditSpaceProvider
<EditSpaceProviderRoot
capabilities={{
navLinks: {},
management: {},
Expand All @@ -67,12 +68,13 @@ describe('EditSpaceAssignedRolesTab', () => {
notifications={notifications}
overlays={overlays}
getPrivilegesAPIClient={getPrivilegeAPIClient}
getSecurityLicense={getSecurityLicenseMock}
theme={theme}
i18n={i18n}
logger={logger}
>
{children}
</EditSpaceProvider>
</EditSpaceProviderRoot>
</IntlProvider>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ export const EditSpaceAssignedRolesTab: FC<Props> = ({ space, features, isReadOn
(defaultSelected?: Role[]) => {
const overlayRef = overlays.openFlyout(
toMountPoint(
<EditSpaceProvider {...services}>
<EditSpaceProvider {...services} dispatch={dispatch} state={state}>
<PrivilegesRolesForm
{...{
space,
Expand Down Expand Up @@ -109,9 +109,10 @@ export const EditSpaceAssignedRolesTab: FC<Props> = ({ space, features, isReadOn
[
overlays,
services,
dispatch,
state,
space,
features,
dispatch,
invokeClient,
getUrlForApp,
theme,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,15 @@ import {
import type { ApplicationStart } from '@kbn/core-application-browser';
import { __IntlProvider as IntlProvider } from '@kbn/i18n-react';

import { EditSpaceProvider, useEditSpaceServices, useEditSpaceStore } from './edit_space_provider';
import {
EditSpaceProviderRoot,
useEditSpaceServices,
useEditSpaceStore,
} from './edit_space_provider';
import { spacesManagerMock } from '../../../spaces_manager/spaces_manager.mock';
import { getPrivilegeAPIClientMock } from '../../privilege_api_client.mock';
import { getRolesAPIClientMock } from '../../roles_api_client.mock';
import { getSecurityLicenseMock } from '../../security_license.mock';

const http = httpServiceMock.createStartContract();
const notifications = notificationServiceMock.createStartContract();
Expand All @@ -45,7 +50,7 @@ const SUTProvider = ({
}: PropsWithChildren<Partial<Pick<ApplicationStart, 'capabilities'>>>) => {
return (
<IntlProvider locale="en">
<EditSpaceProvider
<EditSpaceProviderRoot
{...{
logger,
i18n,
Expand All @@ -58,12 +63,13 @@ const SUTProvider = ({
getUrlForApp: (_) => _,
getRolesAPIClient: getRolesAPIClientMock,
getPrivilegesAPIClient: getPrivilegeAPIClientMock,
getSecurityLicense: getSecurityLicenseMock,
navigateToUrl: jest.fn(),
capabilities,
}}
>
{children}
</EditSpaceProvider>
</EditSpaceProviderRoot>
</IntlProvider>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import type { Logger } from '@kbn/logging';
import type {
PrivilegesAPIClientPublicContract,
RolesAPIClient,
SecurityLicense,
} from '@kbn/security-plugin-types-public';

import {
Expand All @@ -32,7 +33,7 @@ import {
} from './reducers';
import type { SpacesManager } from '../../../spaces_manager';

export interface EditSpaceProviderProps
export interface EditSpaceProviderRootProps
extends Pick<CoreStart, 'theme' | 'i18n' | 'overlays' | 'http' | 'notifications'> {
logger: Logger;
capabilities: ApplicationStart['capabilities'];
Expand All @@ -42,10 +43,7 @@ export interface EditSpaceProviderProps
spacesManager: SpacesManager;
getRolesAPIClient: () => Promise<RolesAPIClient>;
getPrivilegesAPIClient: () => Promise<PrivilegesAPIClientPublicContract>;
}

export interface EditSpaceServices extends EditSpaceProviderProps {
invokeClient<R extends unknown>(arg: (clients: EditSpaceClients) => Promise<R>): Promise<R>;
getSecurityLicense: () => Promise<SecurityLicense>;
}

interface EditSpaceClients {
Expand All @@ -54,6 +52,15 @@ interface EditSpaceClients {
privilegesClient: PrivilegesAPIClientPublicContract;
}

export interface EditSpaceServices
extends Omit<
EditSpaceProviderRootProps,
'getRolesAPIClient' | 'getPrivilegesAPIClient' | 'getSecurityLicense'
> {
invokeClient<R extends unknown>(arg: (clients: EditSpaceClients) => Promise<R>): Promise<R>;
license?: SecurityLicense;
}

export interface EditSpaceStore {
state: IEditSpaceStoreState;
dispatch: Dispatch<IDispatchAction>;
Expand All @@ -63,16 +70,43 @@ const createSpaceRolesContext = once(() => createContext<EditSpaceStore | null>(

const createEditSpaceServicesContext = once(() => createContext<EditSpaceServices | null>(null));

/**
*
* @description EditSpaceProvider is a provider component that wraps the children components with the necessary context providers for the Edit Space feature. It provides the necessary services and state management for the feature,
* this is provided as an export for use with out of band renders within the spaces app
*/
export const EditSpaceProvider = ({
children,
state,
dispatch,
...services
}: PropsWithChildren<EditSpaceProviderProps>) => {
}: PropsWithChildren<EditSpaceServices & EditSpaceStore>) => {
const EditSpaceStoreContext = createSpaceRolesContext();
const EditSpaceServicesContext = createEditSpaceServicesContext();

const clients = useRef(
Promise.all([services.getRolesAPIClient(), services.getPrivilegesAPIClient()])
return (
<EditSpaceServicesContext.Provider value={services}>
<EditSpaceStoreContext.Provider value={{ state, dispatch }}>
{children}
</EditSpaceStoreContext.Provider>
</EditSpaceServicesContext.Provider>
);
};

/**
* @description EditSpaceProviderRoot is the root provider for the Edit Space feature. It instantiates the necessary services and state management for the feature. It ideally
* should only be rendered once
*/
export const EditSpaceProviderRoot = ({
children,
...services
}: PropsWithChildren<EditSpaceProviderRootProps>) => {
const { logger, getRolesAPIClient, getPrivilegesAPIClient, getSecurityLicense } = services;

const clients = useRef(Promise.all([getRolesAPIClient(), getPrivilegesAPIClient()]));
const license = useRef(getSecurityLicense);

const licenseRef = useRef<SecurityLicense>();
const rolesAPIClientRef = useRef<RolesAPIClient>();
const privilegesClientRef = useRef<PrivilegesAPIClientPublicContract>();

Expand All @@ -81,7 +115,14 @@ export const EditSpaceProvider = ({
fetchRolesError: false,
});

const { logger } = services;
const resolveSecurityLicense = useCallback(async () => {
try {
licenseRef.current = await license.current();
} catch (err) {
logger.error('Could not resolve Security License!', err);
}
}, [logger]);

const resolveAPIClients = useCallback(async () => {
try {
[rolesAPIClientRef.current, privilegesClientRef.current] = await clients.current;
Expand All @@ -94,6 +135,10 @@ export const EditSpaceProvider = ({
resolveAPIClients();
}, [resolveAPIClients]);

useEffect(() => {
resolveSecurityLicense();
}, [resolveSecurityLicense]);

const createInitialState = useCallback((state: IEditSpaceStoreState) => {
return state;
}, []);
Expand All @@ -118,11 +163,11 @@ export const EditSpaceProvider = ({
);

return (
<EditSpaceServicesContext.Provider value={{ ...services, invokeClient }}>
<EditSpaceStoreContext.Provider value={{ state, dispatch }}>
{children}
</EditSpaceStoreContext.Provider>
</EditSpaceServicesContext.Provider>
<EditSpaceProvider
{...{ ...services, invokeClient, state, dispatch, license: licenseRef.current }}
>
{children}
</EditSpaceProvider>
);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,14 @@
* 2.0.
*/

export { EditSpaceProvider, useEditSpaceServices, useEditSpaceStore } from './edit_space_provider';
export {
EditSpaceProviderRoot,
EditSpaceProvider,
useEditSpaceServices,
useEditSpaceStore,
} from './edit_space_provider';
export type {
EditSpaceProviderProps,
EditSpaceProviderRootProps,
EditSpaceServices,
EditSpaceStore,
} from './edit_space_provider';
Loading

0 comments on commit ecf451f

Please sign in to comment.