mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[Enterprise Search] Vary Enterprise Search navigation options based on product access (#138775)
* Added an EnterpriseSearchProvider to propagate access data Co-authored-by: Brian McGue <mcgue.brian@gmail.com> Co-authored-by: Rodney Norris <rodney.norris@elastic.co> * Move productAccess into KibanaLogic * Fix PageTemplate tests * Add tests for access based navigation * Push useValues for productAccess down into useEnterpriseSearchNav Co-authored-by: Brian McGue <mcgue.brian@gmail.com> Co-authored-by: Rodney Norris <rodney.norris@elastic.co> Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
b6fce4df84
commit
c7ee95079c
5 changed files with 136 additions and 21 deletions
|
@ -20,6 +20,10 @@ export const mockKibanaValues = {
|
|||
},
|
||||
history: mockHistory,
|
||||
navigateToUrl: jest.fn(),
|
||||
productAccess: {
|
||||
hasAppSearchAccess: true,
|
||||
hasWorkplaceSearchAccess: true,
|
||||
},
|
||||
security: securityMock.createStart(),
|
||||
setBreadcrumbs: jest.fn(),
|
||||
setChromeIsVisible: jest.fn(),
|
||||
|
|
|
@ -18,7 +18,7 @@ import { I18nProvider } from '@kbn/i18n-react';
|
|||
|
||||
import { KibanaContextProvider, KibanaThemeProvider } from '@kbn/kibana-react-plugin/public';
|
||||
|
||||
import { InitialAppData } from '../../common/types';
|
||||
import { InitialAppData, ProductAccess } from '../../common/types';
|
||||
import { PluginsStart, ClientConfigType, ClientData } from '../plugin';
|
||||
|
||||
import { externalUrl } from './shared/enterprise_search_url';
|
||||
|
@ -41,6 +41,12 @@ export const renderApp = (
|
|||
const { publicUrl, errorConnectingMessage, ...initialData } = data;
|
||||
externalUrl.enterpriseSearchUrl = publicUrl || config.host || '';
|
||||
|
||||
const noProductAccess: ProductAccess = {
|
||||
hasAppSearchAccess: false,
|
||||
hasWorkplaceSearchAccess: false,
|
||||
};
|
||||
const productAccess = data.access || noProductAccess;
|
||||
|
||||
const EmptyContext: FC = ({ children }) => <>{children}</>;
|
||||
const CloudContext = plugins.cloud?.CloudContextProvider || EmptyContext;
|
||||
|
||||
|
@ -49,6 +55,7 @@ export const renderApp = (
|
|||
|
||||
const unmountKibanaLogic = mountKibanaLogic({
|
||||
config,
|
||||
productAccess,
|
||||
charts: plugins.charts,
|
||||
cloud: plugins.cloud,
|
||||
history: params.history,
|
||||
|
|
|
@ -14,6 +14,8 @@ import { CloudSetup } from '@kbn/cloud-plugin/public';
|
|||
import { ApplicationStart, ChromeBreadcrumb, ScopedHistory } from '@kbn/core/public';
|
||||
import { SecurityPluginStart } from '@kbn/security-plugin/public';
|
||||
|
||||
import { ProductAccess } from '../../../../common/types';
|
||||
|
||||
import { HttpLogic } from '../http';
|
||||
import { createHref, CreateHrefOptions } from '../react_router_helpers';
|
||||
|
||||
|
@ -22,6 +24,7 @@ type RequiredFieldsOnly<T> = {
|
|||
};
|
||||
interface KibanaLogicProps {
|
||||
config: { host?: string };
|
||||
productAccess: ProductAccess;
|
||||
// Kibana core
|
||||
history: ScopedHistory;
|
||||
navigateToUrl: RequiredFieldsOnly<ApplicationStart['navigateToUrl']>;
|
||||
|
@ -55,6 +58,7 @@ export const KibanaLogic = kea<MakeLogicType<KibanaValues>>({
|
|||
},
|
||||
{},
|
||||
],
|
||||
productAccess: [props.productAccess, {}],
|
||||
security: [props.security, {}],
|
||||
setBreadcrumbs: [props.setBreadcrumbs, {}],
|
||||
setChromeIsVisible: [props.setChromeIsVisible, {}],
|
||||
|
|
|
@ -9,10 +9,24 @@ jest.mock('./nav_link_helpers', () => ({
|
|||
generateNavLink: jest.fn(({ to, items }) => ({ href: to, items })),
|
||||
}));
|
||||
|
||||
import { setMockValues } from '../../__mocks__/kea_logic';
|
||||
|
||||
import { ProductAccess } from '../../../../common/types';
|
||||
|
||||
import { useEnterpriseSearchNav } from './nav';
|
||||
|
||||
describe('useEnterpriseSearchContentNav', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('returns an array of top-level Enterprise Search nav items', () => {
|
||||
const fullProductAccess: ProductAccess = {
|
||||
hasAppSearchAccess: true,
|
||||
hasWorkplaceSearchAccess: true,
|
||||
};
|
||||
setMockValues({ productAccess: fullProductAccess });
|
||||
|
||||
expect(useEnterpriseSearchNav()).toEqual([
|
||||
{
|
||||
href: '/app/enterprise_search/overview',
|
||||
|
@ -53,4 +67,77 @@ describe('useEnterpriseSearchContentNav', () => {
|
|||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('excludes legacy products when the user has no access to them', () => {
|
||||
const noProductAccess: ProductAccess = {
|
||||
hasAppSearchAccess: false,
|
||||
hasWorkplaceSearchAccess: false,
|
||||
};
|
||||
|
||||
setMockValues({ productAccess: noProductAccess });
|
||||
|
||||
expect(useEnterpriseSearchNav()[2]).toEqual({
|
||||
id: 'search',
|
||||
items: [
|
||||
{
|
||||
href: '/app/enterprise_search/elasticsearch',
|
||||
id: 'elasticsearch',
|
||||
name: 'Elasticsearch',
|
||||
},
|
||||
],
|
||||
name: 'Search',
|
||||
});
|
||||
});
|
||||
|
||||
it('excludes App Search when the user has no access to it', () => {
|
||||
const workplaceSearchProductAccess: ProductAccess = {
|
||||
hasAppSearchAccess: false,
|
||||
hasWorkplaceSearchAccess: true,
|
||||
};
|
||||
|
||||
setMockValues({ productAccess: workplaceSearchProductAccess });
|
||||
|
||||
expect(useEnterpriseSearchNav()[2]).toEqual({
|
||||
id: 'search',
|
||||
items: [
|
||||
{
|
||||
href: '/app/enterprise_search/elasticsearch',
|
||||
id: 'elasticsearch',
|
||||
name: 'Elasticsearch',
|
||||
},
|
||||
{
|
||||
href: '/app/enterprise_search/workplace_search',
|
||||
id: 'workplace_search',
|
||||
name: 'Workplace Search',
|
||||
},
|
||||
],
|
||||
name: 'Search',
|
||||
});
|
||||
});
|
||||
|
||||
it('excludes Workplace Search when the user has no access to it', () => {
|
||||
const appSearchProductAccess: ProductAccess = {
|
||||
hasAppSearchAccess: true,
|
||||
hasWorkplaceSearchAccess: false,
|
||||
};
|
||||
|
||||
setMockValues({ productAccess: appSearchProductAccess });
|
||||
|
||||
expect(useEnterpriseSearchNav()[2]).toEqual({
|
||||
id: 'search',
|
||||
items: [
|
||||
{
|
||||
href: '/app/enterprise_search/elasticsearch',
|
||||
id: 'elasticsearch',
|
||||
name: 'Elasticsearch',
|
||||
},
|
||||
{
|
||||
href: '/app/enterprise_search/app_search',
|
||||
id: 'app_search',
|
||||
name: 'App Search',
|
||||
},
|
||||
],
|
||||
name: 'Search',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { useValues } from 'kea';
|
||||
|
||||
import { EuiSideNavItemType } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
|
@ -16,10 +18,13 @@ import {
|
|||
WORKPLACE_SEARCH_PLUGIN,
|
||||
} from '../../../../common/constants';
|
||||
import { SEARCH_INDICES_PATH } from '../../enterprise_search_content/routes';
|
||||
import { KibanaLogic } from '../kibana';
|
||||
|
||||
import { generateNavLink } from './nav_link_helpers';
|
||||
|
||||
export const useEnterpriseSearchNav = () => {
|
||||
const { productAccess } = useValues(KibanaLogic);
|
||||
|
||||
const navItems: Array<EuiSideNavItemType<unknown>> = [
|
||||
{
|
||||
id: 'es_overview',
|
||||
|
@ -63,26 +68,34 @@ export const useEnterpriseSearchNav = () => {
|
|||
to: ELASTICSEARCH_PLUGIN.URL,
|
||||
}),
|
||||
},
|
||||
{
|
||||
id: 'app_search',
|
||||
name: i18n.translate('xpack.enterpriseSearch.nav.appSearchTitle', {
|
||||
defaultMessage: 'App Search',
|
||||
}),
|
||||
...generateNavLink({
|
||||
shouldNotCreateHref: true,
|
||||
to: APP_SEARCH_PLUGIN.URL,
|
||||
}),
|
||||
},
|
||||
{
|
||||
id: 'workplace_search',
|
||||
name: i18n.translate('xpack.enterpriseSearch.nav.workplaceSearchTitle', {
|
||||
defaultMessage: 'Workplace Search',
|
||||
}),
|
||||
...generateNavLink({
|
||||
shouldNotCreateHref: true,
|
||||
to: WORKPLACE_SEARCH_PLUGIN.URL,
|
||||
}),
|
||||
},
|
||||
...(productAccess.hasAppSearchAccess
|
||||
? [
|
||||
{
|
||||
id: 'app_search',
|
||||
name: i18n.translate('xpack.enterpriseSearch.nav.appSearchTitle', {
|
||||
defaultMessage: 'App Search',
|
||||
}),
|
||||
...generateNavLink({
|
||||
shouldNotCreateHref: true,
|
||||
to: APP_SEARCH_PLUGIN.URL,
|
||||
}),
|
||||
},
|
||||
]
|
||||
: []),
|
||||
...(productAccess.hasWorkplaceSearchAccess
|
||||
? [
|
||||
{
|
||||
id: 'workplace_search',
|
||||
name: i18n.translate('xpack.enterpriseSearch.nav.workplaceSearchTitle', {
|
||||
defaultMessage: 'Workplace Search',
|
||||
}),
|
||||
...generateNavLink({
|
||||
shouldNotCreateHref: true,
|
||||
to: WORKPLACE_SEARCH_PLUGIN.URL,
|
||||
}),
|
||||
},
|
||||
]
|
||||
: []),
|
||||
],
|
||||
name: i18n.translate('xpack.enterpriseSearch.nav.searchExperiencesTitle', {
|
||||
defaultMessage: 'Search',
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue