Viewing File: /usr/local/cpanel/whostmgr/docroot/templates/backup_configuration/directives/formValidator.js

/*
# backup_configuration/directives/formValidator.js   Copyright 2022 cPanel, L.L.C.
#                                                           All rights reserved.
# copyright@cpanel.net                                         http://cpanel.net
# This code is subject to the cPanel license. Unauthorized copying is prohibited
*/

/* global define */

define(
    [
        "angular",
        "cjt/util/locale",
        "cjt/validator/validator-utils",
        "cjt/validator/domain-validators",
        "cjt/validator/path-validators",
        "cjt/validator/ip-validators",
        "cjt/validator/validateDirectiveFactory"
    ],
    function(angular, LOCALE, validationUtils, domainValidators, pathValidators, ipValidators) {
        "use strict";

        /* regular expressions used by validation checks */
        var loopbackRegex = /^(127(\.\d+){1,3}|[0:]+1|localhost)$/i;
        var protocolRegex = /^http(s)*:\/*/;
        var portRegex = /:\d*$/;
        var bucketRegex = /^[a-z0-9-]*$/;
        var bucketRegexAmazon = /^[a-z0-9-.]*$/;
        var bucketRegexB2 = /^[A-Za-z0-9-]*$/;
        var bucketBeginRegex = /^[-]/;
        var bucketEndRegex = /[-]$/;
        var bucketBeginRegexAmazon = /^[-.]/;
        var bucketEndRegexAmazon = /[-.]$/;
        var bucketBeginB2 = /^b2-/i;


        /* validation messages */
        var relativePathWarning = LOCALE.maketext("You must enter a relative path.");
        var subordinatePathWarning = LOCALE.maketext("You must enter a path within the user home directory.");
        var loopbackWarning = LOCALE.maketext("You cannot enter a loopback address for the remote address.");
        var noSlashesWarning = LOCALE.maketext("You must enter a value without slashes.");
        var noSpacesWarning = LOCALE.maketext("You must enter a value without spaces.");
        var noProtocolAllowedWarning = LOCALE.maketext("The remote host address must not contain a protocol.");
        var noPathWarning = LOCALE.maketext("The remote host address must not contain path information.");
        var noPortWarning = LOCALE.maketext("The remote host address must not contain a port number.");
        var absolutePathWarning = LOCALE.maketext("You must enter an absolute path.");
        var remoteHostWarning = LOCALE.maketext("The remote host address must be a valid hostname or IP address.");
        var bucketLengthWarning = LOCALE.maketext("The bucket name must be between [numf,3] and [numf,63] characters.");
        var b2BucketLengthWarning = LOCALE.maketext("The bucket name must be between [numf,6] and [numf,50] characters.");
        var bucketNameWarning = LOCALE.maketext("The bucket name must not begin or end with a hyphen.");
        var bucketNameWarningAmazon = LOCALE.maketext("The bucket name must not begin or end with a hyphen or a period.");
        var bucketAllowedCharacters = LOCALE.maketext("The bucket name must only contain numbers, hyphens, and lowercase letters.");
        var bucketAllowedCharactersAmazon = LOCALE.maketext("The bucket name must only contain numbers, periods, hyphens, and lowercase letters.");
        var bucketAllowedCharactersB2 = LOCALE.maketext("The bucket name must only contain numbers, hyphens, and letters.");
        var bucketNameB2Reserved = LOCALE.maketext("The [asis,Backblaze] [asis,B2] bucket name must not begin with “b2-” because [asis,Backblaze] reserves this prefix.");

        var validators = {

            /*
             * Checks to see if a value is a valid backup location.
             *
             * @param {string} val - form value to be evaluated
             * @param {string} arg - optional argument ("absolute") to disable relative path checking
             * @return {ValidationResult} results of the validation
             */
            backupLocation: function(val, arg) {
                var result = validationUtils.initializeValidationResult();
                result.isValid = false;

                // allow optional field to be empty
                if (!val) {
                    result.isValid = true;
                } else if (arg !== "absolute" && val.length > 0 && val[0] === "/") {
                    result.add("backupConfigIssue", relativePathWarning);
                } else if (val.substring(0, 3) === "../") {
                    result.add("backupConfigIssue", subordinatePathWarning);
                } else {
                    result = pathValidators.methods.validPath(val);
                }

                return result;
            },

            /* Checks to see if a value is a valid S3, AmazonS3 or B2 bucket name.
             *
             * @param {string} val - form value to be evaluated
             * @param {string} arg - optional transport type ("amazon" if AmazonS3, "b2" if Backblaze b2)
             * @return {ValidationResult} results of the validation
             */
            bucket: function(val, arg) {
                var result = validationUtils.initializeValidationResult();
                result.isValid = false;

                if (arg === "b2" && bucketBeginB2.test(val)) {
                    result.add("backupConfigIssue", bucketNameB2Reserved);
                } else if (arg === "b2" && !bucketRegexB2.test(val)) {
                    result.add("backupConfigIssue", bucketAllowedCharactersB2);
                } else if (arg === "amazon" && !bucketRegexAmazon.test(val)) {
                    result.add("backupConfigIssue", bucketAllowedCharactersAmazon);
                } else if (arg !== "amazon" && arg !== "b2" && !bucketRegex.test(val)) {
                    result.add("backupConfigIssue", bucketAllowedCharacters);
                } else if (arg === "amazon" && (bucketBeginRegexAmazon.test(val) || bucketEndRegexAmazon.test(val))) {
                    result.add("backupConfigIssue", bucketNameWarningAmazon);
                } else if (arg !== "amazon" && arg !== "b2" && (bucketBeginRegex.test(val) || bucketEndRegex.test(val))) {
                    result.add("backupConfigIssue", bucketNameWarning);
                } else if (arg === "b2" && (val.length < 6 || val.length > 50)) {
                    result.add("backupConfigIssue", b2BucketLengthWarning);
                } else if (val.length < 3 || val.length > 63) {
                    result.add("backupConfigIssue", bucketLengthWarning);
                } else {
                    result.isValid = true;
                }

                return result;
            },

            /*
             * Checks to see if a value is a valid remote host or ip address.
             *
             * @param {string} val - form value to be evaluated
             * @return {ValidationResult} results of the validation
             */

            remoteHost: function(val) {
                var result = validationUtils.initializeValidationResult();
                result.isValid = false;

                var ipCheck = ipValidators.methods.ipv4(val);

                if (ipCheck.isValid) {

                    if (loopbackRegex.test(val)) {

                        // remote destination should not be a loopback
                        result.add("backupConfigIssue", loopbackWarning);
                        return result;
                    }
                    return ipCheck;
                } else {

                    // if it's not a valid ip address
                    // check the hostname for special conditions

                    if (protocolRegex.test(val)) {
                        result.add("backupConfigIssue", noProtocolAllowedWarning);
                        return result;
                    }

                    if (val.indexOf("/") >= 0 || val.indexOf("\\") >= 0) {
                        result.add("backupConfigIssue", noPathWarning);
                        return result;
                    }

                    if (portRegex.test(val)) {
                        result.add("backupConfigIssue", noPortWarning);
                        return result;
                    }
                }

                var fqdnCheck = domainValidators.methods.fqdn(val);

                if (!ipCheck.isValid && !fqdnCheck.isValid) {
                    result.add("backupConfigIssue", remoteHostWarning);
                    return result;
                }

                return fqdnCheck;
            },

            /*
             * Checks a value for the existence of slashes.
             *
             * @param {string} val - form value to be evaluated
             * @return {ValidationResult} results of the validation
             */
            noslashes: function(val) {
                var result = validationUtils.initializeValidationResult();
                result.isValid = false;

                if (val.indexOf("/") < 0 && val.indexOf("\\") < 0) {
                    result.isValid =  true;
                } else {
                    result.add("backupConfigIssue", noSlashesWarning);
                }

                return result;
            },

            /*
             * Checks a value for the existence of spaces.
             *
             * @param {string} val - form value to be evaluated
             * @return {ValidationResult} results of the validation
             */
            nospaces: function(val) {
                var result = validationUtils.initializeValidationResult();
                result.isValid = false;

                if (val.indexOf(" ") < 0) {
                    result.isValid =  true;
                } else {
                    result.add("backupConfigIssue", noSpacesWarning);
                }

                return result;
            },

            /*
             * Checks a value for a valid absolute path format.
             *
             * @param {string} val - form value to be evaluated
             * @return {ValidationResult} results of the validation
             */
            fullPath: function(val) {
                var result = validationUtils.initializeValidationResult();
                result.isValid = true;

                // allow optional field to be empty
                if (!val) {
                    return result;
                } else if (val.indexOf("/") !== 0) {

                    // value must start with a forward slash (/)
                    result.isValid = false;
                    result.add("backupConfigIssue", absolutePathWarning);
                } else {
                    result = pathValidators.methods.validPath(val);
                }

                return result;
            }

        };

        // Generate a directive for each validation function
        var validatorModule = angular.module("cjt2.validate");
        validatorModule.run(["validatorFactory",
            function(validatorFactory) {
                validatorFactory.generate(validators);
            }
        ]);

        return {
            methods: validators,
            name: "backupConfigurationValidators",
            description: "Validation library for Backup Configuration.",
            version: 1.0,
        };
    }
);
Back to Directory File Manager