Skip to content

Commit

Permalink
Conform to Navigation changes from OSD core (opensearch-project#2022)
Browse files Browse the repository at this point in the history
* Adopt to nav changes in core

Signed-off-by: Derek Ho <dxho@amazon.com>

* Lint

Signed-off-by: Derek Ho <dxho@amazon.com>

* feat: enable data source info in new left navigation

Signed-off-by: SuZhou-Joe <suzhou@amazon.com>

* feat: enable data source info in new left navigation

Signed-off-by: SuZhou-Joe <suzhou@amazon.com>

* Address PR feedback

Signed-off-by: Derek Ho <dxho@amazon.com>

* Lint

Signed-off-by: Derek Ho <dxho@amazon.com>

* Fix lint and tests

Signed-off-by: Derek Ho <dxho@amazon.com>

---------

Signed-off-by: Derek Ho <dxho@amazon.com>
Signed-off-by: SuZhou-Joe <suzhou@amazon.com>
Co-authored-by: SuZhou-Joe <suzhou@amazon.com>
  • Loading branch information
derek-ho and SuZhou-Joe authored Jul 19, 2024
1 parent fe847af commit 2f8c6f4
Show file tree
Hide file tree
Showing 12 changed files with 209 additions and 22 deletions.
25 changes: 12 additions & 13 deletions public/apps/configuration/app-router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,11 @@ import { Action, RouteItem, SubAction } from './types';
import { ResourceType } from '../../../common';
import { buildHashUrl, buildUrl } from './utils/url-builder';
import { CrossPageToast } from './cross-page-toast';
import { getDataSourceFromUrl } from '../../utils/datasource-utils';
import { getDataSourceFromUrl, LocalCluster } from '../../utils/datasource-utils';

const LANDING_PAGE_URL = '/getstarted';

const ROUTE_MAP: { [key: string]: RouteItem } = {
export const ROUTE_MAP: { [key: string]: RouteItem } = {
getStarted: {
name: 'Get Started',
href: LANDING_PAGE_URL,
Expand Down Expand Up @@ -145,8 +145,6 @@ export interface DataSourceContextType {
setDataSource: React.Dispatch<React.SetStateAction<DataSourceOption>>;
}

export const LocalCluster = { label: 'Local cluster', id: '' };

export const DataSourceContext = createContext<DataSourceContextType | null>(null);

export function AppRouter(props: AppDependencies) {
Expand All @@ -161,14 +159,15 @@ export function AppRouter(props: AppDependencies) {
<DataSourceContext.Provider value={{ dataSource, setDataSource }}>
<Router>
<EuiPage>
{allNavPanelUrls(multitenancyEnabled).map((route) => (
// Create different routes to update the 'selected' nav item .
<Route key={route} path={route} exact>
<EuiPageSideBar>
<NavPanel items={getRouteList(multitenancyEnabled)} />
</EuiPageSideBar>
</Route>
))}
{!props.coreStart.chrome.navGroup.getNavGroupEnabled() &&
allNavPanelUrls(multitenancyEnabled).map((route) => (
// Create different routes to update the 'selected' nav item .
<Route key={route} path={route} exact>
<EuiPageSideBar>
<NavPanel items={getRouteList(multitenancyEnabled)} />
</EuiPageSideBar>
</Route>
))}
<EuiPageBody>
<Switch>
<Route
Expand Down Expand Up @@ -281,7 +280,7 @@ export function AppRouter(props: AppDependencies) {
}}
/>
)}
<Redirect exact from="/" to={LANDING_PAGE_URL} />
<Redirect exact from="/" to={props.redirect} />
</Switch>
</EuiPageBody>
<CrossPageToast />
Expand Down
2 changes: 2 additions & 0 deletions public/apps/configuration/configuration-app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export function renderApp(
depsStart: SecurityPluginStartDependencies,
params: AppMountParameters,
config: ClientConfigType,
redirect: string,
dataSourceManagement?: DataSourceManagementPluginSetup
) {
const deps = {
Expand All @@ -36,6 +37,7 @@ export function renderApp(
params,
config,
dataSourceManagement,
redirect,
};
ReactDOM.render(
<I18nProvider>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ import {
import { getDashboardsInfo } from '../../../../utils/dashboards-info-utils';
import { LOCAL_CLUSTER_ID } from '../../../../../common';
import { AccessErrorComponent } from '../../access-error-component';
import { LocalCluster } from '../../app-router';
import { LocalCluster } from '../../../../utils/datasource-utils';

export function ConfigureTab1(props: AppDependencies) {
const [isMultiTenancyEnabled, setIsMultiTenancyEnabled] = useState(false);
Expand Down
3 changes: 2 additions & 1 deletion public/apps/configuration/panels/tenant-list/manage_tab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@ import { useContextMenuState } from '../../utils/context-menu';
import { generateResourceName } from '../../utils/resource-utils';
import { DocLinks } from '../../constants';
import { TenantList } from './tenant-list';
import { LocalCluster, getBreadcrumbs } from '../../app-router';
import { getBreadcrumbs } from '../../app-router';
import { LocalCluster } from '../../../../utils/datasource-utils';
import { buildUrl } from '../../utils/url-builder';
import { CrossPageToast } from '../../cross-page-toast';
import { getDashboardsInfo } from '../../../../utils/dashboards-info-utils';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import { AppDependencies } from '../../../types';
import { ExternalLink } from '../../utils/display-utils';
import { DocLinks } from '../../constants';
import { getDashboardsInfo } from '../../../../utils/dashboards-info-utils';
import { LocalCluster } from '../../app-router';
import { LocalCluster } from '../../../../utils/datasource-utils';
import { SecurityPluginTopNavMenu } from '../../top-nav-menu';

interface TenantListProps extends AppDependencies {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ describe('Tenant list', () => {
setBreadcrumbs() {
return 1;
},
navGroup: {
getNavGroupEnabled: jest.fn().mockReturnValue(false),
},
},
};
const config = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -495,7 +495,6 @@ exports[`SecurityPluginTopNavMenu renders DataSourceMenu when dataSource is enab
<Redirect
exact={true}
from="/"
to="/getstarted"
/>
</Switch>
</EuiPageBody>
Expand Down
4 changes: 4 additions & 0 deletions public/apps/configuration/test/app-router.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { getDataSourceFromUrl } from '../../../utils/datasource-utils';

jest.mock('../../../utils/datasource-utils', () => ({
getDataSourceFromUrl: jest.fn(),
LocalCluster: { id: '', label: 'Local cluster' },
}));

describe('SecurityPluginTopNavMenu', () => {
Expand All @@ -30,6 +31,9 @@ describe('SecurityPluginTopNavMenu', () => {
notifications: jest.fn(),
chrome: {
setBreadcrumbs: jest.fn(),
navGroup: {
getNavGroupEnabled: jest.fn().mockReturnValue(false),
},
},
};

Expand Down
6 changes: 5 additions & 1 deletion public/apps/configuration/top-nav-menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@ import React from 'react';
import { DataSourceSelectableConfig } from 'src/plugins/data_source_management/public';
import { DataSourceOption } from 'src/plugins/data_source_management/public/components/data_source_menu/types';
import { AppDependencies } from '../types';
import { setDataSourceInUrl } from '../../utils/datasource-utils';
import {
setDataSourceInUrl,
setDataSource as setDataSourceInSubscription,
} from '../../utils/datasource-utils';

export interface TopNavMenuProps extends AppDependencies {
dataSourcePickerReadOnly: boolean;
Expand All @@ -44,6 +47,7 @@ export const SecurityPluginTopNavMenu = React.memo(
const wrapSetDataSourceWithUpdateUrl = (dataSources: DataSourceOption[]) => {
setDataSourceInUrl(dataSources[0]);
setDataSource(dataSources[0]);
setDataSourceInSubscription(dataSources[0]);
};

return dataSourceEnabled ? (
Expand Down
1 change: 1 addition & 0 deletions public/apps/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export interface AppDependencies {
config: ClientConfigType;
dashboardsInfo: DashboardsInfo;
dataSourceManagement: DataSourceManagementPluginSetup;
redirect?: string;
}

export interface BreadcrumbsPageDependencies extends AppDependencies {
Expand Down
163 changes: 161 additions & 2 deletions public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,18 @@ import { BehaviorSubject } from 'rxjs';
import { SavedObjectsManagementColumn } from 'src/plugins/saved_objects_management/public';
import { i18n } from '@osd/i18n';
import {
AppCategory,
AppMountParameters,
AppNavLinkStatus,
AppStatus,
AppUpdater,
CoreSetup,
CoreStart,
DEFAULT_APP_CATEGORIES,
DEFAULT_NAV_GROUPS,
Plugin,
PluginInitializerContext,
WorkspaceAvailability,
} from '../../../src/core/public';
import { APP_ID_LOGIN, CUSTOM_ERROR_PAGE_URI, LOGIN_PAGE_URI, PLUGIN_NAME } from '../common';
import { APP_ID_CUSTOMERROR } from '../common';
Expand All @@ -50,6 +54,11 @@ import { addTenantToShareURL } from './services/shared-link';
import { interceptError } from './utils/logout-utils';
import { tenantColumn, getNamespacesToRegister } from './apps/configuration/utils/tenant-utils';
import { getDashboardsInfoSafe } from './utils/dashboards-info-utils';
import {
dataSource$,
getDataSourceEnabledUrl,
getDataSourceFromUrl,
} from './utils/datasource-utils';

async function hasApiPermission(core: CoreSetup): Promise<boolean | undefined> {
try {
Expand All @@ -68,8 +77,13 @@ const APP_ID_DASHBOARDS = 'dashboards';
// OpenSearchDashboards app is for legacy url migration
const APP_ID_OPENSEARCH_DASHBOARDS = 'kibana';
const APP_LIST_FOR_READONLY_ROLE = [APP_ID_HOME, APP_ID_DASHBOARDS, APP_ID_OPENSEARCH_DASHBOARDS];
const GLOBAL_TENANT_RENDERING_TEXT = 'Global';
const PRIVATE_TENANT_RENDERING_TEXT = 'Private';

const dataAccessUsersCategory: AppCategory & { group?: AppCategory } = {
id: 'dataAccessAndUsers',
label: 'Data Access and Users',
order: 9000,
euiIconType: 'managementApp',
};

export class SecurityPlugin
implements
Expand All @@ -82,6 +96,15 @@ export class SecurityPlugin
// @ts-ignore : initializerContext not used
constructor(private readonly initializerContext: PluginInitializerContext) {}

private updateDefaultRouteOfSecurityApplications: AppUpdater = () => {
const url = getDataSourceEnabledUrl(getDataSourceFromUrl());
return {
defaultPath: `?${url.searchParams.toString()}`,
};
};

private appStateUpdater = new BehaviorSubject(this.updateDefaultRouteOfSecurityApplications);

public async setup(
core: CoreSetup,
deps: SecurityPluginSetupDependencies
Expand All @@ -97,11 +120,36 @@ export class SecurityPlugin
(config.readonly_mode?.roles || DEFAULT_READONLY_ROLES).includes(role)
);

const mountWrapper = async (params: AppMountParameters, redirect: string) => {
const { renderApp } = await import('./apps/configuration/configuration-app');
const [coreStart, depsStart] = await core.getStartServices();

// merge OpenSearchDashboards yml configuration
includeClusterPermissions(config.clusterPermissions.include);
includeIndexPermissions(config.indexPermissions.include);

excludeFromDisabledTransportCategories(config.disabledTransportCategories.exclude);
excludeFromDisabledRestCategories(config.disabledRestCategories.exclude);

return renderApp(
coreStart,
depsStart as SecurityPluginStartDependencies,
params,
config,
redirect,
deps.dataSourceManagement
);
};

if (mdsEnabled || apiPermission) {
core.application.register({
id: PLUGIN_NAME,
title: 'Security',
order: 9050,
workspaceAvailability: WorkspaceAvailability.outsideWorkspace,
navLinkStatus: core.chrome.navGroup.getNavGroupEnabled()
? AppNavLinkStatus.hidden
: AppNavLinkStatus.visible,
mount: async (params: AppMountParameters) => {
const { renderApp } = await import('./apps/configuration/configuration-app');
const [coreStart, depsStart] = await core.getStartServices();
Expand All @@ -118,12 +166,117 @@ export class SecurityPlugin
depsStart as SecurityPluginStartDependencies,
params,
config,
'/getstarted',
deps.dataSourceManagement
);
},
category: DEFAULT_APP_CATEGORIES.management,
});

if (core.chrome.navGroup.getNavGroupEnabled()) {
core.application.register({
id: `security-dashboards-plugin_getstarted`,
title: 'Get Started',
order: 8040,
workspaceAvailability: WorkspaceAvailability.outsideWorkspace,
updater$: this.appStateUpdater,
mount: async (params: AppMountParameters) => {
return mountWrapper(params, '/getstarted');
},
});
core.application.register({
id: `security-dashboards-plugin_auth`,
title: 'Authentication',
order: 8040,
workspaceAvailability: WorkspaceAvailability.outsideWorkspace,
updater$: this.appStateUpdater,
mount: async (params: AppMountParameters) => {
return mountWrapper(params, '/auth');
},
});
core.application.register({
id: `security-dashboards-plugin_roles`,
title: 'Roles',
order: 8040,
workspaceAvailability: WorkspaceAvailability.outsideWorkspace,
updater$: this.appStateUpdater,
mount: async (params: AppMountParameters) => {
return mountWrapper(params, '/roles');
},
});
core.application.register({
id: `security-dashboards-plugin_users`,
title: 'Internal users',
order: 8040,
workspaceAvailability: WorkspaceAvailability.outsideWorkspace,
updater$: this.appStateUpdater,
mount: async (params: AppMountParameters) => {
return mountWrapper(params, '/users');
},
});
core.application.register({
id: `security-dashboards-plugin_permissions`,
title: 'Permissions',
order: 8040,
workspaceAvailability: WorkspaceAvailability.outsideWorkspace,
updater$: this.appStateUpdater,
mount: async (params: AppMountParameters) => {
return mountWrapper(params, '/permissions');
},
});
core.application.register({
id: `security-dashboards-plugin_tenants`,
title: 'Tenants',
order: 8040,
workspaceAvailability: WorkspaceAvailability.outsideWorkspace,
updater$: this.appStateUpdater,
mount: async (params: AppMountParameters) => {
return mountWrapper(params, '/tenants');
},
});
core.application.register({
id: `security-dashboards-plugin_auditlog`,
title: 'Audit logs',
order: 8040,
workspaceAvailability: WorkspaceAvailability.outsideWorkspace,
updater$: this.appStateUpdater,
mount: async (params: AppMountParameters) => {
return mountWrapper(params, '/auditLogging');
},
});
}

core.chrome.navGroup.addNavLinksToGroup(DEFAULT_NAV_GROUPS.dataAdministration, [
{
id: `security-dashboards-plugin_getstarted`,
category: dataAccessUsersCategory,
},
{
id: `security-dashboards-plugin_auth`,
category: dataAccessUsersCategory,
},
{
id: `security-dashboards-plugin_roles`,
category: dataAccessUsersCategory,
},
{
id: `security-dashboards-plugin_users`,
category: dataAccessUsersCategory,
},
{
id: `security-dashboards-plugin_permissions`,
category: dataAccessUsersCategory,
},
{
id: `security-dashboards-plugin_tenants`,
category: dataAccessUsersCategory,
},
{
id: `security-dashboards-plugin_auditlog`,
category: dataAccessUsersCategory,
},
]);

if (deps.managementOverview) {
deps.managementOverview.register({
id: PLUGIN_NAME,
Expand All @@ -135,6 +288,12 @@ export class SecurityPlugin
}),
});
}

dataSource$.subscribe((dataSourceOption) => {
if (dataSourceOption) {
this.appStateUpdater.next(this.updateDefaultRouteOfSecurityApplications);
}
});
}

core.application.register({
Expand Down
Loading

0 comments on commit 2f8c6f4

Please sign in to comment.