UNPKG

common-password-rules

Version:

Validation methods for some common password policies

153 lines (142 loc) 4.47 kB
'use strict' const ALPHABET_LOWERCASE = 'abcdefghijklmnopqrstuvwxyz'; const ALPHABET_UPPERCASE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; const DIGITS = '0123456789'; const defaultsTo = function(val, def) { return typeof val === 'number' ? val : def; }; const regTest = function(exp, str) { return new RegExp(exp, 'g').test(str); }; const containsSequentialsFrom = function(orderedLists, password, times) { times = defaultsTo(times, 3); let len = password.length; let found = false; password.split('').forEach((letter, index) => { if (found || len - times + 1 <= 0) { return; } let foundIndex = Math.max(orderedLists[0].indexOf(letter), orderedLists[1] ? orderedLists[1].indexOf(letter) : -1); if (foundIndex > -1) { for (let i = 1; i < times; i++) { if (orderedLists[0][foundIndex + i] !== password.charAt(index + i) && (!orderedLists[1] || orderedLists[1][foundIndex + i] !== password.charAt(index + i))) { return; } } found = true; } }); return found; }; /** * @exports commonPasswordRules */ module.exports = { /** * Checks whether the given password contains a lowercase letter. * * @param {String} password Password string * @param {Integer} [times=1] Minimum number of required lowercase letters * @return {Boolean} */ containsLowerCase: (password, times) => { return regTest('(.*?[a-z]){' + defaultsTo(times, 1) + ',}', password); }, /** * Checks whether the given password contains an uppercase letter. * * @param {String} password Password string * @param {Integer} [times=1] Minimum number of required uppercase letters * @return {Boolean} */ containsUpperCase: (password, times) => { return regTest('(.*?[A-Z]){' + defaultsTo(times, 1) + ',}', password); }, /** * Checks whether the given password contains a digit. * * @param {String} password Password string * @param {Integer} [times=1] Minimum number of required digits * @return {Boolean} */ containsDigit: (password, times) => { return regTest('(.*?\\d){' + defaultsTo(times, 1) + ',}', password); }, /** * Checks whether the given password contains a special (non-word) character. * * @param {String} password Password string * @param {Integer} [times=1] Minimum number of required special characters * @return {Boolean} */ containsSpecialChar: (password, times) => { return regTest('(.*?[_\\W]){' + defaultsTo(times, 1) + ',}', password); }, /** * Checks whether the given password contains a character from the given set. * * @param {String} password Password string * @param {String} charSet A regex character set * @param {Integer} [times=1] Minimum number of required characters * @return {Boolean} */ contains: (password, charSet, times) => { return regTest('(.*?' + charSet + '){' + defaultsTo(times, 1) + ',}', password); }, /** * Checks that the given password does not contain recurring alphanumeric * characters. * * @param {String} password Password string * @param {Integer} [times=3] Minimum recursion number * @return {Boolean} */ excludesRecurringChars: (password, times) => { return !regTest('(\\w)\\1{' + (defaultsTo(times, 3) - 1) + ',}', password); }, /** * Checks that the given password does not contain sequential * case-insensitive letters. * * @param {String} password Password string * @param {Integer} [times=3] Minimum sequence * @return {Boolean} */ excludesSequentialLetters: (password, times) => { return !containsSequentialsFrom( [ALPHABET_LOWERCASE, ALPHABET_UPPERCASE], password, times); }, /** * Checks that the given password does not contain sequential digits. * * @param {String} password Password string * @param {Integer} [times=3] Minimum sequence * @return {Boolean} */ excludesSequentialDigits: (password, times) => { return !containsSequentialsFrom( [DIGITS], password, times); }, /** * Checks that the given password does not a possible birth-date. * * @param {String} password Password string * @return {Boolean} */ excludesBirthDate: (password) => { return !regTest( '([0123]\\d|[a-zA-Z_/.-])' + '([0123]\\d|[a-zA-Z_/.-])' + '(19[6789]\\d|20[0]\\d)', password); } };