Sleds/libeye.js/eyeperms.js

249 lines
7.1 KiB
JavaScript

/**
* @preserve Copyright (c) 2014-2015 IONU Security, Inc. All rights reserved.
*
* @file Permissions class for management and signature generation
*/
PERMISSION_KEY_OWNER = 'owner';
PERMISSION_KEY_TOPIC = 'topic';
PERMISSION_READ = 'read';
PERMISSION_WRITE = 'write';
PERMISSION_ADMIN = 'admin';
/*
PERMISSION_DOORWAY = 'doorway';
PERMISSION_STREAM = 'stream';
PERMISSION_HIDE = 'hide';
*/
PERMISSION_ASSIGNMENT_SUFFIX = 'Assign';
PERMISSION_ROOT_KEY = 'perms';
PERMISSION_TYPE_KEY = 'type'; // unset/empty 'file'; 'group'
PERMISSION_MEMBERS_KEY = "mbrs";
PERMISSION_SIGNATURE_KEY = "signature";
PERMISSION_DIGEST_KEY = "digest";
/**
* Permissions object
* @constructor
* @param {string|object} perms - JSON string or object
*/
function Permissions (perms) {
if (!(this instanceof Permissions)){
return new Permissions (perms);
}
if (typeof perms === 'string') {
this.perms = JSON.parse (perms);
}
else if (typeof perms === 'object') {
this.perms = perms;
}
else {
var error = new Error ('Invalid permissions');
throw error;
}
}
function createPermissionsFromOffice(officeId){
return createPermissionsFromCollaborators(officeId, [officeId]);
}
function createPermissionsFromCollaborators(owner, offices, noSub){
var p = {read:[], write:[], admin:[], readAssign:[], writeAssign:[], adminAssign:[]};
for (var i = 0; i < offices.length; ++i) {
var officeId = offices[i];
if (officeId.match(/^urn:sl/) && !noSub) {
officeId = officeId.replace(/^urn:sl:.{6}:/,'').replace(/:.*/,'');
}
p.read.push(officeId);
p.write.push(officeId);
p.admin.push(officeId);
p.readAssign.push(officeId);
p.writeAssign.push(officeId);
p.adminAssign.push(officeId);
//p.hideAssign.push(officeId);
}
p.owner = owner||'';
if (typeof p.owner === 'object'){
p.owner = p.owner._id.replace(/^urn:sl:.{6}:/,'').replace(/:.*/,'');
}
p = new Permissions(p);
return p;
}
function createPermissionsFromTeam(owner, teamUrn){
return createPermissionsFromCollaborators(owner, [teamUrn], true);
}
// Define the prototype methods for Permissions object
Permissions.prototype = {
constructor: Permissions,
/**
* Add all unique references from the current permission key
*
* @param {array} set of all unique references
* @param {string} perms for key, e.g. read/readAssign...
* @return {array} set of all unique references
*/
addUniqueReferences: function (refs, perms) {
if (perms !== undefined) {
var numPerms = perms.length;
for (var j = 0; j < numPerms; ++j) {
var permVal = perms[j];
if (permVal === PERMISSION_KEY_OWNER) {
permVal = this.perms.owner;
}
var urn = permVal;
if (urn.slice (0, 3) !== 'urn') {
urn = this.urnPrefix + permVal + '::';
}
var len = refs.length;
var found = false;
for (var i = 0; i < len; ++i) {
if (refs[i] == urn) {
found = true;
break;
}
}
if (found === false) {
refs.push (urn);
}
}
}
return refs;
},
/**
* Get all the unique references in urn format, sorted with '|' delimiter and optional topic id
*
* @param {string} van - urn string urn:sl:000000:::
* @return {string} ordered set of all references
*/
getOrderedReferences: function (van) {
var refs = [];
var owner = this.perms.owner;
var permissionKeys = [PERMISSION_READ,PERMISSION_WRITE,PERMISSION_ADMIN/*,PERMISSION_DOORWAY,PERMISSION_STREAM,PERMISSION_HIDE*/];
var numKeys = permissionKeys.length, key = null;
this.urnPrefix = '';
if (van !== undefined && van !== null) {
var urnFields = van.split (':');
if (urnFields.length > 4) {
this.urnPrefix = urnFields[0] + ':' + urnFields[1] + ':' + urnFields[2] + ':';
}
}
for (var i = 0; i < numKeys; ++i) {
key = permissionKeys[i];
var perms = this.perms[key];
refs = this.addUniqueReferences (refs, perms);
key = permissionKeys[i] + PERMISSION_ASSIGNMENT_SUFFIX;
perms = this.perms[key];
refs = this.addUniqueReferences (refs, perms);
}
refs.sort();
var delim = '';
var str = '';
refs.forEach(function(value) {
str += delim + value;
delim = '|';
});
// Append "topic"...
var topic = this.perms[PERMISSION_KEY_TOPIC];
if (topic !== undefined && topic.length > 0) {
str += delim + topic;
}
return str;
},
/**
* Convert permissions to ordered JSON string for path hash computation
* removes "owner" property, replaces "owner" in perms arrays with urn
*
* @param {string} van - urn string urn:sl:000000:::
* @return {string} ordered set of all references and optional topic
*/
getSignature: function (van) {
var perms = this.getOrderedReferences (van);
var md = forge.md.md5.create();
md.update (perms);
var sig = md.digest().toHex();
return sig.substring (0, 12);
},
/**
* Convert permissions to ordered JSON string for path hash computation
* removes "owner" property, replaces "owner" in perms arrays with urn
*
* @return {string} JSON string
*/
toOrderedString: function() {
var permissionKeys = [PERMISSION_READ,PERMISSION_WRITE,PERMISSION_ADMIN/*,PERMISSION_DOORWAY,PERMISSION_STREAM,PERMISSION_HIDE*/];
var json = '{';
var numKeys = permissionKeys.length, key = null;
var comma = '';
var owner = this.perms.owner;
for (var i = 0; i < 2; ++i) {
var suffix = (i == 0) ? '' : PERMISSION_ASSIGNMENT_SUFFIX;
for (var j = 0; j < numKeys; ++j) {
key = permissionKeys[j] + suffix;
var perms = this.perms[key];
if (perms === undefined) {
continue;
}
perms.sort();
var numPerms = perms.length;
json += comma + '"' + key + '":[';
var bHasOwner = false;
for (var k = 0; k < numPerms; ++k) {
var permVal = perms[k];
if (permVal === owner) {
bHasOwner = true;
}
if (permVal === PERMISSION_KEY_OWNER) {
if (bHasOwner === true) {
// we already emitted the UUID for owner so don't do it again
// note that normal "assign" logic prevents all other duplicate values
continue;
}
else {
permVal = owner;
}
}
if (k > 0) {
json += ',';
}
json += '"' + permVal + '"';
}
json += ']';
comma = ",";
}
}
// Append "topic"...
var topic = this.perms[PERMISSION_KEY_TOPIC];
if (topic !== undefined && topic.length > 0) {
json += ',"' + PERMISSION_KEY_TOPIC + '":"' + topic + '"';
}
json += '}';
return json;
},
/**
* Generate the path hash, left 12 bytes of hex encoded MD5 hash of the ordered JSON permissions
*
* @return {string} path hash
*/
getPathHash: function () {
var perms = this.toOrderedString();
var md = forge.md.md5.create();
md.update (perms);
var sig = md.digest().toHex();
return sig.substring (0, 12);
}
}