'use strict';
const EventEmitter = require('events').EventEmitter;
const inherits = require('util').inherits;
/**
* @class
* @classdesc Extended user information
* @param {String} identity - Identity of user
* @param {String} uri - uri to user's info object
* @param {Object} datasync - datasync service
* @param {Object} session - session service
*
* @property {String} identity - User identity
* @property {String} friendlyName - User friendly name. Null if not set
* @property {Object} attributes - Object with custom attributes for user
* @fires UserInfo#updated
*/
function UserInfo(identity, uri, datasync, session) {
Object.defineProperties(this, {
_datasync: { value: datasync },
_session: { value: session },
_identity: { value: identity },
_uri: { value: uri, writable: true }, // writable only because of lazy loading of myUserInfo
_attributes: { value: {}, writable: true },
_friendlyName: { value: null, writable: true },
_promiseToFetch: { writable: true },
identity: { enumerable: true, get: () => this._identity },
attributes: { enumerable: true, get: () => this._attributes },
friendlyName: { enumerable: true, get: () => this._friendlyName }
});
EventEmitter.call(this);
this.setMaxListeners(0);
}
inherits(UserInfo, EventEmitter);
UserInfo.prototype._update = function(key, value) {
switch (key) {
case 'friendlyName':
this._friendlyName = value;
break;
case 'attributes':
try {
this._attributes = JSON.parse(value);
} catch (e) {
this._attributes = {};
}
break;
default:
return;
}
this.emit('updated');
};
UserInfo.prototype._fetch = function() {
if (!this._uri) {
return Promise.resolve(this);
}
let update = item => this._update(item.id, item.value.value);
this._promiseToFetch = this._datasync.openMap(this._uri).then(map => {
map.subscribe();
map.on('entityUpdated', update);
return Promise.all([
map.get('friendlyName').then(update),
map.get('attributes').then(update)
]);
})
.then(() => this)
.catch(err => {
this._promiseToFetch = null;
throw err;
});
return this._promiseToFetch;
};
UserInfo.prototype._ensureFetched = function() {
return this._promiseToFetch || this._fetch();
};
/**
* Update the UserInfo's attributes.
* @param {Object} attributes - The new attributes object.
* @returns {Promise<UserInfo|SessionError>} A Promise for the UserInfo
*/
UserInfo.prototype.updateAttributes = function(attributes) {
if (attributes.constructor !== Object) {
throw new Error('Attributes must be an object.');
}
return this._session.addCommand('editUserAttributes', {
username: this._identity,
attributes: JSON.stringify(attributes)
}).then(() => this);
};
/**
* Update the Users's friendlyName.
* @param {String} name - The new friendlyName.
* @returns {Promise<UserInfo|SessionError>} A Promise for the UserInfo
*/
UserInfo.prototype.updateFriendlyName = function(friendlyName) {
return this._session.addCommand('editUserFriendlyName', {
username: this._identity,
friendlyName: friendlyName
}).then(() => this);
};
Object.freeze(UserInfo);
/**
* Fired when the UserInfo's fields have been updated.
* @event UserInfo#updated
*/
module.exports = UserInfo;