Skip to content

Commit 15a19fa

Browse files
[Workspace] fix:Prevent user from visiting dashboards / visualizations when out of a workspace (#9024)
* add workspaceAvailability Signed-off-by: Qxisylolo <[email protected]> * Changeset file for PR #9024 created/updated * add tests Signed-off-by: Qxisylolo <[email protected]> * update test Signed-off-by: Qxisylolo <[email protected]> * fix test use piple Signed-off-by: Qxisylolo <[email protected]> * fix test new Signed-off-by: Qxisylolo <[email protected]> --------- Signed-off-by: Qxisylolo <[email protected]> Co-authored-by: opensearch-changeset-bot[bot] <154024398+opensearch-changeset-bot[bot]@users.noreply.github.com>
1 parent 55f203a commit 15a19fa

File tree

5 files changed

+45
-5
lines changed

5 files changed

+45
-5
lines changed

changelogs/fragments/9024.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
fix:
2+
- Prevent user from visiting dashboards / visualizations when out of a workspace ([#9024](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/9024))

src/plugins/dashboard/public/plugin.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ import { filter, map } from 'rxjs/operators';
3434
import { i18n } from '@osd/i18n';
3535
import { FormattedMessage } from '@osd/i18n/react';
3636

37+
import { UrlForwardingSetup, UrlForwardingStart } from 'src/plugins/url_forwarding/public';
38+
import { isEmpty } from 'lodash';
39+
import { createHashHistory } from 'history';
3740
import {
3841
App,
3942
AppMountParameters,
@@ -43,11 +46,9 @@ import {
4346
Plugin,
4447
PluginInitializerContext,
4548
SavedObjectsClientContract,
49+
WorkspaceAvailability,
4650
ScopedHistory,
47-
} from 'src/core/public';
48-
import { UrlForwardingSetup, UrlForwardingStart } from 'src/plugins/url_forwarding/public';
49-
import { isEmpty } from 'lodash';
50-
import { createHashHistory } from 'history';
51+
} from '../../../../src/core/public';
5152
import { UsageCollectionSetup } from '../../usage_collection/public';
5253
import {
5354
CONTEXT_MENU_TRIGGER,
@@ -367,6 +368,7 @@ export class DashboardPlugin
367368
id: DashboardConstants.DASHBOARDS_ID,
368369
title: 'Dashboards',
369370
order: 2500,
371+
workspaceAvailability: WorkspaceAvailability.insideWorkspace,
370372
euiIconType: 'inputOutput',
371373
defaultPath: `#${DashboardConstants.LANDING_PAGE_PATH}`,
372374
updater$: this.appStateUpdater,

src/plugins/visualize/public/plugin.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ import {
4242
ScopedHistory,
4343
} from 'opensearch-dashboards/public';
4444

45+
import { WorkspaceAvailability } from '../../../../src/core/public';
4546
import {
4647
Storage,
4748
createOsdUrlTracker,
@@ -158,6 +159,7 @@ export class VisualizePlugin
158159
title: 'Visualize',
159160
order: 8000,
160161
euiIconType: 'inputOutput',
162+
workspaceAvailability: WorkspaceAvailability.insideWorkspace,
161163
defaultPath: '#/',
162164
category: DEFAULT_APP_CATEGORIES.opensearchDashboards,
163165
updater$: this.appStateUpdater.asObservable(),

src/plugins/workspace/public/plugin.test.ts

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,14 @@
66
import { BehaviorSubject, Observable, Subscriber } from 'rxjs';
77
import { waitFor } from '@testing-library/dom';
88
import { first } from 'rxjs/operators';
9-
109
import { applicationServiceMock, chromeServiceMock, coreMock } from '../../../core/public/mocks';
1110
import {
1211
ChromeBreadcrumb,
1312
NavGroupStatus,
1413
DEFAULT_NAV_GROUPS,
1514
AppNavLinkStatus,
15+
WorkspaceAvailability,
16+
AppStatus,
1617
} from '../../../core/public';
1718
import { WORKSPACE_FATAL_ERROR_APP_ID, WORKSPACE_DETAIL_APP_ID } from '../common/constants';
1819
import { savedObjectsManagementPluginMock } from '../../saved_objects_management/public/mocks';
@@ -509,6 +510,33 @@ describe('Workspace plugin', () => {
509510
});
510511
});
511512

513+
it('#start should not be able to access app of which workspaceAvailability is set to insideWorkspace when out of workspace', async () => {
514+
const workspacePlugin = new WorkspacePlugin();
515+
const setupMock = getSetupMock();
516+
const coreStart = coreMock.createStart();
517+
await workspacePlugin.setup(setupMock, {});
518+
coreStart.workspaces.currentWorkspace$.next(null);
519+
520+
coreStart.application.capabilities = {
521+
...coreStart.application.capabilities,
522+
dashboard: {
523+
isDashboardAdmin: false,
524+
},
525+
};
526+
527+
workspacePlugin.start(coreStart, getMockDependencies());
528+
529+
const mockApp = {
530+
id: 'dashboards',
531+
workspaceAvailability: WorkspaceAvailability.insideWorkspace,
532+
};
533+
534+
const appUpdater$ = setupMock.application.registerAppUpdater.mock.calls[0][0];
535+
536+
const appState = await appUpdater$.pipe(first()).toPromise();
537+
expect(appState(mockApp)).toEqual({ status: AppStatus.inaccessible });
538+
});
539+
512540
it('#stop should call unregisterNavGroupUpdater', async () => {
513541
const workspacePlugin = new WorkspacePlugin();
514542
const setupMock = getSetupMock();

src/plugins/workspace/public/plugin.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,12 @@ export class WorkspacePlugin
162162
*/
163163
return { status: AppStatus.inaccessible };
164164
});
165+
} else {
166+
this.appUpdater$.next((app) => {
167+
if (app.workspaceAvailability === WorkspaceAvailability.insideWorkspace) {
168+
return { status: AppStatus.inaccessible };
169+
}
170+
});
165171
}
166172
});
167173

0 commit comments

Comments
 (0)