mirror of
https://github.com/fleetdm/fleet
synced 2026-05-24 09:28:54 +00:00
## Issue Cerra #20404 ## Description - Add frontend/API backend for editing software packages. GitOps will be a separate PR. ## More - Please see subtasks for change lists - #21611 - #21613 # Checklist for submitter If some of the following don't apply, delete the relevant line. <!-- Note that API documentation changes are now addressed by the product design team. --> - [x] Changes file added for user-visible changes in `changes/`, `orbit/changes/` or `ee/fleetd-chrome/changes`. See [Changes files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/Committing-Changes.md#changes-files) for more information. - [x] Input data is properly validated, `SELECT *` is avoided, SQL injection is prevented (using placeholders for values in statements) - [x] Manual QA for all new/changed functionality Automated tests will follow in another PR. --------- Co-authored-by: Ian Littman <iansltx@gmail.com> Co-authored-by: Luke Heath <luke@fleetdm.com> Co-authored-by: Jacob Shandling <jacob@fleetdm.com> Co-authored-by: Victor Lyuboslavsky <victor.lyuboslavsky@gmail.com>
99 lines
2.5 KiB
TypeScript
99 lines
2.5 KiB
TypeScript
// @ts-ignore
|
|
import validateQuery from "components/forms/validators/validate_query";
|
|
|
|
import { IPackageFormData, IFormValidation } from "./PackageForm";
|
|
|
|
type IPackageFormValidatorKey = Exclude<
|
|
keyof IPackageFormData,
|
|
"installScript" | "uninstallScript"
|
|
>;
|
|
|
|
type IMessageFunc = (formData: IPackageFormData) => string;
|
|
type IValidationMessage = string | IMessageFunc;
|
|
|
|
interface IValidation {
|
|
name: string;
|
|
isValid: (formData: IPackageFormData) => boolean;
|
|
message?: IValidationMessage;
|
|
}
|
|
|
|
/** configuration defines validations for each filed in the form. It defines rules
|
|
* to determine if a field is valid, and rules for generating an error message.
|
|
*/
|
|
const FORM_VALIDATION_CONFIG: Record<
|
|
IPackageFormValidatorKey,
|
|
{ validations: IValidation[] }
|
|
> = {
|
|
software: {
|
|
validations: [
|
|
{
|
|
name: "required",
|
|
isValid: (formData) => formData.software !== null,
|
|
},
|
|
],
|
|
},
|
|
preInstallQuery: {
|
|
validations: [
|
|
{
|
|
name: "invalidQuery",
|
|
isValid: (formData) => {
|
|
const query = formData.preInstallQuery;
|
|
return (
|
|
query === undefined || query === "" || validateQuery(query).valid
|
|
);
|
|
},
|
|
message: (formData) => validateQuery(formData.preInstallQuery).error,
|
|
},
|
|
],
|
|
},
|
|
postInstallScript: {
|
|
// no validations related to postInstallScript
|
|
validations: [],
|
|
},
|
|
selfService: {
|
|
// no validations related to self service
|
|
validations: [],
|
|
},
|
|
};
|
|
|
|
const getErrorMessage = (
|
|
formData: IPackageFormData,
|
|
message?: IValidationMessage
|
|
) => {
|
|
if (message === undefined || typeof message === "string") {
|
|
return message;
|
|
}
|
|
return message(formData);
|
|
};
|
|
|
|
export const generateFormValidation = (formData: IPackageFormData) => {
|
|
const formValidation: IFormValidation = {
|
|
isValid: true,
|
|
software: {
|
|
isValid: false,
|
|
},
|
|
};
|
|
|
|
Object.keys(FORM_VALIDATION_CONFIG).forEach((key) => {
|
|
const objKey = key as keyof typeof FORM_VALIDATION_CONFIG;
|
|
const failedValidation = FORM_VALIDATION_CONFIG[objKey].validations.find(
|
|
(validation) => !validation.isValid(formData)
|
|
);
|
|
|
|
if (!failedValidation) {
|
|
formValidation[objKey] = {
|
|
isValid: true,
|
|
};
|
|
} else {
|
|
formValidation.isValid = false;
|
|
formValidation[objKey] = {
|
|
isValid: false,
|
|
message: getErrorMessage(formData, failedValidation.message),
|
|
};
|
|
}
|
|
});
|
|
|
|
return formValidation;
|
|
};
|
|
|
|
export default generateFormValidation;
|