You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

7 lines
18 KiB

{
"version": 3,
"sources": ["../src/instance-validator.js"],
"sourcesContent": ["'use strict';\n\nconst _ = require('lodash');\nconst Utils = require('./utils');\nconst sequelizeError = require('./errors');\nconst DataTypes = require('./data-types');\nconst BelongsTo = require('./associations/belongs-to');\nconst validator = require('./utils/validator-extras').validator;\nconst { promisify } = require('util');\n\n/**\n * Instance Validator.\n *\n * @param {Instance} modelInstance The model instance.\n * @param {object} options A dictionary with options.\n *\n * @private\n */\nclass InstanceValidator {\n constructor(modelInstance, options) {\n options = {\n // assign defined and default options\n hooks: true,\n ...options\n };\n\n if (options.fields && !options.skip) {\n options.skip = _.difference(Object.keys(modelInstance.constructor.rawAttributes), options.fields);\n } else {\n options.skip = options.skip || [];\n }\n\n this.options = options;\n\n this.modelInstance = modelInstance;\n\n /**\n * Exposes a reference to validator.js. This allows you to add custom validations using `validator.extend`\n *\n * @name validator\n * @private\n */\n this.validator = validator;\n\n /**\n * All errors will be stored here from the validations.\n *\n * @type {Array} Will contain keys that correspond to attributes which will\n * be Arrays of Errors.\n * @private\n */\n this.errors = [];\n\n /**\n * @type {boolean} Indicates if validations are in progress\n * @private\n */\n this.inProgress = false;\n }\n\n /**\n * The main entry point for the Validation module, invoke to start the dance.\n *\n * @returns {Promise}\n * @private\n */\n async _validate() {\n if (this.inProgress) throw new Error('Validations already in progress.');\n\n this.inProgress = true;\n\n await Promise.all([\n this._perAttributeValidators(),\n this._customValidators()\n ]);\n\n if (this.errors.length) {\n throw new sequelizeError.ValidationError(null, this.errors);\n }\n }\n\n /**\n * Invoke the Validation sequence and run validation hooks if defined\n * - Before Validation Model Hooks\n * - Validation\n * - On validation success: After Validation Model Hooks\n * - On validation failure: Validation Failed Model Hooks\n *\n * @returns {Promise}\n * @private\n */\n async validate() {\n return await (this.options.hooks ? this._validateAndRunHooks() : this._validate());\n }\n\n /**\n * Invoke the Validation sequence and run hooks\n * - Before Validation Model Hooks\n * - Validation\n * - On validation success: After Validation Model Hooks\n * - On validation failure: Validation Failed Model Hooks\n *\n * @returns {Promise}\n * @private\n */\n async _validateAndRunHooks() {\n const runHooks = this.modelInstance.constructor.runHooks.bind(this.modelInstance.constructor);\n await runHooks('beforeValidate', this.modelInstance, this.options);\n\n try {\n await this._validate();\n } catch (error) {\n const newError = await runHooks('validationFailed', this.modelInstance, this.options, error);\n throw newError || error;\n }\n\n await runHooks('afterValidate', this.modelInstance, this.options);\n return this.modelInstance;\n }\n\n /**\n * Will run all the validators defined per attribute (built-in validators and custom validators)\n *\n * @returns {Promise<Array>}\n * @private\n */\n async _perAttributeValidators() {\n // promisify all attribute invocations\n const validators = [];\n\n _.forIn(this.modelInstance.rawAttributes, (rawAttribute, field) => {\n if (this.options.skip.includes(field)) {\n return;\n }\n\n const value = this.modelInstance.dataValues[field];\n\n if (value instanceof Utils.SequelizeMethod) {\n return;\n }\n\n if (!rawAttribute._autoGenerated && !rawAttribute.autoIncrement) {\n // perform validations based on schema\n this._validateSchema(rawAttribute, field, value);\n }\n\n if (Object.prototype.hasOwnProperty.call(this.modelInstance.validators, field)) {\n validators.push(this._singleAttrValidate(value, field, rawAttribute.allowNull));\n }\n });\n\n return await Promise.all(validators);\n }\n\n /**\n * Will run all the custom validators defined in the model's options.\n *\n * @returns {Promise<Array>}\n * @private\n */\n async _customValidators() {\n const validators = [];\n _.each(this.modelInstance.constructor.options.validate, (validator, validatorType) => {\n if (this.options.skip.includes(validatorType)) {\n return;\n }\n\n const valprom = this._invokeCustomValidator(validator, validatorType)\n // errors are handled in settling, stub this\n .catch(() => {});\n\n validators.push(valprom);\n });\n\n return await Promise.all(validators);\n }\n\n /**\n * Validate a single attribute with all the defined built-in validators and custom validators.\n *\n * @private\n *\n * @param {*} value Anything.\n * @param {string} field The field name.\n * @param {boolean} allowNull Whether or not the schema allows null values\n *\n * @returns {Promise} A promise, will always resolve, auto populates error on this.error local object.\n */\n async _singleAttrValidate(value, field, allowNull) {\n // If value is null and allowNull is false, no validators should run (see #9143)\n if ((value === null || value === undefined) && !allowNull) {\n // The schema validator (_validateSchema) has already generated the validation error. Nothing to do here.\n return;\n }\n\n // Promisify each validator\n const validators = [];\n _.forIn(this.modelInstance.validators[field], (test, validatorType) => {\n\n if (['isUrl', 'isURL', 'isEmail'].includes(validatorType)) {\n // Preserve backwards compat. Validator.js now expects the second param to isURL and isEmail to be an object\n if (typeof test === 'object' && test !== null && test.msg) {\n test = {\n msg: test.msg\n };\n } else if (test === true) {\n test = {};\n }\n }\n\n // Custom validators should always run, except if value is null and allowNull is false (see #9143)\n if (typeof test === 'function') {\n validators.push(this._invokeCustomValidator(test, validatorType, true, value, field));\n return;\n }\n\n // If value is null, built-in validators should not run (only custom validators have to run) (see #9134).\n if (value === null || value === undefined) {\n return;\n }\n\n const validatorPromise = this._invokeBuiltinValidator(value, test, validatorType, field);\n // errors are handled in settling, stub this\n validatorPromise.catch(() => {});\n validators.push(validatorPromise);\n });\n\n return Promise\n .all(validators.map(validator => validator.catch(rejection => {\n const isBuiltIn = !!rejection.validatorName;\n this._pushError(isBuiltIn, field, rejection, value, rejection.validatorName, rejection.validatorArgs);\n })));\n }\n\n /**\n * Prepare and invoke a custom validator.\n *\n * @private\n *\n * @param {Function} validator The custom validator.\n * @param {string} validatorType the custom validator type (name).\n * @param {boolean} optAttrDefined Set to true if custom validator was defined from the attribute\n * @param {*} optValue value for attribute\n * @param {string} optField field for attribute\n *\n * @returns {Promise} A promise.\n */\n async _invokeCustomValidator(validator, validatorType, optAttrDefined, optValue, optField) {\n let isAsync = false;\n\n const validatorArity = validator.length;\n // check if validator is async and requires a callback\n let asyncArity = 1;\n let errorKey = validatorType;\n let invokeArgs;\n if (optAttrDefined) {\n asyncArity = 2;\n invokeArgs = optValue;\n errorKey = optField;\n }\n if (validatorArity === asyncArity) {\n isAsync = true;\n }\n\n if (isAsync) {\n try {\n if (optAttrDefined) {\n return await promisify(validator.bind(this.modelInstance, invokeArgs))();\n }\n return await promisify(validator.bind(this.modelInstance))();\n } catch (e) {\n return this._pushError(false, errorKey, e, optValue, validatorType);\n }\n }\n\n try {\n return await validator.call(this.modelInstance, invokeArgs);\n } catch (e) {\n return this._pushError(false, errorKey, e, optValue, validatorType);\n }\n }\n\n /**\n * Prepare and invoke a build-in validator.\n *\n * @private\n *\n * @param {*} value Anything.\n * @param {*} test The test case.\n * @param {string} validatorType One of known to Sequelize validators.\n * @param {string} field The field that is being validated\n *\n * @returns {object} An object with specific keys to invoke the validator.\n */\n async _invokeBuiltinValidator(value, test, validatorType, field) {\n // Cast value as string to pass new Validator.js string requirement\n const valueString = String(value);\n // check if Validator knows that kind of validation test\n if (typeof validator[validatorType] !== 'function') {\n throw new Error(`Invalid validator function: ${validatorType}`);\n }\n\n const validatorArgs = this._extractValidatorArgs(test, validatorType, field);\n\n if (!validator[validatorType](valueString, ...validatorArgs)) {\n throw Object.assign(new Error(test.msg || `Validation ${validatorType} on ${field} failed`), { validatorName: validatorType, validatorArgs });\n }\n }\n\n /**\n * Will extract arguments for the validator.\n *\n * @param {*} test The test case.\n * @param {string} validatorType One of known to Sequelize validators.\n * @param {string} field The field that is being validated.\n *\n * @private\n */\n _extractValidatorArgs(test, validatorType, field) {\n let validatorArgs = test.args || test;\n const isLocalizedValidator = typeof validatorArgs !== 'string' && ['isAlpha', 'isAlphanumeric', 'isMobilePhone'].includes(validatorType);\n\n if (!Array.isArray(validatorArgs)) {\n if (validatorType === 'isImmutable') {\n validatorArgs = [validatorArgs, field, this.modelInstance];\n } else if (isLocalizedValidator || validatorType === 'isIP') {\n validatorArgs = [];\n } else {\n validatorArgs = [validatorArgs];\n }\n } else {\n validatorArgs = validatorArgs.slice(0);\n }\n return validatorArgs;\n }\n\n /**\n * Will validate a single field against its schema definition (isnull).\n *\n * @param {object} rawAttribute As defined in the Schema.\n * @param {string} field The field name.\n * @param {*} value anything.\n *\n * @private\n */\n _validateSchema(rawAttribute, field, value) {\n if (rawAttribute.allowNull === false && (value === null || value === undefined)) {\n const association = Object.values(this.modelInstance.constructor.associations).find(association => association instanceof BelongsTo && association.foreignKey === rawAttribute.fieldName);\n if (!association || !this.modelInstance.get(association.associationAccessor)) {\n const validators = this.modelInstance.validators[field];\n const errMsg = _.get(validators, 'notNull.msg', `${this.modelInstance.constructor.name}.${field} cannot be null`);\n\n this.errors.push(new sequelizeError.ValidationErrorItem(\n errMsg,\n 'notNull Violation', // sequelizeError.ValidationErrorItem.Origins.CORE,\n field,\n value,\n this.modelInstance,\n 'is_null'\n ));\n }\n }\n\n if (rawAttribute.type instanceof DataTypes.STRING || rawAttribute.type instanceof DataTypes.TEXT || rawAttribute.type instanceof DataTypes.CITEXT) {\n if (Array.isArray(value) || _.isObject(value) && !(value instanceof Utils.SequelizeMethod) && !Buffer.isBuffer(value)) {\n this.errors.push(new sequelizeError.ValidationErrorItem(\n `${field} cannot be an array or an object`,\n 'string violation', // sequelizeError.ValidationErrorItem.Origins.CORE,\n field,\n value,\n this.modelInstance,\n 'not_a_string'\n ));\n }\n }\n }\n\n /**\n * Signs all errors retaining the original.\n *\n * @param {boolean} isBuiltin - Determines if error is from builtin validator.\n * @param {string} errorKey - name of invalid attribute.\n * @param {Error|string} rawError - The original error.\n * @param {string|number} value - The data that triggered the error.\n * @param {string} fnName - Name of the validator, if any\n * @param {Array} fnArgs - Arguments for the validator [function], if any\n *\n * @private\n */\n _pushError(isBuiltin, errorKey, rawError, value, fnName, fnArgs) {\n const message = rawError.message || rawError || 'Validation error';\n const error = new sequelizeError.ValidationErrorItem(\n message,\n 'Validation error', // sequelizeError.ValidationErrorItem.Origins.FUNCTION,\n errorKey,\n value,\n this.modelInstance,\n fnName,\n isBuiltin ? fnName : undefined,\n isBuiltin ? fnArgs : undefined\n );\n\n error[InstanceValidator.RAW_KEY_NAME] = rawError;\n\n this.errors.push(error);\n }\n}\n/**\n * The error key for arguments as passed by custom validators\n *\n * @type {string}\n * @private\n */\nInstanceValidator.RAW_KEY_NAME = 'original';\n\nmodule.exports = InstanceValidator;\nmodule.exports.InstanceValidator = InstanceValidator;\nmodule.exports.default = InstanceValidator;\n"],
"mappings": "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",
"names": []
}