Vuln FE Iteration: Free columns, clickable rows, export host call update (#16749)
This commit is contained in:
committed by
mostlikelee
parent
e963e64b3c
commit
4f32ba3235
@@ -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";
|
||||
|
||||
+27
-1
@@ -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";
|
||||
|
||||
+15
-6
@@ -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";
|
||||
|
||||
+2
@@ -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";
|
||||
|
||||
+2
@@ -1,3 +1,5 @@
|
||||
/** software/vulnerabilities/:cve > Vulnerable OS section */
|
||||
|
||||
import React, { useCallback, useMemo } from "react";
|
||||
|
||||
import { InjectedRouter } from "react-router";
|
||||
|
||||
+2
@@ -1,3 +1,5 @@
|
||||
/** software/vulnerabilities/:cve > Vulnerable software section */
|
||||
|
||||
import React, { useCallback, useMemo } from "react";
|
||||
|
||||
import { InjectedRouter } from "react-router";
|
||||
|
||||
+2
@@ -1,3 +1,5 @@
|
||||
/** software/vulnerabilities/:cve > Summary section */
|
||||
|
||||
import React from "react";
|
||||
|
||||
import { IVulnerability } from "interfaces/vulnerability";
|
||||
|
||||
+2
@@ -1,3 +1,5 @@
|
||||
/** software/vulnerabilities/:cve */
|
||||
|
||||
import React, { useContext } from "react";
|
||||
import { useQuery } from "react-query";
|
||||
import { RouteComponentProps } from "react-router";
|
||||
|
||||
+6
@@ -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";
|
||||
|
||||
+33
@@ -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>
|
||||
);
|
||||
|
||||
+9
-4
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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> => {
|
||||
|
||||
Reference in New Issue
Block a user