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
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
178 additions
and
95 deletions
lib/dao-validator.js
lib/dao-validator.js
View file @
706744a
...
...
@@ -3,6 +3,8 @@ var Validator = require("validator")
,
sequelizeError
=
require
(
"./errors"
)
,
Promise
=
require
(
"bluebird"
)
function
noop
()
{}
// Backwards compat for people using old validation function
// We cannot use .extend, since it coerces the first arg to string
Validator
.
notNull
=
function
(
val
)
{
...
...
@@ -81,16 +83,19 @@ Validator.extend('is', function(str, pattern, modifiers) {
* The Main DAO Validator.
*
* @param {sequelize.Model} modelInstance The model instance.
* @param {Object
} o
ptions A dict with options.
* @param {Object
=} optO
ptions A dict with options.
* @constructor
*/
var
DaoValidator
=
module
.
exports
=
function
(
modelInstance
,
options
)
{
options
=
options
||
{}
options
.
skip
=
options
.
skip
||
[]
var
DaoValidator
=
module
.
exports
=
function
(
modelInstance
,
optOptions
)
{
var
options
=
optOptions
||
{}
// assign defined and default options
this
.
options
=
Utils
.
_
.
defaults
(
options
,
{
skip
:
[],
});
this
.
modelInstance
=
modelInstance
this
.
chainer
=
new
Utils
.
QueryChainer
()
this
.
options
=
options
/**
* Expose validator.js to allow users to extend
...
...
@@ -104,7 +109,7 @@ var DaoValidator = module.exports = function(modelInstance, options) {
* @type {Object} Will contain keys that correspond to attributes which will
* be Arrays of Errors.
*/
this
.
errors
=
{}
;
this
.
errors
=
{}
/** @type {boolean} Indicates if validations are in progress */
this
.
inProgress
=
false
;
...
...
@@ -123,26 +128,19 @@ DaoValidator.prototype.validate = function() {
throw
new
Error
(
'Validations already in progress.'
);
}
this
.
inProgress
=
true
;
this
.
errors
=
[];
this
.
errors
=
{}
var
self
=
this
return
new
Utils
.
CustomEventEmitter
(
function
(
emitter
)
{
Promise
.
settle
([
self
.
_
validateAttribute
s
(),
self
.
_
validateSchema
(),
self
.
_
builtinValidator
s
(),
self
.
_
customValidators
(),
]).
then
(
function
()
{
if
(
Object
.
keys
(
self
.
errors
).
length
)
{
emitter
.
emit
(
'success'
,
self
.
errors
)
}
else
{
emitter
.
emit
(
'success'
)
}).
catch
(
function
(
err
)
{
var
error
=
new
sequelizeError
.
ValidationError
(
'Validation error'
)
error
[
DaoValidator
.
RAW_KEY_NAME
]
=
[]
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
()
}
...
...
@@ -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().
* @private
*/
DaoValidator
.
prototype
.
_
validateAttribute
s
=
function
()
{
DaoValidator
.
prototype
.
_
builtinValidator
s
=
function
()
{
var
self
=
this
// promisify all attribute invocations
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
]
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() {
}
/**
* Will
validate a single field against its schema definition (isnull)
.
* Will
run all the custom validators
.
*
* @param {string} field The field name.
* @param {*} value anything.
throw error;
* @return {Promise} A promise, will always resolve,
* auto populates error on this.error local object.
* @return {Promise(Array.<Promise.PromiseInspection>)} A promise from .settle().
* @private
*/
DaoValidator
.
prototype
.
_validateSchema
=
function
(
field
,
value
)
{
DaoValidator
.
prototype
.
_customValidators
=
function
()
{
var
validators
=
[];
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
var
valprom
=
self
.
_invokeCustomValidator
(
validator
,
validatorType
)
// errors are handled in settling, stub this
.
catch
(
noop
)
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
);
}
validators
.
push
(
valprom
)
})
resolve
();
});
};
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 {string} field The field name.
...
...
@@ -248,86 +242,175 @@ DaoValidator.prototype._validateSchema = function(field, value) {
* auto populates error on this.error local object.
* @private
*/
DaoValidator
.
prototype
.
_
validateAttribu
te
=
function
(
value
,
field
)
{
DaoValidator
.
prototype
.
_
builtinAttrValida
te
=
function
(
value
,
field
)
{
var
self
=
this
;
// Promisify each validator
var
validators
=
[];
Utils
.
_
.
forIn
(
this
.
modelInstance
.
validators
[
field
],
function
(
details
,
Utils
.
_
.
forIn
(
this
.
modelInstance
.
validators
[
field
],
function
(
test
,
validatorType
)
{
var
validator
=
self
.
_prepareValidationOfAttribute
.
call
(
self
,
value
,
details
,
validatorType
);
// Check for custom validator.
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
)
.
then
(
this
.
_handleSettledResult
.
bind
(
this
,
field
))
;
.
then
(
this
.
_handleSettledResult
.
bind
(
this
,
field
))
};
/**
* Prepare
Attribute for validation
.
* Prepare
and invoke a custom validator
.
*
* @param {*} value Anything
* @param {Function} validator The 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 {*} test The test case.
* @param {string} validatorType One of known to Sequelize validators.
* @param {Object=} optOptions Options
* @return {Object} An object with specific keys to invoke the validator.
* @private
*/
DaoValidator
.
prototype
.
_prepareValidationOfAttribute
=
function
(
value
,
validator
,
validatorType
,
optOptions
)
{
var
isCustomValidator
=
false
// if true then it's a custom validation method
,
validatorFunction
=
null
// the validation function to call
DaoValidator
.
prototype
.
_invokeBuiltinValidator
=
Promise
.
method
(
function
(
value
,
test
,
validatorType
)
{
// it is a custom validator function?
isCustomValidator
=
true
// check if Validator knows that kind of validation test
if
(
typeof
Validator
[
validatorType
]
!==
'function'
)
{
throw
new
Error
(
'Invalid validator function: '
+
validatorType
)
}
var
validatorArity
=
validator
.
length
;
var
callArgs
=
[]
var
options
=
optOptions
||
{}
var
omitValue
=
!!
options
.
omitValue
// extract extra arguments for the validator
var
validatorArgs
=
test
.
hasOwnProperty
(
'args'
)
?
test
.
args
:
test
;
// extract the error msg
var
errorMessage
=
test
.
hasOwnProperty
(
'msg'
)
?
test
.
msg
:
'Validation '
+
validatorType
+
' failed'
if
(
!
omitValue
)
{
callArgs
.
push
(
value
)
}
// check if validator is async and requires a callback
var
isAsync
=
false
if
(
omitValue
&&
validatorArity
===
1
||
!
omitValue
&&
validatorArity
===
2
)
{
isAsync
=
true
;
if
(
!
Array
.
isArray
(
validatorArgs
))
{
validatorArgs
=
[
validatorArgs
]
}
else
{
validatorArgs
=
validatorArgs
.
slice
(
0
)
;
}
if
(
!
Validator
[
validatorType
].
apply
(
Validator
,
[
value
].
concat
(
validatorArgs
)))
{
throw
errorMessage
}
});
validatorFunction
=
Promise
.
nodeify
(
validator
.
bind
(
this
.
modelInstance
))
/**
* Will validate a single field against its schema definition (isnull).
*
* @param {Object} rawAttribute As defined in the Schema.
* @param {string} field The field name.
* @param {*} value anything.
* @private
*/
DaoValidator
.
prototype
.
_validateSchema
=
function
(
rawAttribute
,
field
,
value
)
{
return
{
fn
:
validatorFunction
,
msg
:
errorMessage
,
args
:
validatorArgs
,
isCustom
:
isCustomValidator
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.
*
* 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 {Array.<Promise.PromiseInspection>} Promise inspection objects.
* @private
*/
DaoValidator
.
prototype
.
_handleSettleResult
=
function
(
field
,
promiseInspections
)
{
DaoValidator
.
prototype
.
_handleSettle
d
Result
=
function
(
field
,
promiseInspections
)
{
var
self
=
this
;
promiseInspections
.
forEach
(
function
(
promiseInspection
)
{
if
(
promiseInspection
.
isRejected
)
{
if
(
promiseInspection
.
isRejected
()
)
{
var
rejection
=
promiseInspection
.
error
();
var
error
=
new
sequelizeError
.
ValidationError
(
'Validation error'
)
error
[
DaoValidator
.
RAW_KEY_NAME
]
=
rejection
if
(
!
self
.
errors
[
field
])
{
self
.
errors
[
field
]
=
[];
}
self
.
errors
[
field
].
push
(
error
);
self
.
_pushError
(
true
,
field
,
rejection
);
}
});
};
/**
* 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