[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:
mohamedhamed-ahmed 2024-10-30 08:43:35 +00:00 committed by GitHub
parent ac5c74a443
commit 5576316aba
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 92 additions and 73 deletions

View file

@ -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({}),

View file

@ -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,