UI – Fix sw detail error handling (#17478)

## Addresses:
-  unreleased bug with error handling on the vulnerability details page
- miscellaneous code and style improvements

Bug (404 and 403s not being omitted from throwing and error as
intended):

![image](https://github.com/fleetdm/fleet/assets/61553566/4d5e556e-c812-497c-85b8-bdc3af0bc805)

Fixed:
<img width="1277" alt="Screenshot 2024-03-07 at 3 37 22 PM"
src="https://github.com/fleetdm/fleet/assets/61553566/55c28bda-7d2f-49e7-ad69-094df8d66b46">

- [x] Manual QA for all new/changed functionality

---------

Co-authored-by: Jacob Shandling <jacob@fleetdm.com>
Co-authored-by: RachelElysia <71795832+RachelElysia@users.noreply.github.com>
This commit is contained in:
Jacob Shandling
2024-03-08 08:21:48 -08:00
committed by GitHub
co-authored by Jacob Shandling RachelElysia
parent a39932b013
commit aa1845a06b
8 changed files with 36 additions and 12 deletions
+7 -5
View File
@@ -204,9 +204,11 @@ export const getErrorReason = (
return "";
};
export const ignoreAxiosError = (err: Error, ignoreStatuses: number[]) => {
if (!isAxiosError(err)) {
return false;
}
return !!err.response && ignoreStatuses.includes(err.response.status);
export const ignoreAxiosError = (err: AxiosError, ignoreStatuses: number[]) => {
// TODO - isAxiosError currently not recognizing axios error, fix
// if (!isAxiosError(err)) {
// return false;
// }
// return !!err.response && ignoreStatuses.includes(err.response.status);
return !!err.status && ignoreStatuses.includes(err.status);
};
@@ -17,7 +17,7 @@ import osVersionsAPI, {
IGetOsVersionQueryKey,
} from "services/entities/operating_systems";
import { IOperatingSystemVersion } from "interfaces/operating_system";
import { SUPPORT_LINK } from "utilities/constants";
import { DEFAULT_USE_QUERY_OPTIONS, SUPPORT_LINK } from "utilities/constants";
import Spinner from "components/Spinner";
import MainContent from "components/MainContent";
@@ -102,6 +102,8 @@ const SoftwareOSDetailsPage = ({
],
({ queryKey }) => osVersionsAPI.getOSVersion(queryKey[0]),
{
...DEFAULT_USE_QUERY_OPTIONS,
retry: false,
enabled: !!osVersionIdFromURL,
select: (data) => data.os_version,
onError: (error) => {
@@ -17,6 +17,8 @@ import softwareAPI, {
IGetSoftwareTitleQueryKey,
} from "services/entities/software";
import { DEFAULT_USE_QUERY_OPTIONS } from "utilities/constants";
import Spinner from "components/Spinner";
import MainContent from "components/MainContent";
import TeamsHeader from "components/TeamsHeader";
@@ -74,7 +76,8 @@ const SoftwareTitleDetailsPage = ({
[{ scope: "softwareById", softwareId, teamId: teamIdForApi }],
({ queryKey }) => softwareAPI.getSoftwareTitle(queryKey[0]),
{
refetchOnWindowFocus: false,
...DEFAULT_USE_QUERY_OPTIONS,
retry: false,
select: (data) => data.software_title,
onError: (error) => {
if (!ignoreAxiosError(error, [403, 404])) {
@@ -21,6 +21,8 @@ import hostsCountAPI, {
import { ISoftwareVersion, formatSoftwareType } from "interfaces/software";
import { ignoreAxiosError } from "interfaces/errors";
import { DEFAULT_USE_QUERY_OPTIONS } from "utilities/constants";
import Spinner from "components/Spinner";
import MainContent from "components/MainContent";
import TeamsHeader from "components/TeamsHeader";
@@ -77,7 +79,8 @@ const SoftwareVersionDetailsPage = ({
[{ scope: "softwareVersion", versionId, teamId: teamIdForApi }],
({ queryKey }) => softwareAPI.getSoftwareVersion(queryKey[0]),
{
refetchOnWindowFocus: false,
...DEFAULT_USE_QUERY_OPTIONS,
retry: false,
select: (data) => data.software,
onError: (error) => {
if (!ignoreAxiosError(error, [403, 404])) {
@@ -58,7 +58,11 @@ const SoftwareVulnSummary = ({
{cvss_score && (
<DataSet
title={
<TooltipWrapper tipContent="The worst case impact across different environments (CVSS base score). This data is reported by the National Vulnerability Database (NVD).">
<TooltipWrapper
tipContent="The worst case impact across different environments (CVSS base score). This data is reported by the National Vulnerability Database (NVD)."
// to match neighboring tooltip wrapper
position="top-end"
>
Severity
</TooltipWrapper>
}
@@ -70,6 +74,7 @@ const SoftwareVulnSummary = ({
title={
<TooltipWrapper
tipContent="The probability that this vulnerability will be exploited in the next 30 days (EPSS probability). This data is reported by FIRST.org."
// to avoid tooltip below
position="top-end"
>
Probability of exploit
@@ -79,6 +84,7 @@ const SoftwareVulnSummary = ({
<ProbabilityOfExploit
probabilityOfExploit={epss_probability}
cisaKnownExploit={cisa_known_exploit}
// to avoid tooltip wrapper above
tooltipPosition="bottom"
/>
}
@@ -25,6 +25,7 @@
&__description {
font-size: $x-small;
line-height: 21px;
}
&__description-list {
@@ -42,5 +43,9 @@
top: 0;
}
}
.tooltip__tooltip-text {
white-space: pre-wrap;
}
}
}
@@ -16,6 +16,8 @@ import softwareVulnAPI, {
} from "services/entities/vulnerabilities";
import { ignoreAxiosError } from "interfaces/errors";
import { DEFAULT_USE_QUERY_OPTIONS } from "utilities/constants";
import Spinner from "components/Spinner";
import MainContent from "components/MainContent";
import TeamsHeader from "components/TeamsHeader";
@@ -78,6 +80,8 @@ const SoftwareVulnerabilityDetailsPage = ({
return softwareVulnAPI.getVulnerability(queryKey[0]);
},
{
...DEFAULT_USE_QUERY_OPTIONS,
retry: false,
onError: (error) => {
if (!ignoreAxiosError(error, [403, 404])) {
handlePageError(error);
@@ -121,7 +125,7 @@ const SoftwareVulnerabilityDetailsPage = ({
);
const renderContent = () => {
if (isVulnLoading || !vuln) {
if (isVulnLoading) {
return <Spinner />;
}
return (
@@ -134,7 +138,7 @@ const SoftwareVulnerabilityDetailsPage = ({
onTeamChange={onTeamChange}
/>
)}
{isVulnError ? (
{isVulnError || !vuln ? (
<DetailsNoHosts
header="Vulnerability not detected"
details={`No hosts ${
@@ -5,7 +5,6 @@
.card {
display: flex;
flex-direction: column;
gap: $pad-large;
padding: $pad-xxlarge;
}