cityhall
Version:
npm library for accessing City Hall Enterprise Settings Server
375 lines (327 loc) • 12 kB
JavaScript
/**
* These are the actual calls to City Hall
*
* They are broken out into a lib.js since they're not particularly user-friendly
* as raw calls. They are wrapped in a user-friendly interface in index.js,
* which will, for example, automatically log the user as well as do some extra
* validation on the input.
*/
var md5 = require('md5');
var hostname = require('os').hostname();
var sanitize = require('./sanitize.js');
var getFirstProperty = function (obj) {
for (var prop in obj) {
if (obj.hasOwnProperty(prop)) {
return prop;
}
}
return undefined;
};
var invalidUri = function(env, path, override) {
return (env == undefined || env == ''
|| path == undefined || path == ''
|| override == undefined
|| ('string' != typeof env)
|| ('string' != typeof path)
|| ('string' != typeof override));
};
var validateUri = function(uri, callback) {
if (uri == undefined) {
sanitize.call(callback, 'missing fully qualified path');
return;
}
if (invalidUri(uri.environment, uri.path, uri.override)) {
sanitize.call(callback, 'must specify environment, path, and override');
return;
}
callback();
};
module.exports = function (url, name, password) {
if (url == undefined) {
throw new Error("Expected a URL to reach City Hall");
}
var http = require('./http.js')(url);
if (name == undefined) {
name = hostname;
}
if (password == undefined) {
password = '';
}
/**
* This is the current logged in user, if you are logged in.
* Will be set by login()
*/
var user_name = '';
/**
* This is the default environment for this session.
* The calls to getVal() and getValOverride() will use this value.
*/
var default_environment = '';
/********************************
* this section is a set of wrappers for the functions that the user
* will actually call. It is done this way so that the actual functions
* can easily wrap them with a call to login if we're logged out.
*/
var getSingleVal = function (url, callback) {
var fullpath = 'env/'+default_environment+sanitize.path(url);
http.get(fullpath, null, function (err, data) {
if (err) {
sanitize.call(callback, err);
return;
}
sanitize.call(callback, null, data.value);
});
};
var getSingleObj = function (obj, callback) {
var env = default_environment;
var params = null;
if (obj.environment != undefined) {
env = obj.environment;
}
if (obj.override != undefined) {
params = {override: obj.override};
}
var fullpath = 'env/'+env+sanitize.path(obj.path);
if (obj.raw) {
http.get(fullpath, params, callback);
} else {
http.get(fullpath, params, function (err, data) {
if (err) {
sanitize.call(callback, err);
return;
}
sanitize.call(callback, null, data.value);
});
}
};
var getNextValue = function (values, response, callback) {
var prop = getFirstProperty(values);
if (prop) {
getSingleObj(values[prop], function (err, data) {
if (err) {
sanitize.call(callback, err);
return;
}
response[prop] = data;
delete values[prop];
getNextValue(values, response, callback);
});
} else {
sanitize.call(callback, null, response);
}
};
var setSingleObj = function (uri, value, callback) {
http.post('env/'+uri.environment+sanitize.path(uri.path)+'?override='+uri.override,
value, callback);
};
var setNextValue = function (values, callback) {
var value = values.pop();
if (value == undefined) {
sanitize.call(callback);
return;
}
var sanitizedSet = sanitize.setCallBody(value);
setSingleObj(value, sanitizedSet, function(err, data) {
if (err) {
sanitize.call(callback, err);
return;
}
setNextValue(values, callback);
});
};
/**
* For information on these functions, check out the documentation in
* index.js, which is a user-friendly wrapper around these calls.
*
* These functions all assume the user is already logged in.
*/
return {
getName: function() {
return user_name;
},
login: function(callback) {
var payload = {'username': name, 'passhash': this.hash(password)};
http.post('auth/', payload, function(err, data) {
if (err) {
sanitize.call(callback, err);
return;
}
http.get('auth/user/' + name + '/default/', null,
function (err, data) {
if (err) {
sanitize.call(callback, err);
return;
}
default_environment = data.value || '';
user_name = name;
sanitize.call(callback);
}
);
});
},
logout: function(callback) {
http.delete('auth/',undefined, function(err, data) {
if (err) {
sanitize.call(callback, err);
return;
}
user_name = '';
sanitize.call(callback);
}
);
},
defaultEnvironment: function() {
return default_environment;
},
setDefaultEnvironment: function(env, callback) {
http.post('auth/user/'+user_name+'/default/', {env: env},
function(err, data) {
if (err) {
sanitize.call(callback, err);
return;
}
default_environment = env;
sanitize.call(callback);
}
);
},
viewUsers: function(env, callback) {
http.get('auth/env/' + env +'/', null, function(err, data) {
if (err) {
sanitize.call(callback, err);
return;
}
sanitize.call(callback, null, data.Users);
});
},
createEnvironment: function(env, callback) {
http.post('auth/env/' + env + '/', {}, callback);
},
getUser: function(user, callback) {
http.get('auth/user/'+user+'/', null, function(err, data) {
if (err) {
sanitize.call(callback, err);
return;
}
sanitize.call(callback, null, data.Environments);
});
},
createUser: function(user, password, callback) {
http.post('auth/user/'+user+'/', {passhash: this.hash(password)}, callback);
},
updatePassword:function(password, callback) {
http.put('auth/user/'+user_name+'/', {passhash: this.hash(password)}, callback);
},
deleteUser: function(user, callback) {
http.delete('auth/user/'+user+'/', undefined, callback);
},
grant: function(user, env, rights, callback) {
http.post('auth/grant/', {env: env, user: user, rights: rights}, callback);
},
getVal: function (val, callback) {
if ((val == undefined) || (getFirstProperty(val) == undefined)) {
sanitize.call(callback, 'must specify value to get');
return;
} else if (typeof val == 'string' || val instanceof String) {
getSingleVal(val, callback);
} else if (val.path == undefined) {
for (var item in val) {
if (val[item].path == undefined) {
sanitize.call(callback, 'must specify value to get ('+item+')');
return;
}
}
getNextValue(val, {}, callback);
} else {
getSingleObj(val, callback);
}
},
setVal: function (uri, value, callback) {
if (value instanceof Array) {
for (var i=0; i<value.length; i++) {
var val = value[i];
if (invalidUri(val.environment, val.path, val.override)) {
sanitize.call(callback, 'must specify environment, path, and override (' + i + ')');
return;
}
var sanitizedSet = sanitize.setCallBody(val);
if (!sanitizedSet) {
sanitize.call(callback, 'must specify value to set (' + i + ')');
return;
}
}
return setNextValue(value, callback);
}
validateUri(uri, function(err, data) {
if (err) {
sanitize.call(callback, err);
return;
}
var sanitizedSet = sanitize.setCallBody(value);
if (!sanitizedSet) {
sanitize.call(callback, 'must specify value to set');
return;
}
setSingleObj(uri, sanitizedSet, callback);
});
},
deleteVal: function(uri, callback) {
validateUri(uri, function(err, data) {
if (err) {
sanitize.call(callback, err);
return;
}
http.delete(
'env/'+uri.environment+sanitize.path(uri.path),
{override:uri.override}, callback
);
});
},
getHistory: function(uri, callback) {
validateUri(uri, function(err, data) {
if (err) {
sanitize.call(callback, err);
return;
}
http.get(
'env/'+uri.environment + sanitize.path(uri.path),
{override: uri.override, viewhistory: true},
function(err, data) {
if (err) {
sanitize.call(callback, err);
return;
}
sanitize.call(callback, null, data.History);
}
);
});
},
getChildren: function(env, path, callback) {
if (invalidUri(env, path, '')) {
sanitize.call(callback, 'Must specify environment and path');
return;
}
http.get('env/'+env+sanitize.path(path), {viewchildren: true},
function (err, data) {
if (err) {
sanitize.call(callback, err);
} else {
sanitize.call(callback, null, {path: data.path, children: data.children});
}
}
);
},
/**
* Hash a password for use with City Hall.
*
* @param password - the plaintext password
* @returns string - City Hall hash of the given password
*/
hash: function(password) {
if ((password == undefined) || (password == '')) {
return '';
}
return md5(password);
}
};
};