From b76b01450a5f3d90b92298b1204da474e8568133 Mon Sep 17 00:00:00 2001 From: Eric Byers Date: Wed, 15 Apr 2015 16:52:31 -0500 Subject: [PATCH 1/5] Split external and internal modules apart, add additional RequestValidation functions, extend Express Request to include RequestValidation. --- express-validator/express-validator.d.ts | 325 ++++++++++++----------- 1 file changed, 171 insertions(+), 154 deletions(-) diff --git a/express-validator/express-validator.d.ts b/express-validator/express-validator.d.ts index 5a5df2fa0..6ec5ece9e 100644 --- a/express-validator/express-validator.d.ts +++ b/express-validator/express-validator.d.ts @@ -5,169 +5,186 @@ /// +// Add RequestValidation Interface on to Express's Request Interface. +declare module Express { + interface Request extends ExpressValidator.RequestValidation {} +} +// External express-validator module. declare module "express-validator" { import express = require('express'); - module ExpressValidator { - - export interface ValidationError { - msg: string; - param: string; - } - - export interface RequestValidation { - check(field:string, message:string): Validator; - assert(field:string, message:string): Validator; - sanitize(field:string): Sanitizer; - onValidationError(func:(msg:string) => void): void; - validationErrors() : any; - } - - export interface Validator { - /** - * Alias for regex() - */ - is(): Validator; - /** - * Alias for notRegex() - */ - not(): Validator; - isEmail(): Validator; - /** - * Accepts http, https, ftp - */ - isUrl(): Validator; - /** - * Combines isIPv4 and isIPv6 - */ - isIP(): Validator; - isIPv4(): Validator; - isIPv6(): Validator; - isAlpha(): Validator; - isAlphanumeric(): Validator; - isNumeric(): Validator; - isHexadecimal(): Validator; - /** - * Accepts valid hexcolors with or without # prefix - */ - isHexColor(): Validator; - /** - * isNumeric accepts zero padded numbers, e.g. '001', isInt doesn't - */ - isInt(): Validator; - isLowercase(): Validator; - isUppercase(): Validator; - isDecimal(): Validator; - /** - * Alias for isDecimal - */ - isFloat(): Validator; - /** - * Check if length is 0 - */ - notNull(): Validator; - isNull(): Validator; - /** - * Not just whitespace (input.trim().length !== 0) - */ - notEmpty(): Validator; - equals(equals:any): Validator; - contains(str:string): Validator; - notContains(str:string): Validator; - /** - * Usage: regex(/[a-z]/i) or regex('[a-z]','i') - */ - regex(pattern:string, modifiers:string): Validator; - notRegex(pattern:string, modifiers:string): Validator; - /** - * max is optional - */ - len(min:number, max?:number): Validator; - /** - * Version can be 3, 4 or 5 or empty, see http://en.wikipedia.org/wiki/Universally_unique_identifier - */ - isUUID(version:number): Validator; - /** - * Alias for isUUID(3) - */ - isUUIDv3(): Validator; - /** - * Alias for isUUID(4) - */ - isUUIDv4(): Validator; - /** - * Alias for isUUID(5) - */ - isUUIDv5(): Validator; - /** - * Uses Date.parse() - regex is probably a better choice - */ - isDate(): Validator; - /** - * Argument is optional and defaults to today. Comparison is non-inclusive - */ - isAfter(date:Date): Validator; - /** - * Argument is optional and defaults to today. Comparison is non-inclusive - */ - isBefore(date:Date): Validator; - isIn(options:string): Validator; - isIn(options:string[]): Validator; - notIn(options:string): Validator; - notIn(options:string[]): Validator; - max(val:string): Validator; - min(val:string): Validator; - /** - * Will work against Visa, MasterCard, American Express, Discover, Diners Club, and JCB card numbering formats - */ - isCreditCard(): Validator; - } - - interface Sanitizer { - /** - * Trim optional `chars`, default is to trim whitespace (\r\n\t ) - */ - trim(...chars:string[]): Sanitizer; - ltrim(...chars:string[]): Sanitizer; - rtrim(...chars:string[]): Sanitizer; - ifNull(replace:any): Sanitizer; - toFloat(): Sanitizer; - toInt(): Sanitizer; - /** - * True unless str = '0', 'false', or str.length == 0 - */ - toBoolean(): Sanitizer; - /** - * False unless str = '1' or 'true' - */ - toBooleanStrict(): Sanitizer; - /** - * Decode HTML entities - */ - entityDecode(): Sanitizer; - entityEncode(): Sanitizer; - /** - * Escape &, <, >, and " - */ - escape(): Sanitizer; - /** - * Remove common XSS attack vectors from user-supplied HTML - */ - xss(): Sanitizer; - /** - * Remove common XSS attack vectors from images - */ - xss(fromImages:boolean): Sanitizer; - } - } - /** * * @middlewareOptions see: https://github.com/ctavan/express-validator#middleware-options */ function ExpressValidator(middlewareOptions?:any):express.RequestHandler; - export = ExpressValidator; } + +// Internal Module. +declare module ExpressValidator { + + export interface ValidationError { + msg: string; + param: string; + } + + export interface RequestValidation { + checkBody(field:string, message:string): Validator; + checkParams(field:string, message:string): Validator; + checkQuery(field:string, message:string): Validator; + checkHeader(field:string, message:string): Validator; + checkFiles(field:string, message:string): Validator; + + filter(field:string): Sanitizer; + sanitize(field:string): Sanitizer; + + check(field:string, message:string): Validator; + validate(field:string, message: string): Validator; + + assert(field:string, message:string): Validator; + + onValidationError(func:(msg:string) => void): void; + validationErrors(): any; + } + + export interface Validator { + /** + * Alias for regex() + */ + is(): Validator; + /** + * Alias for notRegex() + */ + not(): Validator; + isEmail(): Validator; + /** + * Accepts http, https, ftp + */ + isUrl(): Validator; + /** + * Combines isIPv4 and isIPv6 + */ + isIP(): Validator; + isIPv4(): Validator; + isIPv6(): Validator; + isAlpha(): Validator; + isAlphanumeric(): Validator; + isNumeric(): Validator; + isHexadecimal(): Validator; + /** + * Accepts valid hexcolors with or without # prefix + */ + isHexColor(): Validator; + /** + * isNumeric accepts zero padded numbers, e.g. '001', isInt doesn't + */ + isInt(): Validator; + isLowercase(): Validator; + isUppercase(): Validator; + isDecimal(): Validator; + /** + * Alias for isDecimal + */ + isFloat(): Validator; + /** + * Check if length is 0 + */ + notNull(): Validator; + isNull(): Validator; + /** + * Not just whitespace (input.trim().length !== 0) + */ + notEmpty(): Validator; + equals(equals:any): Validator; + contains(str:string): Validator; + notContains(str:string): Validator; + /** + * Usage: regex(/[a-z]/i) or regex('[a-z]','i') + */ + regex(pattern:string, modifiers:string): Validator; + notRegex(pattern:string, modifiers:string): Validator; + /** + * max is optional + */ + len(min:number, max?:number): Validator; + /** + * Version can be 3, 4 or 5 or empty, see http://en.wikipedia.org/wiki/Universally_unique_identifier + */ + isUUID(version:number): Validator; + /** + * Alias for isUUID(3) + */ + isUUIDv3(): Validator; + /** + * Alias for isUUID(4) + */ + isUUIDv4(): Validator; + /** + * Alias for isUUID(5) + */ + isUUIDv5(): Validator; + /** + * Uses Date.parse() - regex is probably a better choice + */ + isDate(): Validator; + /** + * Argument is optional and defaults to today. Comparison is non-inclusive + */ + isAfter(date:Date): Validator; + /** + * Argument is optional and defaults to today. Comparison is non-inclusive + */ + isBefore(date:Date): Validator; + isIn(options:string): Validator; + isIn(options:string[]): Validator; + notIn(options:string): Validator; + notIn(options:string[]): Validator; + max(val:string): Validator; + min(val:string): Validator; + /** + * Will work against Visa, MasterCard, American Express, Discover, Diners Club, and JCB card numbering formats + */ + isCreditCard(): Validator; + } + + interface Sanitizer { + /** + * Trim optional `chars`, default is to trim whitespace (\r\n\t ) + */ + trim(...chars:string[]): Sanitizer; + ltrim(...chars:string[]): Sanitizer; + rtrim(...chars:string[]): Sanitizer; + ifNull(replace:any): Sanitizer; + toFloat(): Sanitizer; + toInt(): Sanitizer; + /** + * True unless str = '0', 'false', or str.length == 0 + */ + toBoolean(): Sanitizer; + /** + * False unless str = '1' or 'true' + */ + toBooleanStrict(): Sanitizer; + /** + * Decode HTML entities + */ + entityDecode(): Sanitizer; + entityEncode(): Sanitizer; + /** + * Escape &, <, >, and " + */ + escape(): Sanitizer; + /** + * Remove common XSS attack vectors from user-supplied HTML + */ + xss(): Sanitizer; + /** + * Remove common XSS attack vectors from images + */ + xss(fromImages:boolean): Sanitizer; + } + +} \ No newline at end of file From 93f4df8e1a421ce209c54ab39bc4eddd925c3094 Mon Sep 17 00:00:00 2001 From: Eric Byers Date: Wed, 15 Apr 2015 17:13:29 -0500 Subject: [PATCH 2/5] Fix validationErrors parameters to have optional mapErrors parameters --- express-validator/express-validator.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/express-validator/express-validator.d.ts b/express-validator/express-validator.d.ts index 6ec5ece9e..4f3686c48 100644 --- a/express-validator/express-validator.d.ts +++ b/express-validator/express-validator.d.ts @@ -47,7 +47,7 @@ declare module ExpressValidator { assert(field:string, message:string): Validator; onValidationError(func:(msg:string) => void): void; - validationErrors(): any; + validationErrors(mapErrors?: boolean): any; } export interface Validator { From ca99daff707027bfed47f30a6603911778529e99 Mon Sep 17 00:00:00 2001 From: Eric Byers Date: Wed, 15 Apr 2015 17:16:24 -0500 Subject: [PATCH 3/5] Return valid array type for validationErrors --- express-validator/express-validator.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/express-validator/express-validator.d.ts b/express-validator/express-validator.d.ts index 4f3686c48..c265a4f8b 100644 --- a/express-validator/express-validator.d.ts +++ b/express-validator/express-validator.d.ts @@ -47,7 +47,7 @@ declare module ExpressValidator { assert(field:string, message:string): Validator; onValidationError(func:(msg:string) => void): void; - validationErrors(mapErrors?: boolean): any; + validationErrors(mapErrors?: boolean): Array; } export interface Validator { From 72fece2722cca1b9c9fe3a6c811c2717149b535a Mon Sep 17 00:00:00 2001 From: Eric Byers Date: Thu, 16 Apr 2015 11:06:23 -0500 Subject: [PATCH 4/5] Adding basic express-validator-tests --- express-validator/express-validator-tests.ts | 35 ++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 express-validator/express-validator-tests.ts diff --git a/express-validator/express-validator-tests.ts b/express-validator/express-validator-tests.ts new file mode 100644 index 000000000..4cfe35c62 --- /dev/null +++ b/express-validator/express-validator-tests.ts @@ -0,0 +1,35 @@ +/// + +// @todo Most of the sanitize/validator methods are not tested here. + +import express = require('express'); +import expressValidator = require('express-validator'); + +var app = express(); + +// Add the middleware to make sure it includes. +app.use(expressValidator({ + errorFormatter: function(param: string, msg: string, value: string): {} { + return {}; + } +})); + +var router: express.Router = express.Router(); + +// Add a sample route so we can use the request. +router.get('/test/:testParam', function(req: express.Request, res: express.Response): void { + + // Various different request tests. + // The fluid calls are just random, making sure to cover a portion of the Validator. + req.checkParams('testParam', 'Invalid testParam').notEmpty().isInt(); + req.checkBody('testBody', 'Invalid testBody').isNumeric(); + req.checkFiles('testFiles', 'Invalid testFiles').isUrl(); + req.checkQuery('testQuery', 'Invalid testQuery').isDate(); + req.checkHeader('testHeader', 'Invalid testHeader').isLowercase().isUppercase(); + + var test = req.filter('postparam').toBoolean(); + var test2 = req.sanitize('postparam').toInt(); + + var errors = req.validationErrors(); + var mappedErrors = req.validationErrors(true); +}); \ No newline at end of file From 573cd80b1cc9f757620d08764ee1f7d4380e1604 Mon Sep 17 00:00:00 2001 From: Eric Byers Date: Wed, 29 Apr 2015 12:24:00 -0500 Subject: [PATCH 5/5] Fixing formatting, using express.Request since it is now extended properly --- express-validator/express-validator-tests.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/express-validator/express-validator-tests.ts b/express-validator/express-validator-tests.ts index d6ae4addb..74bd277e4 100644 --- a/express-validator/express-validator-tests.ts +++ b/express-validator/express-validator-tests.ts @@ -9,7 +9,7 @@ var app = express(); app.use(expressValidator()); -app.post('/:urlparam', function(req: expressValidator.ValidatedRequest, res: express.Response) { +app.post('/:urlparam', function(req: express.Request, res: express.Response) { // checkBody only checks req.body; none of the other req parameters // Similarly checkParams only checks in req.params (URL params) and @@ -17,17 +17,17 @@ app.post('/:urlparam', function(req: expressValidator.ValidatedRequest, res: exp req.checkBody('postparam', 'Invalid postparam').notEmpty().isInt(); req.checkParams('urlparam', 'Invalid urlparam').isAlpha(); req.checkQuery('getparam', 'Invalid getparam').isInt(); - req.checkHeader('testHeader', 'Invalid testHeader').isLowercase().isUppercase(); - req.checkFiles('testFiles', 'Invalid testFiles').isUrl(); + req.checkHeader('testHeader', 'Invalid testHeader').isLowercase().isUppercase(); + req.checkFiles('testFiles', 'Invalid testFiles').isUrl(); - // OR assert can be used to check on all 3 types of params. + // OR assert can be used to check on all 3 types of params. // req.assert('postparam', 'Invalid postparam').notEmpty().isInt(); // req.assert('urlparam', 'Invalid urlparam').isAlpha(); // req.assert('getparam', 'Invalid getparam').isInt(); req.sanitize('postparam').toBoolean(); - req.filter('postparam').toBoolean(); + req.filter('postparam').toBoolean(); var errors = req.validationErrors(); var mappedErrors = req.validationErrors(true);