Comparing version 1.0.3 to 1.0.4
40
index.js
@@ -24,3 +24,4 @@ const fs = require('fs'); | ||
if (!fs.existsSync(self.fn(self.opts.xml)) || force) | ||
self.db = self.fn(self.opts.xml); | ||
if (!fs.existsSync(self.db) || force) | ||
await self.zipExtract(fn, self.opts.xml, self.opts.path); | ||
@@ -41,3 +42,3 @@ | ||
}, | ||
zipExtract: (zip, fn, dest = './') => { | ||
zipExtract: (zip, fn, dest = '.') => { | ||
var z = new Zip({file: zip}); | ||
@@ -49,3 +50,3 @@ return new Promise((resolve, reject) => { | ||
if (err) reject(err); | ||
resolve(dest + fn); | ||
resolve(dest + '/' + fn); | ||
z.close(); | ||
@@ -57,2 +58,3 @@ }) | ||
search: (cust, fn = self.db) => { | ||
if (!cust.search_type) cust.search_type = 'individual'; | ||
// input data clean | ||
@@ -86,8 +88,8 @@ | ||
xml2js.parseString(xml, {explicitArray: false}, (err, res) => { | ||
// if (err) throw new Error(err); | ||
if (err) throw {message: 'TEST'}; | ||
// look only an individual profiles | ||
if (res.sdnEntry.sdnType != 'Individual') return; | ||
if (err) throw new Error(err); | ||
// look only for profiles of the given type | ||
if (res.sdnEntry.sdnType.toLowerCase() != cust.search_type) | ||
return; | ||
// fix XML transform | ||
@@ -101,2 +103,3 @@ res = x(res); | ||
} | ||
function lc(o) { | ||
@@ -132,12 +135,19 @@ for (var k in o) if (o.hasOwnProperty(k) && typeof o[k] == 'string') | ||
for (var i = 0; i < res.idList.length; i++) { | ||
let ok = res.idList[i].idNumber == cust.id; | ||
ok = ok && res.idList[i].idCountry == cust.country; | ||
if (ok) return true; | ||
} | ||
var ok = res.idList.filter(o => { | ||
let ok = o.idNumber == cust.id; | ||
if (o.idCountry && cust.country) | ||
ok = ok && o.idCountry == cust.country; | ||
if (o.idType && cust.id_type) | ||
ok = ok && o.idType == cust.id_type; | ||
return ok; | ||
}); | ||
if (ok.length > 0) return true; | ||
// if not match emerges, try by name | ||
let ok = res.firstName == cust.firstName; | ||
ok = ok && res.lastName == cust.lastName; | ||
ok = cust.firstName || cust.lastName; | ||
if (res.firstName && cust.firstName) | ||
ok = ok && res.firstName == cust.firstName; | ||
if (res.lastName && cust.lastName) | ||
ok = ok && res.lastName == cust.lastName; | ||
if (ok) return true; | ||
@@ -144,0 +154,0 @@ |
{ | ||
"name": "ofac", | ||
"version": "1.0.3", | ||
"version": "1.0.4", | ||
"description": "A module to facilitate OFAC searches", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -0,1 +1,3 @@ | ||
[![npm version](https://badge.fury.io/js/ofac.svg)](https://badge.fury.io/js/ofac) | ||
# OFAC | ||
@@ -50,12 +52,19 @@ | ||
{ | ||
id, country, // and/or | ||
search_type: 'Individual', | ||
id, id_type, country, // and/or | ||
firstName, lastName | ||
} | ||
``` | ||
where `id` represents a passport number or other national identification number. | ||
where: | ||
* `search_type` defines the database domain within which to search. If left unspecified | ||
the module defaults to searches of individuals | ||
* `id` represents a passport number or other national identification number | ||
* `id_type` specifies the type of document to search for e.g. passport, national | ||
ID card, etc. If left unspecified all document types are searched. For more information | ||
on the types supported, please refer to the OFAC website. | ||
The search algorithm gives priority to the id/country as it is more authoritative (and | ||
both are required since the same id may exist in different countries) but failing to find | ||
it match it opts for first name and last name. These values are matched against the canonical | ||
name of the individual but are also match against a possible list of aliases. Searches are | ||
The search algorithm gives priority to the id/country as this information is more authoritative | ||
(and both are required since the same id may exist in different countries) but failing to find | ||
a match it opts for first name and last name. These values are matched against the canonical | ||
name of the individual but are also matched against a possible list of aliases. Searches are | ||
performed against sanitised data, thus "Stella-Marie" will match "Stella Marie", "STELLA MARIE" | ||
@@ -62,0 +71,0 @@ "stella marie", "stella/marie", and other variants |
var fs = require('fs'); | ||
var assert = require('assert').strict; | ||
const ofac = require('../index.js'); | ||
const fn = 't/t.xml'; | ||
const fn = '/tmp/sdn.xml'; | ||
@@ -33,16 +33,20 @@ var expected = [{ | ||
describe('Archive', () => { | ||
var zip = 'sdn_xml.zip', fn = 'sdn.xml'; | ||
var zip = 't/sdn.xml.zip', fn = 'sdn.xml'; | ||
before(() => { | ||
if (fs.existsSync(fn)) fs.unlinkSync(fn); | ||
let path = '/tmp/' + fn; | ||
if (fs.existsSync(path)) fs.unlinkSync(path); | ||
}) | ||
it('Extraction', async () => { | ||
var path = '/tmp/' + fn; | ||
assert.ok(fs.existsSync(zip), 'Archive does not exist'); | ||
assert.ok(!fs.existsSync(fn), 'Extract exists'); | ||
assert.ok(!fs.existsSync(path), 'Extract exists'); | ||
var actual = await ofac.zipExtract(zip, fn, '/tmp/'); | ||
assert.equal(actual, '/tmp/' + fn, 'Extracted a different file'); | ||
assert.ok(fs.existsSync('/tmp/' + fn), 'Extract file does not exist'); | ||
var actual = await ofac.zipExtract(zip, fn, '/tmp'); | ||
assert.equal(actual, path, 'Extracted a different file'); | ||
assert.ok(fs.existsSync(path), 'Extract file does not exist'); | ||
var stats = fs.statSync(path); | ||
assert.equal(stats.size, 10128, 'File incomplete') | ||
}); | ||
}); | ||
describe('search', () => { | ||
describe('Search', () => { | ||
before(() => { | ||
@@ -56,7 +60,27 @@ ofac.init(); | ||
}); | ||
it('Searched by id/country with type', async () => { | ||
var cust = {id: 'J287011', id_type: 'Passport', country: 'Colombia'}; | ||
var actual = await ofac.search(cust, fn); | ||
assert.deepEqual(actual, expected); | ||
}); | ||
it('Searched by id/country with wrong type', async () => { | ||
var cust = {id: 'J287011', id_type: 'Cedula No.', country: 'Colombia'}; | ||
var actual = await ofac.search(cust, fn); | ||
assert.deepEqual(actual, []); | ||
}); | ||
it('Searched by first/last', async () => { | ||
var cust = {firstName: 'Helmer', lastName: 'Herrera-Buitrago'}; | ||
var cust = {firstName: 'Helmer', lastName: 'HERRERA BUITRAGO'}; | ||
var actual = await ofac.search(cust, fn); | ||
assert.deepEqual(actual, expected, 'Name search differs'); | ||
}); | ||
it('Searched case insensitive', async () => { | ||
var cust = {firstName: 'Helmer', lastName: 'herrera buitrago'}; | ||
var actual = await ofac.search(cust, fn); | ||
assert.deepEqual(actual, expected, 'Name search differs'); | ||
}); | ||
it('Searched clean names', async () => { | ||
var cust = {firstName: 'Helmer', lastName: 'herrera-buitrago'}; | ||
var actual = await ofac.search(cust, fn); | ||
assert.deepEqual(actual, expected, 'Name search differs'); | ||
}); | ||
it('Checked aliases', async () => { | ||
@@ -71,3 +95,3 @@ var cust = {firstName: 'Helmer', lastName: 'pacho'}; | ||
() => ofac.search(cust, 't/bad.xml').finally(done), | ||
{message: 'Unhandled error. ([object Object])'} | ||
{message: 'Error: Unexpected close tag\nLine: 0\nColumn: 317\nChar: >'} | ||
); | ||
@@ -74,0 +98,0 @@ }); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
18528
7
231
154