/* * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 */ import React, { Component } from 'react'; import { Switch, Route, Redirect, RouteComponentProps } from 'react-router-dom'; import { EuiSideNav, EuiPage, EuiPageBody, EuiPageSideBar, EuiSideNavItemType, EuiTitle, EuiSpacer, EuiGlobalToastList, EuiFlexGroup, EuiFlexItem, } from '@elastic/eui'; import { Toast } from '@opensearch-project/oui/src/eui_components/toast/global_toast_list'; import { CoreStart } from 'opensearch-dashboards/public'; import { ServicesConsumer } from '../../services'; import { BrowserServices } from '../../models/interfaces'; import { DEFAULT_DATE_RANGE, ROUTES } from '../../utils/constants'; import { CoreServicesConsumer } from '../../components/core_services'; import Findings from '../Findings'; import Detectors from '../Detectors'; import Overview from '../Overview'; import CreateDetector from '../CreateDetector/containers/CreateDetector'; import Alerts from '../Alerts'; import { DetectorDetails } from '../Detectors/containers/Detector/DetectorDetails'; import { UpdateDetectorBasicDetails } from '../Detectors/components/UpdateBasicDetails/UpdateBasicDetails'; import { UpdateDetectorRules } from '../Detectors/components/UpdateRules/UpdateRules'; import UpdateFieldMappings from '../Detectors/components/UpdateFieldMappings/UpdateFieldMappings'; import UpdateAlertConditions from '../Detectors/components/UpdateAlertConditions/UpdateAlertConditions'; import { Rules } from '../Rules/containers/Rules/Rules'; import { CreateRule } from '../Rules/containers/CreateRule/CreateRule'; import { EditRule } from '../Rules/containers/EditRule/EditRule'; import { ImportRule } from '../Rules/containers/ImportRule/ImportRule'; import { DuplicateRule } from '../Rules/containers/DuplicateRule/DuplicateRule'; import { DateTimeFilter } from '../Overview/models/interfaces'; import Callout, { ICalloutProps } from './components/Callout'; import { DataStore } from '../../store/DataStore'; import { CreateCorrelationRule } from '../Correlations/containers/CreateCorrelationRule'; import { CorrelationRules } from '../Correlations/containers/CorrelationRules'; import { Correlations } from '../Correlations/containers/CorrelationsContainer'; import FindingDetailsFlyout, { FindingDetailsFlyoutBaseProps, } from '../Findings/components/FindingDetailsFlyout'; import { LogTypes } from '../LogTypes/containers/LogTypes'; import { LogType } from '../LogTypes/containers/LogType'; import { CreateLogType } from '../LogTypes/containers/CreateLogType'; enum Navigation { SecurityAnalytics = 'Security Analytics', Findings = 'Findings', Detectors = 'Detectors', Rules = 'Detection rules', Overview = 'Overview', Alerts = 'Alerts', Correlations = 'Correlations', CorrelationRules = 'Correlation rules', LogTypes = 'Log types', } /** * Add here the ROUTES for pages on which the EuiPageSideBar should NOT be displayed. */ const HIDDEN_NAV_ROUTES: string[] = [ ROUTES.DETECTORS_CREATE, ROUTES.RULES_CREATE, ROUTES.RULES_EDIT, ROUTES.RULES_DUPLICATE, ROUTES.RULES_IMPORT, ROUTES.EDIT_DETECTOR_DETAILS, ROUTES.EDIT_DETECTOR_RULES, ROUTES.EDIT_FIELD_MAPPINGS, ROUTES.EDIT_DETECTOR_ALERT_TRIGGERS, `${ROUTES.LOG_TYPES}/.+`, ROUTES.LOG_TYPES_CREATE, ]; interface MainProps extends RouteComponentProps { landingPage: string; } interface MainState { getStartedDismissedOnce: boolean; selectedNavItemId: number; dateTimeFilter: DateTimeFilter; callout?: ICalloutProps; toasts?: Toast[]; findingFlyout: FindingDetailsFlyoutBaseProps | null; } const navItemIndexByRoute: { [route: string]: number } = { [ROUTES.OVERVIEW]: 1, [ROUTES.FINDINGS]: 2, [ROUTES.ALERTS]: 3, [ROUTES.DETECTORS]: 4, [ROUTES.RULES]: 5, }; export default class Main extends Component { constructor(props: MainProps) { super(props); this.state = { getStartedDismissedOnce: false, selectedNavItemId: 1, dateTimeFilter: { startTime: DEFAULT_DATE_RANGE.start, endTime: DEFAULT_DATE_RANGE.end, }, findingFlyout: null, }; DataStore.detectors.setHandlers(this.showCallout, this.showToast); DataStore.findings.setFlyoutCallback(this.showFindingFlyout); } showFindingFlyout = (findingFlyout: FindingDetailsFlyoutBaseProps | null) => { this.setState({ findingFlyout, }); }; showCallout = (callout?: ICalloutProps) => { this.setState({ callout, }); }; showToast = (toasts?: any[]) => { this.setState({ toasts, }); }; componentDidMount(): void { this.updateSelectedNavItem(); } componentDidUpdate( prevProps: Readonly, prevState: Readonly, snapshot?: any ): void { if (this.props.location.pathname === prevProps.location.pathname) { return; } this.updateSelectedNavItem(); } setDateTimeFilter = (dateTimeFilter: DateTimeFilter) => { this.setState({ dateTimeFilter: dateTimeFilter, }); }; /** * Returns current component route index * @return {number} */ getCurrentRouteIndex = (): number | undefined => { let index: number | undefined; const pathname = this.props.location.pathname; for (const [route, routeIndex] of Object.entries(navItemIndexByRoute)) { if (pathname.match(new RegExp(`^${route}`))) { index = routeIndex; break; } } return index; }; updateSelectedNavItem() { const routeIndex = this.getCurrentRouteIndex(); if (routeIndex) { this.setState({ selectedNavItemId: routeIndex }); } if (this.props.location.pathname.includes('detector-details')) { this.setState({ selectedNavItemId: navItemIndexByRoute[ROUTES.DETECTORS] }); } } setGetStartedDismissedOnce = () => { this.setState({ getStartedDismissedOnce: true }); }; render() { const { landingPage, location: { pathname }, history, } = this.props; const { callout, findingFlyout, selectedNavItemId: selectedNavItemIndex } = this.state; const sideNav: EuiSideNavItemType<{ style: any }>[] = [ { name: Navigation.SecurityAnalytics, id: 0, renderItem: () => { return ( <>

{Navigation.SecurityAnalytics}

); }, items: [ { name: Navigation.Overview, id: 1, onClick: () => { this.setState({ selectedNavItemId: 1 }); history.push(ROUTES.OVERVIEW); }, isSelected: selectedNavItemIndex === 1, }, { name: Navigation.Findings, id: 2, onClick: () => { this.setState({ selectedNavItemId: 2 }); history.push(ROUTES.FINDINGS); }, isSelected: selectedNavItemIndex === 2, }, { name: Navigation.Alerts, id: 3, onClick: () => { this.setState({ selectedNavItemId: 3 }); history.push(ROUTES.ALERTS); }, isSelected: selectedNavItemIndex === 3, }, { name: Navigation.Detectors, id: 4, onClick: () => { this.setState({ selectedNavItemId: 4 }); history.push(ROUTES.DETECTORS); }, forceOpen: true, isSelected: selectedNavItemIndex === 4, items: [ { name: Navigation.Rules, id: 5, onClick: () => { this.setState({ selectedNavItemId: 5 }); history.push(ROUTES.RULES); }, isSelected: selectedNavItemIndex === 5, }, { name: Navigation.LogTypes, id: 8, onClick: () => { this.setState({ selectedNavItemId: 8 }); history.push(ROUTES.LOG_TYPES); }, isSelected: selectedNavItemIndex === 8, }, ], }, { name: Navigation.Correlations, id: 6, onClick: () => { this.setState({ selectedNavItemId: 6 }); history.push(ROUTES.CORRELATIONS); }, renderItem: (props) => { return ( { this.setState({ selectedNavItemId: 6 }); history.push(ROUTES.CORRELATIONS); }} > {props.children} ); }, isSelected: selectedNavItemIndex === 6, forceOpen: true, items: [ { name: Navigation.CorrelationRules, id: 7, onClick: () => { this.setState({ selectedNavItemId: 7 }); history.push(ROUTES.CORRELATION_RULES); }, isSelected: selectedNavItemIndex === 7, }, ], }, ], }, ]; return ( {(core: CoreStart | null) => core && ( {(services: BrowserServices | null) => services && ( {/* Hide side navigation bar when on any HIDDEN_NAV_ROUTES pages. */} {!HIDDEN_NAV_ROUTES.some((route) => pathname.match(route)) && ( )} {callout ? : null} {findingFlyout ? ( ) : null} ( )} /> ( )} /> ( )} /> ( )} /> ( )} /> ) => { if (!props.location.state?.ruleItem) { props.history.replace(ROUTES.RULES); return ; } return ( ); }} /> ) => { if (!props.location.state?.ruleItem) { props.history.replace(ROUTES.RULES); return ; } return ( ); }} /> ( )} /> ( )} /> ( )} /> ) => ( )} /> ) => ( )} /> ) => ( )} /> ) => ( )} /> ) => ( )} /> ) => ( )} /> ) => ( )} /> ) => ( )} /> ) => { return ( this.setState({ selectedNavItemId: 6 })} dateTimeFilter={this.state.dateTimeFilter} setDateTimeFilter={this.setDateTimeFilter} /> ); }} /> ) => ( )} /> ) => { return ; }} /> ) => { return ; }} /> ) } ) } ); } }