Skip to content

Instantly share code, notes, and snippets.

@balbuf
Created September 5, 2016 22:09
Show Gist options
  • Save balbuf/81a77a754c0c03319452a8e5d68abf48 to your computer and use it in GitHub Desktop.
Save balbuf/81a77a754c0c03319452a8e5d68abf48 to your computer and use it in GitHub Desktop.
Demonstrates a method of managing protected data within objects
(function(){
// an object is used as a "key" since this object cannot be referenced outside of this scope (unless deliberately exposed)
// this exploits the strict equivalence of objects, requiring them to be the exact same instance to be considered equal
var secret = {};
/**
* A simple contrived object to demonstrate privileged getters/setters.
*/
function Person(name, age) {
this._ = new ProtectedData(secret);
this.setName(name);
this.setAge(age);
}
Person.prototype = {
constructor: Person,
getName: function() {
return this._.access(secret).name;
},
setName: function(value) {
this._.access(secret).name = value;
},
getAge: function() {
return this._.access(secret).age;
},
setAge: function(value) {
this._.access(secret).age = value;
},
};
})();
// create a new Person object with name and age
var me = new Person('Steve', 26);
// name is readily available via its getter
console.log(me.getName()); // "Steve"
// name can easily be set to another value
me.setName('Stephen');
console.log(me.getName('Stephen')); // "Stephen"
// the ProtectedData object is exposed and accessible
console.log(typeof me._); // "object"
// ...but its underlying data object is not
console.log(me._.access(secret).name); // Uncaught ReferenceError: secret is not defined
/**
* The object "secret" is completely inaccessible from this scope and thus
* it is not possible to get at the data object within the ProtectedData object.
* That being said, WeakMaps (if available) present a more elegant solution:
* http://fitzgeraldnick.com/2014/01/13/hiding-implementation-details-with-e6-weakmaps.html
*/
/**
* Protected setter/getter which uses an arbitrary object as a "key".
* The safety comes from the object "key" existing only within the protected scope of the consuming objects.
* @param {object} key object used to
* @param {bool} silent silently fails with incorrect key instead of
*/
function ProtectedData(key, silent) {
// key must be an object for it to be secure
if (Object(key) !== key) throw new Error('Invalid key type.');
// property mapping
var props = Object.create(null);
props.__silent__ = silent;
// authenticate the key
function auth(lock) {
if (lock !== key) {
if (props.__silent__) return false;
throw new Error('Access denied.');
}
return true;
}
return {
access: function(key) {
if (auth(key)) return props;
},
setKey: function(oldKey, newKey) {
if (auth(oldKey)) key = newKey;
},
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment