mirror of
https://github.com/fleetdm/fleet
synced 2026-05-23 17:08:53 +00:00
UI - Update validation pattern on SSO settings form (#25387)
## For #25264 https://github.com/user-attachments/assets/031f3636-3c0e-4439-969d-716cb08b2449 - [x] Changes file added for user-visible changes in `changes/` - [x] Manual QA for all new/changed functionality --------- Co-authored-by: Jacob Shandling <jacob@fleetdm.com>
This commit is contained in:
parent
80f503ab6a
commit
8c4275a467
2 changed files with 76 additions and 43 deletions
2
changes/25264-sso-form-validation
Normal file
2
changes/25264-sso-form-validation
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
- Fix form validation behavior on the SSO settings form.
|
||||
-
|
||||
|
|
@ -32,6 +32,50 @@ interface ISsoFormErrors {
|
|||
idp_name?: string | null;
|
||||
}
|
||||
|
||||
const validate = (formData: ISsoFormData) => {
|
||||
const errors: ISsoFormErrors = {};
|
||||
|
||||
const {
|
||||
enableSso,
|
||||
idpImageUrl,
|
||||
metadata,
|
||||
metadataUrl,
|
||||
entityId,
|
||||
idpName,
|
||||
} = formData;
|
||||
|
||||
if (enableSso) {
|
||||
if (idpImageUrl && !validUrl({ url: idpImageUrl })) {
|
||||
errors.idp_image_url = `${idpImageUrl} is not a valid URL`;
|
||||
}
|
||||
|
||||
if (!metadata) {
|
||||
if (!metadataUrl) {
|
||||
errors.metadata_url = "Metadata or Metadata URL must be present";
|
||||
errors.metadata = "Metadata or Metadata URL must be present";
|
||||
} else if (
|
||||
!validUrl({ url: metadataUrl, protocols: ["http", "https"] })
|
||||
) {
|
||||
errors.metadata_url = `${metadataUrl} is not a valid URL`;
|
||||
}
|
||||
}
|
||||
|
||||
if (!entityId) {
|
||||
errors.entity_id = "Entity ID must be present";
|
||||
}
|
||||
|
||||
if (typeof entityId === "string" && entityId.length < 5) {
|
||||
errors.entity_id = "Entity ID must be 5 or more characters";
|
||||
}
|
||||
|
||||
if (!idpName) {
|
||||
errors.idp_name = "Identity provider name must be present";
|
||||
}
|
||||
}
|
||||
|
||||
return errors;
|
||||
};
|
||||
|
||||
const Sso = ({
|
||||
appConfig,
|
||||
handleSubmit,
|
||||
|
|
@ -64,51 +108,35 @@ const Sso = ({
|
|||
const [formErrors, setFormErrors] = useState<ISsoFormErrors>({});
|
||||
|
||||
const onInputChange = ({ name, value }: IFormField) => {
|
||||
setFormData({ ...formData, [name]: value });
|
||||
const newFormData = { ...formData, [name]: value };
|
||||
setFormData(newFormData);
|
||||
const newErrs = validate(newFormData);
|
||||
// only set errors that are updates of existing errors
|
||||
// new errors are only set onBlur or submit
|
||||
const errsToSet: Record<string, string> = {};
|
||||
Object.keys(formErrors).forEach((k) => {
|
||||
// @ts-ignore
|
||||
if (newErrs[k]) {
|
||||
// @ts-ignore
|
||||
errsToSet[k] = newErrs[k];
|
||||
}
|
||||
});
|
||||
setFormErrors(errsToSet);
|
||||
};
|
||||
|
||||
const validateForm = () => {
|
||||
const errors: ISsoFormErrors = {};
|
||||
|
||||
if (enableSso) {
|
||||
if (idpImageUrl && !validUrl({ url: idpImageUrl })) {
|
||||
errors.idp_image_url = `${idpImageUrl} is not a valid URL`;
|
||||
}
|
||||
|
||||
if (!metadata) {
|
||||
if (!metadataUrl) {
|
||||
errors.metadata_url = "Metadata or Metadata URL must be present";
|
||||
errors.metadata = "Metadata or Metadata URL must be present";
|
||||
} else if (
|
||||
!validUrl({ url: metadataUrl, protocols: ["http", "https"] })
|
||||
) {
|
||||
errors.metadata_url = `${metadataUrl} is not a valid URL`;
|
||||
}
|
||||
}
|
||||
|
||||
if (!entityId) {
|
||||
errors.entity_id = "Entity ID must be present";
|
||||
}
|
||||
|
||||
if (typeof entityId === "string" && entityId.length < 5) {
|
||||
errors.entity_id = "Entity ID must be 5 or more characters";
|
||||
}
|
||||
|
||||
if (!idpName) {
|
||||
errors.idp_name = "Identity provider name must be present";
|
||||
}
|
||||
}
|
||||
|
||||
setFormErrors(errors);
|
||||
const onInputBlur = () => {
|
||||
setFormErrors(validate(formData));
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
validateForm();
|
||||
}, [idpImageUrl, metadata, metadataUrl, entityId, idpName]);
|
||||
|
||||
const onFormSubmit = (evt: React.MouseEvent<HTMLFormElement>) => {
|
||||
evt.preventDefault();
|
||||
|
||||
const errs = validate(formData);
|
||||
if (Object.keys(errs).length > 0) {
|
||||
setFormErrors(errs);
|
||||
return;
|
||||
}
|
||||
|
||||
// Formatting of API not UI
|
||||
const formDataToSubmit = {
|
||||
sso_settings: {
|
||||
|
|
@ -135,6 +163,7 @@ const Sso = ({
|
|||
<form onSubmit={onFormSubmit} autoComplete="off">
|
||||
<Checkbox
|
||||
onChange={onInputChange}
|
||||
onBlur={onInputBlur}
|
||||
name="enableSso"
|
||||
value={enableSso}
|
||||
parseTarget
|
||||
|
|
@ -147,7 +176,7 @@ const Sso = ({
|
|||
name="idpName"
|
||||
value={idpName}
|
||||
parseTarget
|
||||
onBlur={validateForm}
|
||||
onBlur={onInputBlur}
|
||||
error={formErrors.idp_name}
|
||||
tooltip="A required human friendly name for the identity provider that will provide single sign-on authentication."
|
||||
/>
|
||||
|
|
@ -158,7 +187,7 @@ const Sso = ({
|
|||
name="entityId"
|
||||
value={entityId}
|
||||
parseTarget
|
||||
onBlur={validateForm}
|
||||
onBlur={onInputBlur}
|
||||
error={formErrors.entity_id}
|
||||
tooltip="The required entity ID is a URI that you use to identify Fleet when configuring the identity provider."
|
||||
/>
|
||||
|
|
@ -168,7 +197,7 @@ const Sso = ({
|
|||
name="idpImageUrl"
|
||||
value={idpImageUrl}
|
||||
parseTarget
|
||||
onBlur={validateForm}
|
||||
onBlur={onInputBlur}
|
||||
error={formErrors.idp_image_url}
|
||||
tooltip={`An optional link to an image such
|
||||
as a logo for the identity provider.`}
|
||||
|
|
@ -180,7 +209,7 @@ const Sso = ({
|
|||
name="metadata"
|
||||
value={metadata}
|
||||
parseTarget
|
||||
onBlur={validateForm}
|
||||
onBlur={onInputBlur}
|
||||
error={formErrors.metadata}
|
||||
tooltip="Metadata XML provided by the identity provider."
|
||||
/>
|
||||
|
|
@ -196,12 +225,13 @@ const Sso = ({
|
|||
name="metadataUrl"
|
||||
value={metadataUrl}
|
||||
parseTarget
|
||||
onBlur={validateForm}
|
||||
onBlur={onInputBlur}
|
||||
error={formErrors.metadata_url}
|
||||
tooltip="Metadata URL provided by the identity provider."
|
||||
/>
|
||||
<Checkbox
|
||||
onChange={onInputChange}
|
||||
onBlur={onInputBlur}
|
||||
name="enableSsoIdpLogin"
|
||||
value={enableSsoIdpLogin}
|
||||
parseTarget
|
||||
|
|
@ -211,6 +241,7 @@ const Sso = ({
|
|||
{isPremiumTier && (
|
||||
<Checkbox
|
||||
onChange={onInputChange}
|
||||
onBlur={onInputBlur}
|
||||
name="enableJitProvisioning"
|
||||
value={enableJitProvisioning}
|
||||
parseTarget
|
||||
|
|
|
|||
Loading…
Reference in a new issue