Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added norway identity card #1324

Merged
merged 9 commits into from
May 28, 2020
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ Validator | Description
**isHexColor(str)** | check if the string is a hexadecimal color.
**isHSL(str)** | check if the string is an HSL (hue, saturation, lightness, optional alpha) color based on [CSS Colors Level 4 specification](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value).<br/><br/>Comma-separated format supported. Space-separated format supported with the exception of a few edge cases (ex: `hsl(200grad+.1%62%/1)`).
**isRgbColor(str, [, includePercentValues])** | check if the string is a rgb or rgba color.<br/><br/>`includePercentValues` defaults to `true`. If you don't want to allow to set `rgb` or `rgba` values with percents, like `rgb(5%,5%,5%)`, or `rgba(90%,90%,90%,.3)`, then set it to false.
**isIdentityCard(str [, locale])** | check if the string is a valid identity card code.<br/><br/>`locale` is one of `['ES', 'IN', 'zh-TW', 'he-IL', 'ar-TN', 'zh-CN']` OR `'any'`. If 'any' is used, function will check if any of the locals match.<br/><br/>Defaults to 'any'.
**isIdentityCard(str [, locale])** | check if the string is a valid identity card code.<br/><br/>`locale` is one of `['ES', 'IN', 'NO', 'zh-TW', 'he-IL', 'ar-TN', 'zh-CN']` OR `'any'`. If 'any' is used, function will check if any of the locals match.<br/><br/>Defaults to 'any'.
**isIn(str, values)** | check if the string is in a array of allowed values.
**isInt(str [, options])** | check if the string is an integer.<br/><br/>`options` is an object which can contain the keys `min` and/or `max` to check the integer is within boundaries (e.g. `{ min: 10, max: 99 }`). `options` can also contain the key `allow_leading_zeroes`, which when set to false will disallow integer values with leading zeroes (e.g. `{ allow_leading_zeroes: false }`). Finally, `options` can contain the keys `gt` and/or `lt` which will enforce integers being greater than or less than, respectively, the value provided (e.g. `{gt: 1, lt: 4}` for a number between 1 and 4).
**isIP(str [, version])** | check if the string is an IP (version 4 or 6).
Expand Down
20 changes: 18 additions & 2 deletions es/lib/isIdentityCard.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,7 @@ var validators = {

var p = [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [1, 5, 7, 6, 2, 8, 3, 0, 9, 4], [5, 8, 0, 3, 7, 9, 6, 1, 4, 2], [8, 9, 1, 6, 0, 4, 3, 5, 2, 7], [9, 4, 5, 3, 1, 2, 6, 8, 7, 0], [4, 2, 8, 6, 5, 7, 3, 9, 0, 1], [2, 7, 9, 3, 8, 0, 6, 4, 1, 5], [7, 0, 4, 6, 9, 1, 3, 2, 5, 8]]; // sanitize user input

var sanitized = str.trim();
console.log(sanitized); // validate the data structure
var sanitized = str.trim(); // validate the data structure

if (!DNI.test(sanitized)) {
return false;
Expand All @@ -43,6 +42,23 @@ var validators = {
});
return c === 0;
},
NO: function NO(str) {
var sanitized = str.trim();
if (isNaN(Number(sanitized))) return false;
if (sanitized.length !== 11) return false;
if (sanitized === '00000000000') return false; // https://no.wikipedia.org/wiki/F%C3%B8dselsnummer

var f = sanitized.split('').map(Number);
var k1 = (11 - (3 * f[0] + 7 * f[1] + 6 * f[2] + 1 * f[3] + 8 * f[4] + 9 * f[5] + 4 * f[6] + 5 * f[7] + 2 * f[8]) % 11) % 11;
var k2 = (11 - (5 * f[0] + 4 * f[1] + 3 * f[2] + 2 * f[3] + 7 * f[4] + 6 * f[5] + 5 * f[6] + 4 * f[7] + 3 * f[8] + 2 * k1) % 11) % 11;

if (k1 === 11) {
k1 = 0;
}

if (k1 !== f[9] || k2 !== f[10]) return false;
return true;
},
'he-IL': function heIL(str) {
var DNI = /^\d{9}$/; // sanitize user input

Expand Down
20 changes: 18 additions & 2 deletions lib/isIdentityCard.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,7 @@ var validators = {

var p = [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [1, 5, 7, 6, 2, 8, 3, 0, 9, 4], [5, 8, 0, 3, 7, 9, 6, 1, 4, 2], [8, 9, 1, 6, 0, 4, 3, 5, 2, 7], [9, 4, 5, 3, 1, 2, 6, 8, 7, 0], [4, 2, 8, 6, 5, 7, 3, 9, 0, 1], [2, 7, 9, 3, 8, 0, 6, 4, 1, 5], [7, 0, 4, 6, 9, 1, 3, 2, 5, 8]]; // sanitize user input

var sanitized = str.trim();
console.log(sanitized); // validate the data structure
var sanitized = str.trim(); // validate the data structure

if (!DNI.test(sanitized)) {
return false;
Expand All @@ -53,6 +52,23 @@ var validators = {
});
return c === 0;
},
NO: function NO(str) {
var sanitized = str.trim();
if (isNaN(Number(sanitized))) return false;
if (sanitized.length !== 11) return false;
if (sanitized === '00000000000') return false; // https://no.wikipedia.org/wiki/F%C3%B8dselsnummer

var f = sanitized.split('').map(Number);
var k1 = (11 - (3 * f[0] + 7 * f[1] + 6 * f[2] + 1 * f[3] + 8 * f[4] + 9 * f[5] + 4 * f[6] + 5 * f[7] + 2 * f[8]) % 11) % 11;
var k2 = (11 - (5 * f[0] + 4 * f[1] + 3 * f[2] + 2 * f[3] + 7 * f[4] + 6 * f[5] + 5 * f[6] + 4 * f[7] + 3 * f[8] + 2 * k1) % 11) % 11;

if (k1 === 11) {
k1 = 0;
}

if (k1 !== f[9] || k2 !== f[10]) return false;
return true;
},
'he-IL': function heIL(str) {
var DNI = /^\d{9}$/; // sanitize user input

Expand Down
21 changes: 20 additions & 1 deletion src/lib/isIdentityCard.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ const validators = {

// sanitize user input
const sanitized = str.trim();
console.log(sanitized);

// validate the data structure
if (!DNI.test(sanitized)) {
Expand All @@ -76,6 +75,26 @@ const validators = {

return c === 0;
},
NO: (str) => {
const sanitized = str.trim();
if (isNaN(Number(sanitized))) return false;
if (sanitized.length !== 11) return false;
if (sanitized === '00000000000') return false;

// https://no.wikipedia.org/wiki/F%C3%B8dselsnummer
const f = sanitized.split('').map(Number);
let k1 = (11 - (((3 * f[0]) + (7 * f[1]) + (6 * f[2])
+ (1 * f[3]) + (8 * f[4]) + (9 * f[5]) + (4 * f[6])
+ (5 * f[7]) + (2 * f[8])) % 11)) % 11;
let k2 = (11 - (((5 * f[0]) + (4 * f[1]) + (3 * f[2])
+ (2 * f[3]) + (7 * f[4]) + (6 * f[5]) + (5 * f[6])
+ (4 * f[7]) + (3 * f[8]) + (2 * k1)) % 11)) % 11;
if (k1 === 11) {
k1 = 0;
}
if (k1 !== f[9] || k2 !== f[10]) return false;
return true;
},
'he-IL': (str) => {
const DNI = /^\d{9}$/;

Expand Down
18 changes: 18 additions & 0 deletions test/validators.js
Original file line number Diff line number Diff line change
Expand Up @@ -3978,6 +3978,24 @@ describe('Validators', () => {
'X1234567L',
],
},
{
locale: 'NO',
valid: [
'09053426694',
'26028338723',
'08031470790',
'12051539514',
'02077448074',
'14035638319',
'13031379673',
'29126214926',
],
invalid: [
'09053426699',
'26028338724',
'92031470790',
],
},
{
locale: 'he-IL',
valid: [
Expand Down
115 changes: 87 additions & 28 deletions validator.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ function _unsupportedIterableToArray(o, minLen) {
if (typeof o === "string") return _arrayLikeToArray(o, minLen);
var n = Object.prototype.toString.call(o).slice(8, -1);
if (n === "Object" && o.constructor) n = o.constructor.name;
if (n === "Map" || n === "Set") return Array.from(n);
if (n === "Map" || n === "Set") return Array.from(o);
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
}

Expand Down Expand Up @@ -1023,6 +1023,7 @@ function isNumeric(str, options) {
* https://docs.microsoft.com/en-us/microsoft-365/compliance/eu-passport-number -- EU Passport Number
* https://countrycode.org/ -- Country Codes
*/

var passportRegexByCountryCode = {
AM: /^[A-Z]{2}\d{7}$/,
// ARMENIA
Expand Down Expand Up @@ -1070,6 +1071,8 @@ var passportRegexByCountryCode = {
// HUNGARY
IE: /^[A-Z0-9]{2}\d{7}$/,
// IRELAND
IN: /^[A-Z]{1}-?\d{7}$/,
// INDIA
IS: /^(A)\d{7}$/,
// ICELAND
IT: /^[A-Z0-9]{2}\d{7}$/,
Expand Down Expand Up @@ -1117,7 +1120,9 @@ var passportRegexByCountryCode = {
*/

function isPassportNumber(str, countryCode) {
assertString(str);
/** Remove All Whitespaces, Convert to UPPERCASE */

var normalizedStr = str.replace(/\s/g, '').toUpperCase();
return countryCode.toUpperCase() in passportRegexByCountryCode && passportRegexByCountryCode[countryCode].test(normalizedStr);
}
Expand Down Expand Up @@ -1345,6 +1350,7 @@ var ibanRegexThroughCountryCode = {
IE: /^(IE[0-9]{2})[A-Z0-9]{4}\d{14}$/,
IL: /^(IL[0-9]{2})\d{19}$/,
IQ: /^(IQ[0-9]{2})[A-Z]{4}\d{15}$/,
IR: /^(IR[0-9]{2})0\d{2}0\d{18}$/,
IS: /^(IS[0-9]{2})\d{22}$/,
IT: /^(IT[0-9]{2})[A-Z]{1}\d{10}[A-Z0-9]{12}$/,
JO: /^(JO[0-9]{2})[A-Z]{4}\d{22}$/,
Expand All @@ -1356,7 +1362,6 @@ var ibanRegexThroughCountryCode = {
LT: /^(LT[0-9]{2})\d{16}$/,
LU: /^(LU[0-9]{2})\d{3}[A-Z0-9]{13}$/,
LV: /^(LV[0-9]{2})[A-Z]{4}[A-Z0-9]{13}$/,
LY: /^((\+?218)|0)?(9[1-6]\d{7}|[1-8]\d{7,9})$/,
MC: /^(MC[0-9]{2})\d{10}[A-Z0-9]{11}\d{2}$/,
MD: /^(MD[0-9]{2})[A-Z0-9]{20}$/,
ME: /^(ME[0-9]{2})\d{18}$/,
Expand Down Expand Up @@ -1471,10 +1476,42 @@ function isHash(str, algorithm) {
return hash.test(str);
}

var jwt = /^([A-Za-z0-9\-_~+\/]+[=]{0,2})\.([A-Za-z0-9\-_~+\/]+[=]{0,2})(?:\.([A-Za-z0-9\-_~+\/]+[=]{0,2}))?$/;
var notBase64 = /[^A-Z0-9+\/=]/i;
var urlSafeBase64 = /^[A-Z0-9_\-]+$/i;
var defaultBase64Options = {
urlSafe: false
};
function isBase64(str, options) {
assertString(str);
options = merge(options, defaultBase64Options);
var len = str.length;

if (options.urlSafe) {
return urlSafeBase64.test(str);
}

if (!len || len % 4 !== 0 || notBase64.test(str)) {
return false;
}

var firstPaddingChar = str.indexOf('=');
return firstPaddingChar === -1 || firstPaddingChar === len - 1 || firstPaddingChar === len - 2 && str[len - 1] === '=';
}

function isJWT(str) {
assertString(str);
return jwt.test(str);
var dotSplit = str.split('.');
var len = dotSplit.length;

if (len > 3 || len < 2) {
return false;
}

return dotSplit.reduce(function (acc, currElem) {
return acc && isBase64(currElem, {
urlSafe: true
});
}, true);
}

function isJSON(str) {
Expand Down Expand Up @@ -1642,6 +1679,43 @@ var validators = {
});
return sanitized.endsWith(controlDigits[number % 23]);
},
IN: function IN(str) {
var DNI = /^[1-9]\d{3}\s?\d{4}\s?\d{4}$/; // multiplication table

var d = [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [1, 2, 3, 4, 0, 6, 7, 8, 9, 5], [2, 3, 4, 0, 1, 7, 8, 9, 5, 6], [3, 4, 0, 1, 2, 8, 9, 5, 6, 7], [4, 0, 1, 2, 3, 9, 5, 6, 7, 8], [5, 9, 8, 7, 6, 0, 4, 3, 2, 1], [6, 5, 9, 8, 7, 1, 0, 4, 3, 2], [7, 6, 5, 9, 8, 2, 1, 0, 4, 3], [8, 7, 6, 5, 9, 3, 2, 1, 0, 4], [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]]; // permutation table

var p = [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [1, 5, 7, 6, 2, 8, 3, 0, 9, 4], [5, 8, 0, 3, 7, 9, 6, 1, 4, 2], [8, 9, 1, 6, 0, 4, 3, 5, 2, 7], [9, 4, 5, 3, 1, 2, 6, 8, 7, 0], [4, 2, 8, 6, 5, 7, 3, 9, 0, 1], [2, 7, 9, 3, 8, 0, 6, 4, 1, 5], [7, 0, 4, 6, 9, 1, 3, 2, 5, 8]]; // sanitize user input

var sanitized = str.trim(); // validate the data structure

if (!DNI.test(sanitized)) {
return false;
}

var c = 0;
var invertedArray = sanitized.replace(/\s/g, '').split('').map(Number).reverse();
invertedArray.forEach(function (val, i) {
c = d[c][p[i % 8][val]];
});
return c === 0;
},
NO: function NO(str) {
var sanitized = str.trim();
if (isNaN(Number(sanitized))) return false;
if (sanitized.length !== 11) return false;
if (sanitized === '00000000000') return false; // https://no.wikipedia.org/wiki/F%C3%B8dselsnummer

var f = sanitized.split('').map(Number);
var k1 = (11 - (3 * f[0] + 7 * f[1] + 6 * f[2] + 1 * f[3] + 8 * f[4] + 9 * f[5] + 4 * f[6] + 5 * f[7] + 2 * f[8]) % 11) % 11;
var k2 = (11 - (5 * f[0] + 4 * f[1] + 3 * f[2] + 2 * f[3] + 7 * f[4] + 6 * f[5] + 5 * f[6] + 4 * f[7] + 3 * f[8] + 2 * k1) % 11) % 11;

if (k1 === 11) {
k1 = 0;
}

if (k1 !== f[9] || k2 !== f[10]) return false;
return true;
},
'he-IL': function heIL(str) {
var DNI = /^\d{9}$/; // sanitize user input

Expand Down Expand Up @@ -2054,6 +2128,7 @@ var phones = {
'ar-IQ': /^(\+?964|0)?7[0-9]\d{8}$/,
'ar-JO': /^(\+?962|0)?7[789]\d{7}$/,
'ar-KW': /^(\+?965)[569]\d{7}$/,
'ar-LY': /^((\+?218)|0)?(9[1-6]\d{7}|[1-8]\d{7,9})$/,
'ar-SA': /^(!?(\+?966)|0)?5\d{8}$/,
'ar-SY': /^(!?(\+?963)|0)?9\d{8}$/,
'ar-TN': /^(\+?216)?[2459]\d{7}$/,
Expand All @@ -2064,6 +2139,7 @@ var phones = {
'da-DK': /^(\+?45)?\s?\d{2}\s?\d{2}\s?\d{2}\s?\d{2}$/,
'de-DE': /^(\+49)?0?1(5[0-25-9]\d|6([23]|0\d?)|7([0-57-9]|6\d))\d{7}$/,
'de-AT': /^(\+43|0)\d{1,4}\d{3,12}$/,
'de-CH': /^(\+41|0)(7[5-9])\d{1,7}$/,
'el-GR': /^(\+?30|0)?(69\d{8})$/,
'en-AU': /^(\+?61|0)4\d{8}$/,
'en-GB': /^(\+?44|0)7\d{9}$/,
Expand All @@ -2087,6 +2163,7 @@ var phones = {
'en-US': /^((\+1|1)?( |-)?)?(\([2-9][0-9]{2}\)|[2-9][0-9]{2})( |-)?([2-9][0-9]{2}( |-)?[0-9]{4})$/,
'en-ZA': /^(\+?27|0)\d{9}$/,
'en-ZM': /^(\+?26)?09[567]\d{7}$/,
'en-ZW': /^(\+263)[0-9]{9}$/,
'es-CL': /^(\+?56|0)[2-9]\d{1}\d{7}$/,
'es-CR': /^(\+506)?[2-8]\d{7}$/,
'es-EC': /^(\+?593|0)([2-7]|9[2-9])\d{7}$/,
Expand Down Expand Up @@ -2133,7 +2210,7 @@ var phones = {
'tr-TR': /^(\+?90|0)?5\d{9}$/,
'uk-UA': /^(\+?38|8)?0\d{9}$/,
'vi-VN': /^(\+?84|0)((3([2-9]))|(5([2689]))|(7([0|6-9]))|(8([1-6|89]))|(9([0-9])))([0-9]{7})$/,
'zh-CN': /^((\+|00)86)?1([358][0-9]|4[579]|6[67]|7[01235678]|9[189])[0-9]{8}$/,
'zh-CN': /^((\+|00)86)?1([3568][0-9]|4[579]|6[67]|7[01235678]|9[189])[0-9]{8}$/,
'zh-TW': /^(\+?886\-?|0)?9\d{8}$/
};
/* eslint-enable max-len */
Expand Down Expand Up @@ -2361,25 +2438,6 @@ function isBase32(str) {
return false;
}

var notBase64 = /[^A-Z0-9+\/=]/i;
function isBase64(str) {
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
assertString(str);

if (options.urlSafe) {
return /^[A-Za-z0-9_-]+$/.test(str);
}

var len = str.length;

if (!len || len % 4 !== 0 || notBase64.test(str)) {
return false;
}

var firstPaddingChar = str.indexOf('=');
return firstPaddingChar === -1 || firstPaddingChar === len - 1 || firstPaddingChar === len - 2 && str[len - 1] === '=';
}

var validMediaType = /^[a-z]+\/[a-z0-9\-\+]+$/i;
var validAttribute = /^[a-z\-]+=[a-z0-9\-]+$/i;
var validData = /^[a-z0-9!\$&'\(\)\*\+,;=\-\._~:@\/\?%\s]*$/i;
Expand Down Expand Up @@ -2467,13 +2525,13 @@ function isMimeType(str) {

var lat = /^\(?[+-]?(90(\.0+)?|[1-8]?\d(\.\d+)?)$/;
var _long = /^\s?[+-]?(180(\.0+)?|1[0-7]\d(\.\d+)?|\d{1,2}(\.\d+)?)\)?$/;
var isLatLong = function (str) {
function isLatLong(str) {
assertString(str);
if (!str.includes(',')) return false;
var pair = str.split(',');
if (pair[0].startsWith('(') && !pair[1].endsWith(')') || pair[1].endsWith(')') && !pair[0].startsWith('(')) return false;
return lat.test(pair[0]) && _long.test(pair[1]);
};
}

var threeDigit = /^\d{3}$/;
var fourDigit = /^\d{4}$/;
Expand Down Expand Up @@ -2516,6 +2574,7 @@ var patterns = {
MT: /^[A-Za-z]{3}\s{0,1}\d{4}$/,
NL: /^\d{4}\s?[a-z]{2}$/i,
NO: fourDigit,
NP: /^(10|21|22|32|33|34|44|45|56|57)\d{3}$|^(977)$/i,
NZ: fourDigit,
PL: /^\d{2}\-\d{3}$/,
PR: /^00[679]\d{2}([ -]\d{4})?$/,
Expand All @@ -2534,7 +2593,7 @@ var patterns = {
ZM: fiveDigit
};
var locales$4 = Object.keys(patterns);
var isPostalCode = function (str, locale) {
function isPostalCode(str, locale) {
assertString(str);

if (locale in patterns) {
Expand All @@ -2556,7 +2615,7 @@ var isPostalCode = function (str, locale) {
}

throw new Error("Invalid locale '".concat(locale, "'"));
};
}

function ltrim(str, chars) {
assertString(str); // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#Escaping
Expand Down