forked from opensearch-project/OpenSearch-Dashboards
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
When getting ui settings within a workspace, it will combine the workspace ui settings with the global ui settings and workspace ui settings have higher priority if the same setting was defined in both places When updating ui settings within a workspace, it will update the workspace ui settings, the global ui settings will remain unchanged. Signed-off-by: Yulong Ruan <ruanyl@amazon.com>
- Loading branch information
Showing
6 changed files
with
275 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
134 changes: 134 additions & 0 deletions
134
src/plugins/workspace/server/saved_objects/workspace_ui_settings_client_wrapper.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
import { httpServerMock, savedObjectsClientMock, coreMock } from '../../../../core/server/mocks'; | ||
import { WorkspaceUiSettingsClientWrapper } from './workspace_ui_settings_client_wrapper'; | ||
import { WORKSPACE_TYPE } from '../../../../core/server'; | ||
|
||
import * as utils from '../../../../core/server/utils'; | ||
|
||
jest.mock('../../../../core/server/utils'); | ||
|
||
describe('WorkspaceUiSettingsClientWrapper', () => { | ||
const createWrappedClient = () => { | ||
const clientMock = savedObjectsClientMock.create(); | ||
const getClientMock = jest.fn().mockReturnValue(clientMock); | ||
const requestHandlerContext = coreMock.createRequestHandlerContext(); | ||
const requestMock = httpServerMock.createOpenSearchDashboardsRequest(); | ||
|
||
clientMock.get.mockImplementation(async (type, id) => { | ||
if (type === 'config') { | ||
return Promise.resolve({ | ||
id, | ||
references: [], | ||
type: 'config', | ||
attributes: { | ||
defaultIndex: 'default-index-global', | ||
}, | ||
}); | ||
} else if (type === WORKSPACE_TYPE) { | ||
return Promise.resolve({ | ||
id, | ||
references: [], | ||
type: WORKSPACE_TYPE, | ||
attributes: { | ||
uiSettings: { | ||
defaultIndex: 'default-index-workspace', | ||
}, | ||
}, | ||
}); | ||
} | ||
return Promise.reject(); | ||
}); | ||
|
||
const wrapper = new WorkspaceUiSettingsClientWrapper(); | ||
wrapper.setScopedClient(getClientMock); | ||
|
||
return { | ||
wrappedClient: wrapper.wrapperFactory({ | ||
client: clientMock, | ||
request: requestMock, | ||
typeRegistry: requestHandlerContext.savedObjects.typeRegistry, | ||
}), | ||
clientMock, | ||
}; | ||
}; | ||
|
||
it('should return workspace ui settings if in a workspace', async () => { | ||
// Currently in a workspace | ||
jest.spyOn(utils, 'getWorkspaceState').mockReturnValue({ requestWorkspaceId: 'workspace-id' }); | ||
|
||
const { wrappedClient } = createWrappedClient(); | ||
|
||
const result = await wrappedClient.get('config', '3.0.0'); | ||
expect(result).toEqual({ | ||
id: '3.0.0', | ||
references: [], | ||
type: 'config', | ||
attributes: { | ||
defaultIndex: 'default-index-workspace', | ||
}, | ||
}); | ||
}); | ||
|
||
it('should return global ui settings if NOT in a workspace', async () => { | ||
// Currently NOT in a workspace | ||
jest.spyOn(utils, 'getWorkspaceState').mockReturnValue({}); | ||
|
||
const { wrappedClient } = createWrappedClient(); | ||
|
||
const result = await wrappedClient.get('config', '3.0.0'); | ||
expect(result).toEqual({ | ||
id: '3.0.0', | ||
references: [], | ||
type: 'config', | ||
attributes: { | ||
defaultIndex: 'default-index-global', | ||
}, | ||
}); | ||
}); | ||
|
||
it('should update workspace ui settings', async () => { | ||
// Currently in a workspace | ||
jest.spyOn(utils, 'getWorkspaceState').mockReturnValue({ requestWorkspaceId: 'workspace-id' }); | ||
|
||
const { wrappedClient, clientMock } = createWrappedClient(); | ||
|
||
clientMock.update.mockResolvedValue({ | ||
id: 'workspace-id', | ||
references: [], | ||
type: WORKSPACE_TYPE, | ||
attributes: { | ||
uiSettings: { | ||
defaultIndex: 'new-index-id', | ||
}, | ||
}, | ||
}); | ||
|
||
await wrappedClient.update('config', '3.0.0', { defaultIndex: 'new-index-id' }); | ||
|
||
expect(clientMock.update).toHaveBeenCalledWith( | ||
WORKSPACE_TYPE, | ||
'workspace-id', | ||
{ | ||
uiSettings: { defaultIndex: 'new-index-id' }, | ||
}, | ||
{} | ||
); | ||
}); | ||
|
||
it('should update global ui settings', async () => { | ||
// Currently NOT in a workspace | ||
jest.spyOn(utils, 'getWorkspaceState').mockReturnValue({}); | ||
|
||
const { wrappedClient, clientMock } = createWrappedClient(); | ||
|
||
await wrappedClient.update('config', '3.0.0', { defaultIndex: 'new-index-id' }); | ||
|
||
expect(clientMock.update).toHaveBeenCalledWith( | ||
'config', | ||
'3.0.0', | ||
{ | ||
defaultIndex: 'new-index-id', | ||
}, | ||
{} | ||
); | ||
}); | ||
}); |
122 changes: 122 additions & 0 deletions
122
src/plugins/workspace/server/saved_objects/workspace_ui_settings_client_wrapper.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
import { getWorkspaceState } from '../../../../core/server/utils'; | ||
import { | ||
SavedObject, | ||
SavedObjectsBaseOptions, | ||
SavedObjectsClientWrapperFactory, | ||
SavedObjectsUpdateOptions, | ||
SavedObjectsUpdateResponse, | ||
SavedObjectsServiceStart, | ||
WORKSPACE_TYPE, | ||
WorkspaceAttribute, | ||
OpenSearchDashboardsRequest, | ||
SavedObjectsClientContract, | ||
} from '../../../../core/server'; | ||
import { WORKSPACE_UI_SETTINGS_CLIENT_WRAPPER_ID } from '../../common/constants'; | ||
|
||
/** | ||
* This saved object client wrapper offers methods to get and update UI settings considering | ||
* the context of the current workspace. | ||
*/ | ||
export class WorkspaceUiSettingsClientWrapper { | ||
private getScopedClient?: SavedObjectsServiceStart['getScopedClient']; | ||
|
||
/** | ||
* WORKSPACE_TYPE is a hidden type, regular saved object client won't return hidden types. | ||
* To access workspace uiSettings which is defined as a property of workspace object, the | ||
* WORKSPACE_TYPE needs to be excluded. | ||
*/ | ||
private getWorkspaceTypeEnabledClient(request: OpenSearchDashboardsRequest) { | ||
return this.getScopedClient?.(request, { | ||
includedHiddenTypes: [WORKSPACE_TYPE], | ||
excludedWrappers: [WORKSPACE_UI_SETTINGS_CLIENT_WRAPPER_ID], | ||
}) as SavedObjectsClientContract; | ||
} | ||
|
||
public setScopedClient(getScopedClient: SavedObjectsServiceStart['getScopedClient']) { | ||
this.getScopedClient = getScopedClient; | ||
} | ||
|
||
public wrapperFactory: SavedObjectsClientWrapperFactory = (wrapperOptions) => { | ||
const getUiSettingsWithWorkspace = async <T = unknown>( | ||
type: string, | ||
id: string, | ||
options: SavedObjectsBaseOptions = {} | ||
): Promise<SavedObject<T>> => { | ||
const { requestWorkspaceId } = getWorkspaceState(wrapperOptions.request); | ||
|
||
/** | ||
* When getting ui settings within a workspace, it will combine the workspace ui settings with | ||
* the global ui settings and workspace ui settings have higher priority if the same setting | ||
* was defined in both places | ||
*/ | ||
if (type === 'config' && requestWorkspaceId) { | ||
const configObject = await wrapperOptions.client.get<Record<string, any>>( | ||
'config', | ||
id, | ||
options | ||
); | ||
|
||
const workspaceObject = await this.getWorkspaceTypeEnabledClient( | ||
wrapperOptions.request | ||
).get<WorkspaceAttribute>(WORKSPACE_TYPE, requestWorkspaceId); | ||
|
||
configObject.attributes = { | ||
...configObject.attributes, | ||
...workspaceObject.attributes.uiSettings, | ||
}; | ||
|
||
return configObject as SavedObject<T>; | ||
} | ||
|
||
return wrapperOptions.client.get(type, id, options); | ||
}; | ||
|
||
const updateUiSettingsWithWorkspace = async <T = unknown>( | ||
type: string, | ||
id: string, | ||
attributes: Partial<T>, | ||
options: SavedObjectsUpdateOptions = {} | ||
): Promise<SavedObjectsUpdateResponse<T>> => { | ||
const { requestWorkspaceId } = getWorkspaceState(wrapperOptions.request); | ||
|
||
/** | ||
* When updating ui settings within a workspace, it will update the workspace ui settings, | ||
* the global ui settings will remain unchanged. | ||
*/ | ||
if (type === 'config' && requestWorkspaceId) { | ||
const configObject = await wrapperOptions.client.get<Record<string, any>>( | ||
'config', | ||
id, | ||
options | ||
); | ||
const savedObjectsClient = this.getWorkspaceTypeEnabledClient(wrapperOptions.request); | ||
|
||
const workspaceObject = await savedObjectsClient.get<WorkspaceAttribute>( | ||
WORKSPACE_TYPE, | ||
requestWorkspaceId | ||
); | ||
|
||
const workspaceUpdateResult = await savedObjectsClient.update<WorkspaceAttribute>( | ||
WORKSPACE_TYPE, | ||
requestWorkspaceId, | ||
{ | ||
...workspaceObject.attributes, | ||
uiSettings: { ...workspaceObject.attributes.uiSettings, ...attributes }, | ||
}, | ||
options | ||
); | ||
|
||
configObject.attributes = { ...workspaceUpdateResult.attributes.uiSettings }; | ||
|
||
return configObject as SavedObjectsUpdateResponse<T>; | ||
} | ||
return wrapperOptions.client.update(type, id, attributes, options); | ||
}; | ||
|
||
return { | ||
...wrapperOptions.client, | ||
get: getUiSettingsWithWorkspace, | ||
update: updateUiSettingsWithWorkspace, | ||
}; | ||
}; | ||
} |