Skip to content

Commit

Permalink
fix: Improved redaction of names (#12)
Browse files Browse the repository at this point in the history
  • Loading branch information
justbbetter committed Dec 21, 2017
1 parent 769a414 commit e688011
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 8 deletions.
25 changes: 22 additions & 3 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ var snakeCase = require('lodash/snakeCase');
var patterns = require('./patterns.js');

function defaultReplace(name) {
return name === 'name' ? '$1NAME' : snakeCase(name).toUpperCase();
return name === 'names' ? '$1NAME' :
name === 'greetOrClose' ? 'NAME' :
snakeCase(name).toUpperCase();
}

function determineReplace(options) {
Expand All @@ -30,11 +32,28 @@ function Redactor(userOpts) {
}

forEach(patternsToUse, function (pattern, name) {
if (pattern === false) {
if (pattern === false || name === 'nameGeneric') {
return;
}

text = text.replace(pattern, replacements[name]);
if (name === 'greetOrClose') {
var pattern2 = patterns.nameGeneric;
pattern.lastIndex = 0;
pattern2.lastIndex = 0;
var mtch = pattern.exec(text);
while (mtch !== null) {
pattern2.lastIndex = pattern.lastIndex;
var mtch2 = pattern2.exec(text);
if (mtch2 !== null && mtch2.index === pattern.lastIndex) {
var suffix = mtch2[5] === null ? '' : mtch2[5];
text = text.slice(0, mtch2.index) + replacements[name] + suffix +
text.slice(mtch2.index + mtch2[0].length);
}
mtch = pattern.exec(text);
}
} else {
text = text.replace(pattern, replacements[name]);
}
});

return text;
Expand Down
8 changes: 6 additions & 2 deletions lib/patterns.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,14 @@ var names = require('./names.json').sort().reverse();
var aptRegex = /(apt|bldg|dept|fl|hngr|lot|pier|rm|ste|slip|trlr|unit|#)\.? *[a-z0-9-]+\b/gi;
var poBoxRegex = /P\.? ?O\.? *Box +\d+/gi;
var roadRegex = /(street|st|road|rd|avenue|ave|drive|dr|loop|court|ct|circle|cir|lane|ln|boulevard|blvd|way)\.?\b/gi;
var greetOrCloseRegex = /((((dear|hi|hello|greetings)|((thanks|thank you|regards|best|sincerely|best regards|warm regards|warmest regards|warmly|all the best)[,.]?))\s+)|([\n\f\r]\s*))/gi;
var greetingRegex = /(^|\.\s+)(dear|hi|hello|greetings|hey|hey there)/gi;
var closingRegex = /(thx|thanks|thank you|regards|best|[a-z]+ly|[a-z]+ regards|all the best|happy [a-z]+ing|take care|have a [a-z]+ (weekend|night|day))/gi;
var newlineRegex = /([\n\f\r-]+\s*)/gi;

module.exports = {
name: new RegExp(`${greetOrCloseRegex.source}((${names.join('|')}) ?)+`, 'gi'),
greetOrClose: new RegExp(`(((${greetingRegex.source})|(${closingRegex.source}\\s*[,.!]*))[\\s-]*)`, 'gi'),
nameGeneric: new RegExp(`( ?(([A-Z][a-z]+)|([A-Z]\\.)))+([,.]|[,.]?$)`, 'gm'),
names: new RegExp(`${newlineRegex.source}([. ]*(${names.join('|')}))+ *$`, 'gim'),
creditCardNumber: /\d{4}[ -]?\d{4}[ -]?\d{4}[ -]?\d{4}|\d{4}[ -]?\d{6}[ -]?\d{4}\d?/g,
streetAddress: new RegExp(`(\\d+\\s*(\\w+ ){1,2}${roadRegex.source}(\\s+${aptRegex.source})?)|(${poBoxRegex.source})`, 'gi'),
zipcode: /\b\d{5}\b(-\d{4})?\b/g,
Expand Down
20 changes: 17 additions & 3 deletions test/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,28 @@ defineTest('index.js', function (Redactor) {
});

it('should replace names', function () {
redactor.redact('blah blah\nThis is very important.').should.equal('blah blah\nThis is very important.');
redactor.redact('blah blah\n\nThank you ..Risemamy McCrubben').should.equal('blah blah\n\nThank you ..NAME');
redactor.redact('blah blah. Thanks -Jon').should.equal('blah blah. Thanks -NAME');
redactor.redact('here\'s my Cliff. blah blah').should.equal('here\'s my Cliff. blah blah');
redactor.redact('here\'s my Clifford. blah blah').should.equal('here\'s my Clifford. blah blah');
redactor.redact('Dear Clifford,\n blah blah').should.equal('Dear NAME,\n blah blah');
redactor.redact('blah blah\n\n\nthanks,\nAnna\n blah blah').should.equal('blah blah\n\n\nthanks,\nNAME\n blah blah');
redactor.redact('blah blah\n\n\nAnna\n blah blah').should.equal('blah blah\n\n\nNAME\n blah blah');
redactor.redact('blah blah\n\n\nAcme Support\n blah blah').should.equal('blah blah\n\n\nAcme Support\n blah blah');
redactor.redact('blah blah\n\n\n Joshua\n blah blah').should.equal('blah blah\n\n\n NAME\n blah blah');
redactor.redact('blah blah\n\n\nAll the best,\n\n-Acme Support\n\nfoo bar').should.equal('blah blah\n\n\nAll the best,\n\n-NAME\n\nfoo bar');
redactor.redact('blah blah\n\n\nAll the best,\n\n--Meg C.\n\nAcme Support').should.equal('blah blah\n\n\nAll the best,\n\n--NAME\n\nAcme Support');
redactor.redact('blah blah\n\n\nAll the best,\n\n-John\n\nAcme Support').should.equal('blah blah\n\n\nAll the best,\n\n-NAME\n\nAcme Support');
redactor.redact('blah blah\nthanks Joshua.\n blah blah').should.equal('blah blah\nthanks NAME.\n blah blah');
redactor.redact('Hi David Johnson,\nHow are you?\n\nthanks Joshua.\n blah blah').should.equal('Hi NAME,\nHow are you?\n\nthanks NAME.\n blah blah');;
redactor.redact('Hi David Johnson,\nHow are you?\n\nthanks Joshua.\n blah blah').should.equal('Hi NAME,\nHow are you?\n\nthanks NAME.\n blah blah');
redactor.redact('Subject. Hi David Johnson.').should.equal('Subject. Hi NAME.');
redactor.redact('to hearing from you.\n\nAll the best,\n\nAngel\nCustomer Experience\nwww.foo.com').should.equal('to hearing from you.\n\nAll the best,\n\nNAME\nCustomer Experience\nwww.foo.com');
redactor.redact('getting this sorted out.\n\nKindest regards,\n\nFoo Bar\nCustomer Experience').should.equal('getting this sorted out.\n\nKindest regards,\n\nNAME\nCustomer Experience');
redactor.redact('blah.\n\nAffectionately,\n\nFoo Bar\nblah').should.equal('blah.\n\nAffectionately,\n\nNAME\nblah');
redactor.redact('blah.\n\nHappy Meditating!\n\nFoo Bar\nblah').should.equal('blah.\n\nHappy Meditating!\n\nNAME\nblah');
redactor.redact('blah.\n\nTake care!\n\nFoo Bar\nblah').should.equal('blah.\n\nTake care!\n\nNAME\nblah');
redactor.redact('blah.\n\nHave a wonderful weekend.\n\nFoo Bar\nblah').should.equal('blah.\n\nHave a wonderful weekend.\n\nNAME\nblah');
});

it('should replace credit card numbers', function () {
Expand Down Expand Up @@ -109,7 +123,7 @@ defineTest('index.js', function (Redactor) {
replace: function (name, defaultReplacement) {
if (name === 'creditCardNumber') {
return value => 'XXXXXXXXXXXX' + value.slice(12);
} else if (name === 'name') {
} else if (name === 'greetOrClose') {
return 'FULL_NAME';
} else {
return defaultReplacement;
Expand All @@ -118,7 +132,7 @@ defineTest('index.js', function (Redactor) {
});

redactor.redact('my CC is 1234567812345678').should.equal('my CC is XXXXXXXXXXXX5678');
redactor.redact('Dear David Johnson, he lives in 90210').should.equal('FULL_NAME, he lives in ZIPCODE');
redactor.redact('Dear David Johnson, he lives in 90210').should.equal('Dear FULL_NAME, he lives in ZIPCODE');
});

it('should accept new patterns', function () {
Expand Down

0 comments on commit e688011

Please sign in to comment.