From d6c9b10cdd0a551990f217a970bed6aaf9cc0b1f Mon Sep 17 00:00:00 2001 From: yubonluo Date: Tue, 25 Jun 2024 17:16:37 +0800 Subject: [PATCH 1/7] Capabilities service add dashboard admin flag Signed-off-by: yubonluo --- src/plugins/workspace/server/plugin.test.ts | 8 ++++++++ src/plugins/workspace/server/plugin.ts | 6 ++++++ 2 files changed, 14 insertions(+) diff --git a/src/plugins/workspace/server/plugin.test.ts b/src/plugins/workspace/server/plugin.test.ts index 0b943cf47252..569514d435b9 100644 --- a/src/plugins/workspace/server/plugin.test.ts +++ b/src/plugins/workspace/server/plugin.test.ts @@ -12,17 +12,25 @@ import * as utilsExports from './utils'; describe('Workspace server plugin', () => { it('#setup', async () => { let value; + const capabilities = {} as any; const setupMock = coreMock.createSetup(); const initializerContextConfigMock = coreMock.createPluginInitializerContext({ enabled: true, }); + const request = httpServerMock.createOpenSearchDashboardsRequest(); + setupMock.capabilities.registerProvider.mockImplementationOnce((fn) => (value = fn())); + setupMock.capabilities.registerSwitcher.mockImplementationOnce((fn) => { + return fn(request, capabilities); + }); + const workspacePlugin = new WorkspacePlugin(initializerContextConfigMock); await workspacePlugin.setup(setupMock); expect(value).toMatchInlineSnapshot(` Object { "workspaces": Object { "enabled": true, + "isDashboardAdmin": true, "permissionEnabled": true, }, } diff --git a/src/plugins/workspace/server/plugin.ts b/src/plugins/workspace/server/plugin.ts index 2ec8447ad817..e31078fb31b0 100644 --- a/src/plugins/workspace/server/plugin.ts +++ b/src/plugins/workspace/server/plugin.ts @@ -30,6 +30,7 @@ import { WorkspaceSavedObjectsClientWrapper } from './saved_objects'; import { cleanWorkspaceId, getWorkspaceIdFromUrl, + getWorkspaceState, updateWorkspaceState, } from '../../../core/server/utils'; import { WorkspaceConflictSavedObjectsClientWrapper } from './saved_objects/saved_objects_wrapper_for_check_workspace_conflict'; @@ -156,8 +157,13 @@ export class WorkspacePlugin implements Plugin { + const isDashboardAdmin = getWorkspaceState(request).isDashboardAdmin !== false; + return { workspaces: { isDashboardAdmin } }; + }); return { client: this.client, From 72a761555569823c274babfb2813af20eebb1576 Mon Sep 17 00:00:00 2001 From: yubonluo Date: Tue, 25 Jun 2024 17:16:37 +0800 Subject: [PATCH 2/7] Capabilities service add dashboard admin flag Signed-off-by: yubonluo --- src/plugins/workspace/server/plugin.test.ts | 10 ++++++++++ src/plugins/workspace/server/plugin.ts | 6 ++++++ 2 files changed, 16 insertions(+) diff --git a/src/plugins/workspace/server/plugin.test.ts b/src/plugins/workspace/server/plugin.test.ts index 0b943cf47252..444cc941c774 100644 --- a/src/plugins/workspace/server/plugin.test.ts +++ b/src/plugins/workspace/server/plugin.test.ts @@ -12,15 +12,25 @@ import * as utilsExports from './utils'; describe('Workspace server plugin', () => { it('#setup', async () => { let value; + const capabilities = {} as any; const setupMock = coreMock.createSetup(); const initializerContextConfigMock = coreMock.createPluginInitializerContext({ enabled: true, }); + const request = httpServerMock.createOpenSearchDashboardsRequest(); + setupMock.capabilities.registerProvider.mockImplementationOnce((fn) => (value = fn())); + setupMock.capabilities.registerSwitcher.mockImplementationOnce((fn) => { + return fn(request, capabilities); + }); + const workspacePlugin = new WorkspacePlugin(initializerContextConfigMock); await workspacePlugin.setup(setupMock); expect(value).toMatchInlineSnapshot(` Object { + "opensearchDashboards": Object { + "isDashboardAdmin": true, + }, "workspaces": Object { "enabled": true, "permissionEnabled": true, diff --git a/src/plugins/workspace/server/plugin.ts b/src/plugins/workspace/server/plugin.ts index 2ec8447ad817..03ba20530a61 100644 --- a/src/plugins/workspace/server/plugin.ts +++ b/src/plugins/workspace/server/plugin.ts @@ -30,6 +30,7 @@ import { WorkspaceSavedObjectsClientWrapper } from './saved_objects'; import { cleanWorkspaceId, getWorkspaceIdFromUrl, + getWorkspaceState, updateWorkspaceState, } from '../../../core/server/utils'; import { WorkspaceConflictSavedObjectsClientWrapper } from './saved_objects/saved_objects_wrapper_for_check_workspace_conflict'; @@ -157,7 +158,12 @@ export class WorkspacePlugin implements Plugin { + const isDashboardAdmin = getWorkspaceState(request).isDashboardAdmin !== false; + return { opensearchDashboards: { isDashboardAdmin } }; + }); return { client: this.client, From ef2dbf6da8d166d0f923de3cf6abf854cc3fbdb6 Mon Sep 17 00:00:00 2001 From: "opensearch-changeset-bot[bot]" <154024398+opensearch-changeset-bot[bot]@users.noreply.github.com> Date: Tue, 25 Jun 2024 09:35:17 +0000 Subject: [PATCH 3/7] Changeset file for PR #7103 created/updated --- changelogs/fragments/7103.yml | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 changelogs/fragments/7103.yml diff --git a/changelogs/fragments/7103.yml b/changelogs/fragments/7103.yml new file mode 100644 index 000000000000..f016a8c9962b --- /dev/null +++ b/changelogs/fragments/7103.yml @@ -0,0 +1,2 @@ +feat: +- [Workspace] Capabilities service add dashboard admin flag ([#7103](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/7103)) \ No newline at end of file From 8ba92dd941617257724b1369b2807c2c8ea91793 Mon Sep 17 00:00:00 2001 From: yubonluo Date: Tue, 25 Jun 2024 22:49:51 +0800 Subject: [PATCH 4/7] optimize the code Signed-off-by: yubonluo --- src/plugins/workspace/server/plugin.test.ts | 19 ++++++++++++++++++- src/plugins/workspace/server/plugin.ts | 1 + 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/plugins/workspace/server/plugin.test.ts b/src/plugins/workspace/server/plugin.test.ts index 444cc941c774..a7fd848cc039 100644 --- a/src/plugins/workspace/server/plugin.test.ts +++ b/src/plugins/workspace/server/plugin.test.ts @@ -6,7 +6,7 @@ import { OnPostAuthHandler, OnPreRoutingHandler } from 'src/core/server'; import { coreMock, httpServerMock } from '../../../core/server/mocks'; import { WorkspacePlugin } from './plugin'; -import { getWorkspaceState } from '../../../core/server/utils'; +import { getWorkspaceState, updateWorkspaceState } from '../../../core/server/utils'; import * as utilsExports from './utils'; describe('Workspace server plugin', () => { @@ -38,6 +38,23 @@ describe('Workspace server plugin', () => { } `); expect(setupMock.savedObjects.addClientWrapper).toBeCalledTimes(4); + + let registerSwitcher; + let result; + updateWorkspaceState(request, { isDashboardAdmin: false }); + registerSwitcher = setupMock.capabilities.registerSwitcher.mock.calls[0][0]; + result = registerSwitcher(request, capabilities); + expect(result).toEqual({ opensearchDashboards: { isDashboardAdmin: false } }); + + updateWorkspaceState(request, { isDashboardAdmin: true }); + registerSwitcher = setupMock.capabilities.registerSwitcher.mock.calls[0][0]; + result = registerSwitcher(request, capabilities); + expect(result).toEqual({ opensearchDashboards: { isDashboardAdmin: true } }); + + updateWorkspaceState(request, {}); + registerSwitcher = setupMock.capabilities.registerSwitcher.mock.calls[0][0]; + result = registerSwitcher(request, capabilities); + expect(result).toEqual({ opensearchDashboards: { isDashboardAdmin: true } }); }); it('#proxyWorkspaceTrafficToRealHandler', async () => { diff --git a/src/plugins/workspace/server/plugin.ts b/src/plugins/workspace/server/plugin.ts index 03ba20530a61..b8ec37a0a2dd 100644 --- a/src/plugins/workspace/server/plugin.ts +++ b/src/plugins/workspace/server/plugin.ts @@ -160,6 +160,7 @@ export class WorkspacePlugin implements Plugin { const isDashboardAdmin = getWorkspaceState(request).isDashboardAdmin !== false; return { opensearchDashboards: { isDashboardAdmin } }; From 3f08191a48ee0df4fbec5863c096e876a55f9907 Mon Sep 17 00:00:00 2001 From: yubonluo Date: Thu, 27 Jun 2024 09:50:15 +0800 Subject: [PATCH 5/7] optimize the code Signed-off-by: yubonluo --- src/plugins/workspace/server/plugin.test.ts | 8 ++++---- src/plugins/workspace/server/plugin.ts | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/plugins/workspace/server/plugin.test.ts b/src/plugins/workspace/server/plugin.test.ts index a7fd848cc039..e67ce5df4638 100644 --- a/src/plugins/workspace/server/plugin.test.ts +++ b/src/plugins/workspace/server/plugin.test.ts @@ -28,7 +28,7 @@ describe('Workspace server plugin', () => { await workspacePlugin.setup(setupMock); expect(value).toMatchInlineSnapshot(` Object { - "opensearchDashboards": Object { + "dashboards": Object { "isDashboardAdmin": true, }, "workspaces": Object { @@ -44,17 +44,17 @@ describe('Workspace server plugin', () => { updateWorkspaceState(request, { isDashboardAdmin: false }); registerSwitcher = setupMock.capabilities.registerSwitcher.mock.calls[0][0]; result = registerSwitcher(request, capabilities); - expect(result).toEqual({ opensearchDashboards: { isDashboardAdmin: false } }); + expect(result).toEqual({ dashboards: { isDashboardAdmin: false } }); updateWorkspaceState(request, { isDashboardAdmin: true }); registerSwitcher = setupMock.capabilities.registerSwitcher.mock.calls[0][0]; result = registerSwitcher(request, capabilities); - expect(result).toEqual({ opensearchDashboards: { isDashboardAdmin: true } }); + expect(result).toEqual({ dashboards: { isDashboardAdmin: true } }); updateWorkspaceState(request, {}); registerSwitcher = setupMock.capabilities.registerSwitcher.mock.calls[0][0]; result = registerSwitcher(request, capabilities); - expect(result).toEqual({ opensearchDashboards: { isDashboardAdmin: true } }); + expect(result).toEqual({ dashboards: { isDashboardAdmin: true } }); }); it('#proxyWorkspaceTrafficToRealHandler', async () => { diff --git a/src/plugins/workspace/server/plugin.ts b/src/plugins/workspace/server/plugin.ts index b8ec37a0a2dd..2f2d18456932 100644 --- a/src/plugins/workspace/server/plugin.ts +++ b/src/plugins/workspace/server/plugin.ts @@ -158,12 +158,12 @@ export class WorkspacePlugin implements Plugin { - const isDashboardAdmin = getWorkspaceState(request).isDashboardAdmin !== false; - return { opensearchDashboards: { isDashboardAdmin } }; + const isDashboardAdmin = !!getWorkspaceState(request).isDashboardAdmin; + return { dashboards: { isDashboardAdmin } }; }); return { From c91bc92c4c073679c7be8380cb31bbd8ff2fa503 Mon Sep 17 00:00:00 2001 From: yubonluo Date: Tue, 2 Jul 2024 12:54:45 +0800 Subject: [PATCH 6/7] if groups/users are not configured or [], login defaults to OSD Admin Signed-off-by: yubonluo --- src/plugins/workspace/server/utils.test.ts | 2 +- src/plugins/workspace/server/utils.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/plugins/workspace/server/utils.test.ts b/src/plugins/workspace/server/utils.test.ts index 15e6783c2cab..095208dca8b9 100644 --- a/src/plugins/workspace/server/utils.test.ts +++ b/src/plugins/workspace/server/utils.test.ts @@ -128,7 +128,7 @@ describe('workspace utils', () => { const configGroups: string[] = []; const configUsers: string[] = []; updateDashboardAdminStateForRequest(mockRequest, groups, users, configGroups, configUsers); - expect(getWorkspaceState(mockRequest)?.isDashboardAdmin).toBe(false); + expect(getWorkspaceState(mockRequest)?.isDashboardAdmin).toBe(true); }); it('should get correct admin config when admin config is enabled ', async () => { diff --git a/src/plugins/workspace/server/utils.ts b/src/plugins/workspace/server/utils.ts index 9037038f16af..d98352050a31 100644 --- a/src/plugins/workspace/server/utils.ts +++ b/src/plugins/workspace/server/utils.ts @@ -67,9 +67,9 @@ export const updateDashboardAdminStateForRequest = ( updateWorkspaceState(request, { isDashboardAdmin: true }); return; } - + // If groups/users are not configured or [], login defaults to OSD Admin if (!configGroups.length && !configUsers.length) { - updateWorkspaceState(request, { isDashboardAdmin: false }); + updateWorkspaceState(request, { isDashboardAdmin: true }); return; } const groupMatchAny = groups.some((group) => configGroups.includes(group)); From ca0957e8ad9c43889c1ca9bbd21c414ea6b6902f Mon Sep 17 00:00:00 2001 From: yubonluo Date: Tue, 2 Jul 2024 13:45:16 +0800 Subject: [PATCH 7/7] optimize the code Signed-off-by: yubonluo --- src/plugins/workspace/server/plugin.test.ts | 4 ++-- src/plugins/workspace/server/plugin.ts | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/plugins/workspace/server/plugin.test.ts b/src/plugins/workspace/server/plugin.test.ts index e67ce5df4638..df9c9edac5ed 100644 --- a/src/plugins/workspace/server/plugin.test.ts +++ b/src/plugins/workspace/server/plugin.test.ts @@ -29,7 +29,7 @@ describe('Workspace server plugin', () => { expect(value).toMatchInlineSnapshot(` Object { "dashboards": Object { - "isDashboardAdmin": true, + "isDashboardAdmin": false, }, "workspaces": Object { "enabled": true, @@ -51,7 +51,7 @@ describe('Workspace server plugin', () => { result = registerSwitcher(request, capabilities); expect(result).toEqual({ dashboards: { isDashboardAdmin: true } }); - updateWorkspaceState(request, {}); + updateWorkspaceState(request, { isDashboardAdmin: undefined }); registerSwitcher = setupMock.capabilities.registerSwitcher.mock.calls[0][0]; result = registerSwitcher(request, capabilities); expect(result).toEqual({ dashboards: { isDashboardAdmin: true } }); diff --git a/src/plugins/workspace/server/plugin.ts b/src/plugins/workspace/server/plugin.ts index 2f2d18456932..1479da984580 100644 --- a/src/plugins/workspace/server/plugin.ts +++ b/src/plugins/workspace/server/plugin.ts @@ -158,11 +158,12 @@ export class WorkspacePlugin implements Plugin { - const isDashboardAdmin = !!getWorkspaceState(request).isDashboardAdmin; + // If the value is undefined/true, the user is dashboard admin. + const isDashboardAdmin = getWorkspaceState(request).isDashboardAdmin !== false; return { dashboards: { isDashboardAdmin } }; });