diff --git a/frontend/pages/hosts/details/OSSettingsModal/OSSettingsTable/OSSettingsErrorCell/OSSettingsErrorCell.tests.tsx b/frontend/pages/hosts/details/OSSettingsModal/OSSettingsTable/OSSettingsErrorCell/OSSettingsErrorCell.tests.tsx index 3a4ce73d9e..83f0190c14 100644 --- a/frontend/pages/hosts/details/OSSettingsModal/OSSettingsTable/OSSettingsErrorCell/OSSettingsErrorCell.tests.tsx +++ b/frontend/pages/hosts/details/OSSettingsModal/OSSettingsTable/OSSettingsErrorCell/OSSettingsErrorCell.tests.tsx @@ -100,4 +100,64 @@ describe("OSSettingsErrorCell", () => { expect(screen.getByText(/Learn more/)).toBeInTheDocument(); expect(screen.getByText(/Learn more/).tagName.toLowerCase()).toBe("a"); }); + + it("renders a formatted tooltip when the error message matches custom scep error patern", () => { + render( + + ); + + expect( + screen.getByText("Settings > Integrations > Certificates") + ).toBeInTheDocument(); + expect( + screen.getByText(/add it and resend the configuration profile/) + ).toBeInTheDocument(); + }); + + it("renders a formatted tooltip when the error message matches digicert guid patern", () => { + render( + + ); + + expect( + screen.getByText("Settings > Integrations > Certificates") + ).toBeInTheDocument(); + expect(screen.getByText(/correct it and resend/)).toBeInTheDocument(); + expect(screen.getByText("DIGICERT_WIFI")).toBeInTheDocument(); + expect(screen.getByText("Profile GUID")).toBeInTheDocument(); + }); + + it("renders a formatted tooltip when the error message matches digicert token patern", () => { + render( + + ); + + expect( + screen.getByText("Settings > Integrations > Certificates") + ).toBeInTheDocument(); + expect(screen.getByText(/correct it and resend/)).toBeInTheDocument(); + expect(screen.getByText("DIGICERT_TEST")).toBeInTheDocument(); + expect(screen.getByText("API token")).toBeInTheDocument(); + }); }); diff --git a/frontend/pages/hosts/details/OSSettingsModal/OSSettingsTable/OSSettingsErrorCell/OSSettingsErrorCell.tsx b/frontend/pages/hosts/details/OSSettingsModal/OSSettingsTable/OSSettingsErrorCell/OSSettingsErrorCell.tsx index 1fcc3c00fa..da2b905323 100644 --- a/frontend/pages/hosts/details/OSSettingsModal/OSSettingsTable/OSSettingsErrorCell/OSSettingsErrorCell.tsx +++ b/frontend/pages/hosts/details/OSSettingsModal/OSSettingsTable/OSSettingsErrorCell/OSSettingsErrorCell.tsx @@ -6,6 +6,8 @@ import { DEFAULT_EMPTY_CELL_VALUE } from "utilities/constants"; import hostAPI from "services/entities/hosts"; import { NotificationContext } from "context/notification"; +import { IHostMdmProfile } from "interfaces/mdm"; + import TooltipTruncatedTextCell from "components/TableContainer/DataTable/TooltipTruncatedTextCell"; import Button from "components/buttons/Button"; import Icon from "components/Icon"; @@ -42,12 +44,99 @@ const RefetchButton = ({ isFetching, onClick }: IRefetchButtonProps) => { ); }; +/** + * formatDetailCertificateError generates the formatted detail for certain errors related to + * certificate profiles. It return a JSX element with the formatted message or null if + * the detail does not match any of the expected patterns. + */ +const formatDetailCertificateError = (detail: IHostMdmProfile["detail"]) => { + const matchTokenErr = detail.match( + /get certificate from (?:DigiCert|Digicert|digicert).*token configured in (?.*) certificate authority is invalid/ + ); + if (matchTokenErr?.groups) { + return ( + <> + Couldn't get certificate from DigiCert. The API token{" "} + configured in {matchTokenErr.groups.ca} certificate authority is + invalid. Please go to{" "} + + Settings {">"} Integrations {">"} Certificates + + , correct it and resend. + + ); + } + + const matchProfileIdErr = detail.match( + /get certificate from (?:DigiCert|Digicert|digicert).*profile_id.*configured in (?.*) certificate authority does(?:n.t| not) exist/ + ); + if (matchProfileIdErr?.groups) { + return ( + <> + Couldn't get certificate from DigiCert. The Profile GUID{" "} + configured in {matchProfileIdErr.groups.ca} certificate authority + doesn't exist. Please go to{" "} + + Settings {">"} Integrations {">"} Certificates + + , correct it and resend. + + ); + } + + const matchFleetVarErr = detail.match( + /populate (?.*) because (?.*) certificate authority does(?:n.t| not) exist/ + ); + if (matchFleetVarErr?.groups) { + return ( + <> + Fleet couldn't populate {matchFleetVarErr.groups.field} because{" "} + {matchFleetVarErr.groups.ca} certificate authority doesn't + exist. Please go to{" "} + + Settings {">"} Integrations {">"} Certificates + + , add it and resend the configuration profile. + + ); + } + + return null; +}; + +/** + * formatDetailIdpEmailError generates the formatted detail for certain errors related to + * host IdP email profiles. It returns a JSX element with the formatted message or null if + * the detail does not match any of the expected patterns. + */ +const formatDetailIdpEmailError = (detail: IHostMdmProfile["detail"]) => { + if (detail.includes("There is no IdP email for this host.")) { + return ( + <> + There is no IdP email for this host. +
+ Fleet couldn't populate +
+ $FLEET_VAR_HOST_END_USER_EMAIL_IDP. +
+ + + ); + } + return null; +}; + /** * generates the formatted tooltip for the error column. * the expected format of the error string is: * "key1: value1, key2: value2, key3: value3" */ -const generateFormattedTooltip = (detail: string) => { +const formatDetailWindowsProfile = (detail: string) => { const keyValuePairs = detail.split(/, */); const formattedElements: JSX.Element[] = []; @@ -90,31 +179,23 @@ const generateErrorTooltip = ( ) => { if (profile.status !== "failed") return null; - // Special case for creating UI link - if (profile.detail.includes("There is no IdP email for this host.")) { - return ( - <> - There is no IdP email for this host. -
- Fleet couldn't populate -
- $FLEET_VAR_HOST_END_USER_EMAIL_IDP. -
- - - ); + // Special case to handle IdP email errors + const idpEmailError = formatDetailIdpEmailError(profile.detail); + if (idpEmailError) { + return idpEmailError; } - if (profile.platform !== "windows") { - return cellValue; + // Special case to handle certificate profile errors + const certificateError = formatDetailCertificateError(profile.detail); + if (certificateError) { + return certificateError; } - return generateFormattedTooltip(profile.detail); + if (profile.platform === "windows") { + return formatDetailWindowsProfile(profile.detail); + } + + return cellValue; }; interface IOSSettingsErrorCellProps {