'use strict';
/**
* @author Marco Lehmann <marco.lehmann@kiwigrid.com>
* @copyright Kiwigrid GmbH 2014-2015
* @module keta.services.User
* @description User Provider
*/
angular.module('keta.services.User',
[
'keta.services.EventBusDispatcher',
'keta.services.EventBusManager',
'keta.services.Logger'
])
/**
* @class UserProvider
* @propertyOf keta.services.User
* @description User Provider
*/
.provider('ketaUser', function UserProvider() {
this.$get = function UserService($q, $log, ketaEventBusDispatcher, ketaEventBusManager) {
// send message and return promise
var sendMessage = function(eventBus, message) {
var deferred = $q.defer();
ketaEventBusDispatcher.send(eventBus, 'userservice', message, function(reply) {
// log if in debug mode
if (ketaEventBusManager.inDebugMode()) {
$log.request(['userservice', message, reply], $log.ADVANCED_FORMATTER);
}
if (angular.isUndefined(reply.code) ||
reply.code >= ketaEventBusDispatcher.RESPONSE_CODE_BAD_REQUEST) {
deferred.reject(reply);
} else {
deferred.resolve(reply);
}
});
return deferred.promise;
};
var returnRejectedPromise = function(message) {
var deferred = $q.defer();
deferred.reject(message);
return deferred.promise;
};
/**
* @class UserInstance
* @propertyOf User
* @description User Instance
* @param {EventBus} givenEventBus eventBus to use for UserInstance
* @param {Object} properties Properties to inject into UserInstance
*/
var UserInstance = function(givenEventBus, properties) {
// keep reference
var that = this;
// save EventBus instance
var eventBus = givenEventBus;
// populate properties
angular.forEach(properties, function(value, key) {
that[key] = value;
// save copy under $pristine
if (!angular.isDefined(that.$pristine)) {
that.$pristine = {};
}
that.$pristine[key] = angular.copy(value);
});
/**
* @name $create
* @function
* @description
* <p>
* Creates a remote UserInstance from local one the method is called on.
* </p>
* @returns {promise} promise
* @example
* angular.module('exampleApp', ['keta.services.User'])
* .controller('ExampleController', function(ketaUser) {
*
* var user = ketaUser.create({
* userId: 'userId'
* });
*
* user.$create()
* .then(function(reply) {
* // success handler
* // ...
* }, function(reply) {
* // error handler
* // ...
* });
*
* });
*/
that.$create = function() {
var cleanedUser = {};
for (var el in that) {
if (that.hasOwnProperty(el) && !angular.isFunction(that[el]) && el !== '$pristine') {
cleanedUser[el] = angular.copy(that[el]);
}
}
return sendMessage(eventBus, {
action: 'createUser',
params: {
userId: cleanedUser.userId
},
body: cleanedUser
});
};
/**
* @name $update
* @function
* @description
* <p>
* Updates a remote UserInstance from local one the method is called on.
* </p>
* @returns {promise} promise
* @example
* angular.module('exampleApp', ['keta.services.User'])
* .controller('ExampleController', function(ketaUser) {
*
* var user = ketaUser.create({
* userId: 'john.doe',
* channel: 'channel',
* givenName: 'John',
* familyName: 'Doe',
* email: 'john.doe@test.com',
* address: {
* street: 'Main Street',
* number: '100 E',
* city: 'Phoenix',
* country: 'USA',
* zip: '85123'
* },
* properties: {
* position: 'left'
* }
* });
*
* user.email = 'john.doe@kiwigrid.com';
* delete user.properties.position;
*
* user.$update()
* .then(function(reply) {
* // success handler
* // ...
* }, function(reply) {
* // error handler
* // ...
* });
*
* });
*/
that.$update = function() {
// create cleaned copies
var cleanedUser = angular.copy(that);
var cleanedUserOriginal = angular.copy(that.$pristine);
delete cleanedUser.$pristine;
delete cleanedUser.$create;
delete cleanedUser.$update;
delete cleanedUser.$delete;
delete cleanedUser.$reset;
// collect changes
// changes on second level are not merged and therefor objects have to be transmitted in full
// except "properties", which are merged on second level too
var changes = {};
angular.forEach(cleanedUser, function(value, key) {
if (key === 'properties') {
if (!angular.isDefined(cleanedUserOriginal.properties) ||
cleanedUserOriginal.properties === null ||
angular.equals(cleanedUserOriginal.properties, {})) {
changes.properties = value;
} else {
angular.forEach(value, function(propValue, propKey) {
if (!angular.isDefined(cleanedUserOriginal.properties[propKey]) ||
!angular.equals(
cleanedUser.properties[propKey],
cleanedUserOriginal.properties[propKey]
)
) {
if (!angular.isDefined(changes.properties)) {
changes.properties = {};
}
changes.properties[propKey] = propValue;
}
});
}
} else if (!angular.equals(cleanedUser[key], cleanedUserOriginal[key])) {
changes[key] = value;
}
});
if (Object.keys(changes).length) {
var deferred = $q.defer();
sendMessage(eventBus, {
action: 'mergeUser',
params: {
userId: that.userId
},
body: changes
}).then(function(reply) {
// reset $pristine copies after success
that.$pristine = {};
angular.forEach(that, function(value, key) {
if (!angular.isFunction(that[key])) {
that.$pristine[key] = angular.copy(that[key]);
}
});
deferred.resolve(reply);
}, function(reply) {
deferred.reject(reply);
});
return deferred.promise;
}
return returnRejectedPromise('No changes found');
};
/**
* @name $delete
* @function
* @description
* <p>
* Deletes a remote UserInstance from local one the method is called on.
* </p>
* @returns {promise} promise
* @example
* angular.module('exampleApp', ['keta.services.User'])
* .controller('ExampleController', function(ketaUser) {
*
* var user = ketaUser.create({
* userId: 'userId'
* });
*
* user.$delete()
* .then(function(reply) {
* // success handler
* // ...
* }, function(reply) {
* // error handler
* // ...
* });
*
* });
*/
that.$delete = function() {
return sendMessage(eventBus, {
action: 'deleteUser',
params: {
userId: that.userId
}
});
};
/**
* @name $reset
* @function
* @description
* <p>
* Resets a UserInstance to it's $pristine state.
* </p>
* @returns {undefined} nothing
* @example
* angular.module('exampleApp', ['keta.services.User'])
* .controller('ExampleController', function(ketaUser) {
*
* var user = ketaUser.create({
* userId: 'john.doe',
* channel: 'channel',
* givenName: 'John',
* familyName: 'Doe',
* email: 'john.doe@test.com',
* address: {
* street: 'Main Street',
* number: '100 E',
* city: 'Phoenix',
* country: 'USA',
* zip: '85123'
* },
* properties: {
* position: 'left'
* }
* });
*
* user.email = 'john.doe@kiwigrid.com';
* delete user.properties.position;
*
* user.$update()
* .then(function(reply) {
* // success handler
* // ...
* }, function(reply) {
* // error handler
* user.$reset();
* });
*
* });
*/
that.$reset = function() {
// remove everything beside methods and $pristine copy
angular.forEach(that, function(value, key) {
if (!angular.isFunction(value) && key !== '$pristine') {
delete that[key];
}
});
// add copies of $pristine values
angular.forEach(that.$pristine, function(value, key) {
that[key] = angular.copy(value);
});
};
};
/**
* @class ketaUser
* @propertyOf UserProvider
* @description User Service
*/
var api = {
/**
* @name create
* @function
* @description
* <p>
* Creates a UserInstance with given EventBus instance and properties.
* </p>
* @param {EventBus} eventBus EventBus instance to use for communication
* @param {Object} properties Properties to set upon UserInstance creation
* @returns {UserInstance} created UserInstance
* @example
* angular.module('exampleApp', ['keta.services.User'])
* .controller('ExampleController', function(ketaUser) {
* var user = ketaUser.create(eventBus, {
* userId: 'john.doe',
* channel: 'channel',
* givenName: 'John',
* familyName: 'Doe',
* email: 'john.doe@test.com',
* address: {
* street: 'Main Street',
* number: '100 E',
* city: 'Phoenix',
* country: 'USA',
* zip: '85123'
* }
* });
* });
*/
create: function(eventBus, properties) {
return new UserInstance(eventBus, properties);
},
/**
* @name getChannel
* @function
* @description
* <p>
* Returns the channel name for given channel id.
* </p>
* @param {EventBus} eventBus EventBus instance to use for communication
* @param {String} channelId Channel id to retrieve.
* @returns {String} channel name
* @example
* angular.module('exampleApp', ['keta.services.User'])
* .controller('ExampleController', function(ketaUser) {
* ketaUser.getChannel(eventBus, 'channel-1')
* .then(function(reply) {
* // reply is channel name
* });
* });
*/
getChannel: function(eventBus, channelId) {
var deferred = $q.defer();
sendMessage(eventBus, {
action: 'getChannel',
params: {
channelId: channelId
}
}).then(function(reply) {
deferred.resolve(reply);
}, function(reply) {
deferred.reject(reply);
});
return deferred.promise;
},
/**
* @name getCurrent
* @function
* @description
* <p>
* Returns the currently logged-in user.
* </p>
* @param {EventBus} eventBus EventBus instance to use for communication
* @returns {UserInstance} current logged-in user
* @example
* angular.module('exampleApp', ['keta.services.User'])
* .controller('ExampleController', function(ketaUser) {
* ketaUser.getCurrentUser(eventBus)
* .then(function(reply) {
* // reply is current UserInstance
* });
* });
*/
getCurrent: function(eventBus) {
var deferred = $q.defer();
sendMessage(eventBus, {
action: 'getCurrentUser'
}).then(function(reply) {
deferred.resolve(new UserInstance(eventBus, reply.result));
}, function(reply) {
deferred.reject(reply);
});
return deferred.promise;
}
};
return api;
};
});