diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.md
index f576d795b93a5..d2e7ef9db05e8 100644
--- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.md
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.md
@@ -126,6 +126,7 @@
| [noSearchSessionStorageCapabilityMessage](./kibana-plugin-plugins-data-public.nosearchsessionstoragecapabilitymessage.md) | Message to display in case storing session session is disabled due to turned off capability |
| [parseSearchSourceJSON](./kibana-plugin-plugins-data-public.parsesearchsourcejson.md) | |
| [QueryStringInput](./kibana-plugin-plugins-data-public.querystringinput.md) | |
+| [SEARCH\_SESSIONS\_MANAGEMENT\_ID](./kibana-plugin-plugins-data-public.search_sessions_management_id.md) | |
| [search](./kibana-plugin-plugins-data-public.search.md) | |
| [SearchBar](./kibana-plugin-plugins-data-public.searchbar.md) | |
| [syncQueryStateWithUrl](./kibana-plugin-plugins-data-public.syncquerystatewithurl.md) | Helper to setup syncing of global data with the URL |
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.search_sessions_management_id.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.search_sessions_management_id.md
new file mode 100644
index 0000000000000..ad16d21403a98
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.search_sessions_management_id.md
@@ -0,0 +1,11 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [SEARCH\_SESSIONS\_MANAGEMENT\_ID](./kibana-plugin-plugins-data-public.search_sessions_management_id.md)
+
+## SEARCH\_SESSIONS\_MANAGEMENT\_ID variable
+
+Signature:
+
+```typescript
+SEARCH_SESSIONS_MANAGEMENT_ID = "search_sessions"
+```
diff --git a/src/plugins/data/public/index.ts b/src/plugins/data/public/index.ts
index 17533eec0a0fa..83a248ee2c3de 100644
--- a/src/plugins/data/public/index.ts
+++ b/src/plugins/data/public/index.ts
@@ -381,6 +381,7 @@ export {
TimeoutErrorMode,
PainlessError,
noSearchSessionStorageCapabilityMessage,
+ SEARCH_SESSIONS_MANAGEMENT_ID,
} from './search';
export type {
diff --git a/src/plugins/data/public/public.api.md b/src/plugins/data/public/public.api.md
index 408573e12eba5..95c849ce74248 100644
--- a/src/plugins/data/public/public.api.md
+++ b/src/plugins/data/public/public.api.md
@@ -2238,6 +2238,11 @@ export const search: {
tabifyGetColumns: typeof tabifyGetColumns;
};
+// Warning: (ae-missing-release-tag) "SEARCH_SESSIONS_MANAGEMENT_ID" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+//
+// @public (undocumented)
+export const SEARCH_SESSIONS_MANAGEMENT_ID = "search_sessions";
+
// Warning: (ae-missing-release-tag) "SearchBar" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
@@ -2601,23 +2606,23 @@ export const UI_SETTINGS: {
// src/plugins/data/public/index.ts:234:27 - (ae-forgotten-export) The symbol "validateIndexPattern" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:234:27 - (ae-forgotten-export) The symbol "flattenHitWrapper" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:234:27 - (ae-forgotten-export) The symbol "formatHitProvider" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:396:20 - (ae-forgotten-export) The symbol "getRequestInspectorStats" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:396:20 - (ae-forgotten-export) The symbol "getResponseInspectorStats" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:396:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:396:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:398:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:399:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:408:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:409:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:410:1 - (ae-forgotten-export) The symbol "Ipv4Address" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:411:1 - (ae-forgotten-export) The symbol "isDateHistogramBucketAggConfig" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:415:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:416:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:419:1 - (ae-forgotten-export) The symbol "parseInterval" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:420:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:423:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:397:20 - (ae-forgotten-export) The symbol "getRequestInspectorStats" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:397:20 - (ae-forgotten-export) The symbol "getResponseInspectorStats" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:397:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:397:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:399:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:400:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:409:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:410:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:411:1 - (ae-forgotten-export) The symbol "Ipv4Address" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:412:1 - (ae-forgotten-export) The symbol "isDateHistogramBucketAggConfig" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:416:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:417:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:420:1 - (ae-forgotten-export) The symbol "parseInterval" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:421:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:424:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/query/state_sync/connect_to_query_state.ts:34:5 - (ae-forgotten-export) The symbol "FilterStateStore" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/search/session/session_service.ts:41:5 - (ae-forgotten-export) The symbol "UrlGeneratorStateMapping" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/search/session/session_service.ts:42:5 - (ae-forgotten-export) The symbol "UrlGeneratorStateMapping" needs to be exported by the entry point index.d.ts
// (No @packageDocumentation comment for this package)
diff --git a/src/plugins/data/public/search/index.ts b/src/plugins/data/public/search/index.ts
index 31a94d69ddf02..b1e0bc490823a 100644
--- a/src/plugins/data/public/search/index.ts
+++ b/src/plugins/data/public/search/index.ts
@@ -38,6 +38,7 @@ export {
SessionsClient,
ISessionsClient,
noSearchSessionStorageCapabilityMessage,
+ SEARCH_SESSIONS_MANAGEMENT_ID,
} from './session';
export { getEsPreference } from './es_search';
diff --git a/src/plugins/data/public/search/session/constants.ts b/src/plugins/data/public/search/session/constants.ts
new file mode 100644
index 0000000000000..5496a541bfd45
--- /dev/null
+++ b/src/plugins/data/public/search/session/constants.ts
@@ -0,0 +1,9 @@
+/*
+ * 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 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+export const SEARCH_SESSIONS_MANAGEMENT_ID = 'search_sessions';
diff --git a/src/plugins/data/public/search/session/index.ts b/src/plugins/data/public/search/session/index.ts
index 82ba1e703a6d6..15410400a33e6 100644
--- a/src/plugins/data/public/search/session/index.ts
+++ b/src/plugins/data/public/search/session/index.ts
@@ -10,3 +10,4 @@ export { SessionService, ISessionService, SearchSessionInfoProvider } from './se
export { SearchSessionState } from './search_session_state';
export { SessionsClient, ISessionsClient } from './sessions_client';
export { noSearchSessionStorageCapabilityMessage } from './i18n';
+export { SEARCH_SESSIONS_MANAGEMENT_ID } from './constants';
diff --git a/src/plugins/data/public/search/session/mocks.ts b/src/plugins/data/public/search/session/mocks.ts
index f6a70d157b5a0..c615be641078b 100644
--- a/src/plugins/data/public/search/session/mocks.ts
+++ b/src/plugins/data/public/search/session/mocks.ts
@@ -41,5 +41,6 @@ export function getSessionServiceMock(): jest.Mocked {
enableStorage: jest.fn(),
isSessionStorageReady: jest.fn(() => true),
getSearchSessionIndicatorUiConfig: jest.fn(() => ({ isDisabled: () => ({ disabled: false }) })),
+ hasAccess: jest.fn(() => true),
};
}
diff --git a/src/plugins/data/public/search/session/session_service.test.ts b/src/plugins/data/public/search/session/session_service.test.ts
index 54c402f51ec70..85c4a00f6f862 100644
--- a/src/plugins/data/public/search/session/session_service.test.ts
+++ b/src/plugins/data/public/search/session/session_service.test.ts
@@ -14,6 +14,7 @@ import { BehaviorSubject } from 'rxjs';
import { SearchSessionState } from './search_session_state';
import { createNowProviderMock } from '../../now_provider/mocks';
import { NowProviderInternalContract } from '../../now_provider';
+import { SEARCH_SESSIONS_MANAGEMENT_ID } from './constants';
describe('Session service', () => {
let sessionService: ISessionService;
@@ -30,7 +31,18 @@ describe('Session service', () => {
startService().then(([coreStart, ...rest]) => [
{
...coreStart,
- application: { ...coreStart.application, currentAppId$: new BehaviorSubject('app') },
+ application: {
+ ...coreStart.application,
+ currentAppId$: new BehaviorSubject('app'),
+ capabilities: {
+ ...coreStart.application.capabilities,
+ management: {
+ kibana: {
+ [SEARCH_SESSIONS_MANAGEMENT_ID]: true,
+ },
+ },
+ },
+ },
},
...rest,
]),
diff --git a/src/plugins/data/public/search/session/session_service.ts b/src/plugins/data/public/search/session/session_service.ts
index 79ae64c5846a5..97e46fce37e8f 100644
--- a/src/plugins/data/public/search/session/session_service.ts
+++ b/src/plugins/data/public/search/session/session_service.ts
@@ -20,6 +20,7 @@ import {
import { ISessionsClient } from './sessions_client';
import { ISearchOptions } from '../../../common';
import { NowProviderInternalContract } from '../../now_provider';
+import { SEARCH_SESSIONS_MANAGEMENT_ID } from './constants';
export type ISessionService = PublicContract;
@@ -68,6 +69,7 @@ export class SessionService {
private searchSessionIndicatorUiConfig?: Partial;
private subscription = new Subscription();
private curApp?: string;
+ private hasAccessToSearchSessions: boolean = false;
constructor(
initializerContext: PluginInitializerContext,
@@ -94,6 +96,9 @@ export class SessionService {
);
getStartServices().then(([coreStart]) => {
+ this.hasAccessToSearchSessions =
+ coreStart.application.capabilities.management?.kibana?.[SEARCH_SESSIONS_MANAGEMENT_ID];
+
// Apps required to clean up their sessions before unmounting
// Make sure that apps don't leave sessions open.
this.subscription.add(
@@ -117,6 +122,15 @@ export class SessionService {
});
}
+ /**
+ * If user has access to search sessions
+ * This resolves to `true` in case at least one app allows user to create search session
+ * In this case search session management is available
+ */
+ public hasAccess() {
+ return this.hasAccessToSearchSessions;
+ }
+
/**
* Used to track pending searches within current session
*
@@ -247,11 +261,21 @@ export class SessionService {
/**
* Infers search session options for sessionId using current session state
+ *
+ * In case user doesn't has access to `search-session` SO returns null,
+ * meaning that sessionId and other session parameters shouldn't be used when doing searches
+ *
* @param sessionId
*/
public getSearchOptions(
sessionId: string
- ): Required> {
+ ): Required> | null {
+ // in case user doesn't have permissions to search session, do not forward sessionId to the server
+ // because user most likely also doesn't have access to `search-session` SO
+ if (!this.hasAccessToSearchSessions) {
+ return null;
+ }
+
const isCurrentSession = this.isCurrentSession(sessionId);
return {
sessionId,
diff --git a/src/plugins/vis_type_timelion/public/helpers/timelion_request_handler.ts b/src/plugins/vis_type_timelion/public/helpers/timelion_request_handler.ts
index c07fd0a278197..832a98a4b28b7 100644
--- a/src/plugins/vis_type_timelion/public/helpers/timelion_request_handler.ts
+++ b/src/plugins/vis_type_timelion/public/helpers/timelion_request_handler.ts
@@ -94,6 +94,8 @@ export function getTimelionRequestHandler({
});
try {
+ const searchSessionOptions =
+ searchSessionId && dataSearch.session.getSearchOptions(searchSessionId);
return await http.post('/api/timelion/run', {
body: JSON.stringify({
sheet: [expression],
@@ -108,8 +110,8 @@ export function getTimelionRequestHandler({
interval: visParams.interval,
timezone,
},
- ...(searchSessionId && {
- searchSession: dataSearch.session.getSearchOptions(searchSessionId),
+ ...(searchSessionOptions && {
+ searchSession: searchSessionOptions,
}),
}),
});
diff --git a/src/plugins/vis_type_timeseries/public/request_handler.ts b/src/plugins/vis_type_timeseries/public/request_handler.ts
index c7beccbceca1a..df321331e6429 100644
--- a/src/plugins/vis_type_timeseries/public/request_handler.ts
+++ b/src/plugins/vis_type_timeseries/public/request_handler.ts
@@ -48,6 +48,8 @@ export const metricsRequestHandler = async ({
});
try {
+ const searchSessionOptions =
+ searchSessionId && dataSearch.session.getSearchOptions(searchSessionId);
return await getCoreStart().http.post(ROUTES.VIS_DATA, {
body: JSON.stringify({
timerange: {
@@ -58,8 +60,8 @@ export const metricsRequestHandler = async ({
filters: input?.filters,
panels: [visParams],
state: uiStateObj,
- ...(searchSessionId && {
- searchSession: dataSearch.session.getSearchOptions(searchSessionId),
+ ...(searchSessionOptions && {
+ searchSession: searchSessionOptions,
}),
}),
});
diff --git a/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/index.ts b/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/index.ts
index 332b30809077c..e13cd06f52a4d 100644
--- a/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/index.ts
+++ b/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/index.ts
@@ -15,6 +15,7 @@ import type { ConfigSchema } from '../../../config';
import type { DataEnhancedStartDependencies } from '../../plugin';
import type { SearchSessionsMgmtAPI } from './lib/api';
import type { AsyncSearchIntroDocumentation } from './lib/documentation';
+import { SEARCH_SESSIONS_MANAGEMENT_ID } from '../../../../../../src/plugins/data/public';
export interface IManagementSectionsPluginsSetup {
management: ManagementSetup;
@@ -38,7 +39,7 @@ export interface AppDependencies {
}
export const APP = {
- id: 'search_sessions',
+ id: SEARCH_SESSIONS_MANAGEMENT_ID,
getI18nName: (): string =>
i18n.translate('xpack.data.mgmt.searchSessions.appTitle', {
defaultMessage: 'Search Sessions',
diff --git a/x-pack/plugins/data_enhanced/public/search/ui/connected_search_session_indicator/connected_search_session_indicator.test.tsx b/x-pack/plugins/data_enhanced/public/search/ui/connected_search_session_indicator/connected_search_session_indicator.test.tsx
index 3437920ed7c98..aacb86f269727 100644
--- a/x-pack/plugins/data_enhanced/public/search/ui/connected_search_session_indicator/connected_search_session_indicator.test.tsx
+++ b/x-pack/plugins/data_enhanced/public/search/ui/connected_search_session_indicator/connected_search_session_indicator.test.tsx
@@ -24,6 +24,7 @@ import userEvent from '@testing-library/user-event';
import { IntlProvider } from 'react-intl';
const coreStart = coreMock.createStart();
+const application = coreStart.application;
const dataStart = dataPluginMock.createStartContract();
const sessionService = dataStart.search.session as jest.Mocked;
let storage: Storage;
@@ -52,7 +53,7 @@ beforeEach(() => {
test("shouldn't show indicator in case no active search session", async () => {
const SearchSessionIndicator = createConnectedSearchSessionIndicator({
sessionService,
- application: coreStart.application,
+ application,
timeFilter,
storage,
disableSaveAfterSessionCompletesTimeout,
@@ -79,7 +80,7 @@ test("shouldn't show indicator in case no active search session", async () => {
test("shouldn't show indicator in case app hasn't opt-in", async () => {
const SearchSessionIndicator = createConnectedSearchSessionIndicator({
sessionService,
- application: coreStart.application,
+ application,
timeFilter,
storage,
disableSaveAfterSessionCompletesTimeout,
@@ -108,7 +109,7 @@ test('should show indicator in case there is an active search session', async ()
const state$ = new BehaviorSubject(SearchSessionState.Loading);
const SearchSessionIndicator = createConnectedSearchSessionIndicator({
sessionService: { ...sessionService, state$ },
- application: coreStart.application,
+ application,
timeFilter,
storage,
disableSaveAfterSessionCompletesTimeout,
@@ -124,12 +125,6 @@ test('should show indicator in case there is an active search session', async ()
test('should be disabled in case uiConfig says so ', async () => {
const state$ = new BehaviorSubject(SearchSessionState.Loading);
- coreStart.application.currentAppId$ = new BehaviorSubject('discover');
- (coreStart.application.capabilities as any) = {
- discover: {
- storeSearchSession: false,
- },
- };
sessionService.getSearchSessionIndicatorUiConfig.mockImplementation(() => ({
isDisabled: () => ({
disabled: true,
@@ -138,7 +133,7 @@ test('should be disabled in case uiConfig says so ', async () => {
}));
const SearchSessionIndicator = createConnectedSearchSessionIndicator({
sessionService: { ...sessionService, state$ },
- application: coreStart.application,
+ application,
timeFilter,
storage,
disableSaveAfterSessionCompletesTimeout,
@@ -157,12 +152,36 @@ test('should be disabled in case uiConfig says so ', async () => {
expect(screen.getByRole('button', { name: 'Save session' })).toBeDisabled();
});
+test('should be disabled in case not enough permissions', async () => {
+ const state$ = new BehaviorSubject(SearchSessionState.Completed);
+ const SearchSessionIndicator = createConnectedSearchSessionIndicator({
+ sessionService: { ...sessionService, state$, hasAccess: () => false },
+ application,
+ timeFilter,
+ storage,
+ disableSaveAfterSessionCompletesTimeout,
+ });
+
+ render(
+
+
+
+ );
+
+ await waitFor(() => screen.getByTestId('searchSessionIndicator'));
+
+ await userEvent.click(screen.getByLabelText('Search session complete'));
+
+ expect(screen.getByRole('button', { name: 'Save session' })).toBeDisabled();
+ expect(screen.getByRole('button', { name: 'Manage sessions' })).toBeDisabled();
+});
+
test('should be disabled during auto-refresh', async () => {
const state$ = new BehaviorSubject(SearchSessionState.Loading);
const SearchSessionIndicator = createConnectedSearchSessionIndicator({
sessionService: { ...sessionService, state$ },
- application: coreStart.application,
+ application,
timeFilter,
storage,
disableSaveAfterSessionCompletesTimeout,
@@ -199,7 +218,7 @@ describe('Completed inactivity', () => {
const SearchSessionIndicator = createConnectedSearchSessionIndicator({
sessionService: { ...sessionService, state$ },
- application: coreStart.application,
+ application,
timeFilter,
storage,
disableSaveAfterSessionCompletesTimeout,
@@ -257,7 +276,7 @@ describe('tour steps', () => {
const state$ = new BehaviorSubject(SearchSessionState.Loading);
const SearchSessionIndicator = createConnectedSearchSessionIndicator({
sessionService: { ...sessionService, state$ },
- application: coreStart.application,
+ application,
timeFilter,
storage,
disableSaveAfterSessionCompletesTimeout,
@@ -294,7 +313,7 @@ describe('tour steps', () => {
const state$ = new BehaviorSubject(SearchSessionState.Loading);
const SearchSessionIndicator = createConnectedSearchSessionIndicator({
sessionService: { ...sessionService, state$ },
- application: coreStart.application,
+ application,
timeFilter,
storage,
disableSaveAfterSessionCompletesTimeout,
@@ -325,7 +344,7 @@ describe('tour steps', () => {
const state$ = new BehaviorSubject(SearchSessionState.Restored);
const SearchSessionIndicator = createConnectedSearchSessionIndicator({
sessionService: { ...sessionService, state$ },
- application: coreStart.application,
+ application,
timeFilter,
storage,
disableSaveAfterSessionCompletesTimeout,
@@ -347,7 +366,7 @@ describe('tour steps', () => {
const state$ = new BehaviorSubject(SearchSessionState.Completed);
const SearchSessionIndicator = createConnectedSearchSessionIndicator({
sessionService: { ...sessionService, state$ },
- application: coreStart.application,
+ application,
timeFilter,
storage,
disableSaveAfterSessionCompletesTimeout,
diff --git a/x-pack/plugins/data_enhanced/public/search/ui/connected_search_session_indicator/connected_search_session_indicator.tsx b/x-pack/plugins/data_enhanced/public/search/ui/connected_search_session_indicator/connected_search_session_indicator.tsx
index 3935b5bb2814b..81769e5a25544 100644
--- a/x-pack/plugins/data_enhanced/public/search/ui/connected_search_session_indicator/connected_search_session_indicator.tsx
+++ b/x-pack/plugins/data_enhanced/public/search/ui/connected_search_session_indicator/connected_search_session_indicator.tsx
@@ -79,6 +79,9 @@ export const createConnectedSearchSessionIndicator = ({
let saveDisabled = false;
let saveDisabledReasonText: string = '';
+ let managementDisabled = false;
+ let managementDisabledReasonText: string = '';
+
if (autoRefreshEnabled) {
saveDisabled = true;
saveDisabledReasonText = i18n.translate(
@@ -104,6 +107,18 @@ export const createConnectedSearchSessionIndicator = ({
saveDisabledReasonText = isSaveDisabledByApp.reasonText;
}
+ // check if user doesn't have access to search_sessions and search_sessions mgtm
+ // this happens in case there is no app that allows current user to use search session
+ if (!sessionService.hasAccess()) {
+ managementDisabled = saveDisabled = true;
+ managementDisabledReasonText = saveDisabledReasonText = i18n.translate(
+ 'xpack.data.searchSessionIndicator.disabledDueToDisabledGloballyMessage',
+ {
+ defaultMessage: "You don't have permissions to manage search sessions",
+ }
+ );
+ }
+
const { markOpenedDone, markRestoredDone } = useSearchSessionTour(
storage,
searchSessionIndicator,
@@ -143,6 +158,8 @@ export const createConnectedSearchSessionIndicator = ({
state={state}
saveDisabled={saveDisabled}
saveDisabledReasonText={saveDisabledReasonText}
+ managementDisabled={managementDisabled}
+ managementDisabledReasonText={managementDisabledReasonText}
onContinueInBackground={onContinueInBackground}
onSaveResults={onSaveResults}
onCancel={onCancel}
diff --git a/x-pack/plugins/data_enhanced/public/search/ui/search_session_indicator/search_session_indicator.tsx b/x-pack/plugins/data_enhanced/public/search/ui/search_session_indicator/search_session_indicator.tsx
index eb58039ff58f7..0d31ce0c98f19 100644
--- a/x-pack/plugins/data_enhanced/public/search/ui/search_session_indicator/search_session_indicator.tsx
+++ b/x-pack/plugins/data_enhanced/public/search/ui/search_session_indicator/search_session_indicator.tsx
@@ -31,7 +31,8 @@ export interface SearchSessionIndicatorProps {
onCancel?: () => void;
viewSearchSessionsLink?: string;
onSaveResults?: () => void;
-
+ managementDisabled?: boolean;
+ managementDisabledReasonText?: string;
saveDisabled?: boolean;
saveDisabledReasonText?: string;
@@ -78,17 +79,22 @@ const ContinueInBackgroundButton = ({
const ViewAllSearchSessionsButton = ({
viewSearchSessionsLink = 'management/kibana/search_sessions',
buttonProps = {},
+ managementDisabled,
+ managementDisabledReasonText,
}: ActionButtonProps) => (
-
-
-
+
+
+
+
+
);
const SaveButton = ({
diff --git a/x-pack/plugins/features/server/oss_features.ts b/x-pack/plugins/features/server/oss_features.ts
index 2d9e01427a277..6c599461f438a 100644
--- a/x-pack/plugins/features/server/oss_features.ts
+++ b/x-pack/plugins/features/server/oss_features.ts
@@ -21,6 +21,9 @@ export const buildOSSFeatures = ({ savedObjectTypes, includeTimelion }: BuildOSS
name: i18n.translate('xpack.features.discoverFeatureName', {
defaultMessage: 'Discover',
}),
+ management: {
+ kibana: ['search_sessions'],
+ },
order: 100,
category: DEFAULT_APP_CATEGORIES.kibana,
app: ['discover', 'kibana'],
@@ -95,6 +98,9 @@ export const buildOSSFeatures = ({ savedObjectTypes, includeTimelion }: BuildOSS
read: [],
},
ui: ['storeSearchSession'],
+ management: {
+ kibana: ['search_sessions'],
+ },
},
],
},
@@ -166,6 +172,9 @@ export const buildOSSFeatures = ({ savedObjectTypes, includeTimelion }: BuildOSS
name: i18n.translate('xpack.features.dashboardFeatureName', {
defaultMessage: 'Dashboard',
}),
+ management: {
+ kibana: ['search_sessions'],
+ },
order: 200,
category: DEFAULT_APP_CATEGORIES.kibana,
app: ['dashboards', 'kibana'],
@@ -260,6 +269,9 @@ export const buildOSSFeatures = ({ savedObjectTypes, includeTimelion }: BuildOSS
read: [],
},
ui: ['storeSearchSession'],
+ management: {
+ kibana: ['search_sessions'],
+ },
},
],
},