Skip to content
Toggle navigation
Projects
Groups
Snippets
Help
public
/
sequelize
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Settings
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
不要怂,就是干,撸起袖子干!
Commit 706744aa
authored
Mar 07, 2014
by
Thanasis Polychronakis
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
major refactoring of dao-validator module
1 parent
84509752
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
182 additions
and
99 deletions
lib/dao-validator.js
lib/dao-validator.js
View file @
706744a
...
@@ -3,6 +3,8 @@ var Validator = require("validator")
...
@@ -3,6 +3,8 @@ var Validator = require("validator")
,
sequelizeError
=
require
(
"./errors"
)
,
sequelizeError
=
require
(
"./errors"
)
,
Promise
=
require
(
"bluebird"
)
,
Promise
=
require
(
"bluebird"
)
function
noop
()
{}
// Backwards compat for people using old validation function
// Backwards compat for people using old validation function
// We cannot use .extend, since it coerces the first arg to string
// We cannot use .extend, since it coerces the first arg to string
Validator
.
notNull
=
function
(
val
)
{
Validator
.
notNull
=
function
(
val
)
{
...
@@ -81,16 +83,19 @@ Validator.extend('is', function(str, pattern, modifiers) {
...
@@ -81,16 +83,19 @@ Validator.extend('is', function(str, pattern, modifiers) {
* The Main DAO Validator.
* The Main DAO Validator.
*
*
* @param {sequelize.Model} modelInstance The model instance.
* @param {sequelize.Model} modelInstance The model instance.
* @param {Object
} o
ptions A dict with options.
* @param {Object
=} optO
ptions A dict with options.
* @constructor
* @constructor
*/
*/
var
DaoValidator
=
module
.
exports
=
function
(
modelInstance
,
options
)
{
var
DaoValidator
=
module
.
exports
=
function
(
modelInstance
,
optOptions
)
{
options
=
options
||
{}
var
options
=
optOptions
||
{}
options
.
skip
=
options
.
skip
||
[]
// assign defined and default options
this
.
options
=
Utils
.
_
.
defaults
(
options
,
{
skip
:
[],
});
this
.
modelInstance
=
modelInstance
this
.
modelInstance
=
modelInstance
this
.
chainer
=
new
Utils
.
QueryChainer
()
this
.
chainer
=
new
Utils
.
QueryChainer
()
this
.
options
=
options
/**
/**
* Expose validator.js to allow users to extend
* Expose validator.js to allow users to extend
...
@@ -104,7 +109,7 @@ var DaoValidator = module.exports = function(modelInstance, options) {
...
@@ -104,7 +109,7 @@ var DaoValidator = module.exports = function(modelInstance, options) {
* @type {Object} Will contain keys that correspond to attributes which will
* @type {Object} Will contain keys that correspond to attributes which will
* be Arrays of Errors.
* be Arrays of Errors.
*/
*/
this
.
errors
=
{}
;
this
.
errors
=
{}
/** @type {boolean} Indicates if validations are in progress */
/** @type {boolean} Indicates if validations are in progress */
this
.
inProgress
=
false
;
this
.
inProgress
=
false
;
...
@@ -123,27 +128,20 @@ DaoValidator.prototype.validate = function() {
...
@@ -123,27 +128,20 @@ DaoValidator.prototype.validate = function() {
throw
new
Error
(
'Validations already in progress.'
);
throw
new
Error
(
'Validations already in progress.'
);
}
}
this
.
inProgress
=
true
;
this
.
inProgress
=
true
;
this
.
errors
=
[];
this
.
errors
=
{}
var
self
=
this
var
self
=
this
return
new
Utils
.
CustomEventEmitter
(
function
(
emitter
)
{
return
new
Utils
.
CustomEventEmitter
(
function
(
emitter
)
{
Promise
.
settle
([
Promise
.
settle
([
self
.
_
validateAttribute
s
(),
self
.
_
builtinValidator
s
(),
self
.
_
validateSchema
(),
self
.
_
customValidators
(),
]).
then
(
function
()
{
]).
then
(
function
()
{
emitter
.
emit
(
'success'
)
if
(
Object
.
keys
(
self
.
errors
).
length
)
{
}).
catch
(
function
(
err
)
{
emitter
.
emit
(
'success'
,
self
.
errors
)
var
error
=
new
sequelizeError
.
ValidationError
(
'Validation error'
)
}
else
{
error
[
DaoValidator
.
RAW_KEY_NAME
]
=
[]
emitter
.
emit
(
'success'
)
}
Utils
.
_
.
each
(
err
,
function
(
value
)
{
})
error
[
DaoValidator
.
RAW_KEY_NAME
].
push
(
value
[
DaoValidator
.
RAW_KEY_NAME
]);
delete
value
[
DaoValidator
.
RAW_KEY_NAME
]
Utils
.
_
.
extend
(
error
,
value
)
})
emitter
.
emit
(
'success'
,
error
)
})
}).
run
()
}).
run
()
}
}
...
@@ -182,22 +180,30 @@ DaoValidator.prototype.hookValidate = function() {
...
@@ -182,22 +180,30 @@ DaoValidator.prototype.hookValidate = function() {
}
}
/**
/**
* Will
validate all attributes based on their schema rules and defined
validators.
* Will
run all the built-in
validators.
*
*
* @return {Promise(Array.<Promise.PromiseInspection>)} A promise from .settle().
* @return {Promise(Array.<Promise.PromiseInspection>)} A promise from .settle().
* @private
* @private
*/
*/
DaoValidator
.
prototype
.
_
validateAttribute
s
=
function
()
{
DaoValidator
.
prototype
.
_
builtinValidator
s
=
function
()
{
var
self
=
this
var
self
=
this
// promisify all attribute invocations
// promisify all attribute invocations
var
validators
=
[];
var
validators
=
[];
_
.
forIn
(
this
.
modelInstance
.
rawAttributes
,
function
(
rawAttribute
,
field
)
{
Utils
.
_
.
forIn
(
this
.
modelInstance
.
rawAttributes
,
function
(
rawAttribute
,
field
)
{
if
(
self
.
options
.
skip
.
indexOf
(
field
)
>=
0
)
{
return
}
var
value
=
self
.
modelInstance
.
dataValues
[
field
]
var
value
=
self
.
modelInstance
.
dataValues
[
field
]
if
(
self
.
modelInstance
.
validators
.
hasOwnProperty
(
field
))
{
validators
.
push
(
self
.
_validateAttribute
(
value
,
field
))
if
(
!
rawAttribute
.
_autoGenerated
)
{
// perform validations based on schema
self
.
_validateSchema
(
rawAttribute
,
field
,
value
)
}
if
(
self
.
modelInstance
.
validators
.
hasOwnProperty
(
field
))
{
validators
.
push
(
self
.
_builtinAttrValidate
.
call
(
self
,
value
,
field
))
}
}
})
})
...
@@ -205,42 +211,30 @@ DaoValidator.prototype._validateAttributes = function() {
...
@@ -205,42 +211,30 @@ DaoValidator.prototype._validateAttributes = function() {
}
}
/**
/**
* Will
validate a single field against its schema definition (isnull)
.
* Will
run all the custom validators
.
*
*
* @param {string} field The field name.
* @return {Promise(Array.<Promise.PromiseInspection>)} A promise from .settle().
* @param {*} value anything.
throw error;
* @return {Promise} A promise, will always resolve,
* auto populates error on this.error local object.
* @private
* @private
*/
*/
DaoValidator
.
prototype
.
_validateSchema
=
function
(
field
,
value
)
{
DaoValidator
.
prototype
.
_customValidators
=
function
()
{
var
validators
=
[];
var
self
=
this
;
var
self
=
this
;
return
new
Promise
(
function
(
resolve
)
{
Utils
.
_
.
each
(
this
.
modelInstance
.
__options
.
validate
,
function
(
validator
,
validatorType
)
{
var
hasAllowedNull
=
((
rawAttribute
===
undefined
||
rawAttribute
.
allowNull
===
true
)
&&
((
value
===
null
)
||
(
value
===
undefined
)))
var
isSkipped
=
self
.
options
.
skip
.
length
>
0
&&
self
.
options
.
skip
.
indexOf
(
field
)
!==
-
1
if
(
!
hasAllowedNull
&&
!
isSkipped
)
{
var
error
=
new
sequelizeError
.
ValidationError
(
field
+
' cannot be null'
)
error
.
path
=
field
error
.
value
=
value
error
.
type
=
'notNull Violation'
if
(
!
self
.
errors
[
field
])
{
self
.
errors
[
field
]
=
[];
}
self
.
errors
[
field
].
push
(
error
);
}
resolve
();
var
valprom
=
self
.
_invokeCustomValidator
(
validator
,
validatorType
)
});
// errors are handled in settling, stub this
};
.
catch
(
noop
)
validators
.
push
(
valprom
)
})
return
Promise
.
settle
(
validators
)
}
/**
/**
* Validate a single attribute with all the defined validators.
* Validate a single attribute with all the defined
built-in
validators.
*
*
* @param {*} value Anything.
* @param {*} value Anything.
* @param {string} field The field name.
* @param {string} field The field name.
...
@@ -248,86 +242,175 @@ DaoValidator.prototype._validateSchema = function(field, value) {
...
@@ -248,86 +242,175 @@ DaoValidator.prototype._validateSchema = function(field, value) {
* auto populates error on this.error local object.
* auto populates error on this.error local object.
* @private
* @private
*/
*/
DaoValidator
.
prototype
.
_
validateAttribu
te
=
function
(
value
,
field
)
{
DaoValidator
.
prototype
.
_
builtinAttrValida
te
=
function
(
value
,
field
)
{
var
self
=
this
;
var
self
=
this
;
// Promisify each validator
// Promisify each validator
var
validators
=
[];
var
validators
=
[];
Utils
.
_
.
forIn
(
this
.
modelInstance
.
validators
[
field
],
function
(
details
,
Utils
.
_
.
forIn
(
this
.
modelInstance
.
validators
[
field
],
function
(
test
,
validatorType
)
{
validatorType
)
{
var
validator
=
self
.
_prepareValidationOfAttribute
.
call
(
self
,
value
,
details
,
// Check for custom validator.
validatorType
);
if
(
typeof
test
===
'function'
)
{
return
validators
.
push
(
self
.
_invokeCustomValidator
(
test
,
validatorType
,
true
,
value
,
field
))
}
validators
.
push
(
Promise
.
nodeify
(
validator
));
var
validatorPromise
=
self
.
_invokeBuiltinValidator
(
value
,
test
,
validatorType
);
// errors are handled in settling, stub this
validatorPromise
.
catch
(
noop
)
validators
.
push
(
validatorPromise
)
});
});
return
Promise
.
settle
(
validators
)
return
Promise
.
settle
(
validators
)
.
then
(
this
.
_handleSettledResult
.
bind
(
this
,
field
))
;
.
then
(
this
.
_handleSettledResult
.
bind
(
this
,
field
))
};
};
/**
/**
* Prepare Attribute for validation.
* Prepare and invoke a custom validator.
*
* @param {Function} validator The custom validator.
* @param {string} validatorType the custom validator type (name).
* @param {boolean=} optAttrDefined Set to true if custom validator was defined
* from the Attribute
* @return {Promise} A promise.
* @private
*/
DaoValidator
.
prototype
.
_invokeCustomValidator
=
Promise
.
method
(
function
(
validator
,
validatorType
,
optAttrDefined
,
optValue
,
optField
)
{
var
validatorFunction
=
null
// the validation function to call
var
isAsync
=
false
var
validatorArity
=
validator
.
length
;
// check if validator is async and requires a callback
var
asyncArity
=
1
;
var
errorKey
=
validatorType
;
var
invokeArgs
;
if
(
optAttrDefined
)
{
asyncArity
=
2
;
invokeArgs
=
optValue
;
errorKey
=
optField
;
}
if
(
validatorArity
===
asyncArity
)
{
isAsync
=
true
;
}
if
(
isAsync
)
{
if
(
optAttrDefined
)
{
validatorFunction
=
Promise
.
promisify
(
validator
.
bind
(
this
.
modelInstance
,
invokeArgs
))
}
else
{
validatorFunction
=
Promise
.
promisify
(
validator
.
bind
(
this
.
modelInstance
))
}
return
validatorFunction
()
.
catch
(
this
.
_pushError
.
bind
(
this
,
false
,
errorKey
))
}
else
{
return
Promise
.
try
(
validator
.
bind
(
this
.
modelInstance
,
invokeArgs
))
.
catch
(
this
.
_pushError
.
bind
(
this
,
false
,
errorKey
))
}
})
/**
* Prepare and invoke a build-in validator.
*
*
* @param {*} value Anything
* @param {*} value Anything
.
* @param {
Function} validator The validator
.
* @param {
*} test The test case
.
* @param {string} validatorType One of known to Sequelize validators.
* @param {string} validatorType One of known to Sequelize validators.
* @param {Object=} optOptions Options
* @return {Object} An object with specific keys to invoke the validator.
* @return {Object} An object with specific keys to invoke the validator.
* @private
* @private
*/
*/
DaoValidator
.
prototype
.
_prepareValidationOfAttribute
=
function
(
value
,
validator
,
DaoValidator
.
prototype
.
_invokeBuiltinValidator
=
Promise
.
method
(
function
(
value
,
validatorType
,
optOptions
)
{
test
,
validatorType
)
{
var
isCustomValidator
=
false
// if true then it's a custom validation method
,
validatorFunction
=
null
// the validation function to call
// it is a custom validator function?
// check if Validator knows that kind of validation test
isCustomValidator
=
true
if
(
typeof
Validator
[
validatorType
]
!==
'function'
)
{
throw
new
Error
(
'Invalid validator function: '
+
validatorType
)
}
var
validatorArity
=
validator
.
length
;
// extract extra arguments for the validator
var
callArgs
=
[]
var
validatorArgs
=
test
.
hasOwnProperty
(
'args'
)
?
test
.
args
:
test
;
var
options
=
optOptions
||
{}
// extract the error msg
var
omitValue
=
!!
options
.
omitValue
var
errorMessage
=
test
.
hasOwnProperty
(
'msg'
)
?
test
.
msg
:
'Validation '
+
validatorType
+
' failed'
if
(
!
omitValue
)
{
callArgs
.
push
(
value
)
}
// check if validator is async and requires a callback
if
(
!
Array
.
isArray
(
validatorArgs
))
{
var
isAsync
=
false
validatorArgs
=
[
validatorArgs
]
if
(
omitValue
&&
validatorArity
===
1
||
!
omitValue
&&
validatorArity
===
2
)
{
}
else
{
isAsync
=
true
;
validatorArgs
=
validatorArgs
.
slice
(
0
);
}
if
(
!
Validator
[
validatorType
].
apply
(
Validator
,
[
value
].
concat
(
validatorArgs
)))
{
throw
errorMessage
}
}
});
validatorFunction
=
Promise
.
nodeify
(
validator
.
bind
(
this
.
modelInstance
))
return
{
/**
fn
:
validatorFunction
,
* Will validate a single field against its schema definition (isnull).
msg
:
errorMessage
,
*
args
:
validatorArgs
,
* @param {Object} rawAttribute As defined in the Schema.
isCustom
:
isCustomValidator
* @param {string} field The field name.
* @param {*} value anything.
* @private
*/
DaoValidator
.
prototype
.
_validateSchema
=
function
(
rawAttribute
,
field
,
value
)
{
if
(
rawAttribute
.
allowNull
===
false
&&
((
value
===
null
)
||
(
value
===
undefined
)))
{
var
error
=
new
sequelizeError
.
ValidationError
(
field
+
' cannot be null'
)
error
.
path
=
field
error
.
value
=
value
error
.
type
=
'notNull Violation'
if
(
!
this
.
errors
.
hasOwnProperty
(
field
))
{
this
.
errors
[
field
]
=
[];
}
this
.
errors
[
field
].
push
(
error
);
}
}
}
};
/**
/**
* Handles the returned result of a Promise.settle.
* Handles the returned result of a Promise.settle.
*
*
* If errors are found it populates this.error
and throws an Array of the errors
.
* If errors are found it populates this.error.
*
*
* @param {string} field The attribute name.
* @param {string} field The attribute name.
* @param {Array.<Promise.PromiseInspection>} Promise inspection objects.
* @param {Array.<Promise.PromiseInspection>} Promise inspection objects.
* @private
* @private
*/
*/
DaoValidator
.
prototype
.
_handleSettleResult
=
function
(
field
,
promiseInspections
)
{
DaoValidator
.
prototype
.
_handleSettle
d
Result
=
function
(
field
,
promiseInspections
)
{
var
self
=
this
;
var
self
=
this
;
promiseInspections
.
forEach
(
function
(
promiseInspection
)
{
promiseInspections
.
forEach
(
function
(
promiseInspection
)
{
if
(
promiseInspection
.
isRejected
)
{
if
(
promiseInspection
.
isRejected
()
)
{
var
rejection
=
promiseInspection
.
error
();
var
rejection
=
promiseInspection
.
error
();
var
error
=
new
sequelizeError
.
ValidationError
(
'Validation error'
)
self
.
_pushError
(
true
,
field
,
rejection
);
error
[
DaoValidator
.
RAW_KEY_NAME
]
=
rejection
if
(
!
self
.
errors
[
field
])
{
self
.
errors
[
field
]
=
[];
}
self
.
errors
[
field
].
push
(
error
);
}
}
});
});
};
};
/**
* Signs all errors retaining the original.
*
* @param {boolean} isBuiltin Determines if error is from builtin validator.
* @param {string} errorKey The error key to assign on this.errors object.
* @param {Error|string} rawError The original error.
* @private
*/
DaoValidator
.
prototype
.
_pushError
=
function
(
isBuiltin
,
errorKey
,
rawError
)
{
if
(
!
this
.
errors
.
hasOwnProperty
(
errorKey
))
{
this
.
errors
[
errorKey
]
=
[];
}
if
(
isBuiltin
)
{
this
.
errors
[
errorKey
].
push
(
rawError
);
return
;
}
var
error
=
new
sequelizeError
.
ValidationError
()
error
[
DaoValidator
.
RAW_KEY_NAME
]
=
rawError
error
.
message
=
rawError
.
message
||
rawError
||
'Validation error'
this
.
errors
[
errorKey
].
push
(
error
);
};
Write
Preview
Markdown
is supported
Attach a file
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to post a comment