Skip to content

Commit

Permalink
Merge pull request #846 from hitbits/master
Browse files Browse the repository at this point in the history
Added isIdentityCard for identity card codes validation
  • Loading branch information
chriso committed Sep 24, 2018
2 parents 43540cd + eb7fe69 commit 0649c05
Show file tree
Hide file tree
Showing 8 changed files with 237 additions and 1 deletion.
1 change: 1 addition & 0 deletions README.md
Expand Up @@ -85,6 +85,7 @@ Validator | Description
**isHash(str, algorithm)** | check if the string is a hash of type algorithm.<br/><br/>Algorithm is one of `['md4', 'md5', 'sha1', 'sha256', 'sha384', 'sha512', 'ripemd128', 'ripemd160', 'tiger128', 'tiger160', 'tiger192', 'crc32', 'crc32b']`
**isHexColor(str)** | check if the string is a hexadecimal color.
**isHexadecimal(str)** | check if the string is a hexadecimal number.
**isIdentityCard(str [, locale])** | check if the string is a valid identity card code.<br/><br/>`locale` is one of `['ES']` OR `'any'`. If 'any' is used, function will check if any of the locals match.<br/><br/>Defaults to 'any'.
**isIP(str [, version])** | check if the string is an IP (version 4 or 6).
**isIPRange(str)** | check if the string is an IP Range(version 4 only).
**isISBN(str [, version])** | check if the string is an ISBN (version 10 or 13).
Expand Down
5 changes: 5 additions & 0 deletions index.js
Expand Up @@ -188,6 +188,10 @@ var _isCreditCard = require('./lib/isCreditCard');

var _isCreditCard2 = _interopRequireDefault(_isCreditCard);

var _isIdentityCard = require('./lib/isIdentityCard');

var _isIdentityCard2 = _interopRequireDefault(_isIdentityCard);

var _isISIN = require('./lib/isISIN');

var _isISIN2 = _interopRequireDefault(_isISIN);
Expand Down Expand Up @@ -347,6 +351,7 @@ var validator = {
isBefore: _isBefore2.default,
isIn: _isIn2.default,
isCreditCard: _isCreditCard2.default,
isIdentityCard: _isIdentityCard2.default,
isISIN: _isISIN2.default,
isISBN: _isISBN2.default,
isISSN: _isISSN2.default,
Expand Down
64 changes: 64 additions & 0 deletions lib/isIdentityCard.js
@@ -0,0 +1,64 @@
'use strict';

Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = isIdentityCard;

var _assertString = require('./util/assertString');

var _assertString2 = _interopRequireDefault(_assertString);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

var validators = {
ES: function ES(str) {
(0, _assertString2.default)(str);

var DNI = /^[0-9X-Z][0-9]{7}[TRWAGMYFPDXBNJZSQVHLCKE]$/;

var charsValue = {
X: 0,
Y: 1,
Z: 2
};

var controlDigits = ['T', 'R', 'W', 'A', 'G', 'M', 'Y', 'F', 'P', 'D', 'X', 'B', 'N', 'J', 'Z', 'S', 'Q', 'V', 'H', 'L', 'C', 'K', 'E'];

// sanitize user input
var sanitized = str.trim().toUpperCase();

// validate the data structure
if (!DNI.test(sanitized)) {
return false;
}

// validate the control digit
var number = sanitized.slice(0, -1).replace(/[X,Y,Z]/g, function (char) {
return charsValue[char];
});

return sanitized.endsWith(controlDigits[number % 23]);
}
};

function isIdentityCard(str) {
var locale = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'any';

(0, _assertString2.default)(str);
if (locale in validators) {
return validators[locale](str);
} else if (locale === 'any') {
for (var key in validators) {
if (validators.hasOwnProperty(key)) {
var validator = validators[key];
if (validator(str)) {
return true;
}
}
}
return false;
}
throw new Error('Invalid locale \'' + locale + '\'');
}
module.exports = exports['default'];
2 changes: 2 additions & 0 deletions src/index.js
Expand Up @@ -58,6 +58,7 @@ import isBefore from './lib/isBefore';
import isIn from './lib/isIn';

import isCreditCard from './lib/isCreditCard';
import isIdentityCard from './lib/isIdentityCard';

import isISIN from './lib/isISIN';
import isISBN from './lib/isISBN';
Expand Down Expand Up @@ -148,6 +149,7 @@ const validator = {
isBefore,
isIn,
isCreditCard,
isIdentityCard,
isISIN,
isISBN,
isISSN,
Expand Down
51 changes: 51 additions & 0 deletions src/lib/isIdentityCard.js
@@ -0,0 +1,51 @@
import assertString from './util/assertString';

const validators = {
ES: (str) => {
assertString(str);

const DNI = /^[0-9X-Z][0-9]{7}[TRWAGMYFPDXBNJZSQVHLCKE]$/;

const charsValue = {
X: 0,
Y: 1,
Z: 2,
};

const controlDigits = [
'T', 'R', 'W', 'A', 'G', 'M', 'Y', 'F', 'P', 'D', 'X', 'B',
'N', 'J', 'Z', 'S', 'Q', 'V', 'H', 'L', 'C', 'K', 'E',
];

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

// validate the data structure
if (!DNI.test(sanitized)) {
return false;
}

// validate the control digit
const number = sanitized.slice(0, -1).replace(/[X,Y,Z]/g, char => charsValue[char]);

return sanitized.endsWith(controlDigits[number % 23]);
},
};

export default function isIdentityCard(str, locale = 'any') {
assertString(str);
if (locale in validators) {
return validators[locale](str);
} else if (locale === 'any') {
for (const key in validators) {
if (validators.hasOwnProperty(key)) {
const validator = validators[key];
if (validator(str)) {
return true;
}
}
}
return false;
}
throw new Error(`Invalid locale '${locale}'`);
}
61 changes: 61 additions & 0 deletions test/validators.js
Expand Up @@ -2921,6 +2921,67 @@ describe('Validators', () => {
});
});

it('should validate identity cards', () => {
const fixtures = [
{
locale: 'ES',
valid: [
'99999999R',
'12345678Z',
'01234567L',
'01234567l',
'X1234567l',
'x1234567l',
'X1234567L',
'Y1234567X',
'Z1234567R',
],
invalid: [
'123456789',
'12345678A',
'12345 678Z',
'12345678-Z',
'1234*6789',
'1234*678Z',
'12345678!',
'1234567L',
'A1234567L',
'X1234567A',
'Y1234567B',
'Z1234567C',
],
},
];

let allValid = [];
let allInvalid = [];

// Test fixtures
fixtures.forEach((fixture) => {
if (fixture.valid) allValid = allValid.concat(fixture.valid);
if (fixture.invalid) allInvalid = allInvalid.concat(fixture.invalid);
test({
validator: 'isIdentityCard',
valid: fixture.valid,
invalid: fixture.invalid,
args: [fixture.locale],
});
});

// Test generics
test({
validator: 'isIdentityCard',
valid: [
...allValid,
],
invalid: [
'foo',
...allInvalid,
],
args: ['any'],
});
});

it('should validate ISINs', () => {
test({
validator: 'isISIN',
Expand Down
52 changes: 52 additions & 0 deletions validator.js
Expand Up @@ -950,6 +950,57 @@ function isCreditCard(str) {
return !!(sum % 10 === 0 ? sanitized : false);
}

var validators = {
ES: function ES(str) {
assertString(str);

var DNI = /^[0-9X-Z][0-9]{7}[TRWAGMYFPDXBNJZSQVHLCKE]$/;

var charsValue = {
X: 0,
Y: 1,
Z: 2
};

var controlDigits = ['T', 'R', 'W', 'A', 'G', 'M', 'Y', 'F', 'P', 'D', 'X', 'B', 'N', 'J', 'Z', 'S', 'Q', 'V', 'H', 'L', 'C', 'K', 'E'];

// sanitize user input
var sanitized = str.trim().toUpperCase();

// validate the data structure
if (!DNI.test(sanitized)) {
return false;
}

// validate the control digit
var number = sanitized.slice(0, -1).replace(/[X,Y,Z]/g, function (char) {
return charsValue[char];
});

return sanitized.endsWith(controlDigits[number % 23]);
}
};

function isIdentityCard(str) {
var locale = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'any';

assertString(str);
if (locale in validators) {
return validators[locale](str);
} else if (locale === 'any') {
for (var key in validators) {
if (validators.hasOwnProperty(key)) {
var validator = validators[key];
if (validator(str)) {
return true;
}
}
}
return false;
}
throw new Error('Invalid locale \'' + locale + '\'');
}

var isin = /^[A-Z]{2}[0-9A-Z]{9}[0-9]$/;

function isISIN(str) {
Expand Down Expand Up @@ -1710,6 +1761,7 @@ var validator = {
isBefore: isBefore,
isIn: isIn,
isCreditCard: isCreditCard,
isIdentityCard: isIdentityCard,
isISIN: isISIN,
isISBN: isISBN,
isISSN: isISSN,
Expand Down
2 changes: 1 addition & 1 deletion validator.min.js

Large diffs are not rendered by default.

0 comments on commit 0649c05

Please sign in to comment.