[TIP] Restrict content visibility for non-enterprise users (#138097) (#138358)

(cherry picked from commit 335d63a516)

Co-authored-by: Luke Gmys <lgmys@users.noreply.github.com>
This commit is contained in:
Kibana Machine 2022-08-09 05:13:31 -04:00 committed by GitHub
parent d831a8122d
commit ffda8c0e44
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 134 additions and 14 deletions

View file

@ -12,6 +12,7 @@ import { SpyRoute } from '../../common/utils/route/spy_routes';
import { SecurityPageName } from '../../../common/constants';
import { useKibana } from '../../common/lib/kibana';
import { FiltersGlobal } from '../../common/components/filters_global';
import { licenseService } from '../../common/hooks/use_license';
const ThreatIntelligence = () => {
const services = useKibana().services;
@ -20,6 +21,7 @@ const ThreatIntelligence = () => {
const securitySolutionContext: ThreatIntelligenceSecuritySolutionContext = {
getFiltersGlobalComponent: () => FiltersGlobal,
licenseService,
};
return (

View file

@ -97,6 +97,11 @@ const mockSecurityContext: ThreatIntelligenceSecuritySolutionContext = {
() =>
({ children }) =>
<div>{children}</div>,
licenseService: {
isEnterprise() {
return true;
},
},
};
mockCoreStart.uiSettings.get.mockImplementation(mockUiSetting);

View file

@ -0,0 +1,55 @@
/*
* 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 { render, screen } from '@testing-library/react';
import React from 'react';
import { ThreatIntelligenceSecuritySolutionContext } from '../../types';
import { SecuritySolutionContext } from '../security_solution_context';
import { EnterpriseGuard } from './enterprise_guard';
describe('<EnterpriseGuard />', () => {
describe('when on enterprise plan', () => {
it('should render specified children', () => {
render(
<SecuritySolutionContext.Provider
value={
{
licenseService: { isEnterprise: jest.fn().mockReturnValue(true) },
} as unknown as ThreatIntelligenceSecuritySolutionContext
}
>
<EnterpriseGuard>
<div>enterprise only content</div>
</EnterpriseGuard>
</SecuritySolutionContext.Provider>
);
expect(screen.queryByText('enterprise only content')).toBeInTheDocument();
});
});
describe('when not on enterprise plan', () => {
it('should render specified children', () => {
render(
<SecuritySolutionContext.Provider
value={
{
licenseService: { isEnterprise: jest.fn().mockReturnValue(false) },
} as unknown as ThreatIntelligenceSecuritySolutionContext
}
>
<EnterpriseGuard fallback={<div>fallback for non enterprise</div>}>
<div>enterprise only content</div>
</EnterpriseGuard>
</SecuritySolutionContext.Provider>
);
expect(screen.queryByText('enterprise only content')).not.toBeInTheDocument();
expect(screen.queryByText('fallback for non enterprise')).toBeInTheDocument();
});
});
});

View file

@ -0,0 +1,24 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import React, { ReactElement } from 'react';
import { FC } from 'react';
import { useSecurityContext } from '../../hooks/use_security_context';
interface EnterpriseGuardProps {
fallback?: ReactElement;
}
export const EnterpriseGuard: FC<EnterpriseGuardProps> = ({ children, fallback = null }) => {
const { licenseService } = useSecurityContext();
if (licenseService.isEnterprise()) {
return <>{children}</>;
}
return fallback;
};

View file

@ -0,0 +1,8 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
export * from './enterprise_guard';

View file

@ -6,15 +6,11 @@
*/
import React from 'react';
import { FC, useContext } from 'react';
import { SecuritySolutionContext } from './security_solution_context';
import { FC } from 'react';
import { useSecurityContext } from '../hooks/use_security_context';
export const FiltersGlobal: FC = ({ children }) => {
const contextValue = useContext(SecuritySolutionContext);
if (!contextValue) {
throw new Error('FiltersGlobal can only be used within Security Solution Context');
}
const contextValue = useSecurityContext();
const Component = contextValue.getFiltersGlobalComponent();

View file

@ -0,0 +1,22 @@
/*
* 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 { useContext } from 'react';
import { SecuritySolutionContext } from '../containers/security_solution_context';
import { ThreatIntelligenceSecuritySolutionContext } from '../types';
export const useSecurityContext = (): ThreatIntelligenceSecuritySolutionContext => {
const contextValue = useContext(SecuritySolutionContext);
if (!contextValue) {
throw new Error(
'SecuritySolutionContext can only be used within SecuritySolutionContext provider'
);
}
return contextValue;
};

View file

@ -18,6 +18,7 @@ import {
ThreatIntelligenceSecuritySolutionContext,
} from './types';
import { SecuritySolutionContext } from './containers/security_solution_context';
import { EnterpriseGuard } from './containers/enterprise_guard';
interface AppProps {
securitySolutionContext: ThreatIntelligenceSecuritySolutionContext;
@ -35,13 +36,15 @@ export const createApp =
({ securitySolutionContext }: AppProps) =>
(
<IntlProvider>
<KibanaContextProvider services={services}>
<SecuritySolutionContext.Provider value={securitySolutionContext}>
<Suspense fallback={<div />}>
<LazyIndicatorsPage />
</Suspense>
</SecuritySolutionContext.Provider>
</KibanaContextProvider>
<SecuritySolutionContext.Provider value={securitySolutionContext}>
<EnterpriseGuard>
<KibanaContextProvider services={services}>
<Suspense fallback={<div />}>
<LazyIndicatorsPage />
</Suspense>
</KibanaContextProvider>
</EnterpriseGuard>
</SecuritySolutionContext.Provider>
</IntlProvider>
);

View file

@ -30,6 +30,11 @@ export type Services = {
dataViews: DataViewsPublicPluginStart;
} & CoreStart;
export interface LicenseAware {
isEnterprise(): boolean;
}
export interface ThreatIntelligenceSecuritySolutionContext {
getFiltersGlobalComponent: () => ComponentType<{ children: ReactNode }>;
licenseService: LicenseAware;
}