Vuln FE Iteration: Free columns, clickable rows, export host call update (#16749)

This commit is contained in:
RachelElysia
2024-02-15 10:35:58 -07:00
committed by mostlikelee
parent e963e64b3c
commit 4f32ba3235
18 changed files with 128 additions and 17 deletions
@@ -1,3 +1,5 @@
/** software/os OS tab */
import React, { useCallback, useContext, useMemo } from "react";
import { InjectedRouter } from "react-router";
import { Row } from "react-table";
@@ -1,6 +1,8 @@
/** software/os/:id */
import React from "react";
import { useQuery } from "react-query";
import { RouteComponentProps } from "react-router/lib/Router";
import { InjectedRouter } from "react-router";
import osVersionsAPI, {
IOSVersionResponse,
@@ -42,13 +44,14 @@ interface ISoftwareOSDetailsRouteParams {
id: string;
}
type ISoftwareOSDetailsPageProps = RouteComponentProps<
undefined,
ISoftwareOSDetailsRouteParams
>;
interface ISoftwareOSDetailsPageProps {
routeParams: ISoftwareOSDetailsRouteParams;
router: InjectedRouter;
}
const SoftwareOSDetailsPage = ({
routeParams,
router,
}: ISoftwareOSDetailsPageProps) => {
const osVersionIdFromURL = parseInt(routeParams.id, 10);
@@ -82,6 +85,7 @@ const SoftwareOSDetailsPage = ({
data={osVersionDetails.vulnerabilities}
itemName="version"
isLoading={isLoading}
router={router}
/>
);
};
@@ -1,3 +1,5 @@
/** software/titles/:id */
import React from "react";
import { RouteComponentProps } from "react-router";
import { useQuery } from "react-query";
@@ -1,8 +1,13 @@
/** software/titles/:id > Versions section */
import React, { useMemo } from "react";
import { InjectedRouter } from "react-router";
import { Row } from "react-table";
import PATHS from "router/paths";
import { ISoftwareTitleVersion } from "interfaces/software";
import { GITHUB_NEW_ISSUE_LINK } from "utilities/constants";
import { buildQueryStringFromParams } from "utilities/url";
import TableContainer from "components/TableContainer";
import EmptyTable from "components/EmptyTable";
@@ -39,11 +44,31 @@ interface ISoftwareTitleDetailsTableProps {
isLoading: boolean;
}
interface IRowProps extends Row {
original: {
id?: number;
};
}
const SoftwareTitleDetailsTable = ({
router,
data,
isLoading,
}: ISoftwareTitleDetailsTableProps) => {
const handleRowSelect = (row: IRowProps) => {
const hostsBySoftwareParams = {
software_version_id: row.original.id,
};
const path = hostsBySoftwareParams
? `${PATHS.MANAGE_HOSTS}?${buildQueryStringFromParams(
hostsBySoftwareParams
)}`
: PATHS.MANAGE_HOSTS;
router.push(path);
};
const softwareTableHeaders = useMemo(
() => generateSoftwareTitleDetailsTableConfig(router),
[router]
@@ -62,7 +87,8 @@ const SoftwareTitleDetailsTable = ({
defaultSortHeader={DEFAULT_SORT_HEADER}
defaultSortDirection={DEFAULT_SORT_DIRECTION}
disablePagination
// TODO: add row click handler
disableMultiRowSelect
onSelectSingleRow={handleRowSelect}
/>
);
};
@@ -1,3 +1,8 @@
/**
software/titles Software tab > Table
software/versions Software tab > Table (version toggle on)
*/
import React, { useCallback, useContext, useMemo } from "react";
import { InjectedRouter } from "react-router";
import { Row } from "react-table";
@@ -1,3 +1,8 @@
/**
software/titles Software tab
software/versions Software tab (version toggle on)
*/
import React from "react";
import { InjectedRouter } from "react-router";
import { useQuery } from "react-query";
@@ -1,6 +1,8 @@
/** software/versions/:id */
import React from "react";
import { useQuery } from "react-query";
import { RouteComponentProps } from "react-router";
import { InjectedRouter } from "react-router";
import softwareAPI, {
ISoftwareVersionResponse,
@@ -22,17 +24,22 @@ const baseClass = "software-version-details-page";
interface ISoftwareVersionDetailsRouteParams {
id: string;
team_id?: string;
}
type ISoftwareTitleDetailsPageProps = RouteComponentProps<
undefined,
ISoftwareVersionDetailsRouteParams
>;
interface ISoftwareOSDetailsPageProps {
routeParams: ISoftwareVersionDetailsRouteParams;
router: InjectedRouter;
}
const SoftwareVersionDetailsPage = ({
routeParams,
}: ISoftwareTitleDetailsPageProps) => {
router,
}: ISoftwareOSDetailsPageProps) => {
const versionId = parseInt(routeParams.id, 10);
const teamId = routeParams.team_id
? parseInt(routeParams.team_id, 10)
: undefined;
const {
data: softwareVersion,
@@ -90,6 +97,8 @@ const SoftwareVersionDetailsPage = ({
data={softwareVersion.vulnerabilities ?? []}
itemName="software item"
isLoading={isSoftwareVersionLoading}
router={router}
teamId={teamId}
/>
</div>
</>
@@ -1,3 +1,5 @@
/** software/vulnerabilities Vulnerabilities tab */
import React from "react";
import { useQuery } from "react-query";
import { InjectedRouter } from "react-router";
@@ -1,3 +1,5 @@
/** software/vulnerabilities Vulnerabilities tab > Table */
import React, { useCallback, useContext, useMemo } from "react";
import { InjectedRouter } from "react-router";
import { Row } from "react-table";
@@ -1,3 +1,5 @@
/** software/vulnerabilities/:cve > Vulnerable OS section */
import React, { useCallback, useMemo } from "react";
import { InjectedRouter } from "react-router";
@@ -1,3 +1,5 @@
/** software/vulnerabilities/:cve > Vulnerable software section */
import React, { useCallback, useMemo } from "react";
import { InjectedRouter } from "react-router";
@@ -1,3 +1,5 @@
/** software/vulnerabilities/:cve > Summary section */
import React from "react";
import { IVulnerability } from "interfaces/vulnerability";
@@ -1,3 +1,5 @@
/** software/vulnerabilities/:cve */
import React, { useContext } from "react";
import { useQuery } from "react-query";
import { RouteComponentProps } from "react-router";
@@ -1,3 +1,9 @@
/**
software/titles/:id > Top section
software/versions/:id > Top section
software/os/:id > Top section
*/
import React from "react";
import { QueryParams } from "utilities/url";
@@ -1,9 +1,18 @@
/**
software/versions/:id > Vulnerabilities table
software/os/:id > Vulnerabilities table
*/
import React, { useContext, useMemo } from "react";
import classnames from "classnames";
import { InjectedRouter } from "react-router";
import { Row } from "react-table";
import PATHS from "router/paths";
import { AppContext } from "context/app";
import { ISoftwareVulnerability } from "interfaces/software";
import { GITHUB_NEW_ISSUE_LINK } from "utilities/constants";
import { buildQueryStringFromParams } from "utilities/url";
import TableContainer from "components/TableContainer";
import EmptyTable from "components/EmptyTable";
@@ -41,6 +50,14 @@ interface ISoftwareVulnerabilitiesTableProps {
itemName: string;
isLoading: boolean;
className?: string;
router: InjectedRouter;
teamId?: number;
}
interface IRowProps extends Row {
original: {
cve?: string;
};
}
const SoftwareVulnerabilitiesTable = ({
@@ -48,11 +65,25 @@ const SoftwareVulnerabilitiesTable = ({
itemName,
isLoading,
className,
router,
teamId,
}: ISoftwareVulnerabilitiesTableProps) => {
const { isPremiumTier, isSandboxMode } = useContext(AppContext);
const classNames = classnames(baseClass, className);
const handleRowSelect = (row: IRowProps) => {
const hostsBySoftwareParams = { cve: row.original.cve, team_id: teamId };
const path = hostsBySoftwareParams
? `${PATHS.MANAGE_HOSTS}?${buildQueryStringFromParams(
hostsBySoftwareParams
)}`
: PATHS.MANAGE_HOSTS;
router.push(path);
};
const tableHeaders = useMemo(
() => generateTableConfig(Boolean(isPremiumTier), Boolean(isSandboxMode)),
[isPremiumTier, isSandboxMode]
@@ -71,6 +102,8 @@ const SoftwareVulnerabilitiesTable = ({
pageSize={20}
resultsTitle={"vulnerabilities"}
showMarkAllPages={false}
disableMultiRowSelect
onSelectSingleRow={handleRowSelect}
/>
</div>
);
@@ -65,9 +65,6 @@ const generateTableConfig = (
);
},
},
];
const premiumHeaders: IDataColumn[] = [
{
title: "Severity",
accessor: "cvss_score",
@@ -221,7 +218,15 @@ const generateTableConfig = (
},
];
return isPremiumTier ? tableHeaders.concat(premiumHeaders) : tableHeaders;
if (!isPremiumTier) {
return tableHeaders.filter(
(header) =>
header.accessor !== "epss_probability" &&
header.accessor !== "cve_published"
);
}
return tableHeaders;
};
export default generateTableConfig;
+2
View File
@@ -203,6 +203,7 @@ export default {
const munkiIssueId = options?.munkiIssueId;
const osSettings = options?.osSettings;
const diskEncryptionStatus = options?.diskEncryptionStatus;
const vulnerability = options?.vulnerability;
if (!sortBy.length) {
throw Error("sortBy is a required field.");
@@ -231,6 +232,7 @@ export default {
lowDiskSpaceHosts,
osSettings,
diskEncryptionStatus,
vulnerability,
}),
status,
label_id: label,
+1 -1
View File
@@ -9,7 +9,6 @@ import {
HOSTS_QUERY_PARAMS,
MacSettingsStatusQueryParam,
} from "services/entities/hosts";
import vulnerability from "interfaces/vulnerability";
type QueryValues = string | number | boolean | undefined | null;
export type QueryParams = Record<string, QueryValues>;
@@ -120,6 +119,7 @@ export const reconcileMutuallyExclusiveHostParams = ({
osName,
osVersion,
osSettings,
vulnerability,
diskEncryptionStatus,
bootstrapPackageStatus,
}: IMutuallyExclusiveHostParams): Record<string, unknown> => {