From 8e1ead5fdee07b2712b0482c3c7846e036ef4968 Mon Sep 17 00:00:00 2001 From: SuZhou-Joe Date: Wed, 9 Aug 2023 18:16:17 +0800 Subject: [PATCH] Change public objects logic & Search with ACL control (#71) * feat: update public workspace Signed-off-by: SuZhou-Joe * refractor: change public objects logic Signed-off-by: SuZhou-Joe * feat: create public workspace when service start Signed-off-by: SuZhou-Joe * feat: some modify Signed-off-by: SuZhou-Joe * feature: some optimize and create workspace when ui settings is open Signed-off-by: SuZhou-Joe * feat: update Signed-off-by: SuZhou-Joe * feat: update Signed-off-by: SuZhou-Joe * feat: update Signed-off-by: SuZhou-Joe * feat: update Signed-off-by: SuZhou-Joe * temp: submit Signed-off-by: SuZhou-Joe * feat: update Signed-off-by: SuZhou-Joe * feat: update Signed-off-by: SuZhou-Joe * feat: update Signed-off-by: SuZhou-Joe * feat: update Signed-off-by: SuZhou-Joe * feat: update query dsl Signed-off-by: SuZhou-Joe * feat: use same constants Signed-off-by: SuZhou-Joe * feat: make it run Signed-off-by: SuZhou-Joe * feat: remove dashboard admin Signed-off-by: SuZhou-Joe * feat: modify query DSL Signed-off-by: SuZhou-Joe * feat: modify query DSL Signed-off-by: SuZhou-Joe * feat: modify query DSL Signed-off-by: SuZhou-Joe * feat: list principals route Signed-off-by: SuZhou-Joe * feat: optimize query DSL Signed-off-by: SuZhou-Joe * feat: change public logic Signed-off-by: SuZhou-Joe * feat: update Signed-off-by: SuZhou-Joe * feat: update Signed-off-by: SuZhou-Joe * feat: remove init Signed-off-by: SuZhou-Joe * feat: add judgement when workspaceList is empty Signed-off-by: SuZhou-Joe --------- Signed-off-by: SuZhou-Joe --- .../saved_objects/saved_objects_client.ts | 42 +++++++--- src/core/public/utils/index.ts | 6 +- .../public/workspace/workspaces_client.ts | 34 ++++---- .../permission_control/routes/index.ts | 2 + .../routes/{principles.ts => principals.ts} | 0 src/core/server/saved_objects/routes/share.ts | 4 +- .../saved_objects/service/lib/repository.ts | 6 +- .../service/lib/search_dsl/query_params.ts | 8 -- .../service/saved_objects_client.ts | 1 - src/core/server/server.ts | 4 +- src/core/server/workspaces/constants.ts | 1 - .../workspace_saved_objects_client_wrapper.ts | 45 +++++++--- .../server/workspaces/workspaces_service.ts | 84 ++++++++++++++++++- src/core/utils/constants.ts | 6 ++ src/core/utils/index.ts | 8 +- .../objects_table/saved_objects_table.tsx | 5 +- .../components/utils/workspace_column.tsx | 9 -- src/plugins/workspace/public/plugin.ts | 15 +++- 18 files changed, 206 insertions(+), 74 deletions(-) rename src/core/server/saved_objects/permission_control/routes/{principles.ts => principals.ts} (100%) diff --git a/src/core/public/saved_objects/saved_objects_client.ts b/src/core/public/saved_objects/saved_objects_client.ts index 356e555cfc53..b0e3245f74e5 100644 --- a/src/core/public/saved_objects/saved_objects_client.ts +++ b/src/core/public/saved_objects/saved_objects_client.ts @@ -42,6 +42,7 @@ import { import { SimpleSavedObject } from './simple_saved_object'; import { HttpFetchOptions, HttpSetup } from '../http'; +import { PUBLIC_WORKSPACE } from '../../utils'; type SavedObjectsFindOptions = Omit< SavedObjectFindOptionsServer, @@ -184,7 +185,11 @@ const getObjectsToFetch = (queue: BatchQueueEntry[]): ObjectTypeAndId[] => { export class SavedObjectsClient { private http: HttpSetup; private batchQueue: BatchQueueEntry[]; - private currentWorkspaceId?: string; + /** + * if currentWorkspaceId is undefined, it means + * we should not carry out workspace info when doing any operation. + */ + private currentWorkspaceId: string | undefined; /** * Throttled processing of get requests into bulk requests at 100ms interval @@ -229,11 +234,11 @@ export class SavedObjectsClient { this.batchQueue = []; } - private async _getCurrentWorkspace(): Promise { - return this.currentWorkspaceId || null; + private _getCurrentWorkspace(): string | undefined { + return this.currentWorkspaceId; } - public async setCurrentWorkspace(workspaceId: string): Promise { + public setCurrentWorkspace(workspaceId: string): boolean { this.currentWorkspaceId = workspaceId; return true; } @@ -259,7 +264,13 @@ export class SavedObjectsClient { const query = { overwrite: options.overwrite, }; - const currentWorkspaceId = await this._getCurrentWorkspace(); + const currentWorkspaceId = this._getCurrentWorkspace(); + let finalWorkspaces; + if (options.hasOwnProperty('workspaces')) { + finalWorkspaces = options.workspaces; + } else if (typeof currentWorkspaceId === 'string') { + finalWorkspaces = [currentWorkspaceId]; + } const createRequest: Promise> = this.savedObjectsFetch(path, { method: 'POST', @@ -268,9 +279,9 @@ export class SavedObjectsClient { attributes, migrationVersion: options.migrationVersion, references: options.references, - ...(options.workspaces || currentWorkspaceId + ...(finalWorkspaces ? { - workspaces: options.workspaces || [currentWorkspaceId], + workspaces: finalWorkspaces, } : {}), }), @@ -366,14 +377,21 @@ export class SavedObjectsClient { queryDSL: 'queryDSL', }; - const workspaces = [ - ...(options.workspaces || [await this._getCurrentWorkspace()]), - 'public', - ].filter((item) => item); + const currentWorkspaceId = this._getCurrentWorkspace(); + let finalWorkspaces; + if (options.hasOwnProperty('workspaces')) { + finalWorkspaces = options.workspaces; + } else if (typeof currentWorkspaceId === 'string') { + finalWorkspaces = Array.from(new Set([PUBLIC_WORKSPACE, currentWorkspaceId])); + } const renamedQuery = renameKeys(renameMap, { ...options, - workspaces, + ...(finalWorkspaces + ? { + workspaces: finalWorkspaces, + } + : {}), }); const query = pick.apply(null, [renamedQuery, ...Object.values(renameMap)]) as Partial< Record diff --git a/src/core/public/utils/index.ts b/src/core/public/utils/index.ts index ad363c53bd42..4f958a60ae66 100644 --- a/src/core/public/utils/index.ts +++ b/src/core/public/utils/index.ts @@ -32,4 +32,8 @@ export { shareWeakReplay } from './share_weak_replay'; export { Sha256 } from './crypto'; export { MountWrapper, mountReactNode } from './mount'; export { getWorkspaceIdFromUrl, WORKSPACE_TYPE } from './workspace'; -export { WORKSPACE_PATH_PREFIX } from '../../utils'; +export { + WORKSPACE_PATH_PREFIX, + PUBLIC_WORKSPACE, + WORKSPACE_FEATURE_FLAG_KEY_IN_UI_SETTINGS, +} from '../../utils'; diff --git a/src/core/public/workspace/workspaces_client.ts b/src/core/public/workspace/workspaces_client.ts index 46ca139d9551..2f8c204bf418 100644 --- a/src/core/public/workspace/workspaces_client.ts +++ b/src/core/public/workspace/workspaces_client.ts @@ -48,25 +48,27 @@ export class WorkspacesClient { combineLatest([this.workspaceList$, this.currentWorkspaceId$]).subscribe( ([workspaceList, currentWorkspaceId]) => { - const currentWorkspace = this.findWorkspace([workspaceList, currentWorkspaceId]); + if (workspaceList.length) { + const currentWorkspace = this.findWorkspace([workspaceList, currentWorkspaceId]); - /** - * Do a simple idempotent verification here - */ - if (!isEqual(currentWorkspace, this.currentWorkspace$.getValue())) { - this.currentWorkspace$.next(currentWorkspace); - } - - if (currentWorkspaceId && !currentWorkspace?.id) { /** - * Current workspace is staled + * Do a simple idempotent verification here */ - this.currentWorkspaceId$.error({ - reason: WORKSPACE_ERROR_REASON_MAP.WORKSPACE_STALED, - }); - this.currentWorkspace$.error({ - reason: WORKSPACE_ERROR_REASON_MAP.WORKSPACE_STALED, - }); + if (!isEqual(currentWorkspace, this.currentWorkspace$.getValue())) { + this.currentWorkspace$.next(currentWorkspace); + } + + if (currentWorkspaceId && !currentWorkspace?.id) { + /** + * Current workspace is staled + */ + this.currentWorkspaceId$.error({ + reason: WORKSPACE_ERROR_REASON_MAP.WORKSPACE_STALED, + }); + this.currentWorkspace$.error({ + reason: WORKSPACE_ERROR_REASON_MAP.WORKSPACE_STALED, + }); + } } } ); diff --git a/src/core/server/saved_objects/permission_control/routes/index.ts b/src/core/server/saved_objects/permission_control/routes/index.ts index edd694b0ada0..405bd22bdbe9 100644 --- a/src/core/server/saved_objects/permission_control/routes/index.ts +++ b/src/core/server/saved_objects/permission_control/routes/index.ts @@ -5,6 +5,7 @@ import { InternalHttpServiceSetup } from '../../../http'; import { SavedObjectsPermissionControlContract } from '../client'; +import { registerListRoute } from './principals'; import { registerValidateRoute } from './validate'; export function registerPermissionCheckRoutes({ @@ -17,4 +18,5 @@ export function registerPermissionCheckRoutes({ const router = http.createRouter('/api/saved_objects_permission_control/'); registerValidateRoute(router, permissionControl); + registerListRoute(router, permissionControl); } diff --git a/src/core/server/saved_objects/permission_control/routes/principles.ts b/src/core/server/saved_objects/permission_control/routes/principals.ts similarity index 100% rename from src/core/server/saved_objects/permission_control/routes/principles.ts rename to src/core/server/saved_objects/permission_control/routes/principals.ts diff --git a/src/core/server/saved_objects/routes/share.ts b/src/core/server/saved_objects/routes/share.ts index 340709017e7b..526ad24893c6 100644 --- a/src/core/server/saved_objects/routes/share.ts +++ b/src/core/server/saved_objects/routes/share.ts @@ -9,7 +9,7 @@ import { exportSavedObjectsToStream } from '../export'; import { validateObjects } from './utils'; import { collectSavedObjects } from '../import/collect_saved_objects'; import { WORKSPACE_TYPE } from '../../workspaces'; -import { GLOBAL_WORKSPACE_ID } from '../../workspaces/constants'; +import { PUBLIC_WORKSPACE } from '../../../utils/constants'; const SHARE_LIMIT = 10000; @@ -73,7 +73,7 @@ export const registerShareRoute = (router: IRouter) => { (obj) => obj.workspaces && obj.workspaces.length > 0 && - !obj.workspaces.includes(GLOBAL_WORKSPACE_ID) + !obj.workspaces.includes(PUBLIC_WORKSPACE) ) .map((obj) => ({ id: obj.id, type: obj.type, workspaces: obj.workspaces })); diff --git a/src/core/server/saved_objects/service/lib/repository.ts b/src/core/server/saved_objects/service/lib/repository.ts index 0fd6efd2675f..6adefe16848d 100644 --- a/src/core/server/saved_objects/service/lib/repository.ts +++ b/src/core/server/saved_objects/service/lib/repository.ts @@ -87,7 +87,7 @@ import { FIND_DEFAULT_PER_PAGE, SavedObjectsUtils, } from './utils'; -import { GLOBAL_WORKSPACE_ID } from '../../../workspaces/constants'; +import { PUBLIC_WORKSPACE } from '../../../../utils/constants'; // BEWARE: The SavedObjectClient depends on the implementation details of the SavedObjectsRepository // so any breaking changes to this repository are considered breaking changes to the SavedObjectsClient. @@ -1299,7 +1299,7 @@ export class SavedObjectsRepository { if ( obj.workspaces && obj.workspaces.length > 0 && - !obj.workspaces.includes(GLOBAL_WORKSPACE_ID) + !obj.workspaces.includes(PUBLIC_WORKSPACE) ) { return intersection(obj.workspaces, options.workspaces).length === 0; } @@ -1352,7 +1352,7 @@ export class SavedObjectsRepository { params: { time, workspaces, - globalWorkspaceId: GLOBAL_WORKSPACE_ID, + globalWorkspaceId: PUBLIC_WORKSPACE, }, }, }, diff --git a/src/core/server/saved_objects/service/lib/search_dsl/query_params.ts b/src/core/server/saved_objects/service/lib/search_dsl/query_params.ts index 4ddbe992bcfc..d9fbf7199c18 100644 --- a/src/core/server/saved_objects/service/lib/search_dsl/query_params.ts +++ b/src/core/server/saved_objects/service/lib/search_dsl/query_params.ts @@ -142,14 +142,6 @@ function getClauseForWorkspace(workspace: string) { }; } - if (workspace === 'public') { - return { - bool: { - must_not: [{ exists: { field: 'workspaces' } }], - }, - }; - } - return { bool: { must: [{ term: { workspaces: workspace } }], diff --git a/src/core/server/saved_objects/service/saved_objects_client.ts b/src/core/server/saved_objects/service/saved_objects_client.ts index ff37d3e45537..3a71c28c74ba 100644 --- a/src/core/server/saved_objects/service/saved_objects_client.ts +++ b/src/core/server/saved_objects/service/saved_objects_client.ts @@ -29,7 +29,6 @@ */ import { Permissions } from '../permission_control/acl'; - import { ISavedObjectsRepository } from './lib'; import { SavedObject, diff --git a/src/core/server/server.ts b/src/core/server/server.ts index a3a7678ae21e..afdbdc7b4846 100644 --- a/src/core/server/server.ts +++ b/src/core/server/server.ts @@ -262,7 +262,9 @@ export class Server { opensearch: opensearchStart, savedObjects: savedObjectsStart, }); - await this.workspaces.start(); + await this.workspaces.start({ + savedObjects: savedObjectsStart, + }); this.coreStart = { capabilities: capabilitiesStart, diff --git a/src/core/server/workspaces/constants.ts b/src/core/server/workspaces/constants.ts index c9bf406e50c9..73c2d6010846 100644 --- a/src/core/server/workspaces/constants.ts +++ b/src/core/server/workspaces/constants.ts @@ -4,4 +4,3 @@ */ export const WORKSPACE_TYPE = 'workspace'; -export const GLOBAL_WORKSPACE_ID = 'public'; diff --git a/src/core/server/workspaces/saved_objects/workspace_saved_objects_client_wrapper.ts b/src/core/server/workspaces/saved_objects/workspace_saved_objects_client_wrapper.ts index 0a028b7e356e..5f852d48a068 100644 --- a/src/core/server/workspaces/saved_objects/workspace_saved_objects_client_wrapper.ts +++ b/src/core/server/workspaces/saved_objects/workspace_saved_objects_client_wrapper.ts @@ -214,26 +214,49 @@ export class WorkspaceSavedObjectsClientWrapper { ); if (options.workspaces) { const isEveryWorkspaceIsPermitted = options.workspaces.every((item) => - // TODO modify this line to use permittedWorkspaceIds if public workspace is also a workspace - ['public', ...(permittedWorkspaceIds || [])]?.includes(item) + (permittedWorkspaceIds || []).includes(item) ); if (!isEveryWorkspaceIsPermitted) { throw generateWorkspacePermissionError(); } } else { const queryDSL = ACL.genereateGetPermittedSavedObjectsQueryDSL( - [ - PermissionMode.LibraryRead, - PermissionMode.LibraryWrite, - PermissionMode.Management, - PermissionMode.Read, - PermissionMode.Write, - ], + [PermissionMode.Read, PermissionMode.Write], principals, options.type ); - options.workspaces = permittedWorkspaceIds; - options.queryDSL = queryDSL; + options.workspaces = undefined; + /** + * Select all the docs that + * 1. ACL matches read or write permission OR + * 2. workspaces matches library_read or library_write or management OR + * 3. Advanced settings + */ + options.queryDSL = { + query: { + bool: { + filter: [ + { + bool: { + should: [ + { + term: { + type: 'config', + }, + }, + queryDSL.query, + { + terms: { + workspaces: permittedWorkspaceIds, + }, + }, + ], + }, + }, + ], + }, + }, + }; } } diff --git a/src/core/server/workspaces/workspaces_service.ts b/src/core/server/workspaces/workspaces_service.ts index ba79ead6097d..2c322e38edb6 100644 --- a/src/core/server/workspaces/workspaces_service.ts +++ b/src/core/server/workspaces/workspaces_service.ts @@ -3,17 +3,25 @@ * SPDX-License-Identifier: Apache-2.0 */ import { URL } from 'node:url'; +import { i18n } from '@osd/i18n'; import { CoreService } from '../../types'; import { CoreContext } from '../core_context'; import { InternalHttpServiceSetup } from '../http'; import { Logger } from '../logging'; import { registerRoutes } from './routes'; -import { InternalSavedObjectsServiceSetup } from '../saved_objects'; -import { IWorkspaceDBImpl } from './types'; +import { + ISavedObjectsRepository, + InternalSavedObjectsServiceSetup, + SavedObjectsServiceStart, +} from '../saved_objects'; +import { IWorkspaceDBImpl, WorkspaceAttribute } from './types'; import { WorkspacesClientWithSavedObject } from './workspaces_client'; import { WorkspaceSavedObjectsClientWrapper } from './saved_objects'; import { InternalUiSettingsServiceSetup } from '../ui_settings'; import { uiSettings } from './ui_settings'; +import { WORKSPACE_TYPE } from './constants'; +import { MANAGEMENT_WORKSPACE, PUBLIC_WORKSPACE, PermissionMode } from '../../utils'; +import { ACL, Permissions } from '../saved_objects/permission_control/acl'; export interface WorkspacesServiceSetup { client: IWorkspaceDBImpl; @@ -29,6 +37,10 @@ export interface WorkspacesSetupDeps { uiSettings: InternalUiSettingsServiceSetup; } +export interface WorkpsaceStartDeps { + savedObjects: SavedObjectsServiceStart; +} + export type InternalWorkspacesServiceSetup = WorkspacesServiceSetup; export type InternalWorkspacesServiceStart = WorkspacesServiceStart; @@ -89,9 +101,75 @@ export class WorkspacesService }; } - public async start(): Promise { + private async checkAndCreateWorkspace( + internalRepository: ISavedObjectsRepository, + workspaceId: string, + workspaceAttribute: Omit, + permissions?: Permissions + ) { + /** + * Internal repository is attached to global tenant. + */ + try { + await internalRepository.get(WORKSPACE_TYPE, workspaceId); + } catch (error) { + this.logger.debug(error?.toString() || ''); + this.logger.info(`Workspace ${workspaceId} is not found, create it by using internal user`); + try { + const createResult = await internalRepository.create(WORKSPACE_TYPE, workspaceAttribute, { + id: workspaceId, + permissions, + }); + if (createResult.id) { + this.logger.info(`Created workspace ${createResult.id} in global tenant.`); + } + } catch (e) { + this.logger.error(`Create ${workspaceId} workspace error: ${e?.toString() || ''}`); + } + } + } + + private async setupWorkspaces(startDeps: WorkpsaceStartDeps) { + const internalRepository = startDeps.savedObjects.createInternalRepository(); + const publicWorkspaceACL = new ACL().addPermission( + [PermissionMode.LibraryRead, PermissionMode.LibraryWrite], + { + users: ['*'], + } + ); + const managementWorkspaceACL = new ACL().addPermission([PermissionMode.LibraryRead], { + users: ['*'], + }); + + await Promise.all([ + this.checkAndCreateWorkspace( + internalRepository, + PUBLIC_WORKSPACE, + { + name: i18n.translate('workspaces.public.workspace.default.name', { + defaultMessage: 'public', + }), + }, + publicWorkspaceACL.getPermissions() + ), + this.checkAndCreateWorkspace( + internalRepository, + MANAGEMENT_WORKSPACE, + { + name: i18n.translate('workspaces.management.workspace.default.name', { + defaultMessage: 'Management', + }), + }, + managementWorkspaceACL.getPermissions() + ), + ]); + } + + public async start(startDeps: WorkpsaceStartDeps): Promise { this.logger.debug('Starting SavedObjects service'); + this.setupWorkspaces(startDeps); + return { client: this.client as IWorkspaceDBImpl, }; diff --git a/src/core/utils/constants.ts b/src/core/utils/constants.ts index a58af8947131..5ebf5c0af141 100644 --- a/src/core/utils/constants.ts +++ b/src/core/utils/constants.ts @@ -17,3 +17,9 @@ export enum PrincipalType { Users = 'users', Groups = 'groups', } + +export const PUBLIC_WORKSPACE = 'public'; + +export const MANAGEMENT_WORKSPACE = 'management'; + +export const WORKSPACE_FEATURE_FLAG_KEY_IN_UI_SETTINGS = 'workspace:enabled'; diff --git a/src/core/utils/index.ts b/src/core/utils/index.ts index 9f19132ea8bc..4118a850c828 100644 --- a/src/core/utils/index.ts +++ b/src/core/utils/index.ts @@ -37,4 +37,10 @@ export { IContextProvider, } from './context'; export { DEFAULT_APP_CATEGORIES } from './default_app_categories'; -export { WORKSPACE_PATH_PREFIX, PermissionMode } from './constants'; +export { + WORKSPACE_PATH_PREFIX, + PermissionMode, + PUBLIC_WORKSPACE, + WORKSPACE_FEATURE_FLAG_KEY_IN_UI_SETTINGS, + MANAGEMENT_WORKSPACE, +} from './constants'; diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx index ca0aad55a0cb..b82fede2498e 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx @@ -94,6 +94,7 @@ import { import { Header, Table, Flyout, Relationships } from './components'; import { DataPublicPluginStart } from '../../../../../plugins/data/public'; import { SavedObjectsCopyModal } from './components/copy_modal'; +import { PUBLIC_WORKSPACE } from '../../../../../core/public/utils'; interface ExportAllOption { id: string; @@ -179,7 +180,9 @@ export class SavedObjectsTable extends Component()); - const publicWsName = i18n.translate('workspace.public.name', { - defaultMessage: 'public', - }); - wsLookUp?.set('public', publicWsName); - - if (!workspaces) { - return {publicWsName}; - } - const workspaceNames = workspaces?.map((wsId) => wsLookUp?.get(wsId)).join(' | '); return {workspaceNames}; diff --git a/src/plugins/workspace/public/plugin.ts b/src/plugins/workspace/public/plugin.ts index 2d6da177165e..8776b7bef8c8 100644 --- a/src/plugins/workspace/public/plugin.ts +++ b/src/plugins/workspace/public/plugin.ts @@ -29,7 +29,12 @@ import { import { mountDropdownList } from './mount'; import { SavedObjectsManagementPluginSetup } from '../../saved_objects_management/public'; import { getWorkspaceColumn } from './components/utils/workspace_column'; -import { getWorkspaceIdFromUrl, WORKSPACE_PATH_PREFIX } from '../../../core/public/utils'; +import { + getWorkspaceIdFromUrl, + PUBLIC_WORKSPACE, + WORKSPACE_PATH_PREFIX, +} from '../../../core/public/utils'; +import { WORKSPACE_FEATURE_FLAG_KEY_IN_UI_SETTINGS } from '../../../core/public/utils'; interface WorkspacesPluginSetupDeps { savedObjectsManagement?: SavedObjectsManagementPluginSetup; @@ -63,7 +68,7 @@ export class WorkspacesPlugin implements Plugin<{}, {}, WorkspacesPluginSetupDep }; public async setup(core: CoreSetup, { savedObjectsManagement }: WorkspacesPluginSetupDeps) { // If workspace feature is disabled, it will not load the workspace plugin - if (core.uiSettings.get('workspace:enabled') === false) { + if (core.uiSettings.get(WORKSPACE_FEATURE_FLAG_KEY_IN_UI_SETTINGS) === false) { return {}; } @@ -194,7 +199,9 @@ export class WorkspacesPlugin implements Plugin<{}, {}, WorkspacesPluginSetupDep if (this.coreStart) { return this.coreStart.workspaces.client.currentWorkspaceId$.subscribe( (currentWorkspaceId) => { - this.coreStart?.savedObjects.client.setCurrentWorkspace(currentWorkspaceId); + if (currentWorkspaceId) { + this.coreStart?.savedObjects.client.setCurrentWorkspace(currentWorkspaceId); + } } ); } @@ -262,7 +269,7 @@ export class WorkspacesPlugin implements Plugin<{}, {}, WorkspacesPluginSetupDep public start(core: CoreStart) { // If workspace feature is disabled, it will not load the workspace plugin - if (core.uiSettings.get('workspace:enabled') === false) { + if (core.uiSettings.get(WORKSPACE_FEATURE_FLAG_KEY_IN_UI_SETTINGS) === false) { return {}; }