diff --git a/src/web/components/menu/menu.jsx b/src/web/components/menu/menu.jsx index 1e8a30fa80..7c41042129 100644 --- a/src/web/components/menu/menu.jsx +++ b/src/web/components/menu/menu.jsx @@ -10,60 +10,42 @@ import {AppNavigation} from '@greenbone/opensight-ui-components'; import useTranslation from 'web/hooks/useTranslation'; import useCapabilities from 'web/utils/useCapabilities'; import useGmp from 'web/utils/useGmp'; +import {useRouteMatch} from 'react-router-dom'; -import TaskIcon from 'web/components/icon/taskicon'; import Link from 'web/components/link/link'; -import ReportIcon from 'web/components/icon/reporticon'; -import ResultIcon from 'web/components/icon/resulticon'; -import VulnerabilityIcon from 'web/components/icon/vulnerabilityicon'; -import NoteIcon from 'web/components/icon/noteicon'; -import OverrideIcon from 'web/components/icon/overrideicon'; -import HostIcon from 'web/components/icon/hosticon'; -import OperatingSystemIcon from 'web/components/icon/ossvgicon'; -import TlsCertificateIcon from 'web/components/icon/tlscertificateicon'; -import TicketIcon from 'web/components/icon/ticketicon'; -import PolicyIcon from 'web/components/icon/policyicon'; -import AuditIcon from 'web/components/icon/auditicon'; -import NvtIcon from 'web/components/icon/nvticon'; -import CveIcon from 'web/components/icon/cveicon'; -import CpeIcon from 'web/components/icon/cpelogoicon'; -import CertBundAdvIcon from 'web/components/icon/certbundadvicon'; -import DfnCertAdvIcon from 'web/components/icon/dfncertadvicon'; -import TargetIcon from 'web/components/icon/targeticon'; -import PortListIcon from 'web/components/icon/portlisticon'; -import CvssIcon from 'web/components/icon/cvssicon'; -import CredentialIcon from 'web/components/icon/credentialicon'; -import ScanConfigIcon from 'web/components/icon/scanconfigicon'; -import AlertIcon from 'web/components/icon/alerticon'; -import ScheduleIcon from 'web/components/icon/scheduleicon'; -import ReportFormatIcon from 'web/components/icon/reportformaticon'; -import ScannerIcon from 'web/components/icon/scannericon'; -import FilterIcon from 'web/components/icon/filtericon'; -import TagsSvgIcon from 'web/components/icon/tagssvgicon'; -import UserIcon from 'web/components/icon/usericon'; -import GroupIcon from 'web/components/icon/groupicon'; -import RoleIcon from 'web/components/icon/roleicon'; -import PermissionIcon from 'web/components/icon/permissionicon'; -import PerformanceIcon from 'web/components/icon/performanceicon'; -import TrashcanIcon from 'web/components/icon/trashcanicon'; -import FeedIcon from 'web/components/icon/feedicon'; -import LdapIcon from 'web/components/icon/ldapicon'; -import RadiusIcon from 'web/components/icon/radiusicon'; +import { + BarChart3, + Server, + ShieldCheck, + View, + Wrench, + SlidersHorizontal, + FileCheck, + CircleHelp, +} from 'lucide-react'; const Menu = () => { const [_] = useTranslation(); const capabilities = useCapabilities(); const gmp = useGmp(); - const mayOpScans = [ + function checkCapabilities(capabilitiesList) { + return capabilitiesList.reduce( + (sum, cur) => sum || capabilities.mayAccess(cur), + false, + ); + } + + const mayOpScans = checkCapabilities([ 'tasks', 'reports', 'results', 'vulns', 'overrides', 'notes', - ].reduce((sum, cur) => sum || capabilities.mayAccess(cur), false); - const mayOpConfiguration = [ + ]); + + const mayOpConfiguration = checkCapabilities([ 'targets', 'port_lists', 'credentials', @@ -75,278 +57,320 @@ const Menu = () => { 'scanners', 'filters', 'tags', - ].reduce((sum, cur) => sum || capabilities.mayAccess(cur), false); - const mayOpResilience = ['tickets', 'policies', 'audits'].reduce( - (sum, cur) => sum || capabilities.mayAccess(cur), - false, - ); - const mayOpAssets = ['assets', 'tls_certificates'].reduce( - (sum, cur) => sum || capabilities.mayAccess(cur), - false, - ); + ]); - const menuPoints = [ - [ + const mayOpResilience = checkCapabilities(['tickets', 'policies', 'audits']); + + const mayOpAssets = checkCapabilities(['assets', 'tls_certificates']); + + const useIsActive = path => Boolean(useRouteMatch(path)); + + const isUserActive = useIsActive('/users'); + const isGroupsActive = useIsActive('/groups'); + const isRolesActive = useIsActive('/roles'); + const isPermissionsActive = useIsActive('/permissions'); + const isPerformanceActive = useIsActive('/performance'); + const isTrashcanActive = useIsActive('/trashcan'); + const isFeedStatusActive = useIsActive('/feedstatus'); + const isLdapActive = useIsActive('/ldap'); + const isRadiusActive = useIsActive('/radius'); + + const isCvssCalculatorActive = useIsActive('/cvsscalculator'); + const isAboutActive = useIsActive('/about'); + + const subNavConfigs = { + scans: [ { - icon: () => {}, - label: _('Dashboards'), - to: '/', + label: 'Tasks', + to: '/tasks', + activeCondition: useIsActive('/tasks'), + }, + { + label: 'Reports', + to: '/reports', + activeCondition: useIsActive('/reports'), + }, + { + label: 'Results', + to: '/results', + activeCondition: useIsActive('/results'), + }, + { + label: 'Vulnerabilities', + to: '/vulnerabilities', + activeCondition: useIsActive('/vulnerabilities'), + }, + { + label: 'Notes', + to: '/notes', + activeCondition: useIsActive('/notes'), + }, + { + label: 'Overrides', + to: '/overrides', + activeCondition: useIsActive('/overrides'), }, ], - [ - mayOpScans && { - icon: () => {}, - label: _('Scans'), - key: 'scans', - subNav: [ - capabilities.mayAccess('tasks') && { - icon: TaskIcon, - label: _('Tasks'), - to: '/tasks', - }, - capabilities.mayAccess('reports') && { - icon: ReportIcon, - label: _('Reports'), - to: '/reports', - }, - capabilities.mayAccess('results') && { - icon: ResultIcon, - label: _('Results'), - to: '/results', - }, - capabilities.mayAccess('vulns') && { - icon: VulnerabilityIcon, - label: _('Vulnerabilities'), - to: '/vulnerabilities', - }, - capabilities.mayAccess('notes') && { - icon: NoteIcon, - label: _('Notes'), - to: '/notes', - }, - capabilities.mayAccess('overrides') && { - icon: OverrideIcon, - label: _('Overrides'), - to: '/overrides', - }, - ].filter(Boolean), + assets: [ + { + label: 'Hosts', + to: '/hosts', + activeCondition: useIsActive('/hosts'), }, - mayOpAssets && { - icon: () => {}, - label: _('Assets'), - key: 'assets', - subNav: [ - capabilities.mayAccess('assets') && { - icon: HostIcon, - label: _('Hosts'), - to: '/hosts', - }, - capabilities.mayAccess('assets') && { - icon: OperatingSystemIcon, - label: _('Operating Systems'), - to: '/operatingsystems', - }, - capabilities.mayAccess('tls_certificates') && { - icon: TlsCertificateIcon, - label: _('TLS Certificates'), - to: '/tlscertificates', - }, - ].filter(Boolean), + { + label: 'Operating Systems', + to: '/operatingsystems', + activeCondition: useIsActive('/operatingsystems'), }, - mayOpResilience && { - icon: () => {}, - label: _('Resilience'), - key: 'resilience', - subNav: [ - capabilities.mayAccess('tickets') && { - icon: TicketIcon, - label: _('Remediation Tickets'), - to: '/tickets', - }, - capabilities.mayAccess('policies') && { - icon: PolicyIcon, - label: _('Compliance Policies'), - to: '/policies', - }, - capabilities.mayAccess('audits') && { - icon: AuditIcon, - label: _('Compliance Audits'), - to: '/audits', - }, - ].filter(Boolean), + { + label: 'TLS Certificates', + to: '/tlscertificates', + activeCondition: useIsActive('/tlscertificates'), }, - capabilities.mayAccess('info') && { - icon: () => {}, - label: _('SecInfo'), - key: 'secinfo', - subNav: [ - { - icon: NvtIcon, - label: _('NVTs'), - to: '/nvts', - }, - { - icon: CveIcon, - label: _('CVEs'), - to: '/cves', - }, - { - icon: CpeIcon, - label: _('CPEs'), - to: '/cpes', - }, - { - icon: CertBundAdvIcon, - label: _('CERT-Bund Advisories'), - to: '/certbunds', - }, - { - icon: DfnCertAdvIcon, - label: _('DFN-CERT Advisories'), - to: '/dfncerts', - }, - ], + ], + resilience: [ + { + label: 'Remediation Tickets', + to: '/tickets', + activeCondition: useIsActive('/tickets'), }, - mayOpConfiguration && { - icon: () => {}, - label: _('Configuration'), - key: 'configuration', - subNav: [ - capabilities.mayAccess('targets') && { - icon: TargetIcon, - label: _('Targets'), - to: '/targets', - }, - capabilities.mayAccess('port_lists') && { - icon: PortListIcon, - label: _('Port Lists'), - to: '/portlists', - }, - capabilities.mayAccess('credentials') && { - icon: CredentialIcon, - label: _('Credentials'), - to: '/credentials', - }, - capabilities.mayAccess('configs') && { - icon: ScanConfigIcon, - label: _('Scan Configs'), - to: '/scanconfigs', - }, - capabilities.mayAccess('alerts') && { - icon: AlertIcon, - label: _('Alerts'), - to: '/alerts', - }, - capabilities.mayAccess('schedules') && { - icon: ScheduleIcon, - label: _('Schedules'), - to: '/schedules', - }, - capabilities.mayAccess('report_configs') && { - icon: ReportFormatIcon, - label: _('Report Configs'), - to: '/reportconfigs', - }, - capabilities.mayAccess('report_formats') && { - icon: ReportFormatIcon, - label: _('Report Formats'), - to: '/reportformats', - }, - capabilities.mayAccess('scanners') && { - icon: ScannerIcon, - label: _('Scanners'), - to: '/scanners', - }, - capabilities.mayAccess('filters') && { - icon: FilterIcon, - label: _('Filters'), - to: '/filters', - }, - capabilities.mayAccess('tags') && { - icon: TagsSvgIcon, - label: _('Tags'), - to: '/tags', - }, - ].filter(Boolean), + { + label: 'Compliance Policies', + to: '/policies', + activeCondition: useIsActive('/policies'), + }, + { + label: 'Compliance Audits', + to: '/audits', + activeCondition: useIsActive('/audits'), + }, + ], + secInfo: [ + { + label: 'NVTs', + to: '/nvts', + activeCondition: useIsActive('/nvts'), + }, + { + label: 'CVEs', + to: '/cves', + activeCondition: useIsActive('/cves'), + }, + { + label: 'CPEs', + to: '/cpes', + activeCondition: useIsActive('/cpes'), + }, + { + label: 'CERT-Bund Advisories', + to: '/certbunds', + activeCondition: useIsActive('/certbunds'), + }, + { + label: 'DFN-CERT Advisories', + to: '/dfncerts', + activeCondition: useIsActive('/dfncerts'), + }, + ], + configuration: [ + { + label: 'Targets', + to: '/targets', + activeCondition: useIsActive('/targets'), + }, + { + label: 'Port Lists', + to: '/portlists', + activeCondition: useIsActive('/portlists'), }, { - icon: () => {}, + label: 'Credentials', + to: '/credentials', + activeCondition: useIsActive('/credentials'), + }, + { + label: 'Scan Configs', + to: '/scanconfigs', + activeCondition: useIsActive('/scanconfigs'), + }, + { + label: 'Alerts', + to: '/alerts', + activeCondition: useIsActive('/alerts'), + }, + { + label: 'Schedules', + to: '/schedules', + activeCondition: useIsActive('/schedules'), + }, + { + label: 'Report Configs', + to: '/reportconfigs', + activeCondition: useIsActive('/reportconfigs'), + }, + { + label: 'Report Formats', + to: '/reportformats', + activeCondition: useIsActive('/reportformats'), + }, + { + label: 'Scanners', + to: '/scanners', + activeCondition: useIsActive('/scanners'), + }, + { + label: 'Filters', + to: '/filters', + activeCondition: useIsActive('/filters'), + }, + { + label: 'Tags', + to: '/tags', + activeCondition: useIsActive('/tags'), + }, + ], + }; + + const createMenuItemWithSubNav = (label, key, icon, config) => ({ + label: _(label), + key: key, + icon: icon, + subNav: config + .map(({label, to, activeCondition}) => ({ + label: _(label), + to: to, + active: activeCondition, + })) + .filter(Boolean), + }); + + const menuPoints = [ + [ + { + label: _('Dashboards'), + to: '/', + active: useRouteMatch({ + path: '/', + exact: true, + }), + icon: BarChart3, + }, + ], + [ + mayOpScans && + createMenuItemWithSubNav( + 'Scans', + 'scans', + ShieldCheck, + subNavConfigs.scans, + ), + mayOpAssets && + createMenuItemWithSubNav( + 'Assets', + 'assets', + Server, + subNavConfigs.assets, + ), + mayOpResilience && + createMenuItemWithSubNav( + 'Resilience', + 'resilience', + FileCheck, + subNavConfigs.resilience, + ), + capabilities.mayAccess('info') && + createMenuItemWithSubNav( + 'Security Information', + 'secInfo', + View, + subNavConfigs.secInfo, + ), + mayOpConfiguration && + createMenuItemWithSubNav( + 'Configuration', + 'configuration', + Wrench, + subNavConfigs.configuration, + ), + { label: _('Administration'), key: 'administration', + icon: SlidersHorizontal, subNav: [ capabilities.mayAccess('users') && { - icon: UserIcon, label: _('Users'), to: '/users', + active: isUserActive, }, capabilities.mayAccess('groups') && { - icon: GroupIcon, label: _('Groups'), to: '/groups', + active: isGroupsActive, }, capabilities.mayAccess('roles') && { - icon: RoleIcon, label: _('Roles'), to: '/roles', + active: isRolesActive, }, capabilities.mayAccess('permissions') && { - icon: PermissionIcon, label: _('Permissions'), to: '/permissions', + active: isPermissionsActive, }, capabilities.mayAccess('system_reports') && { - icon: PerformanceIcon, label: _('Performance'), to: '/performance', + active: isPerformanceActive, }, { - icon: TrashcanIcon, label: _('Trashcan'), to: '/trashcan', + active: isTrashcanActive, }, capabilities.mayAccess('feeds') && { - icon: FeedIcon, label: _('Feed Status'), to: '/feedstatus', + active: isFeedStatusActive, }, capabilities.mayOp('describe_auth') && capabilities.mayOp('modify_auth') && { - icon: LdapIcon, label: _('LDAP'), to: '/ldap', + active: isLdapActive, }, capabilities.mayOp('describe_auth') && capabilities.mayOp('modify_auth') && { - icon: RadiusIcon, label: _('RADIUS'), to: '/radius', + active: isRadiusActive, }, ].filter(Boolean), }, { - icon: () => {}, label: _('Help'), key: 'help', + icon: CircleHelp, subNav: [ { label: _('User Manual'), to: 'https://docs.greenbone.net/GSM-Manual/gos-22.04/en/', + isExternal: true, }, { - icon: CvssIcon, label: _('CVSS Calculator'), to: '/cvsscalculator', + active: isCvssCalculatorActive, }, { label: _('About'), to: '/about', + active: isAboutActive, }, ], }, ].filter(Boolean), [ gmp.settings.enableAssetManagement && { - icon: () => {}, label: _('Asset'), to: '/asset-management', isExternal: true,