API Docs for: 0.8.0
Show:

File: include/validation/validation_service.js

/*
    Copyright (C) 2016  PencilBlue, LLC

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
'use strict';

//dependencies
var _        = require('lodash');
var semver   = require('semver');
var ObjectID = require('mongodb').ObjectID;
var util     = require('../util.js');

module.exports = function ValidationModule(pb) {

    /**
     * Provides a set of functions for common validations.
     *
     * @class ValidationService
     * @constructor
     */
    function ValidationService(){}

    //constants
    /**
     * Pattern to validate a file name
     * @private
     * @static
     * @property
     * @type {RegExp}
     */
    var FILE_NAME_SAFE_REGEX = /^[a-zA-Z0-9-_\.]+$/;

    /**
     * Pattern to validate a semantic package version
     * @private
     * @static
     * @property
     * @type {RegExp}
     */
    var VERSION_REGEX        = /^[0-9]+\.[0-9]+\.[0-9]+$/;

    /**
     * A pattern to validate an email address
     * @private
     * @static
     * @property
     * @type {RegExp}
     */
    var EMAIL_REGEX          = /^[-a-z0-9~!$%^&*_=+}{\'?]+(\.[-a-z0-9~!$%^&*_=+}{\'?]+)*@([a-z0-9_][-a-z0-9_]*(\.[-a-z0-9_]+)*\.(aero|arpa|biz|com|coop|edu|gov|info|int|mil|museum|name|net|org|pro|travel|mobi|[a-z][a-z])|([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}))(:[0-9]{1,5})?$/i;

    /**
     * A pattern to validate a fully qualified URL
     * @private
     * @static
     * @property
     * @type {RegExp}
     */
    var URL_REGEX            = /^(http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/;

    /**
     * A pattern to validate a relative URL (no protocol, host, or port)
     * @private
     * @static
     * @property
     * @type {RegExp}
     */
    var URL_REGEX_NO_HOST    = /^\/.*\/{0,1}$/;

    /**
     * Checks to see if the value is a valid ID string
     * @static
     * @method isIdStr
     * @param {String} val The value under test
     * @param {Boolean} [required=false] Indicates if the value is required. When
     * FALSE, null will be an acceptable value.
     * @return {Boolean} TRUE if the value is valid, FALSE if not
     */
    ValidationService.isIdStr = function(val, required) {
        if (!required && (val === null || val === undefined)) {
            return true;
        }
        else if (!util.isString(val)) {
            return false;
        }
        return ValidationService.isId(val, required);
    };

    /**
     * Checks to see if the value is a valid ID string or an instance of ObjectID.
     * @static
     * @method isId
     * @param {String|ObjectID} val The value under test
     * @param {Boolean} [required=false] Indicates if the value is required. When
     * FALSE, null will be an acceptable value.
     * @return {Boolean} TRUE if the value is valid, FALSE if not
     */
    ValidationService.isId = function(val, required) {
        if (!required && (val === null || val === undefined)) {
            return true;
        }

        var id = pb.DAO.getObjectId(val);
        return id instanceof ObjectID;
    };

    /**
     * Validates an email address
     * @deprecated
     * @method validateEmail
     * @param {String} value
     * @param {Boolean} [required=false]
     */
    ValidationService.validateEmail = function(value, required) {
        return ValidationService.isEmail(value, required);
    };

    /**
     * Validates an email address
     *
     * @method isEmail
     * @param {String} value
     * @param {Boolean} [required=false]
     */
    ValidationService.isEmail = function(value, required) {
        if (!value && !required) {
            return true;
        }

        return util.isString(value) && value.search(EMAIL_REGEX) !== -1;
    };

    /**
     * Validates a version number
     * @deprecated
     * @method validateVersionNum
     * @param {String} value
     * @param {Boolean} [required=false]
     */
    ValidationService.validateVersionNum = function(value, required) {
        return ValidationService.isVersionNum(value, required);
    };

    /**
     * Validates a version number
     *
     * @method isVersionNum
     * @param {String} value
     * @param {Boolean} [required=false]
     */
    ValidationService.isVersionNum = function(value, required) {
        if (!value && !required) {
            return true;
        }

        return util.isString(value) && value.search(VERSION_REGEX) !== -1;
    };

    /**
     * Validates a version expression
     *
     * @method isVersionExpression
     * @param {String} expression
     * @param {Boolean} [required=false]
     */
    ValidationService.isVersionExpression = function(expression, required) {
        if (!expression && !required) {
            return true;
        }
        return semver.validRange(expression) !== null;
    };

    /**
     * Validates an URL
     * @deprecated
     * @method validateUrl
     * @param {String} value
     * @param {Boolean} [required=false]
     */
    ValidationService.validateUrl = function(value, required) {
        return ValidationService.isUrl(value, required);
    };

    /**
     * Validates an URL
     *
     * @method isUrl
     * @param {String} value
     * @param {Boolean} [required=false]
     */
    ValidationService.isUrl = function(value, required) {
        if (!value && !required) {
            return true;
        }

        return util.isString(value) && (value.search(URL_REGEX) !== -1 || value.search(URL_REGEX_NO_HOST) !== -1);
    };

    /**
     * Validates a file name
     * @deprecated
     * @method validateSafeFileName
     * @param {String} value
     * @param {Boolean} [required=false]
     */
    ValidationService.validateSafeFileName = function(value, required) {
        return ValidationService.isSafeFileName(value, required);
    };

    /**
     * Validates a file name
     *
     * @method isSafeFileName
     * @param {String} value
     * @param {Boolean} [required=false]
     */
    ValidationService.isSafeFileName = function(value, required) {
        if (!value && !required) {
            return true;
        }

        return util.isString(value) && value.search(FILE_NAME_SAFE_REGEX) !== -1;
    };

    /**
     * Validates a string
     * @deprecated
     * @method validateStr
     * @param {String} value
     * @param {Boolean} [required=false]
     */
    ValidationService.validateStr = function(value, required) {
        return ValidationService.isStr(value, required);
    };

    /**
     * Validates a string
     *
     * @method isStr
     * @param {String} value
     * @param {Boolean} [required=false]
     */
    ValidationService.isStr = function(value, required) {
        if (!value && !required) {
            return true;
        }
        return util.isString(value);
    };

    /**
     * Validates a string is not empty
     * @deprecated
     * @method validateNonEmptyStr
     * @param {String} value
     * @param {Boolean} [required=false]
     */
    ValidationService.validateNonEmptyStr = function(value, required) {
        return ValidationService.isNonEmptyStr(value, required);
    };

    /**
     * Validates a string is not empty
     *
     * @method isNonEmptyStr
     * @param {String} value
     * @param {Boolean} [required=false]
     */
    ValidationService.isNonEmptyStr = function(value, required) {
        if (!value && !required) {
            return true;
        }
        return util.isString(value) && value.length > 0;
    };

    /**
     * Validates an array
     * @deprecated
     * @method validateArray
     * @param {Array} value
     * @param {Boolean} [required=false]
     */
    ValidationService.validateArray = function(value, required) {
        return ValidationService.isArray(value, required);
    };

    /**
     * Validates an array
     *
     * @method isArray
     * @param {Array} value
     * @param {Boolean} [required=false]
     */
    ValidationService.isArray = function(value, required) {
        if (!value && !required) {
            return true;
        }
        return util.isArray(value);
    };

    /**
     * Validates an object
     * @deprecated
     * @method validateObject
     * @param {Object} value
     * @param {Boolean} [required=false]
     */
    ValidationService.validateObject = function(value, required) {
        return ValidationService.isObj(value, required);
    };

    /**
     * Validates an object
     *
     * @method isObject
     * @param {Object} value
     * @param {Boolean} [required=false]
     */
    ValidationService.isObj = function(value, required) {
        if (!value && !required) {
            return true;
        }
        return util.isObject(value);
    };

    /**
     * Validates that the value is an integer.
     * @static
     * @method isInt
     * @param {Integer} val The value under test
     * @param {Boolean} [required=false] Indicates if the value is required. When
     * FALSE, null will be an acceptable value.
     * @param {Boolean} strict Indicates if the value must be a number rather than a string representing a number.
     * @return {Boolean} TRUE if the value is valid, FALSE if not
     */
    ValidationService.isInt = function(val, required, strict) {
        if (!required && (val === null || val === undefined)) {
            return true;
        }

        var parsed = parseInt(val, 10);
        if (strict && val !== parsed) {
            return false;
        }
        return val == parsed;
    };

    /**
     * Validates that the value is a float.
     * @static
     * @method isFloat
     * @param {*} val The value under test
     * @param {Boolean} [required=false] Indicates if the value is required. When
     * FALSE, null will be an acceptable value.
     * @param {Boolean} strict Indicates if the value must be a number rather than a string representing a number.
     * @return {Boolean} TRUE if the value is valid, FALSE if not
     */
    ValidationService.isFloat = function(val, required, strict) {
        if (!required && (val === null || val === undefined)) {
            return true;
        }

        var parsed = parseFloat(val);
        if ((Math.floor(parsed) === val) || (strict && val !== parsed)) {
            return false;
        }
        return val == parsed;
    };

    /**
     * Validates that the value is a number.
     * @static
     * @method isNum
     * @param {*} val The value under test
     * @param {Boolean} [required=false] Indicates if the value is required. When
     * FALSE, null will be an acceptable value.
     * @return {Boolean} TRUE if the value is valid, FALSE if not
     */
    ValidationService.isNum = function(val, required) {
        if (!required && (val === null || val === undefined)) {
            return true;
        }

        return !isNaN(val);
    };

    /**
     * Validates that the value is a boolean.
     * @static
     * @method isBool
     * @param {*} val The value under test
     * @return {Boolean} TRUE if the value is valid, FALSE if not
     */
    ValidationService.isBool = function(val) {
        return util.isBoolean(val);
    };

    /**
     * Validates that the value is null, defined, an empty object, and empty
     * array or an empty string.
     * @static
     * @method isEmpty
     * @param {*} val The value under test
     * @return {Boolean} TRUE if the value is valid, FALSE if not
     */
    ValidationService.isEmpty = function(val) {
        return val === null || val === undefined || val === '' || _.isEqual(val, {}) || _.isEqual(val, []);
    };

    /**
     * Validates that the value is a date object
     * @static
     * @method isDate
     * @param {*} val The value under test
     * @param {boolean} [required=false]
     * @return {Boolean} TRUE if the value is valid, FALSE if not
     */
    ValidationService.isDate = function(val, required) {
        if (!required && (val === null || val === undefined)) {
            return true;
        }
        return util.isDate(val) && !isNaN(val.getTime());
    };

    return ValidationService;
};