mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
[Stream] Fix callout privileges (#198030)
closes https://github.com/elastic/kibana/issues/197044 closes https://github.com/elastic/kibana/issues/197988 ## 📝 Summary The PR targets fixing 3 bugs: 1. The callout shouldn't be shown if `Logs Explorer` isn't available, otherwise the link displayed in the callout will cause a problem. [Fix here](https://github.com/elastic/kibana/pull/198030/files#diff-8c5f793d1bf0d933c73047f31ded8a5a65f91e4f8d5230fc4e40dfb9b245fec1R66) 2. The callout shouldn't be shown if `Logs Explorer` is available but the user doesn't have privilege to access it, otherwise we end up in `Application Not Found` page. [Fix here](https://github.com/elastic/kibana/pull/198030/files#diff-8c5f793d1bf0d933c73047f31ded8a5a65f91e4f8d5230fc4e40dfb9b245fec1R66) 3. The side nav entry for `Logs Explorer` should be hidden if `Logs Explorer` is disabled. [Fix here](https://github.com/elastic/kibana/pull/198030/files#diff-ad4e42fbe4d2a7a99ec5d52fbf127ded12f0efe02a10e3afa0409b40be1f4bcfR397)
This commit is contained in:
parent
ac5c74a443
commit
5576316aba
2 changed files with 92 additions and 73 deletions
|
@ -9,13 +9,17 @@ import { EuiCallOut } from '@elastic/eui';
|
|||
import React from 'react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { EuiButton } from '@elastic/eui';
|
||||
import { AllDatasetsLocatorParams, ALL_DATASETS_LOCATOR_ID } from '@kbn/deeplinks-observability';
|
||||
import {
|
||||
AllDatasetsLocatorParams,
|
||||
ALL_DATASETS_LOCATOR_ID,
|
||||
DatasetLocatorParams,
|
||||
} from '@kbn/deeplinks-observability';
|
||||
import { getRouterLinkProps } from '@kbn/router-utils';
|
||||
import useLocalStorage from 'react-use/lib/useLocalStorage';
|
||||
|
||||
import { euiThemeVars } from '@kbn/ui-theme';
|
||||
import { css } from '@emotion/css';
|
||||
import { SharePublicStart } from '@kbn/share-plugin/public/plugin';
|
||||
import { LocatorPublic } from '@kbn/share-plugin/common';
|
||||
import { useKibanaContextForPlugin } from '../hooks/use_kibana';
|
||||
|
||||
const pageConfigurations = {
|
||||
|
@ -44,14 +48,22 @@ interface LogsDeprecationCalloutProps {
|
|||
|
||||
export const LogsDeprecationCallout = ({ page }: LogsDeprecationCalloutProps) => {
|
||||
const {
|
||||
services: { share },
|
||||
services: {
|
||||
share,
|
||||
application: {
|
||||
capabilities: { discover, fleet },
|
||||
},
|
||||
},
|
||||
} = useKibanaContextForPlugin();
|
||||
|
||||
const { dismissalStorageKey, message } = pageConfigurations[page];
|
||||
|
||||
const [isDismissed, setDismissed] = useLocalStorage(dismissalStorageKey, false);
|
||||
|
||||
if (isDismissed) {
|
||||
const allDatasetLocator =
|
||||
share.url.locators.get<AllDatasetsLocatorParams>(ALL_DATASETS_LOCATOR_ID);
|
||||
|
||||
if (isDismissed || !(allDatasetLocator && discover?.show && fleet?.read)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -71,7 +83,7 @@ export const LogsDeprecationCallout = ({ page }: LogsDeprecationCalloutProps) =>
|
|||
fill
|
||||
data-test-subj="infraLogsDeprecationCalloutTryLogsExplorerButton"
|
||||
color="warning"
|
||||
{...getLogsExplorerLinkProps(share)}
|
||||
{...getLogsExplorerLinkProps(allDatasetLocator)}
|
||||
>
|
||||
{i18n.translate('xpack.infra.logsDeprecationCallout.tryLogsExplorerButtonLabel', {
|
||||
defaultMessage: 'Try Logs Explorer',
|
||||
|
@ -81,9 +93,7 @@ export const LogsDeprecationCallout = ({ page }: LogsDeprecationCalloutProps) =>
|
|||
);
|
||||
};
|
||||
|
||||
const getLogsExplorerLinkProps = (share: SharePublicStart) => {
|
||||
const locator = share.url.locators.get<AllDatasetsLocatorParams>(ALL_DATASETS_LOCATOR_ID)!;
|
||||
|
||||
const getLogsExplorerLinkProps = (locator: LocatorPublic<DatasetLocatorParams>) => {
|
||||
return getRouterLinkProps({
|
||||
href: locator.getRedirectUrl({}),
|
||||
onClick: () => locator.navigate({}),
|
||||
|
|
|
@ -13,6 +13,7 @@ import {
|
|||
DEFAULT_APP_CATEGORIES,
|
||||
PluginInitializerContext,
|
||||
AppDeepLinkLocations,
|
||||
AppStatus,
|
||||
} from '@kbn/core/public';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import {
|
||||
|
@ -34,6 +35,7 @@ import {
|
|||
} from '@kbn/observability-shared-plugin/common';
|
||||
import { OBSERVABILITY_ENABLE_LOGS_STREAM } from '@kbn/management-settings-ids';
|
||||
import { NavigationEntry } from '@kbn/observability-shared-plugin/public';
|
||||
import { OBSERVABILITY_LOGS_EXPLORER_APP_ID } from '@kbn/deeplinks-observability/constants';
|
||||
import type { InfraPublicConfig } from '../common/plugin_config_types';
|
||||
import { createInventoryMetricRuleType } from './alerting/inventory';
|
||||
import { createLogThresholdRuleType } from './alerting/log_threshold';
|
||||
|
@ -137,61 +139,53 @@ export class Plugin implements InfraClientPluginClass {
|
|||
/** !! Need to be kept in sync with the deepLinks in x-pack/plugins/observability_solution/infra/public/plugin.ts */
|
||||
pluginsSetup.observabilityShared.navigation.registerSections(
|
||||
startDep$AndHostViewFlag$.pipe(
|
||||
map(
|
||||
([
|
||||
[
|
||||
{
|
||||
application: { capabilities },
|
||||
},
|
||||
],
|
||||
]) => {
|
||||
const { infrastructure, logs } = capabilities;
|
||||
return [
|
||||
...(logs.show
|
||||
? [
|
||||
{
|
||||
label: logsTitle,
|
||||
sortKey: 200,
|
||||
entries: getLogsNavigationEntries({
|
||||
capabilities,
|
||||
config: this.config,
|
||||
routes: logRoutes,
|
||||
}),
|
||||
},
|
||||
]
|
||||
: []),
|
||||
...(infrastructure.show
|
||||
? [
|
||||
{
|
||||
label: metricsTitle,
|
||||
sortKey: 300,
|
||||
entries: [
|
||||
{
|
||||
label: inventoryTitle,
|
||||
app: 'metrics',
|
||||
path: '/inventory',
|
||||
},
|
||||
...(this.config.featureFlags.metricsExplorerEnabled
|
||||
? [
|
||||
{
|
||||
label: metricsExplorerTitle,
|
||||
app: 'metrics',
|
||||
path: '/explorer',
|
||||
},
|
||||
]
|
||||
: []),
|
||||
{
|
||||
label: hostsTitle,
|
||||
app: 'metrics',
|
||||
path: '/hosts',
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
: []),
|
||||
];
|
||||
}
|
||||
)
|
||||
map(([[{ application }]]) => {
|
||||
const { infrastructure, logs } = application.capabilities;
|
||||
return [
|
||||
...(logs.show
|
||||
? [
|
||||
{
|
||||
label: logsTitle,
|
||||
sortKey: 200,
|
||||
entries: getLogsNavigationEntries({
|
||||
application,
|
||||
config: this.config,
|
||||
routes: logRoutes,
|
||||
}),
|
||||
},
|
||||
]
|
||||
: []),
|
||||
...(infrastructure.show
|
||||
? [
|
||||
{
|
||||
label: metricsTitle,
|
||||
sortKey: 300,
|
||||
entries: [
|
||||
{
|
||||
label: inventoryTitle,
|
||||
app: 'metrics',
|
||||
path: '/inventory',
|
||||
},
|
||||
...(this.config.featureFlags.metricsExplorerEnabled
|
||||
? [
|
||||
{
|
||||
label: metricsExplorerTitle,
|
||||
app: 'metrics',
|
||||
path: '/explorer',
|
||||
},
|
||||
]
|
||||
: []),
|
||||
{
|
||||
label: hostsTitle,
|
||||
app: 'metrics',
|
||||
path: '/hosts',
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
: []),
|
||||
];
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
|
@ -388,11 +382,11 @@ export class Plugin implements InfraClientPluginClass {
|
|||
}
|
||||
|
||||
const getLogsNavigationEntries = ({
|
||||
capabilities,
|
||||
application,
|
||||
config,
|
||||
routes,
|
||||
}: {
|
||||
capabilities: CoreStart['application']['capabilities'];
|
||||
application: CoreStart['application'];
|
||||
config: InfraPublicConfig;
|
||||
routes: LogsAppRoutes;
|
||||
}) => {
|
||||
|
@ -400,14 +394,16 @@ const getLogsNavigationEntries = ({
|
|||
|
||||
if (!config.featureFlags.logsUIEnabled) return entries;
|
||||
|
||||
if (capabilities.discover?.show && capabilities.fleet?.read) {
|
||||
entries.push({
|
||||
label: 'Explorer',
|
||||
app: 'observability-logs-explorer',
|
||||
path: '/',
|
||||
isBetaFeature: true,
|
||||
});
|
||||
}
|
||||
getLogsExplorerAccessibility$(application).subscribe((isAccessible) => {
|
||||
if (isAccessible) {
|
||||
entries.push({
|
||||
label: 'Explorer',
|
||||
app: 'observability-logs-explorer',
|
||||
path: '/',
|
||||
isBetaFeature: true,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Display Stream nav entry when Logs Stream is enabled
|
||||
if (routes.stream) entries.push(createNavEntryFromRoute(routes.stream));
|
||||
|
@ -420,6 +416,19 @@ const getLogsNavigationEntries = ({
|
|||
return entries;
|
||||
};
|
||||
|
||||
const getLogsExplorerAccessibility$ = (application: CoreStart['application']) => {
|
||||
const { capabilities, applications$ } = application;
|
||||
return applications$.pipe(
|
||||
map(
|
||||
(apps) =>
|
||||
(apps.get(OBSERVABILITY_LOGS_EXPLORER_APP_ID)?.status ?? AppStatus.inaccessible) ===
|
||||
AppStatus.accessible &&
|
||||
capabilities.discover?.show &&
|
||||
capabilities.fleet?.read
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
const createNavEntryFromRoute = ({ path, title }: LogsRoute): NavigationEntry => ({
|
||||
app: 'logs',
|
||||
label: title,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue