blob: 824f2935c40c148446352f31c6a51cfa08153192 [file] [log] [blame]
/*
* This module is a collection of classes designed to make working with
* the Appigee App Services API as easy as possible.
* Learn more at http://apigee.com/docs/usergrid
*
* Copyright 2012 Apigee Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* @author rod simpson (rod@apigee.com)
*/
(function(window, localStorage){
//Hack around IE console.log
window.console = window.console || {};
window.console.log = window.console.log || function() {};
//Usergrid namespace encapsulates this SDK
window.Usergrid = window.Usergrid || {};
Usergrid = Usergrid || {};
Usergrid.SDK_VERSION = '0.10.07';
Usergrid.browser = Usergrid.browser || {};
Usergrid.Client = function(options,url) {
//usergrid enpoint
this.URI = url || 'https://api.usergrid.com';
//Find your Orgname and Appname in the Admin portal (http://apigee.com/usergrid)
if (options.orgName) {
this.set('orgName', options.orgName);
}
if (options.appName) {
this.set('appName', options.appName);
}
if(options.keys){
this._keys = options.keys;
}
//other options
this.buildCurl = options.buildCurl || false;
this.logging = options.logging || false;
//timeout and callbacks
this._callTimeout = options.callTimeout || 30000; //default to 30 seconds
this._callTimeoutCallback = options.callTimeoutCallback || null;
this.logoutCallback = options.logoutCallback || null;
};
/*
* Main function for making requests to the API. Can be called directly.
*
* options object:
* `method` - http method (GET, POST, PUT, or DELETE), defaults to GET
* `qs` - object containing querystring values to be appended to the uri
* `body` - object containing entity body for POST and PUT requests
* `endpoint` - API endpoint, for example 'users/fred'
* `mQuery` - boolean, set to true if running management query, defaults to false
*
* @method request
* @public
* @params {object} options
* @param {function} callback
* @return {callback} callback(err, data)
*/
Usergrid.Client.prototype.request = function (options, callback) {
callback = callback || function(){console.error('no callback handed to client.request().')};
var self = this;
var method = options.method || "GET";
var endpoint = options.endpoint;
var body = options.body || {};
var qs = options.qs || {};
var mQuery = options.mQuery || false;
//is this a query to the management endpoint?
var orgName = this.get("orgName");
var appName = this.get("appName");
if (!mQuery && !orgName && !appName) {
if (typeof this.logoutCallback === "function") {
return this.logoutCallback(true, "no_org_or_app_name_specified");
}
}
var uri;
if (mQuery) {
uri = this.URI + "/" + endpoint;
} else {
uri = this.URI + "/" + orgName + "/" + appName + "/" + endpoint;
}
if (self.getToken()) {
qs.access_token = self.getToken();
}
var developerkey=self.get("developerkey");
if (developerkey) {
qs.key = developerkey;
}
var isIE9 = Usergrid.browser.isIE9 = $.browser.msie && $.browser.version <= 9;
(isIE9) && (method === 'PUT' || method === 'DELETE') && (function(){ qs['method_override'] = method;})();
//append params to the path
var encoded_params = encodeParams(qs);
if (encoded_params) {
uri += "?" + encoded_params;
}
//stringify the body object
body = options.formData ? null : JSON.stringify(body);
//so far so good, so run the query
//*** ie9 hack
var xhr;
//check to see if ie9 - if so, convert delete and put calls to a POST
if (isIE9) { //XDomainRequest
xhr = new XDomainRequest();
(method === 'PUT' || method === 'DELETE') && (function() { method = 'POST';})();
xhr.open(method, uri);
}else{
xhr = new XMLHttpRequest();
xhr.open(method, uri, true);
//add content type = json if there is a json payload
if (!options.formData) {
xhr.setRequestHeader("Content-Type", "application/json");
xhr.setRequestHeader("Accept", "application/json");
}
}
xhr.isIE9 = isIE9;
// Handle response.
xhr.onerror = function(response) {
self._end = new Date().getTime();
if (self.logging) {
console.log("success (time: " + self.calcTimeDiff() + "): " + method + " " + uri);
}
if (self.logging) {
console.log("Error: API call failed at the network level.");
}
//network error
clearTimeout(timeout);
var err = true;
if (typeof callback === "function") {
callback(err, response);
}
};
xhr.onload = function(response) {
//call timing, get time, then log the call
self._end = new Date().getTime();
if (self.logging) {
console.log("success (time: " + self.calcTimeDiff() + "): " + method + " " + uri);
}
//call completed
clearTimeout(timeout);
//decode the response
try {
response = JSON.parse(xhr.responseText);
} catch (e) {
response = {
error: "unhandled_error",
error_description: xhr.responseText
};
xhr.status = xhr.status === 200 ? 400 : xhr.status;
console.error(e);
}
if (!xhr.isIE9 && xhr.status != 200) {
//there was an api error
var error = response.error;
var error_description = response.error_description;
if (self.logging) {
console.log("Error (" + xhr.status + ")(" + error + "): " + error_description);
}
if (error == "auth_expired_session_token" || error == "auth_missing_credentials" || error == "auth_unverified_oath" || error == "expired_token" || error == "unauthorized" || error == "auth_invalid") {
//these errors mean the user is not authorized for whatever reason. If a logout function is defined, call it
//if the user has specified a logout callback:
if (typeof self.logoutCallback === "function") {
return self.logoutCallback(true, response);
}
}
if (typeof callback === "function") {
callback(true, response);
}
} else {
if (typeof callback === "function") {
callback(false, response);
}
}
};
var timeout = setTimeout(function() {
xhr.abort();
if (self._callTimeoutCallback === "function") {
self._callTimeoutCallback("API CALL TIMEOUT");
} else {
callback("API CALL TIMEOUT");
}
}, self._callTimeout);
//set for 30 seconds
if (this.logging) {
console.log("calling: " + method + " " + uri);
}
if (this.buildCurl) {
var curlOptions = {
uri: uri,
body: body,
method: method
};
this.buildCurlCall(curlOptions);
}
this._start = new Date().getTime();
xhr.send(options.formData || body);
};
Usergrid.Client.prototype.keys = function(o) {
var a = [];
for (var propertyName in o) {
a.push(propertyName);
}
return a;
}
/*
* Main function for creating new groups. Call this directly.
*
* @method createGroup
* @public
* @params {string} path
* @param {function} callback
* @return {callback} callback(err, data)
*/
Usergrid.Client.prototype.createGroup = function(options, callback) {
var getOnExist = options.getOnExist || false;
var options = {
path: options.path,
client: this,
data:options
}
var group = new Usergrid.Group(options);
group.fetch(function(err, data){
var okToSave = (err && ('service_resource_not_found' === data.error || 'no_name_specified' === data.error || 'null_pointer' === data.error || Usergrid.browser.isIE9)) || (!err && getOnExist);
if (okToSave) {
group.save(function(err, data){
if (typeof(callback) === 'function') {
callback(err, group);
}
});
} else {
if(typeof(callback) === 'function') {
callback(err, group);
}
}
});
}
/*
* Main function for creating new entities - should be called directly.
*
* options object: options {data:{'type':'collection_type', 'key':'value'}, uuid:uuid}}
*
* @method createEntity
* @public
* @params {object} options
* @param {function} callback
* @return {callback} callback(err, data)
*/
Usergrid.Client.prototype.createEntity = function (options, callback) {
// todo: replace the check for new / save on not found code with simple save
// when users PUT on no user fix is in place.
/*
var options = {
client:this,
data:options
}
var entity = new Usergrid.Entity(options);
entity.save(function(err, data) {
if (typeof(callback) === 'function') {
callback(err, entity);
}
});
*/
var getOnExist = options.getOnExist || false; //if true, will return entity if one already exists
var options = {
client:this,
data:options
}
var entity = new Usergrid.Entity(options);
entity.fetch(function(err, data) {
//if the fetch doesn't find what we are looking for, or there is no error, do a save
if (Usergrid.browser.isIE9 || 'service_resource_not_found' === data.error || 'no_name_specified' === data.error || 'null_pointer' === data.error) {
entity.set(options.data); //add the data again just in case
entity.save(function(err, data) {
if (typeof(callback) === 'function') {
callback(err, entity, data);
}
});
} else {
if (getOnExist) {
// entity exists and they want it returned
if (typeof(callback) === 'function') {
callback(err, entity, data);
}
} else {
//entity exists but they want an error to that effect
err = true;
callback(err, 'duplicate entity already exists');
}
}
});
}
/*
* Main function for getting existing entities - should be called directly.
*
* You must supply a uuid or (username or name). Username only applies to users.
* Name applies to all custom entities
*
* options object: options {data:{'type':'collection_type', 'name':'value', 'username':'value'}, uuid:uuid}}
*
* @method createEntity
* @public
* @params {object} options
* @param {function} callback
* @return {callback} callback(err, data)
*/
Usergrid.Client.prototype.getEntity = function (options, callback) {
var options = {
client:this,
data:options
}
var entity = new Usergrid.Entity(options);
entity.fetch(function(err, data) {
if (typeof(callback) === 'function') {
callback(err, entity, data);
}
});
}
/*
* Main function for restoring an entity from serialized data.
*
* serializedObject should have come from entityObject.serialize();
*
* @method restoreEntity
* @public
* @param {string} serializedObject
* @return {object} Entity Object
*/
Usergrid.Client.prototype.restoreEntity = function (serializedObject) {
var data = JSON.parse(serializedObject);
var options = {
client:this,
data:data
}
var entity = new Usergrid.Entity(options);
return entity;
}
/*
* Main function for creating new collections - should be called directly.
*
* options object: options {client:client, type: type, qs:qs}
*
* @method createCollection
* @public
* @params {object} options
* @param {function} callback
* @return {callback} callback(err, data)
*/
Usergrid.Client.prototype.createCollection = function (options, callback) {
options.client = this;
var collection = new Usergrid.Collection(options, function(err, data) {
if (typeof(callback) === 'function') {
callback(err, collection, data);
}
});
}
/*
* Main function for restoring a collection from serialized data.
*
* serializedObject should have come from collectionObject.serialize();
*
* @method restoreCollection
* @public
* @param {string} serializedObject
* @return {object} Collection Object
*/
Usergrid.Client.prototype.restoreCollection = function (serializedObject) {
var data = JSON.parse(serializedObject);
data.client = this;
var collection = new Usergrid.Collection(data);
return collection;
}
/*
* Main function for retrieving a user's activity feed.
*
* @method getFeedForUser
* @public
* @params {string} username
* @param {function} callback
* @return {callback} callback(err, data, activities)
*/
Usergrid.Client.prototype.getFeedForUser = function(username, callback) {
var options = {
method: "GET",
endpoint: "users/"+username+"/feed"
}
this.request(options, function(err, data){
if(typeof(callback) === "function") {
if(err) {
callback(err);
} else {
callback(err, data, data.entities);
}
}
});
}
/*
* Function for creating new activities for the current user - should be called directly.
*
* //user can be any of the following: "me", a uuid, a username
* Note: the "me" alias will reference the currently logged in user (e.g. 'users/me/activties')
*
* //build a json object that looks like this:
* var options =
* {
* "actor" : {
* "displayName" :"myusername",
* "uuid" : "myuserid",
* "username" : "myusername",
* "email" : "myemail",
* "picture": "http://path/to/picture",
* "image" : {
* "duration" : 0,
* "height" : 80,
* "url" : "http://www.gravatar.com/avatar/",
* "width" : 80
* },
* },
* "verb" : "post",
* "content" : "My cool message",
* "lat" : 48.856614,
* "lon" : 2.352222
* }
*
* @method createEntity
* @public
* @params {string} user // "me", a uuid, or a username
* @params {object} options
* @param {function} callback
* @return {callback} callback(err, data)
*/
Usergrid.Client.prototype.createUserActivity = function (user, options, callback) {
options.type = 'users/'+user+'/activities';
var options = {
client:this,
data:options
}
var entity = new Usergrid.Entity(options);
entity.save(function(err, data) {
if (typeof(callback) === 'function') {
callback(err, entity);
}
});
}
/*
* Function for creating user activities with an associated user entity.
*
* user object:
* The user object passed into this function is an instance of Usergrid.Entity.
*
* @method createUserActivityWithEntity
* @public
* @params {object} user
* @params {string} content
* @param {function} callback
* @return {callback} callback(err, data)
*/
Usergrid.Client.prototype.createUserActivityWithEntity = function(user, content, callback) {
var username = user.get("username");
var options = {
actor: {
"displayName":username,
"uuid":user.get("uuid"),
"username":username,
"email":user.get("email"),
"picture":user.get("picture"),
"image": {
"duration":0,
"height":80,
"url":user.get("picture"),
"width":80
},
},
"verb":"post",
"content":content };
this.createUserActivity(username, options, callback);
}
/*
* A private method to get call timing of last call
*/
Usergrid.Client.prototype.calcTimeDiff = function () {
var seconds = 0;
var time = this._end - this._start;
try {
seconds = ((time/10) / 60).toFixed(2);
} catch(e) { return 0; }
return seconds;
}
/*
* A public method to store the OAuth token for later use - uses localstorage if available
*
* @method setToken
* @public
* @params {string} token
* @return none
*/
Usergrid.Client.prototype.setToken = function (token) {
this.set('token', token);
}
/*
* A public method to get the OAuth token
*
* @method getToken
* @public
* @return {string} token
*/
Usergrid.Client.prototype.getToken = function () {
return this.get('token');
}
Usergrid.Client.prototype.setObject = function(key, value) {
if (value) {
value = JSON.stringify(value);
}
this.set(key, value);
}
Usergrid.Client.prototype.set = function (key, value) {
var keyStore = 'apigee_' + key;
this[key] = value;
if(typeof(Storage)!=="undefined"){
if (value) {
localStorage.setItem(keyStore, value);
} else {
localStorage.removeItem(keyStore);
}
}
}
Usergrid.Client.prototype.getObject = function(key) {
return JSON.parse(this.get(key));
}
Usergrid.Client.prototype.get = function (key) {
var keyStore = 'apigee_' + key;
if (this[key]) {
return this[key];
} else if(typeof(Storage)!=="undefined") {
return localStorage.getItem(keyStore);
}
return null;
}
/*
* A public facing helper method for signing up users
*
* @method signup
* @public
* @params {string} username
* @params {string} password
* @params {string} email
* @params {string} name
* @param {function} callback
* @return {callback} callback(err, data)
*/
Usergrid.Client.prototype.signup = function(username, password, email, name, callback) {
var self = this;
var options = {
type:"users",
username:username,
password:password,
email:email,
name:name
};
this.createEntity(options, callback);
}
/*
*
* A public method to log in an app user - stores the token for later use
*
* @method login
* @public
* @params {string} username
* @params {string} password
* @param {function} callback
* @return {callback} callback(err, data)
*/
Usergrid.Client.prototype.login = function (username, password, callback) {
var self = this;
var options = {
method:'POST',
endpoint:'token',
body:{
username: username,
password: password,
grant_type: 'password'
}
};
this.request(options, function(err, data) {
var user = {};
if (err && self.logging) {
console.log('error trying to log user in');
} else {
var options = {
client:self,
data:data.user
}
user = new Usergrid.Entity(options);
self.setToken(data.access_token);
}
if (typeof(callback) === 'function') {
callback(err, data, user);
}
});
}
Usergrid.Client.prototype.reAuthenticateLite = function (callback) {
var self = this;
var options = {
method:'GET',
endpoint:'management/me',
mQuery:true
};
this.request(options, function(err, response) {
if (err && self.logging) {
console.log('error trying to re-authenticate user');
} else {
//save the re-authed token and current email/username
self.setToken(response.access_token);
}
if (typeof(callback) === 'function') {
callback(err);
}
});
}
Usergrid.Client.prototype.reAuthenticate = function (email, callback) {
var self = this;
var options = {
method:'GET',
endpoint:'management/users/'+email,
mQuery:true
};
this.request(options, function(err, response) {
var organizations = {};
var applications = {};
var user = {};
if (err && self.logging) {
console.log('error trying to full authenticate user');
} else {
var data = response.data;
self.setToken(data.token);
self.set('email', data.email);
//delete next block and corresponding function when iframes are refactored
localStorage.setItem('accessToken', data.token);
localStorage.setItem('userUUID', data.uuid);
localStorage.setItem('userEmail', data.email);
//end delete block
var userData = {
"username" : data.username,
"email" : data.email,
"name" : data.name,
"uuid" : data.uuid
}
var options = {
client:self,
data:userData
}
user = new Usergrid.Entity(options);
organizations = data.organizations;
var org = '';
try {
//if we have an org stored, then use that one. Otherwise, use the first one.
var existingOrg = self.get('orgName');
org = (organizations[existingOrg])?organizations[existingOrg]:organizations[Object.keys(organizations)[0]];
self.set('orgName', org.name);
} catch(e) {
err = true;
if (self.logging) { console.log('error selecting org'); }
} //should always be an org
applications = self.parseApplicationsArray(org);
self.selectFirstApp(applications);
self.setObject('organizations', organizations);
self.setObject('applications', applications);
}
if (typeof(callback) === 'function') {
callback(err, data, user, organizations, applications);
}
});
}
Usergrid.Client.prototype.orgLogin = function (username, password, callback) {
var self = this;
var options = {
method:'POST',
endpoint:'management/token',
mQuery:true,
body:{
username: username,
password: password,
grant_type: 'password'
}
};
this.request(options, function(err, data) {
var user = {};
var organizations = {};
var applications = {};
if (err && self.logging) {
console.log('error trying to log user in');
} else {
var options = {
client:self,
data:data.user
}
user = new Usergrid.Entity(options);
self.setToken(data.access_token);
self.set('email', data.user.email);
//delete next block and corresponding function when iframes are refactored
localStorage.setItem('accessToken', data.access_token);
localStorage.setItem('userUUID', data.user.uuid);
localStorage.setItem('userEmail', data.user.email);
//end delete block
organizations = data.user.organizations;
var org = '';
try {
//if we have an org stored, then use that one. Otherwise, use the first one.
var existingOrg = self.get('orgName');
org = (organizations[existingOrg])?organizations[existingOrg]:organizations[Object.keys(organizations)[0]];
self.set('orgName', org.name);
} catch(e) {
err = true;
if (self.logging) { console.log('error selecting org'); }
} //should always be an org
applications = self.parseApplicationsArray(org);
self.selectFirstApp(applications);
self.setObject('organizations', organizations);
self.setObject('applications', applications);
}
if (typeof(callback) === 'function') {
callback(err, data, user, organizations, applications);
}
});
}
Usergrid.Client.prototype.parseApplicationsArray = function (org) {
var applications = {};
for (var key in org.applications) {
var uuid = org.applications[key];
var name = key.split("/")[1];
applications[name] = ({uuid:uuid, name:name});
}
return applications;
}
Usergrid.Client.prototype.selectFirstApp = function (applications) {
try {
//try to select an app if one exists (will use existing if possible)
var existingApp = this.get('appName');
var firstApp = Object.keys(applications)[0];
var appName = (applications[existingApp])?existingApp:Object.keys(applications)[0];
this.set('appName', appName);
} catch(e){}//may or may not be an application, if no, just fall through
return appName;
}
Usergrid.Client.prototype.createApplication = function (name, callback) {
var self = this;
var options = {
method:'POST',
endpoint:'management/organizations/'+ this.get('orgName') + '/applications',
mQuery:true,
body:{name:name}
};
this.request(options, function(err, response) {
var applications = {};
if (err && self.logging) {
console.log('error trying to create new application');
if (typeof(callback) === 'function') {
callback(err, applications);
}
} else {
self.getApplications(callback);
}
});
}
Usergrid.Client.prototype.getApplications = function(callback) {
var self = this;
var options = {
method:'GET',
endpoint:'management/organizations/'+this.get('orgName')+'/applications',
mQuery:true
};
this.request(options, function(err, data) {
/*
//grab the applications
var applicationsData = data.data;
var applicationNames = self.keys(applicationsData).sort();
var firstApp = '';
var applications = [];
var count = 0;
for (var i in applicationNames) {
var name = applicationNames[i];
var uuid = applicationsData[name];
name = name.split("/")[1];
applications.push({uuid:uuid, name:name});
if (count===0) {
firstApp = name;
}
count++;
} */
applications = self.parseApplicationsArray({applications:data.data});
self.selectFirstApp(applications);
self.setObject('applications',applications);
if(typeof(callback) === 'function') {
callback(err, applications);
}
});
}
Usergrid.Client.prototype.getAdministrators = function (callback) {
var self = this;
var options = {
method:'GET',
endpoint:'management/organizations/'+this.get('orgName')+'/users',
mQuery:true
};
this.request(options, function (err, data) {
var administrators = [];
if (err) {
} else {
var administrators = [];
for(var i in data.data) {
var admin = data.data[i];
admin.image = self.getDisplayImage(admin.email, admin.picture);
administrators.push(admin);
}
}
if (typeof(callback) === 'function') {
callback(err, administrators);
}
});
}
Usergrid.Client.prototype.createAdministrator = function (email, callback) {
var self = this;
var options = {
method:'POST',
endpoint:'management/organizations/'+ this.get('orgName') + '/users',
mQuery:true,
body:{email:email, password:''}
};
this.request(options, function(err, response) {
var admins = {};
if (err && self.logging) {
console.log('error trying to create new administrator');
if (typeof(callback) === 'function') {
callback(err, admins);
}
} else {
self.getAdministrators(callback);
}
});
}
/*
* A public method to log in an app user with facebook - stores the token for later use
*
* @method loginFacebook
* @public
* @params {string} username
* @params {string} password
* @param {function} callback
* @return {callback} callback(err, data)
*/
Usergrid.Client.prototype.loginFacebook = function (facebookToken, callback) {
var self = this;
var options = {
method:'GET',
endpoint:'auth/facebook',
qs:{
fb_access_token: facebookToken
}
};
this.request(options, function(err, data) {
var user = {};
if (err && self.logging) {
console.log('error trying to log user in');
} else {
var options = {
client: self,
data: data.user
}
user = new Usergrid.Entity(options);
self.setToken(data.access_token);
}
if (typeof(callback) === 'function') {
callback(err, data, user);
}
});
}
/*
* A public method to get the currently logged in user entity
*
* @method getLoggedInUser
* @public
* @param {function} callback
* @return {callback} callback(err, data)
*/
Usergrid.Client.prototype.getLoggedInUser = function (callback) {
if (!this.getToken()) {
callback(true, null, null);
} else {
var self = this;
var options = {
method:'GET',
endpoint:'users/me'
};
this.request(options, function(err, data) {
if (err) {
if (self.logging) {
console.log('error trying to log user in');
}
if (typeof(callback) === 'function') {
callback(err, data, null);
}
} else {
var options = {
client:self,
data:data.entities[0]
}
var user = new Usergrid.Entity(options);
if (typeof(callback) === 'function') {
callback(err, data, user);
}
}
});
}
}
/*
* A public method to test if a user is logged in - does not guarantee that the token is still valid,
* but rather that one exists
*
* @method isLoggedIn
* @public
* @return {boolean} Returns true the user is logged in (has token and uuid), false if not
*/
Usergrid.Client.prototype.isLoggedIn = function () {
if (this.getToken()) {
return true;
}
return false;
}
/*
* A public method to log out an app user - clears all user fields from client
*
* @method logout
* @public
* @return none
*/
Usergrid.Client.prototype.logout = function () {
this.setToken(null);
this.setObject('organizations', null);
this.setObject('applications', null);
this.set('orgName', null);
this.set('appName', null);
this.set('email', null);
this.set("developerkey", null);
}
/*
* A private method to build the curl call to display on the command line
*
* @method buildCurlCall
* @private
* @param {object} options
* @return {string} curl
*/
Usergrid.Client.prototype.buildCurlCall = function (options) {
var curl = 'curl';
var method = (options.method || 'GET').toUpperCase();
var body = options.body || {};
var uri = options.uri;
//curl - add the method to the command (no need to add anything for GET)
if (method === 'POST') {curl += ' -X POST'; }
else if (method === 'PUT') { curl += ' -X PUT'; }
else if (method === 'DELETE') { curl += ' -X DELETE'; }
else { curl += ' -X GET'; }
//curl - append the path
curl += ' ' + uri;
//curl - add the body
if (body !== '"{}"' && method !== 'GET' && method !== 'DELETE') {
//curl - add in the json obj
curl += " -d '" + body + "'";
}
//log the curl command to the console
console.log(curl);
return curl;
}
Usergrid.Client.prototype.getDisplayImage = function (email, picture, size) {
try {
if (picture) {
return picture;
}
var size = size || 50;
if (email.length) {
return 'https://secure.gravatar.com/avatar/' + MD5(email) + '?s=' + size;
} else {
return 'https://apigee.com/usergrid/img/user_profile.png';
}
} catch(e) {
return 'https://apigee.com/usergrid/img/user_profile.png';
}
}
/*
* A class to Model a Usergrid Entity.
* Set the type of entity in the 'data' json object
*
* @constructor
* @param {object} options {client:client, data:{'type':'collection_type', 'key':'value'}, uuid:uuid}}
*/
Usergrid.Entity = function(options) {
if (options) {
this._data = options.data || {};
this._client = options.client || {};
}
};
/*
* returns a serialized version of the entity object
*
* Note: use the client.restoreEntity() function to restore
*
* @method serialize
* @return {string} data
*/
Usergrid.Entity.prototype.serialize = function () {
return JSON.stringify(this._data);
}
/*
* gets a specific field or the entire data object. If null or no argument
* passed, will return all data, else, will return a specific field
*
* @method get
* @param {string} field
* @return {string} || {object} data
*/
Usergrid.Entity.prototype.get = function (field) {
if (field) {
return this._data[field];
} else {
return this._data;
}
}
/*
* adds a specific key value pair or object to the Entity's data
* is additive - will not overwrite existing values unless they
* are explicitly specified
*
* @method set
* @param {string} key || {object}
* @param {string} value
* @return none
*/
Usergrid.Entity.prototype.set = function (key, value) {
if (typeof key === 'object') {
for(var field in key) {
this._data[field] = key[field];
}
} else if (typeof key === 'string') {
if (value === null) {
delete this._data[key];
} else {
this._data[key] = value;
}
} else {
this._data = {};
}
}
/*
* Saves the entity back to the database
*
* @method save
* @public
* @param {function} callback
* @return {callback} callback(err, data)
*/
Usergrid.Entity.prototype.save = function (callback) {
var type = this.get('type');
var method = 'POST';
if (isUUID(this.get('uuid'))) {
method = 'PUT';
type += '/' + this.get('uuid');
}
//update the entity
var self = this;
var data = {};
var entityData = this.get();
//remove system specific properties
for (var item in entityData) {
if (item === 'metadata' || item === 'created' || item === 'modified' ||
item === 'type' || item === 'activated' || item ==='uuid') { continue; }
data[item] = entityData[item];
}
var options = {
method:method,
endpoint:type,
body:data
};
//save the entity first
this._client.request(options, function (err, retdata) {
if (err && self._client.logging) {
console.log('could not save entity');
if (typeof(callback) === 'function') {
return callback(err, retdata, self);
}
} else {
if (retdata.entities) {
if (retdata.entities.length) {
var entity = retdata.entities[0];
self.set(entity);
//for connections, API returns type
self.set('type', retdata.path);
}
}
//if this is a user, update the password if it has been specified;
var needPasswordChange = (self.get('type') === 'user' && entityData.oldpassword && entityData.newpassword);
if (needPasswordChange) {
//Note: we have a ticket in to change PUT calls to /users to accept the password change
// once that is done, we will remove this call and merge it all into one
var pwdata = {};
pwdata.oldpassword = entityData.oldpassword;
pwdata.newpassword = entityData.newpassword;
var options = {
method:'PUT',
endpoint:type+'/password',
body:pwdata
}
self._client.request(options, function (err, data) {
if (err && self._client.logging) {
console.log('could not update user');
}
//remove old and new password fields so they don't end up as part of the entity object
self.set('oldpassword', null);
self.set('newpassword', null);
if (typeof(callback) === 'function') {
callback(err, data, self);
}
});
} else if (typeof(callback) === 'function') {
callback(err, retdata, self);
}
}
});
}
/*
* refreshes the entity by making a GET call back to the database
*
* @method fetch
* @public
* @param {function} callback
* @return {callback} callback(err, data)
*/
Usergrid.Entity.prototype.fetch = function (callback) {
var type = this.get('type');
var self = this;
//if a uuid is available, use that, otherwise, use the name
if (this.get('uuid')) {
type += '/' + this.get('uuid');
} else {
if (type === 'users') {
if (this.get('username')) {
type += '/' + this.get('username');
} else {
if (typeof(callback) === 'function') {
var error = 'no_name_specified';
if (self._client.logging) {
console.log(error);
}
return callback(true, {error:error}, self)
}
}
} else if (type === 'a path') {
///TODO add code to deal with the type as a path
if (this.get('path')) {
type += '/' + encodeURIComponent(this.get('name'));
} else {
if (typeof(callback) === 'function') {
var error = 'no_name_specified';
if (self._client.logging) {
console.log(error);
}
return callback(true, {error:error}, self)
}
}
} else {
if (this.get('name')) {
type += '/' + encodeURIComponent(this.get('name'));
} else {
if (typeof(callback) === 'function') {
var error = 'no_name_specified';
if (self._client.logging) {
console.log(error);
}
return callback(true, {error:error}, self)
}
}
}
}
var options = {
method:'GET',
endpoint:type
};
this._client.request(options, function (err, data) {
if (err && self._client.logging) {
console.log('could not get entity');
} else {
if (data.user) {
self.set(data.user);
self._json = JSON.stringify(data.user, null, 2);
} else if (data.entities) {
if (data.entities.length) {
var entity = data.entities[0];
self.set(entity);
}
}
}
if (typeof(callback) === 'function') {
callback(err, data, self);
}
});
}
/*
* deletes the entity from the database - will only delete
* if the object has a valid uuid
*
* @method destroy
* @public
* @param {function} callback
* @return {callback} callback(err, data)
*
*/
Usergrid.Entity.prototype.destroy = function (callback) {
var type = this.get('type');
if (isUUID(this.get('uuid'))) {
type += '/' + this.get('uuid');
} else {
if (typeof(callback) === 'function') {
var error = 'Error trying to delete object - no uuid specified.';
if (self._client.logging) {
console.log(error);
}
callback(true, error);
}
}
var self = this;
var options = {
method:'DELETE',
endpoint:type
};
this._client.request(options, function (err, data) {
if (err && self._client.logging) {
console.log('entity could not be deleted');
} else {
self.set(null);
}
if (typeof(callback) === 'function') {
callback(err, data);
}
});
}
/*
* connects one entity to another
*
* @method connect
* @public
* @param {string} connection
* @param {object} entity
* @param {function} callback
* @return {callback} callback(err, data)
*
*/
Usergrid.Entity.prototype.connect = function (connection, entity, callback) {
var self = this;
//connectee info
var connecteeType = entity.get('type');
var connectee = this.getEntityId(entity);
if (!connectee) {
if (typeof(callback) === 'function') {
var error = 'Error trying to delete object - no uuid specified.';
if (self._client.logging) {
console.log(error);
}
callback(true, error);
}
return;
}
//connector info
var connectorType = this.get('type');
var connector = this.getEntityId(this);
if (!connector) {
if (typeof(callback) === 'function') {
var error = 'Error in connect - no uuid specified.';
if (self._client.logging) {
console.log(error);
}
callback(true, error);
}
return;
}
var endpoint = connectorType + '/' + connector + '/' + connection + '/' + connecteeType + '/' + connectee;
var options = {
method:'POST',
endpoint:endpoint
};
this._client.request(options, function (err, data) {
if (err && self._client.logging) {
console.log('entity could not be connected');
}
if (typeof(callback) === 'function') {
callback(err, data);
}
});
}
/*
* returns a unique identifier for an entity
*
* @method connect
* @public
* @param {object} entity
* @param {function} callback
* @return {callback} callback(err, data)
*
*/
Usergrid.Entity.prototype.getEntityId = function (entity) {
var id = false;
if (isUUID(entity.get('uuid'))) {
id = entity.get('uuid');
} else {
if (type === 'users') {
id = entity.get('username');
} else if (entity.get('name')) {
id = entity.get('name');
}
}
return id;
}
/*
* gets an entities connections
*
* @method getConnections
* @public
* @param {string} connection
* @param {object} entity
* @param {function} callback
* @return {callback} callback(err, data, connections)
*
*/
Usergrid.Entity.prototype.getConnections = function (connection, callback) {
var self = this;
//connector info
var connectorType = this.get('type');
var connector = this.getEntityId(this);
if (!connector) {
if (typeof(callback) === 'function') {
var error = 'Error in getConnections - no uuid specified.';
if (self._client.logging) {
console.log(error);
}
callback(true, error);
}
return;
}
var endpoint = connectorType + '/' + connector + '/' + connection + '/';
var options = {
method:'GET',
endpoint:endpoint
};
this._client.request(options, function (err, data) {
if (err && self._client.logging) {
console.log('entity could not be connected');
}
self[connection] = {};
var length = data.entities.length;
for (var i=0;i<length;i++)
{
if (data.entities[i].type === 'user'){
self[connection][data.entities[i].username] = data.entities[i];
} else {
self[connection][data.entities[i].name] = data.entities[i]
}
}
if (typeof(callback) === 'function') {
callback(err, data, data.entities);
}
});
}
Usergrid.Entity.prototype.getGroups = function (callback) {
var self = this;
var endpoint = 'users' + '/' + this.get('uuid') + '/groups' ;
var options = {
method:'GET',
endpoint:endpoint
};
this._client.request(options, function (err, data) {
if (err && self._client.logging) {
console.log('entity could not be connected');
}
self['groups'] = data.entities;
if (typeof(callback) === 'function') {
callback(err, data, data.entities);
}
});
}
Usergrid.Entity.prototype.getActivities = function (callback) {
var self = this;
var endpoint = this.get('type') + '/' + this.get('uuid') + '/activities' ;
var options = {
method:'GET',
endpoint:endpoint
};
this._client.request(options, function (err, data) {
if (err && self._client.logging) {
console.log('entity could not be connected');
}
for(entity in data.entities) {
data.entities[entity].createdDate = (new Date(data.entities[entity].created)).toUTCString();
}
self['activities'] = data.entities;
if (typeof(callback) === 'function') {
callback(err, data, data.entities);
}
});
}
Usergrid.Entity.prototype.getFollowing = function (callback) {
var self = this;
var endpoint = 'users' + '/' + this.get('uuid') + '/following' ;
var options = {
method:'GET',
endpoint:endpoint
};
this._client.request(options, function (err, data) {
if (err && self._client.logging) {
console.log('could not get user following');
}
for(entity in data.entities) {
data.entities[entity].createdDate = (new Date(data.entities[entity].created)).toUTCString();
var image = self._client.getDisplayImage(data.entities[entity].email, data.entities[entity].picture);
data.entities[entity]._portal_image_icon = image;
}
self['following'] = data.entities;
if (typeof(callback) === 'function') {
callback(err, data, data.entities);
}
});
}
Usergrid.Entity.prototype.getFollowers = function (callback) {
var self = this;
var endpoint = 'users' + '/' + this.get('uuid') + '/followers' ;
var options = {
method:'GET',
endpoint:endpoint
};
this._client.request(options, function (err, data) {
if (err && self._client.logging) {
console.log('could not get user followers');
}
for(entity in data.entities) {
data.entities[entity].createdDate = (new Date(data.entities[entity].created)).toUTCString();
var image = self._client.getDisplayImage(data.entities[entity].email, data.entities[entity].picture);
data.entities[entity]._portal_image_icon = image;
}
self['followers'] = data.entities;
if (typeof(callback) === 'function') {
callback(err, data, data.entities);
}
});
}
Usergrid.Entity.prototype.getRoles = function (callback) {
var self = this;
var endpoint = this.get('type') + '/' + this.get('uuid') + '/roles' ;
var options = {
method:'GET',
endpoint:endpoint
};
this._client.request(options, function (err, data) {
if (err && self._client.logging) {
console.log('could not get user roles');
}
self['roles'] = data.entities;
if (typeof(callback) === 'function') {
callback(err, data, data.entities);
}
});
}
Usergrid.Entity.prototype.getPermissions = function (callback) {
var self = this;
var endpoint = this.get('type') + '/' + this.get('uuid') + '/permissions' ;
var options = {
method:'GET',
endpoint:endpoint
};
this._client.request(options, function (err, data) {
if (err && self._client.logging) {
console.log('could not get user permissions');
}
var permissions = [];
if (data.data) {
var perms = data.data;
var count = 0;
for (var i in perms) {
count++;
var perm = perms[i];
var parts = perm.split(':');
var ops_part = "";
var path_part = parts[0];
if (parts.length > 1) {
ops_part = parts[0];
path_part = parts[1];
}
ops_part.replace("*", "get,post,put,delete")
var ops = ops_part.split(',');
var ops_object = {}
ops_object['get'] = 'no';
ops_object['post'] = 'no';
ops_object['put'] = 'no';
ops_object['delete'] = 'no';
for (var j in ops) {
ops_object[ops[j]] = 'yes';
}
permissions.push( {operations : ops_object, path : path_part, perm : perm});
}
}
self['permissions'] = permissions;
if (typeof(callback) === 'function') {
callback(err, data, data.entities);
}
});
}
/*
* disconnects one entity from another
*
* @method disconnect
* @public
* @param {string} connection
* @param {object} entity
* @param {function} callback
* @return {callback} callback(err, data)
*
*/
Usergrid.Entity.prototype.disconnect = function (connection, entity, callback) {
var self = this;
//connectee info
var connecteeType = entity.get('type');
var connectee = this.getEntityId(entity);
if (!connectee) {
if (typeof(callback) === 'function') {
var error = 'Error trying to delete object - no uuid specified.';
if (self._client.logging) {
console.log(error);
}
callback(true, error);
}
return;
}
//connector info
var connectorType = this.get('type');
var connector = this.getEntityId(this);
if (!connector) {
if (typeof(callback) === 'function') {
var error = 'Error in connect - no uuid specified.';
if (self._client.logging) {
console.log(error);
}
callback(true, error);
}
return;
}
var endpoint = connectorType + '/' + connector + '/' + connection + '/' + connecteeType + '/' + connectee;
var options = {
method:'DELETE',
endpoint:endpoint
};
this._client.request(options, function (err, data) {
if (err && self._client.logging) {
console.log('entity could not be disconnected');
}
if (typeof(callback) === 'function') {
callback(err, data);
}
});
}
/*
* The Collection class models Usergrid Collections. It essentially
* acts as a container for holding Entity objects, while providing
* additional funcitonality such as paging, and saving
*
* @constructor
* @param {string} options - configuration object
* @param {function} callback
* @return {callback} callback(err, data)
*/
Usergrid.Collection = function(options, callback) {
if (options) {
this._client = options.client;
this._type = options.type;
this.qs = options.qs || {};
//iteration
this._list = options.list || [];
this._iterator = options.iterator || -1; //first thing we do is increment, so set to -1
//paging
this._previous = options.previous || [];
this._next = options.next || null;
this._cursor = options.cursor || null;
//restore entities if available
if (options.list) {
var count = options.list.length;
for(var i=0;i<count;i++){
//make new entity with
var entity = this._client.restoreEntity(options.list[i]);
this._list[i] = entity;
}
}
}
if (callback) {
//populate the collection
this.fetch(callback);
}
}
/*
* gets the data from the collection object for serialization
*
* @method serialize
* @return {object} data
*/
Usergrid.Collection.prototype.serialize = function () {
//pull out the state from this object and return it
var data = {}
data.type = this._type;
data.qs = this.qs;
data.iterator = this._iterator;
data.previous = this._previous;
data.next = this._next;
data.cursor = this._cursor;
this.resetEntityPointer();
var i=0;
data.list = [];
while(this.hasNextEntity()) {
var entity = this.getNextEntity();
data.list[i] = entity.serialize();
i++;
}
data = JSON.stringify(data);
return data;
}
Usergrid.Collection.prototype.addCollection = function (collectionName, options, callback) {
self = this;
options.client = this._client;
var collection = new Usergrid.Collection(options, function(err, data) {
if (typeof(callback) === 'function') {
collection.resetEntityPointer();
while(collection.hasNextEntity()) {
var user = collection.getNextEntity();
var email = user.get('email');
var image = self._client.getDisplayImage(user.get('email'), user.get('picture'));
user._portal_image_icon = image;
}
self[collectionName] = collection;
callback(err, collection);
}
});
}
/*
* Populates the collection from the server
*
* @method fetch
* @param {function} callback
* @return {callback} callback(err, data)
*/
Usergrid.Collection.prototype.fetch = function (callback) {
var self = this;
var qs = this.qs;
//add in the cursor if one is available
if (this._cursor) {
qs.cursor = this._cursor;
} else {
delete qs.cursor;
}
var options = {
method:'GET',
endpoint:this._type,
qs:this.qs
};
this._client.request(options, function (err, data) {
if(err && self._client.logging) {
console.log('error getting collection');
} else {
//save the cursor if there is one
var cursor = data.cursor || null;
self.saveCursor(cursor);
if (data.entities) {
self.resetEntityPointer();
var count = data.entities.length;
//save entities locally
self._list = []; //clear the local list first
for (var i=0;i<count;i++) {
var uuid = data.entities[i].uuid;
if (uuid) {
var entityData = data.entities[i] || {};
self._baseType = data.entities[i].type; //store the base type in the collection
entityData.type = self._type;//make sure entities are same type (have same path) as parent collection.
var entityOptions = {
client:self._client,
data:entityData
};
var ent = new Usergrid.Entity(entityOptions);
ent._json = JSON.stringify(entityData, null, 2);
//if this is a user, add in an icon image
if (self._type === 'users' || self._type ==='user' || data.entities[i].type == 'user') {
var email = entityData.email;
var picture = entityData.picture;
var image = self._client.getDisplayImage(email, picture);
ent._portal_image_icon = image;
}
var ct = self._list.length;
self._list[ct] = ent;
}
}
}
}
if (typeof(callback) === 'function') {
callback(err, data);
}
});
}
/*
* Adds a new Entity to the collection (saves, then adds to the local object)
*
* @method addNewEntity
* @param {object} entity
* @param {function} callback
* @return {callback} callback(err, data, entity)
*/
Usergrid.Collection.prototype.addEntity = function (options, callback) {
var self = this;
options.type = this._type;
//create the new entity
this._client.createEntity(options, function (err, entity) {
if (err) {
if (typeof(callback) === 'function') {
callback(err, entity);
}
} else {
if (entity.type === '/users') {
var image = self._client.getDisplayImage(entity.email, entity.picture);
entity._portal_image_icon = image;
}
if (!err) {
//then add the entity to the list
var count = self._list.length;
self._list[count] = entity;
}
if (typeof(callback) === 'function') {
callback(err, entity);
}
}
});
}
Usergrid.Collection.prototype.addExistingEntity = function (entity) {
//entity should already exist in the db, so just add it to the list
var count = this._list.length;
this._list[count] = entity;
}
/*
* Removes the Entity from the collection, then destroys the object on the server
*
* @method destroyEntity
* @param {object} entity
* @param {function} callback
* @return {callback} callback(err, data)
*/
Usergrid.Collection.prototype.destroyEntity = function (entity, callback) {
var self = this;
entity.destroy(function(err, data) {
if (err) {
if (self._client.logging) {
console.log('could not destroy entity');
}
if (typeof(callback) === 'function') {
callback(err, data);
}
} else {
//destroy was good, so repopulate the collection
self.fetch(callback);
}
});
//remove entity from the local store
this.removeEntity(entity);
}
Usergrid.Collection.prototype.removeEntity = function (entity) {
var uuid = entity.get('uuid');
for (key in this._list) {
var listItem = this._list[key];
if (listItem.get('uuid') === uuid) {
return this._list.splice(key, 1);
}
}
return false;
}
/*
* Looks up an Entity by UUID
*
* @method getEntityByUUID
* @param {string} UUID
* @param {function} callback
* @return {callback} callback(err, data, entity)
*/
Usergrid.Collection.prototype.getEntityByUUID = function (uuid, callback) {
for (key in this._list) {
var listItem = this._list[key];
if (listItem.get('uuid') === uuid) {
return listItem;
}
}
//get the entity from the database
var options = {
data: {
type: this._type,
uuid:uuid
},
client: this._client
}
var entity = new Usergrid.Entity(options);
entity.fetch(callback);
}
/*
* Returns the first Entity of the Entity list - does not affect the iterator
*
* @method getFirstEntity
* @return {object} returns an entity object
*/
Usergrid.Collection.prototype.getFirstEntity = function () {
var count = this._list.length;
if (count > 0) {
return this._list[0];
}
return null;
}
/*
* Returns the last Entity of the Entity list - does not affect the iterator
*
* @method getLastEntity
* @return {object} returns an entity object
*/
Usergrid.Collection.prototype.getLastEntity = function () {
var count = this._list.length;
if (count > 0) {
return this._list[count-1];
}
return null;
}
/*
* Entity iteration -Checks to see if there is a "next" entity
* in the list. The first time this method is called on an entity
* list, or after the resetEntityPointer method is called, it will
* return true referencing the first entity in the list
*
* @method hasNextEntity
* @return {boolean} true if there is a next entity, false if not
*/
Usergrid.Collection.prototype.hasNextEntity = function () {
var next = this._iterator + 1;
var hasNextElement = (next >=0 && next < this._list.length);
if(hasNextElement) {
return true;
}
return false;
}
/*
* Entity iteration - Gets the "next" entity in the list. The first
* time this method is called on an entity list, or after the method
* resetEntityPointer is called, it will return the,
* first entity in the list
*
* @method hasNextEntity
* @return {object} entity
*/
Usergrid.Collection.prototype.getNextEntity = function () {
this._iterator++;
var hasNextElement = (this._iterator >= 0 && this._iterator <= this._list.length);
if(hasNextElement) {
return this._list[this._iterator];
}
return false;
}
/*
* Entity iteration - Checks to see if there is a "previous"
* entity in the list.
*
* @method hasPrevEntity
* @return {boolean} true if there is a previous entity, false if not
*/
Usergrid.Collection.prototype.hasPrevEntity = function () {
var previous = this._iterator - 1;
var hasPreviousElement = (previous >=0 && previous < this._list.length);
if(hasPreviousElement) {
return true;
}
return false;
}
/*
* Entity iteration - Gets the "previous" entity in the list.
*
* @method getPrevEntity
* @return {object} entity
*/
Usergrid.Collection.prototype.getPrevEntity = function () {
this._iterator--;
var hasPreviousElement = (this._iterator >= 0 && this._iterator <= this._list.length);
if(hasPreviousElement) {
return this.list[this._iterator];
}
return false;
}
/*
* Entity iteration - Resets the iterator back to the beginning
* of the list
*
* @method resetEntityPointer
* @return none
*/
Usergrid.Collection.prototype.resetEntityPointer = function () {
this._iterator = -1;
}
/*
* Method to save off the cursor just returned by the last API call
*
* @public
* @method saveCursor
* @return none
*/
Usergrid.Collection.prototype.saveCursor = function(cursor) {
//if current cursor is different, grab it for next cursor
if (this._next !== cursor) {
this._next = cursor;
}
}
/*
* Resets the paging pointer (back to original page)
*
* @public
* @method resetPaging
* @return none
*/
Usergrid.Collection.prototype.resetPaging = function() {
this._previous = [];
this._next = null;
this._cursor = null;
}
/*
* Paging - checks to see if there is a next page od data
*
* @method hasNextPage
* @return {boolean} returns true if there is a next page of data, false otherwise
*/
Usergrid.Collection.prototype.hasNextPage = function () {
return (this._next);
}
/*
* Paging - advances the cursor and gets the next
* page of data from the API. Stores returned entities
* in the Entity list.
*
* @method getNextPage
* @param {function} callback
* @return {callback} callback(err, data)
*/
Usergrid.Collection.prototype.getNextPage = function (callback) {
if (this.hasNextPage()) {
//set the cursor to the next page of data
this._previous.push(this._cursor);
this._cursor = this._next;
//empty the list
this._list = [];
this.fetch(callback);
}
}
/*
* Paging - checks to see if there is a previous page od data
*
* @method hasPreviousPage
* @return {boolean} returns true if there is a previous page of data, false otherwise
*/
Usergrid.Collection.prototype.hasPreviousPage = function () {
return (this._previous.length > 0);
}
/*
* Paging - reverts the cursor and gets the previous
* page of data from the API. Stores returned entities
* in the Entity list.
*
* @method getPreviousPage
* @param {function} callback
* @return {callback} callback(err, data)
*/
Usergrid.Collection.prototype.getPreviousPage = function (callback) {
if (this.hasPreviousPage()) {
this._next=null; //clear out next so the comparison will find the next item
this._cursor = this._previous.pop();
//empty the list
this._list = [];
this.fetch(callback);
}
}
/*
* A class to model a Usergrid group.
* Set the path in the options object.
*
* @constructor
* @param {object} options {client:client, data: {'key': 'value'}, path:'path'}
*/
Usergrid.Group = function(options, callback) {
this._path = options.path;
this._list = [];
this._client = options.client;
this._data = options.data || {};
this._data.type = "groups";
}
/*
* Inherit from Usergrid.Entity.
* Note: This only accounts for data on the group object itself.
* You need to use add and remove to manipulate group membership.
*/
Usergrid.Group.prototype = new Usergrid.Entity();
/*
* Fetches current group data, and members.
*
* @method fetch
* @public
* @param {function} callback
* @returns {function} callback(err, data)
*/
Usergrid.Group.prototype.fetch = function(callback) {
var self = this;
var groupEndpoint = 'groups/'+this._path;
var memberEndpoint = 'groups/'+this._path+'/users';
var groupOptions = {
method:'GET',
endpoint:groupEndpoint
}
var memberOptions = {
method:'GET',
endpoint:memberEndpoint
}
this._client.request(groupOptions, function(err, data){
if(err) {
if(self._client.logging) {
console.log('error getting group');
}
if(typeof(callback) === 'function') {
callback(err, data);
}
} else {
if(data.entities) {
var groupData = data.entities[0];
self._data = groupData || {};
self._client.request(memberOptions, function(err, data) {
if(err && self._client.logging) {
console.log('error getting group users');
} else {
if(data.entities) {
var count = data.entities.length;
self._list = [];
for (var i = 0; i < count; i++) {
var uuid = data.entities[i].uuid;
if(uuid) {
var entityData = data.entities[i] || {};
var entityOptions = {
type: entityData.type,
client: self._client,
uuid:uuid,
data:entityData
};
var entity = new Usergrid.Entity(entityOptions);
self._list.push(entity);
}
}
}
}
if(typeof(callback) === 'function') {
callback(err, data, self._list);
}
});
}
}
});
}
/*
* Retrieves the members of a group.
*
* @method members
* @public
* @param {function} callback
* @return {function} callback(err, data);
*/
Usergrid.Group.prototype.members = function(callback) {
if(typeof(callback) === 'function') {
callback(null, this._list);
}
}
/*
* Adds a user to the group, and refreshes the group object.
*
* Options object: {user: user_entity}
*
* @method add
* @public
* @params {object} options
* @param {function} callback
* @return {function} callback(err, data)
*/
Usergrid.Group.prototype.add = function(options, callback) {
var self = this;
var options = {
method:"POST",
endpoint:"groups/"+this._path+"/users/"+options.user.get('username')
}
this._client.request(options, function(error, data){
if(error) {
if(typeof(callback) === 'function') {
callback(error, data, data.entities);
}
} else {
self.fetch(callback);
}
});
}
/*
* Removes a user from a group, and refreshes the group object.
*
* Options object: {user: user_entity}
*
* @method remove
* @public
* @params {object} options
* @param {function} callback
* @return {function} callback(err, data)
*/
Usergrid.Group.prototype.remove = function(options, callback) {
var self = this;
var options = {
method:"DELETE",
endpoint:"groups/"+this._path+"/users/"+options.user.get('username')
}
this._client.request(options, function(error, data){
if(error) {
if(typeof(callback) === 'function') {
callback(error, data);
}
} else {
self.fetch(callback);
}
});
}
/*
* Gets feed for a group.
*
* @public
* @method feed
* @param {function} callback
* @returns {callback} callback(err, data, activities)
*/
Usergrid.Group.prototype.feed = function(callback) {
var self = this;
var endpoint = "groups/"+this._path+"/feed";
var options = {
method:"GET",
endpoint:endpoint
}
this._client.request(options, function(err, data){
if (err && self.logging) {
console.log('error trying to log user in');
}
if(typeof(callback) === 'function') {
callback(err, data, data.entities);
}
});
}
/*
* Creates activity and posts to group feed.
*
* options object: {user: user_entity, content: "activity content"}
*
* @public
* @method createGroupActivity
* @params {object} options
* @param {function} callback
* @returns {callback} callback(err, entity)
*/
Usergrid.Group.prototype.createGroupActivity = function(options, callback){
var user = options.user;
var options = {
actor: {
"displayName":user.get("username"),
"uuid":user.get("uuid"),
"username":user.get("username"),
"email":user.get("email"),
"picture":user.get("picture"),
"image": {
"duration":0,
"height":80,
"url":user.get("picture"),
"width":80
},
},
"verb":"post",
"content":options.content };
options.type = 'groups/'+this._path+'/activities';
var options = {
client:this._client,
data:options
}
var entity = new Usergrid.Entity(options);
entity.save(function(err, data) {
if (typeof(callback) === 'function') {
callback(err, entity);
}
});
}
/*
* Tests if the string is a uuid
*
* @public
* @method isUUID
* @param {string} uuid The string to test
* @returns {Boolean} true if string is uuid
*/
function isUUID (uuid) {
var uuidValueRegex = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
if (!uuid) return false;
return uuidValueRegex.test(uuid);
}
/*
* method to encode the query string parameters
*
* @method encodeParams
* @public
* @params {object} params - an object of name value pairs that will be urlencoded
* @return {string} Returns the encoded string
*/
function encodeParams (params) {
tail = [];
var item = [];
if (params instanceof Array) {
for (i in params) {
item = params[i];
if ((item instanceof Array) && (item.length > 1)) {
tail.push(item[0] + "=" + encodeURIComponent(item[1]));
}
}
} else {
for (var key in params) {
if (params.hasOwnProperty(key)) {
var value = params[key];
if (value instanceof Array) {
for (i in value) {
item = value[i];
tail.push(key + "=" + encodeURIComponent(item));
}
} else {
tail.push(key + "=" + encodeURIComponent(value));
}
}
}
}
return tail.join("&");
}
})(window,sessionStorage);