Created
September 13, 2012 08:03
-
-
Save distracteddev/3712776 to your computer and use it in GitHub Desktop.
Password Validating Function
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
REGULAR USAGE | |
verifier.exec('myInvalidPassword') -> returns an [] of error messages | |
EXTENDED USAGE | |
verify = function(passwd, options) { | |
// Some logic | |
return errors || null; | |
}; | |
// Extend the original exec() function with extend | |
verify = verifier.extend(verify); | |
// Use our new function to verify passwords | |
verify('myPassword'); | |
EXTENDED ASYNC USAGE | |
verify = function(passwd, options, cb) { | |
// Some logic | |
cb(errors || null) | |
} | |
verify = verifier.extend(verify); | |
verify('myPassword', function(errors) { | |
// Async validation complete | |
}); | |
*/ | |
var verifier = { | |
/** | |
* Verifies the passwd meets certain strength requirements | |
* @param {string} passwd | |
* @param {object} [options] | |
* @param {string} [options.firstName] | |
* @param {string} [options.lastName] | |
* @param {string} [options.confirm] | |
* @return {Array} || null | |
*/ | |
exec: function(passwd, options) { | |
if (arguments.length < 1) { | |
throw new Error("You must pass a password string to the verifier.exec() function"); | |
} | |
options = options || {}; | |
// Lets define some test objects that consist of a regEx and an error message: | |
// matches any non-new-line character 8 or more times | |
var properLength = { re: /.{8,}/, errorMsg: 'The password must be at least 8 characters in length.<br/>'}; | |
// matches at least one capital character | |
var hasCapital = { re: /[A-Z]/, errorMsg: 'The password must contain at least 1 capital letter.<br/>'}; | |
// matches at least one lower-case character | |
var hasLowercase = {re: /[a-z]/, errorMsg: 'The password must contain at least 1 lower case letter.<br/>'}; | |
// matches at least one special character | |
var hasSpecial = { re: /\W/, errorMsg: 'The password must contain at least 1 special chracter.<br/>'}; | |
// matches at least one numeral character | |
var hasNumeral = { re: /\d/, errorMsg: 'The password must contain at least 1 number.<br/>'}; | |
// if the user's name is part of the password, reject it | |
// Create an array holding all of the tests we want run | |
var tests = [properLength, hasCapital, hasSpecial, hasNumeral, hasLowercase]; | |
// Push optional tests onto the array if the required data is provided | |
// if any names are provided, make sure they aren't used within the password | |
if (options.firstName || options.lastName) { | |
var names; | |
var restricted = []; | |
if (options.firstName) { | |
restricted.push(options.firstName); | |
} | |
if (options.lastName) { | |
restricted.push(options.lastName); | |
} | |
// Join all restricted words by the regEx OR operator | |
names = new RegExp(restricted.join('|')); | |
// Build the test and push it onto our tests array | |
var containsName = {re: names, errorMsg: 'Your password cannot contain either your First or Last name', expected: false}; | |
tests.push(containsName); | |
} | |
// If a confirm password has been provided, ensure it matches the original | |
if (options.confirm) { | |
var confirmRegEx = new RegExp('$' + options.confirm + '^'); | |
var confirmPassword = {re: regEx, errorMsg: 'The passwords you provided do not match'}; | |
tests.push(confirmPassword); | |
} | |
// Array of error messages | |
var errors = null; | |
// Run each of our pre-defined tests | |
tests.forEach(function(test) { | |
var expected = test.expected; | |
// If no expected result, assume the re should test to true | |
if (expected === undefined) { | |
expected = true; | |
} | |
// Run the regEx and compare to expected result | |
if (test.re.test(passwd) !== expected) { | |
// Oops, an error occured. If this is the first error, init errors. | |
if (!errors) { | |
errors = []; | |
} | |
errors.push(test.errorMsg); | |
} | |
}); | |
// Either null or an array of error messages. | |
// NOTE: If errors exist, should we Return errors.join('<br/>') instead? | |
return errors; | |
}, | |
/** | |
* Takes the verify function and returns a new function that calls | |
* both verifier.exec() and verify on the passed arguments | |
* @param verify | |
* @return {function} | |
*/ | |
extend: function(verify) { | |
var exec = this.exec; | |
// If a callback is provided to the returned function, it will assume | |
// that 'verify' is asynchronous. | |
return function(passwd, options, cb) { | |
// Deal with variable number of args | |
if (typeof options === 'function') { | |
cb = options; | |
options = {}; | |
} | |
// Run both verify functions | |
var errors = exec(passwd, options); | |
var moreErrors; | |
// If a callback is provided, assume verify is asynchronous | |
if (typeof cb === 'function') { | |
// Pass along the options object incase it is needed. | |
verify(passwd, options, function(errs) { | |
moreErrors = errs; | |
// Concat the error messages if neccessary. | |
if (errors && moreErrors) { | |
errors = errors.concat(moreErrors); | |
} | |
// If both are null, null will be returned | |
// If one is an array, that array will be returned. | |
var result = errors || moreErrors; | |
cb(result); | |
}); | |
} else { | |
// If no callback is provided, assume verify is synchronous | |
moreErrors = verify(passwd, options); | |
// concat | |
if (errors && moreErrors) { | |
errors = errors.concat(moreErrors); | |
} | |
// return | |
return errors || moreErrors; | |
} | |
}; | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment