Skip to content

Instantly share code, notes, and snippets.

@bc-jasond
Created September 12, 2017 00:09
Show Gist options
  • Save bc-jasond/95bbc98076717234ce183e12035472f3 to your computer and use it in GitHub Desktop.
Save bc-jasond/95bbc98076717234ce183e12035472f3 to your computer and use it in GitHub Desktop.
/*
We are implementing a `view` that must consume
some external service (which we've mocked below). The service returns
data that needs to be sanitized for client consumption -- in the
below example it includes sensitive information like SSN, email, etc.... The
exercises work through simple sanitizations, to slightly more complex
ones, before asking that the interviewee try to define a general approach
to solving the problem.
*/
var _ = require('lodash');
var externalService = function(projectName){
// Mock; in real life we use some information
// about the project to, say, read from a
// particular URL.
return {
'project': 'Sanitization Project',
'users': [
{
'username': 'z',
'email': '[email protected]',
'ssn': '111223333',
'apiKeys': [
{
'codename': 'tugboat',
'code': 'la8dfh47',
},
{
'codename': 'titanic',
'code': 'dg810fj3',
},
]
},
{
'username': 'bk',
'email': '[email protected]',
'ssn': '889900000',
'apiKeys': [],
}
],
};
};
function last4(obj, key) {
const ssnReplaceChars = '*****';
const ssnLast4 = obj[key].substring(5);
obj[key] = `${ssnReplaceChars}${ssnLast4}`;
}
function strip(obj, key) {
delete obj[key];
}
var sanitize = function(response){
//const blacklisted = ['ssn', 'code'];
if (_.isObject(response)) {
for (let key in response.keys()) {
if (definition.hasOwnProperty(key)) {
definition[key](response, key);
}
sanitize(response[key]);
// value = transformations[transformation](value, key, response);
}
}
if (_.isArray(response)) {
_.map(response, sanitize);
}
return response;
};
var view = function(projectName){
response = externalService(projectName);
sanitize(response);
return response;
};
var response = view('part 0');
// Part 4:
//
// Seems like this is getting to be a common occurrence -- let's
// make it easier on ourselves. Any time you see key, do value.
var definition = {
ssn: 'last4',
email: 'strip',
code: 'strip'
};
response = view('part 4');
console.assert(response.users[0].ssn == '*****3333', 'last 4');
console.assert(response.users[1].ssn == '*****0000', 'last 4');
console.assert(!response.users[0].email, 'stripped email');
console.assert(!response.users[1].email, 'stripped email');
console.assert(!response.users[0].apiKeys[0].code, 'stripped first code');
console.assert(!response.users[0].apiKeys[1].code, 'stripped second code');
console.info('part 4 done!');
// Part 4 solution
var transformations = {
'last-4': function(value){
return value.replace(/^.{5}/, '*****')
},
'domain-only': function(value){
return '****@' + value.split('@')[1];
},
'strip': function(value, key, response){
delete response[key];
}
};
var sanitize = function(response){
if(_.isObject(response)){
_.forEach(response, function(value, key){
var transformation = definition[key];
if(transformation){
value = transformations[transformation](value, key, response);
}
if(!_.isUndefined(value)){
response[key] = value;
sanitize(value);
}
});
}
else if(_.isArray(response)){
_.map(response, sanitize);
}
return;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment