diff --git a/frontend/pages/admin/IntegrationsPage/cards/CertificateAuthorities/components/AddCertAuthorityModal/_styles.scss b/frontend/pages/admin/IntegrationsPage/cards/CertificateAuthorities/components/AddCertAuthorityModal/_styles.scss
index 8457d0880e..f126bf1c2c 100644
--- a/frontend/pages/admin/IntegrationsPage/cards/CertificateAuthorities/components/AddCertAuthorityModal/_styles.scss
+++ b/frontend/pages/admin/IntegrationsPage/cards/CertificateAuthorities/components/AddCertAuthorityModal/_styles.scss
@@ -1,5 +1,4 @@
.add-cert-authority-modal {
-
&__cert-authority-dropdown {
margin-bottom: $pad-large;
}
diff --git a/frontend/pages/admin/IntegrationsPage/cards/CertificateAuthorities/components/AddCertAuthorityModal/helpers.tsx b/frontend/pages/admin/IntegrationsPage/cards/CertificateAuthorities/components/AddCertAuthorityModal/helpers.tsx
index e241dee672..988c0c884e 100644
--- a/frontend/pages/admin/IntegrationsPage/cards/CertificateAuthorities/components/AddCertAuthorityModal/helpers.tsx
+++ b/frontend/pages/admin/IntegrationsPage/cards/CertificateAuthorities/components/AddCertAuthorityModal/helpers.tsx
@@ -1,4 +1,8 @@
+import React from "react";
+
+import CustomLink from "components/CustomLink";
import { IDropdownOption } from "interfaces/dropdownOption";
+import { getErrorReason } from "interfaces/errors";
const DEFAULT_CERT_AUTHORITY_OPTIONS: IDropdownOption[] = [
{ label: "Digicert", value: "digicert" },
@@ -24,10 +28,66 @@ export const generateDropdownOptions = (hasNDESCert: boolean) => {
return DEFAULT_CERT_AUTHORITY_OPTIONS;
};
-const DEFAULT_ERROR_MESSAGE =
- "Couldn't add certificate authority. Please try again.";
+/**
+ * errors used in the add certificate authority flow
+ */
+const DEFAULT_ERROR = "Please try again.";
+const INVALID_API_TOKEN_ERROR =
+ "Invalid API token. Please correct and try again.";
+const INVALID_PROFILE_GUID_ERROR =
+ "Invalid profile GUID. Please correct and try again.";
+const INVALID_URL_ERROR = "Invalid URL. Please correct and try again.";
+const PRIVATE_KEY_NOT_CONFIGURED_ERROR = (
+ <>
+ Private key must be configured.{" "}
+
+ >
+);
+const INVALID_SCEP_URL_ERROR =
+ "Invalid SCEP URL. Please correct and try again.";
+const INVALID_ADMIN_URL_OR_CREDENTIALS_ERROR =
+ "Invalid admin URL or credentials. Please correct and try again.";
+const NDES_PASSWORD_CACHE_FULL_ERROR =
+ "The NDES password cache is full. Please increase the number of cached passwords in NDES and try again.";
+const INVALID_CHALLENGE_ERROR =
+ "Invalid challenge. Please correct and try again.";
-// eslint-disable-next-line import/prefer-default-export
-export const getErrorMessage = (e: unknown) => {
- return DEFAULT_ERROR_MESSAGE;
+/**
+ * Gets the error message we want to display from the api error message.
+ * This is used in both add and edit certificate authority flows.
+ */
+export const getDisplayErrMessage = (err: unknown) => {
+ let message: string | JSX.Element = DEFAULT_ERROR;
+ const reason = getErrorReason(err);
+
+ if (reason.includes("invalid API token")) {
+ message = INVALID_API_TOKEN_ERROR;
+ } else if (reason.includes("invalid profile GUID")) {
+ message = INVALID_PROFILE_GUID_ERROR;
+ } else if (reason.includes("invalid URL")) {
+ message = INVALID_URL_ERROR;
+ } else if (reason.includes("private key")) {
+ message = PRIVATE_KEY_NOT_CONFIGURED_ERROR;
+ } else if (reason.includes("invalid SCEP URL")) {
+ message = INVALID_SCEP_URL_ERROR;
+ } else if (reason.includes("invalid admin URL or credentials")) {
+ message = INVALID_ADMIN_URL_OR_CREDENTIALS_ERROR;
+ } else if (reason.includes("password cache is full")) {
+ message = NDES_PASSWORD_CACHE_FULL_ERROR;
+ } else if (reason.includes("invalid challenge")) {
+ message = INVALID_CHALLENGE_ERROR;
+ } else {
+ message = DEFAULT_ERROR;
+ }
+
+ return message;
+};
+
+export const getErrorMessage = (err: unknown) => {
+ return `Couldn't add certificate authority. ${getDisplayErrMessage(err)}`;
};
diff --git a/frontend/pages/admin/IntegrationsPage/cards/CertificateAuthorities/components/CustomSCEPForm/CustomSCEPForm.tsx b/frontend/pages/admin/IntegrationsPage/cards/CertificateAuthorities/components/CustomSCEPForm/CustomSCEPForm.tsx
index 9be5a4d90f..4fb92db9ff 100644
--- a/frontend/pages/admin/IntegrationsPage/cards/CertificateAuthorities/components/CustomSCEPForm/CustomSCEPForm.tsx
+++ b/frontend/pages/admin/IntegrationsPage/cards/CertificateAuthorities/components/CustomSCEPForm/CustomSCEPForm.tsx
@@ -1,11 +1,17 @@
-import React, { useState } from "react";
+import React, { useContext, useMemo, useState } from "react";
+
+import { AppContext } from "context/app";
// @ts-ignore
import InputField from "components/forms/fields/InputField";
import Button from "components/buttons/Button";
import TooltipWrapper from "components/TooltipWrapper";
-import { ICustomSCEPFormValidation, validateFormData } from "./helpers";
+import {
+ generateFormValidations,
+ ICustomSCEPFormValidation,
+ validateFormData,
+} from "./helpers";
const baseClass = "ndes-form";
@@ -19,6 +25,7 @@ interface ICustomSCEPFormProps {
formData: ICustomSCEPFormData;
submitBtnText: string;
isSubmitting: boolean;
+ isEditing?: boolean;
onChange: (update: { name: string; value: string }) => void;
onSubmit: () => void;
onCancel: () => void;
@@ -28,10 +35,20 @@ const CustomSCEPForm = ({
formData,
submitBtnText,
isSubmitting,
+ isEditing = false,
onChange,
onSubmit,
onCancel,
}: ICustomSCEPFormProps) => {
+ const { config } = useContext(AppContext);
+ const validations = useMemo(
+ () =>
+ generateFormValidations(
+ config?.integrations.custom_scep_proxy ?? [],
+ isEditing
+ ),
+ [config?.integrations.custom_scep_proxy]
+ );
const [
formValidation,
setFormValidation,
@@ -48,7 +65,10 @@ const CustomSCEPForm = ({
const onInputChange = (update: { name: string; value: string }) => {
setFormValidation(
- validateFormData({ ...formData, [update.name]: update.value })
+ validateFormData(
+ { ...formData, [update.name]: update.value },
+ validations
+ )
);
onChange(update);
};
diff --git a/frontend/pages/admin/IntegrationsPage/cards/CertificateAuthorities/components/CustomSCEPForm/helpers.ts b/frontend/pages/admin/IntegrationsPage/cards/CertificateAuthorities/components/CustomSCEPForm/helpers.ts
index 705ee3a192..8d86246c72 100644
--- a/frontend/pages/admin/IntegrationsPage/cards/CertificateAuthorities/components/CustomSCEPForm/helpers.ts
+++ b/frontend/pages/admin/IntegrationsPage/cards/CertificateAuthorities/components/CustomSCEPForm/helpers.ts
@@ -1,3 +1,5 @@
+import { ICertificatesIntegrationCustomSCEP } from "interfaces/integration";
+
import valid_url from "components/forms/validators/valid_url";
import { ICustomSCEPFormData } from "./CustomSCEPForm";
@@ -21,56 +23,76 @@ interface IValidation {
message?: IValidationMessage;
}
-const FORM_VALIDATIONS: Record<
+type IFormValidations = Record<
IFormValidationKey,
{ validations: IValidation[] }
-> = {
- name: {
- validations: [
- {
- name: "required",
- isValid: (formData: ICustomSCEPFormData) => {
- return formData.name.length > 0;
+>;
+
+export const generateFormValidations = (
+ customSCEPIntegrations: ICertificatesIntegrationCustomSCEP[],
+ isEditing: boolean
+) => {
+ const FORM_VALIDATIONS: IFormValidations = {
+ name: {
+ validations: [
+ {
+ name: "required",
+ isValid: (formData: ICustomSCEPFormData) => {
+ return formData.name.length > 0;
+ },
},
- },
- {
- name: "invalidCharacters",
- isValid: (formData: ICustomSCEPFormData) => {
- return /^[a-zA-Z0-9_]+$/.test(formData.name);
+ {
+ name: "invalidCharacters",
+ isValid: (formData: ICustomSCEPFormData) => {
+ return /^[a-zA-Z0-9_]+$/.test(formData.name);
+ },
+ message:
+ "Invalid characters. Only letters, numbers and underscores allowed.",
},
- message:
- "Inalid characters. Only letters, numbers and underscores allowed.",
- },
- ],
- },
- scepURL: {
- validations: [
- {
- name: "required",
- isValid: (formData: ICustomSCEPFormData) => {
- return formData.scepURL.length > 0;
+ {
+ name: "unique",
+ isValid: (formData: ICustomSCEPFormData) => {
+ return (
+ isEditing ||
+ customSCEPIntegrations.find(
+ (cert) => cert.name === formData.name
+ ) === undefined
+ );
+ },
+ message: "Name is already used by another custom SCEP CA.",
},
- },
- {
- name: "validUrl",
- isValid: (formData: ICustomSCEPFormData) => {
- return valid_url({ url: formData.scepURL });
+ ],
+ },
+ scepURL: {
+ validations: [
+ {
+ name: "required",
+ isValid: (formData: ICustomSCEPFormData) => {
+ return formData.scepURL.length > 0;
+ },
},
- message: (formData: ICustomSCEPFormData) =>
- `${formData.scepURL} is not a valid URL`,
- },
- ],
- },
- challenge: {
- validations: [
- {
- name: "required",
- isValid: (formData: ICustomSCEPFormData) => {
- return formData.challenge.length > 0;
+ {
+ name: "validUrl",
+ isValid: (formData: ICustomSCEPFormData) => {
+ return valid_url({ url: formData.scepURL });
+ },
+ message: "Must be a valid URL.",
},
- },
- ],
- },
+ ],
+ },
+ challenge: {
+ validations: [
+ {
+ name: "required",
+ isValid: (formData: ICustomSCEPFormData) => {
+ return formData.challenge.length > 0;
+ },
+ },
+ ],
+ },
+ };
+
+ return FORM_VALIDATIONS;
};
const getErrorMessage = (
@@ -84,14 +106,17 @@ const getErrorMessage = (
};
// eslint-disable-next-line import/prefer-default-export
-export const validateFormData = (formData: ICustomSCEPFormData) => {
+export const validateFormData = (
+ formData: ICustomSCEPFormData,
+ validationConfig: IFormValidations
+) => {
const formValidation: ICustomSCEPFormValidation = {
isValid: true,
};
- Object.keys(FORM_VALIDATIONS).forEach((key) => {
- const objKey = key as keyof typeof FORM_VALIDATIONS;
- const failedValidation = FORM_VALIDATIONS[objKey].validations.find(
+ Object.keys(validationConfig).forEach((key) => {
+ const objKey = key as keyof typeof validationConfig;
+ const failedValidation = validationConfig[objKey].validations.find(
(validation) => !validation.isValid(formData)
);
@@ -110,39 +135,3 @@ export const validateFormData = (formData: ICustomSCEPFormData) => {
return formValidation;
};
-
-const BAD_SCEP_URL_ERROR = "Invalid SCEP URL. Please correct and try again.";
-const BAD_CREDENTIALS_ERROR =
- "Couldn't add. Admin URL or credentials are invalid.";
-const CACHE_ERROR =
- "The NDES password cache is full. Please increase the number of cached passwords in NDES and try again. By default, NDES caches 5 passwords and they expire 60 minutes after they are created.";
-const INSUFFICIENT_PERMISSIONS_ERROR =
- "Couldn't add. This account doesn't have sufficient permissions. Please use the account with enroll permission.";
-const SCEP_URL_TIMEOUT_ERROR =
- "Couldn't add. Request to NDES (SCEP URL) timed out. Please try again.";
-const DEFAULT_ERROR =
- "Something went wrong updating your SCEP server. Please try again.";
-
-// export const getErrorMessage = (
-// err: unknown,
-// formData: ICustomSCEPFormData
-// ) => {
-// const reason = getErrorReason(err);
-
-// if (reason.includes("invalid admin URL or credentials")) {
-// return BAD_CREDENTIALS_ERROR;
-// } else if (reason.includes("the password cache is full")) {
-// return CACHE_ERROR;
-// } else if (reason.includes("does not have sufficient permissions")) {
-// INSUFFICIENT_PERMISSIONS_ERROR;
-// } else if (
-// reason.includes(formData.scepURL) &&
-// reason.includes("context deadline exceeded")
-// ) {
-// return SCEP_URL_TIMEOUT_ERROR;
-// } else if (reason.includes("invalid SCEP URL")) {
-// return BAD_SCEP_URL_ERROR;
-// }
-
-// return DEFAULT_ERROR;
-// };
diff --git a/frontend/pages/admin/IntegrationsPage/cards/CertificateAuthorities/components/DigicertForm/DigicertForm.tsx b/frontend/pages/admin/IntegrationsPage/cards/CertificateAuthorities/components/DigicertForm/DigicertForm.tsx
index 9f30595060..59855b02c9 100644
--- a/frontend/pages/admin/IntegrationsPage/cards/CertificateAuthorities/components/DigicertForm/DigicertForm.tsx
+++ b/frontend/pages/admin/IntegrationsPage/cards/CertificateAuthorities/components/DigicertForm/DigicertForm.tsx
@@ -1,11 +1,17 @@
-import React, { useState } from "react";
+import React, { useContext, useMemo, useState } from "react";
+
+import { AppContext } from "context/app";
// @ts-ignore
import InputField from "components/forms/fields/InputField";
import Button from "components/buttons/Button";
import CustomLink from "components/CustomLink";
import TooltipWrapper from "components/TooltipWrapper";
-import { validateFormData, IDigicertFormValidation } from "./helpers";
+import {
+ validateFormData,
+ IDigicertFormValidation,
+ generateFormValidations,
+} from "./helpers";
const baseClass = "digicert-form";
@@ -23,6 +29,7 @@ interface IDigicertFormProps {
formData: IDigicertFormData;
submitBtnText: string;
isSubmitting: boolean;
+ isEditing?: boolean;
onChange: (update: { name: string; value: string }) => void;
onSubmit: () => void;
onCancel: () => void;
@@ -32,10 +39,18 @@ const DigicertForm = ({
formData,
submitBtnText,
isSubmitting,
+ isEditing = false,
onChange,
onSubmit,
onCancel,
}: IDigicertFormProps) => {
+ const { config } = useContext(AppContext);
+ const validations = useMemo(
+ () =>
+ generateFormValidations(config?.integrations.digicert ?? [], isEditing),
+ [config?.integrations.digicert, isEditing]
+ );
+
const [formValidation, setFormValidation] = useState(
{
isValid: false,
@@ -59,7 +74,10 @@ const DigicertForm = ({
const onInputChange = (update: { name: string; value: string }) => {
setFormValidation(
- validateFormData({ ...formData, [update.name]: update.value })
+ validateFormData(
+ { ...formData, [update.name]: update.value },
+ validations
+ )
);
onChange(update);
};
diff --git a/frontend/pages/admin/IntegrationsPage/cards/CertificateAuthorities/components/DigicertForm/helpers.ts b/frontend/pages/admin/IntegrationsPage/cards/CertificateAuthorities/components/DigicertForm/helpers.ts
index ddc946f18b..b1e6beae07 100644
--- a/frontend/pages/admin/IntegrationsPage/cards/CertificateAuthorities/components/DigicertForm/helpers.ts
+++ b/frontend/pages/admin/IntegrationsPage/cards/CertificateAuthorities/components/DigicertForm/helpers.ts
@@ -1,4 +1,7 @@
+import { ICertificatesIntegrationDigicert } from "interfaces/integration";
+
import valid_url from "components/forms/validators/valid_url";
+
import { IDigicertFormData } from "./DigicertForm";
// TODO: create a validator abstraction for this and the other form validation files
@@ -23,86 +26,105 @@ interface IValidation {
message?: IValidationMessage;
}
-const FORM_VALIDATIONS: Record<
+type IFormValidations = Record<
IFormValidationKey,
{ validations: IValidation[] }
-> = {
- name: {
- validations: [
- {
- name: "required",
- isValid: (formData: IDigicertFormData) => {
- return formData.name.length > 0;
+>;
+
+export const generateFormValidations = (
+ digicertIntegrations: ICertificatesIntegrationDigicert[],
+ isEditing: boolean
+) => {
+ const FORM_VALIDATIONS: IFormValidations = {
+ name: {
+ validations: [
+ {
+ name: "required",
+ isValid: (formData: IDigicertFormData) => {
+ return formData.name.length > 0;
+ },
},
- },
- {
- name: "invalidCharacters",
- isValid: (formData: IDigicertFormData) => {
- return /^[a-zA-Z0-9_]+$/.test(formData.name);
+ {
+ name: "invalidCharacters",
+ isValid: (formData: IDigicertFormData) => {
+ return /^[a-zA-Z0-9_]+$/.test(formData.name);
+ },
+ message:
+ "Invalid characters. Only letters, numbers and underscores allowed.",
},
- message:
- "Inalid characters. Only letters, numbers and underscores allowed.",
- },
- ],
- },
- url: {
- validations: [
- {
- name: "required",
- isValid: (formData: IDigicertFormData) => {
- return formData.url.length > 0;
+ {
+ name: "unique",
+ isValid: (formData: IDigicertFormData) => {
+ return (
+ isEditing ||
+ digicertIntegrations.find(
+ (cert) => cert.name === formData.name
+ ) === undefined
+ );
+ },
+ message: "Name is already used by another DigiCert CA.",
},
- },
- {
- name: "validUrl",
- isValid: (formData: IDigicertFormData) => {
- return valid_url({ url: formData.url });
+ ],
+ },
+ url: {
+ validations: [
+ {
+ name: "required",
+ isValid: (formData: IDigicertFormData) => {
+ return formData.url.length > 0;
+ },
},
- message: (formData: IDigicertFormData) =>
- `${formData.url} is not a valid URL`,
- },
- ],
- },
- apiToken: {
- validations: [
- {
- name: "required",
- isValid: (formData: IDigicertFormData) => {
- return formData.apiToken.length > 0;
+ {
+ name: "validUrl",
+ isValid: (formData: IDigicertFormData) => {
+ return valid_url({ url: formData.url });
+ },
+ message: "Must be a valid URL.",
},
- },
- ],
- },
- profileId: {
- validations: [
- {
- name: "required",
- isValid: (formData: IDigicertFormData) => {
- return formData.profileId.length > 0;
+ ],
+ },
+ apiToken: {
+ validations: [
+ {
+ name: "required",
+ isValid: (formData: IDigicertFormData) => {
+ return formData.apiToken.length > 0;
+ },
},
- },
- ],
- },
- commonName: {
- validations: [
- {
- name: "required",
- isValid: (formData: IDigicertFormData) => {
- return formData.commonName.length > 0;
+ ],
+ },
+ profileId: {
+ validations: [
+ {
+ name: "required",
+ isValid: (formData: IDigicertFormData) => {
+ return formData.profileId.length > 0;
+ },
},
- },
- ],
- },
- certificateSeatId: {
- validations: [
- {
- name: "required",
- isValid: (formData: IDigicertFormData) => {
- return formData.certificateSeatId.length > 0;
+ ],
+ },
+ commonName: {
+ validations: [
+ {
+ name: "required",
+ isValid: (formData: IDigicertFormData) => {
+ return formData.commonName.length > 0;
+ },
},
- },
- ],
- },
+ ],
+ },
+ certificateSeatId: {
+ validations: [
+ {
+ name: "required",
+ isValid: (formData: IDigicertFormData) => {
+ return formData.certificateSeatId.length > 0;
+ },
+ },
+ ],
+ },
+ };
+ return FORM_VALIDATIONS;
};
const getErrorMessage = (
@@ -115,15 +137,17 @@ const getErrorMessage = (
return message(formData);
};
-// eslint-disable-next-line import/prefer-default-export
-export const validateFormData = (formData: IDigicertFormData) => {
+export const validateFormData = (
+ formData: IDigicertFormData,
+ validationConfig: IFormValidations
+) => {
const formValidation: IDigicertFormValidation = {
isValid: true,
};
- Object.keys(FORM_VALIDATIONS).forEach((key) => {
- const objKey = key as keyof typeof FORM_VALIDATIONS;
- const failedValidation = FORM_VALIDATIONS[objKey].validations.find(
+ Object.keys(validationConfig).forEach((key) => {
+ const objKey = key as keyof typeof validationConfig;
+ const failedValidation = validationConfig[objKey].validations.find(
(validation) => !validation.isValid(formData)
);
diff --git a/frontend/pages/admin/IntegrationsPage/cards/CertificateAuthorities/components/EditCertAuthorityModal/EditCertAuthorityModal.tsx b/frontend/pages/admin/IntegrationsPage/cards/CertificateAuthorities/components/EditCertAuthorityModal/EditCertAuthorityModal.tsx
index 1ac6919d36..0bfb60d79b 100644
--- a/frontend/pages/admin/IntegrationsPage/cards/CertificateAuthorities/components/EditCertAuthorityModal/EditCertAuthorityModal.tsx
+++ b/frontend/pages/admin/IntegrationsPage/cards/CertificateAuthorities/components/EditCertAuthorityModal/EditCertAuthorityModal.tsx
@@ -13,7 +13,7 @@ import Modal from "components/Modal";
import {
generateDefaultFormData,
- generateErrorMessage,
+ getErrorMessage,
getCertificateAuthorityType,
} from "./helpers";
@@ -68,7 +68,7 @@ const EditCertAuthorityModal = ({
onExit();
setConfig(newConfig);
} catch (e) {
- renderFlash("error", generateErrorMessage(e));
+ renderFlash("error", getErrorMessage(e));
}
setIsUpdating(false);
};
@@ -93,6 +93,7 @@ const EditCertAuthorityModal = ({
formData={formData}
submitBtnText="Save"
isSubmitting={isUpdating}
+ isEditing
onChange={onChangeForm}
onSubmit={onEditCertAuthority}
onCancel={onExit}
diff --git a/frontend/pages/admin/IntegrationsPage/cards/CertificateAuthorities/components/EditCertAuthorityModal/_styles.scss b/frontend/pages/admin/IntegrationsPage/cards/CertificateAuthorities/components/EditCertAuthorityModal/_styles.scss
deleted file mode 100644
index ff608def43..0000000000
--- a/frontend/pages/admin/IntegrationsPage/cards/CertificateAuthorities/components/EditCertAuthorityModal/_styles.scss
+++ /dev/null
@@ -1,3 +0,0 @@
-.edit-cert-authority-modal {
-
-}
diff --git a/frontend/pages/admin/IntegrationsPage/cards/CertificateAuthorities/components/EditCertAuthorityModal/helpers.tsx b/frontend/pages/admin/IntegrationsPage/cards/CertificateAuthorities/components/EditCertAuthorityModal/helpers.tsx
index 8d52de3276..44336fb228 100644
--- a/frontend/pages/admin/IntegrationsPage/cards/CertificateAuthorities/components/EditCertAuthorityModal/helpers.tsx
+++ b/frontend/pages/admin/IntegrationsPage/cards/CertificateAuthorities/components/EditCertAuthorityModal/helpers.tsx
@@ -2,22 +2,13 @@ import {
ICertificateAuthorityType,
ICertificateIntegration,
ICertificatesIntegrationCustomSCEP,
- ICertificatesIntegrationDigicert,
- ICertificatesIntegrationNDES,
isCustomSCEPCertIntegration,
isDigicertCertIntegration,
isNDESCertIntegration,
} from "interfaces/integration";
import { ICertFormData } from "../AddCertAuthorityModal/AddCertAuthorityModal";
-
-const DEFAULT_ERROR_MESSAGE =
- "Couldn't edit certificate authority. Please try again.";
-
-// eslint-disable-next-line import/prefer-default-export
-export const generateErrorMessage = (e: unknown) => {
- return DEFAULT_ERROR_MESSAGE;
-};
+import { getDisplayErrMessage } from "../AddCertAuthorityModal/helpers";
export const getCertificateAuthorityType = (
certAuthority: ICertificateIntegration
@@ -56,3 +47,7 @@ export const generateDefaultFormData = (
challenge: customSCEPcert.challenge,
};
};
+
+export const getErrorMessage = (err: unknown) => {
+ return `Couldn't edit certificate authority. ${getDisplayErrMessage(err)}`;
+};
diff --git a/frontend/pages/admin/IntegrationsPage/cards/CertificateAuthorities/components/NDESForm/NDESForm.tsx b/frontend/pages/admin/IntegrationsPage/cards/CertificateAuthorities/components/NDESForm/NDESForm.tsx
index 892dcf3b42..311d3daf6a 100644
--- a/frontend/pages/admin/IntegrationsPage/cards/CertificateAuthorities/components/NDESForm/NDESForm.tsx
+++ b/frontend/pages/admin/IntegrationsPage/cards/CertificateAuthorities/components/NDESForm/NDESForm.tsx
@@ -20,6 +20,7 @@ interface INDESFormProps {
formData: INDESFormData;
submitBtnText: string;
isSubmitting: boolean;
+ isEditing?: boolean;
onChange: (update: { name: string; value: string }) => void;
onSubmit: () => void;
onCancel: () => void;
@@ -29,6 +30,7 @@ const NDESForm = ({
formData,
submitBtnText,
isSubmitting,
+ isEditing = false,
onChange,
onSubmit,
onCancel,
@@ -58,6 +60,7 @@ const NDESForm = ({
label="SCEP URL"
name="scepURL"
value={scepURL}
+ error={formValidation.scepURL?.message}
onChange={onInputChange}
parseTarget
placeholder="https://example.com/certsrv/mscep/mscep.dll"
@@ -67,6 +70,7 @@ const NDESForm = ({
label="Admin URL"
name="adminURL"
value={adminURL}
+ error={formValidation.adminURL?.message}
onChange={onInputChange}
parseTarget
placeholder="https://example.com/certsrv/mscep_admin/"
diff --git a/frontend/pages/admin/IntegrationsPage/cards/CertificateAuthorities/components/NDESForm/helpers.ts b/frontend/pages/admin/IntegrationsPage/cards/CertificateAuthorities/components/NDESForm/helpers.ts
index 3af2e45906..b3f3c61052 100644
--- a/frontend/pages/admin/IntegrationsPage/cards/CertificateAuthorities/components/NDESForm/helpers.ts
+++ b/frontend/pages/admin/IntegrationsPage/cards/CertificateAuthorities/components/NDESForm/helpers.ts
@@ -1,12 +1,15 @@
import { getErrorReason } from "interfaces/errors";
+
+import valid_url from "components/forms/validators/valid_url";
+
import { INDESFormData } from "./NDESForm";
// TODO: create a validator abstraction for this and the other form validation files
export interface INDESFormValidation {
isValid: boolean;
- scepURL?: { isValid: boolean };
- adminURL?: { isValid: boolean };
+ scepURL?: { isValid: boolean; message?: string };
+ adminURL?: { isValid: boolean; message?: string };
username?: { isValid: boolean };
password?: { isValid: boolean };
}
@@ -33,6 +36,13 @@ const FORM_VALIDATIONS: Record<
return formData.scepURL.length > 0;
},
},
+ {
+ name: "validUrl",
+ isValid: (formData: INDESFormData) => {
+ return valid_url({ url: formData.scepURL });
+ },
+ message: "Must be a valid URL.",
+ },
],
},
adminURL: {
@@ -43,6 +53,13 @@ const FORM_VALIDATIONS: Record<
return formData.adminURL.length > 0;
},
},
+ {
+ name: "validUrl",
+ isValid: (formData: INDESFormData) => {
+ return valid_url({ url: formData.adminURL });
+ },
+ message: "Must be a valid URL",
+ },
],
},
username: {
@@ -67,6 +84,16 @@ const FORM_VALIDATIONS: Record<
},
};
+const getValifationErrorMessage = (
+ formData: INDESFormData,
+ message?: IValidationMessage
+) => {
+ if (message === undefined || typeof message === "string") {
+ return message;
+ }
+ return message(formData);
+};
+
// eslint-disable-next-line import/prefer-default-export
export const validateFormData = (formData: INDESFormData) => {
const formValidation: INDESFormValidation = {
@@ -87,6 +114,7 @@ export const validateFormData = (formData: INDESFormData) => {
formValidation.isValid = false;
formValidation[objKey] = {
isValid: false,
+ message: getValifationErrorMessage(formData, failedValidation.message),
};
}
});