Skip to content

Commit

Permalink
[TIP] Restrict content visibility for non-enterprise users (elastic#1…
Browse files Browse the repository at this point in the history
…38097) (elastic#138358)

(cherry picked from commit 335d63a)

Co-authored-by: Luke Gmys <[email protected]>
  • Loading branch information
kibanamachine and lgmys authored Aug 9, 2022
1 parent d831a81 commit ffda8c0
Show file tree
Hide file tree
Showing 9 changed files with 134 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -20,6 +21,7 @@ const ThreatIntelligence = () => {

const securitySolutionContext: ThreatIntelligenceSecuritySolutionContext = {
getFiltersGlobalComponent: () => FiltersGlobal,
licenseService,
};

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,11 @@ const mockSecurityContext: ThreatIntelligenceSecuritySolutionContext = {
() =>
({ children }) =>
<div>{children}</div>,
licenseService: {
isEnterprise() {
return true;
},
},
};

mockCoreStart.uiSettings.get.mockImplementation(mockUiSetting);
Expand Down
Original file line number Diff line number Diff line change
@@ -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();
});
});
});
Original file line number Diff line number Diff line change
@@ -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;
};
Original file line number Diff line number Diff line change
@@ -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';
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down
Original file line number Diff line number Diff line change
@@ -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;
};
17 changes: 10 additions & 7 deletions x-pack/plugins/threat_intelligence/public/plugin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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>
);

Expand Down
5 changes: 5 additions & 0 deletions x-pack/plugins/threat_intelligence/public/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ export type Services = {
dataViews: DataViewsPublicPluginStart;
} & CoreStart;

export interface LicenseAware {
isEnterprise(): boolean;
}

export interface ThreatIntelligenceSecuritySolutionContext {
getFiltersGlobalComponent: () => ComponentType<{ children: ReactNode }>;
licenseService: LicenseAware;
}

0 comments on commit ffda8c0

Please sign in to comment.