[Logs Explorer] Fix privilege checks bug (#198368)

## Summary

This PR enhances the privilege checks for Logs Explorer side nav
visibility.
This commit is contained in:
mohamedhamed-ahmed 2024-10-31 14:36:23 +00:00 committed by GitHub
parent 750452eb11
commit 76ccc9c562
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 65 additions and 39 deletions

View file

@ -6,13 +6,19 @@
*/
import { History } from 'history';
import { CoreStart } from '@kbn/core/public';
import React from 'react';
import { AppStatus, CoreStart } from '@kbn/core/public';
import React, { useMemo } from 'react';
import ReactDOM from 'react-dom';
import { Router, Routes, Route } from '@kbn/shared-ux-router';
import { AppMountParameters } from '@kbn/core/public';
import { Storage } from '@kbn/kibana-utils-plugin/public';
import { AllDatasetsLocatorParams, ALL_DATASETS_LOCATOR_ID } from '@kbn/deeplinks-observability';
import {
AllDatasetsLocatorParams,
ALL_DATASETS_LOCATOR_ID,
OBSERVABILITY_LOGS_EXPLORER_APP_ID,
} from '@kbn/deeplinks-observability';
import useObservable from 'react-use/lib/useObservable';
import { map } from 'rxjs';
import { LinkToLogsPage } from '../pages/link_to/link_to_logs';
import { LogsPage } from '../pages/logs';
import { InfraClientStartDeps, InfraClientStartExports } from '../types';
@ -57,7 +63,22 @@ const LogsApp: React.FC<{
storage: Storage;
theme$: AppMountParameters['theme$'];
}> = ({ core, history, pluginStart, plugins, setHeaderActionMenu, storage, theme$ }) => {
const { logs, discover, fleet } = core.application.capabilities;
const { logs } = core.application.capabilities;
const isLogsExplorerAppAccessible = useObservable(
useMemo(
() =>
core.application.applications$.pipe(
map(
(apps) =>
(apps.get(OBSERVABILITY_LOGS_EXPLORER_APP_ID)?.status ?? AppStatus.inaccessible) ===
AppStatus.accessible
)
),
[core.application.applications$]
),
false
);
return (
<CoreProviders core={core} pluginStart={pluginStart} plugins={plugins} theme$={theme$}>
@ -74,7 +95,7 @@ const LogsApp: React.FC<{
toastsService={core.notifications.toasts}
>
<Routes>
{Boolean(discover?.show && fleet?.read) && (
{isLogsExplorerAppAccessible && (
<Route
path="/"
exact

View file

@ -21,8 +21,15 @@ import {
MetricsExplorerLocatorParams,
ObservabilityTriggerId,
} from '@kbn/observability-shared-plugin/common';
import { BehaviorSubject, combineLatest, from } from 'rxjs';
import { map } from 'rxjs';
import {
BehaviorSubject,
combineLatest,
distinctUntilChanged,
from,
of,
switchMap,
map,
} from 'rxjs';
import type { EmbeddableApiContext } from '@kbn/presentation-publishing';
import { apiCanAddNewPanel } from '@kbn/presentation-containers';
import { IncompatibleActionError, ADD_PANEL_TRIGGER } from '@kbn/ui-actions-plugin/public';
@ -132,14 +139,18 @@ export class Plugin implements InfraClientPluginClass {
messageFields: this.config.sources?.default?.fields?.message,
});
const startDep$AndHostViewFlag$ = combineLatest([from(core.getStartServices())]);
const startDep$AndAccessibleFlag$ = from(core.getStartServices()).pipe(
switchMap(([{ application }]) =>
combineLatest([of(application), getLogsExplorerAccessible$(application)])
)
);
const logRoutes = getLogsAppRoutes({ isLogsStreamEnabled });
/** !! 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 }]]) => {
startDep$AndAccessibleFlag$.pipe(
map(([application, isLogsExplorerAccessible]) => {
const { infrastructure, logs } = application.capabilities;
return [
...(logs.show
@ -148,7 +159,7 @@ export class Plugin implements InfraClientPluginClass {
label: logsTitle,
sortKey: 200,
entries: getLogsNavigationEntries({
application,
isLogsExplorerAccessible,
config: this.config,
routes: logRoutes,
}),
@ -310,16 +321,13 @@ export class Plugin implements InfraClientPluginClass {
);
},
});
startDep$AndHostViewFlag$.subscribe(
([_startServices]: [[CoreStart, InfraClientStartDeps, InfraClientStartExports]]) => {
this.appUpdater$.next(() => ({
deepLinks: getInfraDeepLinks({
metricsExplorerEnabled: this.config.featureFlags.metricsExplorerEnabled,
}),
}));
}
);
startDep$AndAccessibleFlag$.subscribe(([_applicationStart, _isLogsExplorerAccessible]) => {
this.appUpdater$.next(() => ({
deepLinks: getInfraDeepLinks({
metricsExplorerEnabled: this.config.featureFlags.metricsExplorerEnabled,
}),
}));
});
// Setup telemetry events
this.telemetry.setup({ analytics: core.analytics });
@ -382,11 +390,11 @@ export class Plugin implements InfraClientPluginClass {
}
const getLogsNavigationEntries = ({
application,
isLogsExplorerAccessible,
config,
routes,
}: {
application: CoreStart['application'];
isLogsExplorerAccessible: boolean;
config: InfraPublicConfig;
routes: LogsAppRoutes;
}) => {
@ -394,16 +402,14 @@ const getLogsNavigationEntries = ({
if (!config.featureFlags.logsUIEnabled) return entries;
getLogsExplorerAccessibility$(application).subscribe((isAccessible) => {
if (isAccessible) {
entries.push({
label: 'Explorer',
app: 'observability-logs-explorer',
path: '/',
isBetaFeature: true,
});
}
});
if (isLogsExplorerAccessible) {
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));
@ -416,16 +422,15 @@ const getLogsNavigationEntries = ({
return entries;
};
const getLogsExplorerAccessibility$ = (application: CoreStart['application']) => {
const { capabilities, applications$ } = application;
const getLogsExplorerAccessible$ = (application: CoreStart['application']) => {
const { 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
)
AppStatus.accessible
),
distinctUntilChanged()
);
};