spincycle
Version:
A reactive message router and object manager that lets clients subscribe to object property changes on the server
1,111 lines (1,068 loc) • 41.2 kB
JavaScript
// Generated by CoffeeScript 1.12.6
(function() {
var ClientEndpoints, DB, ObjectManager, ResolveModule, SuperModel, debug, defer, e, error, objStore, util, uuid,
bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
util = require('util');
defer = require('node-promise').defer;
SuperModel = require('./SuperModel');
e = require('./EventManager');
DB = require('./DB');
ClientEndpoints = require('./ClientEndpoints');
objStore = require('./OStore');
error = require('./Error').error;
ResolveModule = require('./ResolveModule');
uuid = require('node-uuid');
debug = process.env["DEBUG"];
ObjectManager = (function() {
function ObjectManager(messageRouter) {
this.messageRouter = messageRouter;
this.resolveReferences = bind(this.resolveReferences, this);
this.onDeregisterForPopulationChanges = bind(this.onDeregisterForPopulationChanges, this);
this.onRegisterForPopulationChanges = bind(this.onRegisterForPopulationChanges, this);
this.onDeregisterForUpdatesOn = bind(this.onDeregisterForUpdatesOn, this);
this.onRegisterForUpdatesOn = bind(this.onRegisterForUpdatesOn, this);
this.persistUpdates = bind(this.persistUpdates, this);
this.onUpdateObject = bind(this.onUpdateObject, this);
this.getObjectPullThrough = bind(this.getObjectPullThrough, this);
this.expose = bind(this.expose, this);
this.parseList = bind(this.parseList, this);
this._countObjects = bind(this._countObjects, this);
this._listObjects = bind(this._listObjects, this);
this.getAggregateObjects = bind(this.getAggregateObjects, this);
this._getObject = bind(this._getObject, this);
this._updateObject = bind(this._updateObject, this);
this._deleteObject = bind(this._deleteObject, this);
this._createObject = bind(this._createObject, this);
this.getModelFor = bind(this.getModelFor, this);
this.onGetModelFor = bind(this.onGetModelFor, this);
this.onGetAccessTypesFor = bind(this.onGetAccessTypesFor, this);
this.onListTypes = bind(this.onListTypes, this);
this.getTypes = bind(this.getTypes, this);
this.registerUpdateObjectHook = bind(this.registerUpdateObjectHook, this);
this.setup = bind(this.setup, this);
this.updateObjectHooks = [];
this.populationListeners = [];
SuperModel.onCreate((function(_this) {
return function(newmodel) {
var client, k, results, sublist;
sublist = _this.populationListeners[newmodel.type] || {};
results = [];
for (k in sublist) {
client = sublist[k];
if (ClientEndpoints.exists(client)) {
console.log('sending population update create to client ' + client);
results.push(ClientEndpoints.sendToEndpoint(client, {
status: e.general.SUCCESS,
info: 'POPULATION_UPDATE',
payload: {
added: newmodel.toClient()
}
}));
} else {
results.push(void 0);
}
}
return results;
};
})(this));
}
ObjectManager.prototype.setup = function() {
this.messageRouter.addTarget('registerForUpdatesOn', 'obj', this.onRegisterForUpdatesOn);
this.messageRouter.addTarget('deRegisterForUpdatesOn', 'id,listenerid', this.onDeregisterForUpdatesOn);
this.messageRouter.addTarget('updateObject', 'obj', this.onUpdateObject);
this.messageRouter.addTarget('listTypes', '<noargs>', this.onListTypes);
this.messageRouter.addTarget('getModelFor', 'modelname', this.onGetModelFor);
this.messageRouter.addTarget('getAccessTypesFor', 'modelname', this.onGetAccessTypesFor);
this.messageRouter.addTarget('registerForPopulationChangesFor', 'type', this.onRegisterForPopulationChanges);
return this.messageRouter.addTarget('deRegisterForPopulationChangesFor', 'id,listenerid', this.onDeregisterForPopulationChanges);
};
ObjectManager.prototype.registerUpdateObjectHook = function(hook) {
return this.updateObjectHooks.push(hook);
};
ObjectManager.prototype.getTypes = function() {
var k, ref, types, v;
types = [];
ref = ResolveModule.modulecache;
for (k in ref) {
v = ref[k];
types.push(k.toLowerCase());
}
return types;
};
ObjectManager.prototype.onListTypes = function(msg) {
var k, ref, types, v;
types = [];
ref = ResolveModule.modulecache;
for (k in ref) {
v = ref[k];
types.push(k);
}
return msg.replyFunc({
status: e.general.SUCCESS,
info: 'list types',
payload: types
});
};
ObjectManager.prototype.onGetAccessTypesFor = function(msg) {
var rv;
if (msg.modelname) {
rv = {
create: this.messageRouter.authMgr.canUserCreateThisObject(msg.modelname, msg.user, msg.sessionId),
read: this.messageRouter.authMgr.canUserReadFromThisObject(msg.modelname, msg.user, msg.sessionId),
write: this.messageRouter.authMgr.canUserWriteToThisObject(msg.modelname, msg.user, msg.sessionId),
list: this.messageRouter.authMgr.canUserListTheseObjects(msg.modelname, msg.user, msg.sessionId)
};
return msg.replyFunc({
status: e.general.SUCCESS,
info: 'access types for ' + msg.modelname,
payload: rv
});
} else {
return msg.replyFunc({
status: e.general.FAILURE,
info: "getAccessTypesFor missing parameter",
payload: null
});
}
};
ObjectManager.prototype.onGetModelFor = function(msg) {
if (msg.modelname) {
return this.messageRouter.resolver.resolve(msg.modelname, (function(_this) {
return function(path) {
var rv;
if (debug) {
console.log('onGetModelFor ' + msg.modelname + ' got back require path ' + path);
}
rv = _this.getModelFor(msg.modelname);
return msg.replyFunc({
status: e.general.SUCCESS,
info: 'get model',
payload: rv
});
};
})(this));
} else {
return msg.replyFunc({
status: e.general.FAILURE,
info: "getModelFor missing parameter",
payload: null
});
}
};
ObjectManager.prototype.getModelFor = function(modelname) {
var k, model, ref, rv, v;
model = ResolveModule.modulecache[modelname] || ResolveModule.modulecache[modelname.toLowerCase()];
if (!model) {
ref = ResolveModule.modulecache;
for (k in ref) {
v = ref[k];
console.log('------- model in modulecache : ' + k);
}
}
rv = [];
model.model.forEach(function(property) {
if (property["public"]) {
return rv.push(property);
}
});
return rv;
};
ObjectManager.prototype._createObject = function(msg) {
var ref;
console.log('objmgr.createObject called');
if (msg.obj && msg.obj.type) {
if (ref = msg.obj.type.toLowerCase(), indexOf.call(this.getTypes(), ref) >= 0) {
if (this.messageRouter.authMgr.canUserCreateThisObject(msg.obj.type, msg.user, msg.sessionId)) {
if (debug) {
console.dir(msg);
}
msg.obj.createdAt = Date.now();
msg.obj.modifiedAt = Date.now();
msg.obj.createdBy = msg.user.id;
msg.obj.userRef = msg.user.id;
return SuperModel.resolver.createObjectFrom(msg.obj).then((function(_this) {
return function(o) {
return o.serialize().then(function() {
_this.messageRouter.gaugeMetric('create', 1, {
type: msg.obj.type,
'username': msg.user.name,
'useremail': msg.user.email,
'provider': msg.user.provider,
'organization': msg.user.organization
});
return msg.replyFunc({
status: e.general.SUCCESS,
info: 'new ' + msg.obj.type,
payload: o
});
});
};
})(this));
} else {
return msg.replyFunc({
status: e.general.NOT_ALLOWED,
info: 'not allowed to create objects of that type',
payload: msg.obj.type
});
}
} else {
return msg.replyFunc({
status: e.general.FAILURE,
info: 'unkown model type',
payload: msg.obj.type
});
}
} else {
return msg.replyFunc({
status: e.general.FAILURE,
info: '_createObject missing parameter',
payload: null
});
}
};
ObjectManager.prototype._deleteObject = function(msg) {
var ref;
if (msg.obj && msg.obj.type && msg.obj.id) {
console.log('delete got type ' + msg.obj.type + ', and id ' + msg.obj.id);
if (ref = msg.obj.type.toLowerCase(), indexOf.call(this.getTypes(), ref) >= 0) {
return this.getObjectPullThrough(msg.obj.id, msg.obj.type).then((function(_this) {
return function(obj) {
if (obj) {
if (_this.messageRouter.authMgr.canUserWriteToThisObject(obj, msg.user, msg.obj, msg.sessionId)) {
return DB.remove(obj, function(removestatus) {
var client, k, sublist;
_this.messageRouter.gaugeMetric('delete', 1, {
type: msg.obj.type,
'username': msg.user.name,
'useremail': msg.user.email,
'provider': msg.user.provider,
'organization': msg.user.organization
});
sublist = _this.populationListeners[msg.type] || {};
for (k in sublist) {
client = sublist[k];
if (ClientEndpoints.exists(client)) {
ClientEndpoints.sendToEndpoint(client, {
status: e.general.SUCCESS,
info: 'POPULATION_UPDATE',
payload: {
removed: obj.toClient()
}
});
}
}
objStore.removeObject(obj);
return msg.replyFunc({
status: e.general.SUCCESS,
info: 'delete object',
payload: obj.id
});
});
} else {
return msg.replyFunc({
status: e.general.NOT_ALLOWED,
info: 'not allowed to delete object',
payload: msg.obj.id
});
}
} else {
console.log('No object found with id ' + msg.obj.id);
console.dir(objStore.objects.map(function(o) {
return o.type === msg.obj.type;
}));
return msg.replyFunc({
status: e.general.NOT_ALLOWED,
info: e.gamemanager.NO_SUCH_OBJECT,
payload: msg.obj.id
});
}
};
})(this));
} else {
return msg.replyFunc({
status: e.general.FAILURE,
info: 'unkown model type',
payload: msg.obj.type
});
}
} else {
return msg.replyFunc({
status: e.general.FAILURE,
info: '_deleteObject missing parameter',
payload: null
});
}
};
ObjectManager.prototype._updateObject = function(msg) {
return this.onUpdateObject(msg);
};
ObjectManager.prototype._getObject = function(msg) {
var id, ref;
if (msg.type && ((msg.obj && msg.obj.id) || msg.id)) {
if (ref = msg.type.toLowerCase(), indexOf.call(this.getTypes(), ref) >= 0) {
id = msg.id || msg.obj.id;
if (id.indexOf && id.indexOf('all_') > -1) {
return this.getAggregateObjects(msg);
} else {
if (typeof id !== 'object') {
return this.getObjectPullThrough(id, msg.type).then((function(_this) {
return function(obj) {
var tc;
if (obj) {
if (_this.messageRouter.authMgr.canUserReadFromThisObject(obj, msg.user, msg.sessionId)) {
tc = obj.toClient();
_this.messageRouter.gaugeMetric('get', 1, {
type: msg.type,
'username': msg.user.name,
'useremail': msg.user.email,
'provider': msg.user.provider,
'organization': msg.user.organization
});
if (_this.messageRouter.authMgr.filterOutgoing) {
return _this.messageRouter.authMgr.filterOutgoing(tc, msg.user).then(function(ftc) {
if (ftc) {
if (debug) {
console.log('_getObject for filteroutgoing ' + msg.type + ' returns ' + JSON.stringify(tc));
}
return msg.replyFunc({
status: e.general.SUCCESS,
info: 'update object',
payload: ftc
});
} else {
return msg.replyFunc({
status: e.general.NOT_ALLOWED,
info: 'not allowed to read from that object',
payload: obj.id,
statuscode: 403
});
}
});
} else {
if (debug) {
console.log('_getObject for ' + msg.type + ' returns ' + JSON.stringify(tc));
}
return msg.replyFunc({
status: e.general.SUCCESS,
info: 'get object',
payload: tc
});
}
} else {
console.log('_getObject got NOT ALLOWED for user ' + msg.user.id + ' for ' + msg.type + ' id ' + obj.id);
return msg.replyFunc({
status: e.general.NOT_ALLOWED,
info: 'not allowed to read from that object',
payload: id,
statuscode: 403
});
}
} else {
console.log('_getObject No object found with id ' + id + ' of type ' + msg.type);
return msg.replyFunc({
status: e.general.NOT_ALLOWED,
info: 'no such object',
payload: id,
statuscode: 404
});
}
};
})(this));
} else {
console.log('_getObject provided id ' + id + ' of type ' + msg.type + ' is an object!!');
console.dir(id);
return msg.replyFunc({
status: e.general.NOT_ALLOWED,
info: 'id value is an object!!!',
payload: id,
statuscode: 400
});
}
}
} else {
return msg.replyFunc({
status: e.general.FAILURE,
info: 'unkown model type',
payload: msg.obj.type,
statuscode: 417
});
}
} else {
return msg.replyFunc({
status: e.general.FAILURE,
info: '_getObject for ' + msg.type + ' missing parameter',
payload: null,
statuscode: 417
});
}
};
ObjectManager.prototype.getAggregateObjects = function(msg) {
var obj, rv;
if (!this.messageRouter.authMgr.canUserListTheseObjects(msg.type, msg.user, msg.sessionId)) {
return msg.replyFunc({
status: e.general.NOT_ALLOWED,
info: 'not allowed to list objects of type ' + msg.type,
payload: msg.type
});
} else {
rv = objStore.listObjectsByType(msg.obj.type);
obj = {
id: msg.obj.id,
list: rv
};
return msg.replyFunc({
status: e.general.SUCCESS,
info: 'get object',
payload: obj
});
}
};
ObjectManager.prototype._listObjects = function(msg) {
var ref;
if (typeof msg.type !== 'undefined') {
if (ref = msg.type.toLowerCase(), indexOf.call(this.getTypes(), ref) >= 0) {
if (this.messageRouter.authMgr.canUserListTheseObjects(msg.type, msg.user, msg.sessionId) === false) {
return msg.replyFunc({
status: e.general.NOT_ALLOWED,
info: 'not allowed to list objects of type ' + msg.type,
payload: msg.type
});
} else {
if (msg.query) {
if (debug) {
console.log('executing query for property ' + msg.query.property + ', value ' + msg.query.value);
}
if (msg.query.limit || msg.query.skip || msg.query.sort || msg.query.wildcard) {
if (msg.query.value && msg.query.value !== '') {
return DB.findQuery(msg.type, msg.query).then((function(_this) {
return function(records) {
return _this.parseList(records, msg);
};
})(this));
} else {
return DB.all(msg.type, msg.query, (function(_this) {
return function(records) {
return _this.parseList(records, msg);
};
})(this));
}
} else {
return DB.findMany(msg.type, msg.query.property, msg.query.value).then((function(_this) {
return function(records) {
return _this.parseList(records, msg);
};
})(this));
}
} else {
return DB.all(msg.type, msg.query, (function(_this) {
return function(records) {
return _this.parseList(records, msg);
};
})(this));
}
}
} else {
return msg.replyFunc({
status: e.general.FAILURE,
info: 'unkown model type',
payload: msg.obj.type
});
}
} else {
return msg.replyFunc({
status: e.general.FAILURE,
info: '_listObjects missing parameter',
payload: null
});
}
};
ObjectManager.prototype._countObjects = function(msg) {
var ref;
if (typeof msg.type !== 'undefined') {
if (ref = msg.type.toLowerCase(), indexOf.call(this.getTypes(), ref) >= 0) {
if (this.messageRouter.authMgr.canUserListTheseObjects(msg.type, msg.user, msg.sessionId) === false) {
this.messageRouter.gaugeMetric('count', 1, {
type: msg.type,
'username': msg.user.name,
'useremail': msg.user.email,
'provider': msg.user.provider,
'organization': msg.user.organization
});
return msg.replyFunc({
status: e.general.NOT_ALLOWED,
info: 'not allowed to count objects of type ' + msg.type,
payload: msg.type
});
} else {
return DB.count(msg.type).then((function(_this) {
return function(v) {
return msg.replyFunc({
status: e.general.SUCCESS,
info: 'count objects',
payload: v
});
};
})(this));
}
} else {
return msg.replyFunc({
status: e.general.FAILURE,
info: 'unknown model type',
payload: msg.type
});
}
} else {
return msg.replyFunc({
status: e.general.FAILURE,
info: '_listObjects missing parameter',
payload: null
});
}
};
ObjectManager.prototype.parseList = function(_records, msg) {
var checkFinish, count, rv;
this.messageRouter.gaugeMetric('list', 1, {
type: msg.type,
'username': msg.user.name,
'useremail': msg.user.email,
'provider': msg.user.provider,
'organization': msg.user.organization
});
checkFinish = (function(_this) {
return function(rv) {
if (--count === 0) {
if (debug) {
console.log('ObjectManager.parseList returns ' + rv.length + ' records');
}
return msg.replyFunc({
status: e.general.SUCCESS,
info: 'list objects',
payload: rv
});
}
};
})(this);
count = _records.length;
if (debug) {
console.log('ObjectManager.parseList resolving ' + count + ' records');
}
if (count === 0) {
if (debug) {
console.log('ObjectManager.parseList -- returning empty set');
}
return msg.replyFunc({
status: e.general.SUCCESS,
info: 'list objects',
payload: []
});
} else {
rv = [];
return _records.forEach((function(_this) {
return function(r) {
if (debug) {
console.log('ObjectManager.parseList calling DB.get for id ' + r.id);
}
return DB.get(r.type, [r.id]).then(function(record) {
var tc;
if (record && record[0]) {
tc = record[0];
if (_this.messageRouter.authMgr.filterOutgoing) {
return _this.messageRouter.authMgr.filterOutgoing(tc, msg.user).then(function(tres) {
if (debug) {
console.log('parseList got reply from filterOutgoing and it was a ' + tres + ' count = ' + count);
}
if (debug) {
console.dir(tres);
}
if (tres) {
rv.push(tres);
}
return checkFinish(rv);
});
} else {
rv.push(tc);
return checkFinish(rv);
}
} else {
if (debug) {
console.log(' empty records for ' + r.id);
}
return checkFinish(rv);
}
});
};
})(this));
}
};
ObjectManager.prototype.expose = function(type) {
objStore.types[type] = type;
this.messageRouter.addTarget('_create' + type, 'obj', (function(_this) {
return function(msg) {
msg.type = type;
return _this._createObject(msg);
};
})(this));
this.messageRouter.addTarget('_delete' + type, 'obj', (function(_this) {
return function(msg) {
msg.type = type;
return _this._deleteObject(msg);
};
})(this));
this.messageRouter.addTarget('_update' + type, 'obj', (function(_this) {
return function(msg) {
msg.type = type;
return _this._updateObject(msg);
};
})(this));
this.messageRouter.addTarget('_get' + type, 'obj', (function(_this) {
return function(msg) {
msg.type = type;
return _this._getObject(msg);
};
})(this));
this.messageRouter.addTarget('_list' + type + 's', '<noargs>', (function(_this) {
return function(msg) {
msg.type = type;
return _this._listObjects(msg);
};
})(this));
return this.messageRouter.addTarget('_count' + type + 's', '<noargs>', (function(_this) {
return function(msg) {
msg.type = type;
return _this._countObjects(msg);
};
})(this));
};
ObjectManager.prototype.getObjectPullThrough = function(id, type) {
var q;
q = defer();
if (!type) {
console.log('- Objectmanager::getObjectPullThrough called with null type.');
q.resolve();
} else if (!id || id === null || id === 'null') {
console.log('- Objectmanager::getObjectPullThrough called with null id for type ' + type);
q.resolve();
} else {
objStore.getObject(id, type).then((function(_this) {
return function(o) {
if (!o) {
if (debug) {
console.log('- getObjectPullThrough did not find object type ' + type + ' id ' + id + ' in ostore, getting from db');
}
return DB.get(type, [id]).then(function(record) {
if (debug) {
console.log('- getObjectPullThrough getting record from db');
}
if (debug) {
console.dir(record);
}
if (!record || !record[0] || record[0] === null) {
if (debug) {
console.log('- getObjectPullThrough got null record. resolving null');
}
return q.resolve(null);
} else {
return _this.messageRouter.resolver.createObjectFrom(record).then(function(oo) {
if (debug) {
console.log('- getObjectPullThrough got object ' + oo.id + ' ' + oo.type);
}
return q.resolve(oo);
});
}
});
} else {
return q.resolve(o);
}
};
})(this));
}
return q;
};
ObjectManager.prototype.onUpdateObject = function(msg) {
var ref;
if (msg.obj && msg.obj.type && msg.obj.id) {
if (ref = msg.obj.type.toLowerCase(), indexOf.call(this.getTypes(), ref) >= 0) {
return DB.getFromStoreOrDB(msg.obj.type, msg.obj.id).then((function(_this) {
return function(obj) {
var canwrite;
if (obj) {
canwrite = _this.messageRouter.authMgr.canUserWriteToThisObject(obj, msg.user, msg.obj, msg.sessionId);
if (canwrite) {
if (!_this.areDataTrashed(msg.obj)) {
return _this.persistUpdates(obj, msg.obj).then(function(res) {
if (!res) {
return msg.replyFunc({
status: e.general.FAILURE,
info: 'db error for object update',
payload: msg.obj.id
});
} else {
_this.messageRouter.gaugeMetric('update', 1, {
type: msg.obj.type,
'username': msg.user.name,
'useremail': msg.user.email,
'provider': msg.user.provider,
'organization': msg.user.organization
});
return msg.replyFunc({
status: e.general.SUCCESS,
info: e.gamemanager.UPDATE_OBJECT_SUCCESS,
payload: msg.obj.id
});
}
});
} else {
console.log('object update fail: data is TRASHED!!!!');
return msg.replyFunc({
status: e.general.NOT_ALLOWED,
info: 'one or more arrays have ben contaminated with null values',
payload: msg.obj.id
});
}
} else {
console.log('object update fail: not allowed to write');
return msg.replyFunc({
status: e.general.NOT_ALLOWED,
info: e.gamemanager.UPDATE_OBJECT_FAIL,
payload: msg.obj.id
});
}
} else {
console.log('No object of type ' + msg.obj.type + ' found with id ' + msg.obj.id);
return msg.replyFunc({
status: e.general.NOT_ALLOWED,
info: e.gamemanager.NO_SUCH_OBJECT,
payload: msg.obj.id
});
}
};
})(this));
} else {
return msg.replyFunc({
status: e.general.FAILURE,
info: 'missing parameter(s) for object update',
payload: msg.obj
});
}
} else {
console.log('onUpdateObject got wrong or missing parameters');
console.dir(msg.obj);
return msg.replyFunc({
status: e.general.FAILURE,
info: 'missing parameter(s) for object update',
payload: msg.obj
});
}
};
ObjectManager.prototype.persistUpdates = function(obj, robj, force) {
var borked, model, q;
q = defer();
model = this.getModelFor(obj.type);
borked = false;
model.forEach((function(_this) {
return function(row) {
if (row.array && robj[row.name] && !Array.isArray(robj[row.name])) {
console.log('BORK detected for property ' + row.name);
return borked = true;
}
};
})(this));
if (borked) {
console.log('borketh object entered. scalar where there should be an array..');
console.log('---------------------------------------------------------------');
console.dir(robj);
q.resolve(false);
} else {
obj.record = {};
model.forEach((function(_this) {
return function(m) {
var add, k, v;
k = m.name;
v = robj[k];
if (k !== 'id' && k !== 'type' && k !== 'createdAt' && k !== 'modifiedAt') {
add = true;
if (!v) {
add = false;
}
if (add) {
return obj.record[k] = v;
}
}
};
})(this));
obj.loadFromIds(obj.constructor.model).then((function(_this) {
return function() {
objStore.storeObject(obj);
objStore.updateObj(obj, force);
if (debug) {
console.log('persisting ' + obj.id + ' type ' + obj.type + ' in db. modifiedAt = ' + obj.modifiedAt + ' createdAt = ' + obj.createdAt);
}
return obj.serialize(robj).then(function(res) {
var record;
if (!res) {
console.log('persisting failed');
console.dir(obj);
return q.resolve(false);
} else {
record = obj.toClient();
_this.updateObjectHooks.forEach(function(hook) {
return hook(record);
});
return q.resolve(true);
}
});
};
})(this));
}
return q;
};
ObjectManager.prototype.areDataTrashed = function(obj) {
var k, trashed, v;
trashed = false;
for (k in obj) {
v = obj[k];
if (Array.isArray(v)) {
v.forEach(function(el) {
if (el === null || !el) {
trashed = true;
}
});
}
}
return trashed;
};
ObjectManager.prototype.onRegisterForUpdatesOn = function(msg) {
if (msg.obj || !msg.obj.id || !msg.obj.type) {
if (debug) {
console.log('onRegisterForUpdatesOn called for ' + msg.obj.type + ' ' + msg.obj.id);
}
return DB.getFromStoreOrDB(msg.obj.type, msg.obj.id).then((function(_this) {
return function(obj) {
var listenerId, rememberedListenerId;
if (obj && obj.id) {
if (_this.messageRouter.authMgr.canUserReadFromThisObject(obj, msg.user, msg.sessionId)) {
rememberedListenerId = void 0;
listenerId = objStore.addListenerFor(msg.obj.id, msg.obj.type, function(uobj) {
var toclient;
toclient = uobj.toClient();
if (debug) {
console.dir(toclient);
}
if (ClientEndpoints.exists(msg.client)) {
return ClientEndpoints.sendToEndpoint(msg.client, {
status: e.general.SUCCESS,
info: 'OBJECT_UPDATE',
payload: toclient
});
} else {
console.log('removing dangling endpoint from object updates for obj id ' + msg.id + ' and listenerId ' + rememberedListenerId);
return objStore.removeListenerFor(msg.id, rememberedListenerId);
}
});
rememberedListenerId = listenerId;
ClientEndpoints.onDisconnect(function(adr) {
if (adr === msg.client) {
return objStore.removeListenerFor(msg.obj.id, listenerId);
}
});
return msg.replyFunc({
status: e.general.SUCCESS,
info: e.gamemanager.REGISTER_UPDATES,
payload: listenerId
});
} else {
return msg.replyFunc({
status: e.general.NOT_ALLOWED,
info: 'Not allowed to register for updates on that object',
payload: msg.obj.id
});
}
} else {
if (debug) {
console.log('Could not find object: ' + msg.obj.type + ' id ' + msg.obj.id);
}
return msg.replyFunc({
status: e.general.NOT_ALLOWED,
info: e.gamemanager.NO_SUCH_OBJECT,
payload: msg.obj.id
});
}
};
})(this), error);
} else {
return msg.replyFunc({
status: e.general.FAILURE,
info: 'onRegisterForUpdatesOn missing parameter',
payload: null
});
}
};
ObjectManager.prototype.onDeregisterForUpdatesOn = function(msg) {
if (debug) {
console.log('onDeregisterForUpdatesOn called for id ' + msg.id + ' and listener id ' + msg.listenerid);
}
if (msg.id && msg.listenerid && msg.type) {
objStore.removeListenerFor(msg.id, msg.listenerid);
return msg.replyFunc({
status: e.general.SUCCESS,
info: 'deregistered listener for object',
payload: msg.id
});
} else {
return msg.replyFunc({
status: e.general.FAILURE,
info: 'onDeregisterForUpdatesOn missing parameter',
payload: null
});
}
};
ObjectManager.prototype.onRegisterForPopulationChanges = function(msg) {
var poplistenid, ref, sublist;
if (msg.type) {
if (ref = msg.type.toLowerCase(), indexOf.call(this.getTypes(), ref) >= 0) {
poplistenid = uuid.v4();
sublist = this.populationListeners[msg.type] || {};
sublist[poplistenid] = msg.client;
this.populationListeners[msg.type] = sublist;
msg.replyFunc({
status: e.general.SUCCESS,
info: 'registered for population changes for type ' + msg.type,
payload: poplistenid
});
return ClientEndpoints.onDisconnect((function(_this) {
return function(adr) {
if (adr === msg.client) {
sublist = _this.populationListeners[msg.type] || {};
return delete sublist[poplistenid];
}
};
})(this));
} else {
return msg.replyFunc({
status: e.general.FAILURE,
info: 'onRegisterForPopulationChanges unknown type',
payload: msg.type
});
}
} else {
return msg.replyFunc({
status: e.general.FAILURE,
info: 'onRegisterForPopulationChanges missing parameter',
payload: null
});
}
};
ObjectManager.prototype.onDeregisterForPopulationChanges = function(msg) {
var sublist;
if (msg.type && msg.listenerid) {
sublist = this.populationListeners[msg.type] || {};
return delete sublist[poplistenid];
} else {
return msg.replyFunc({
status: e.general.FAILURE,
info: 'onDeregisterForPopulationChanges missing parameter',
payload: null
});
}
};
ObjectManager.prototype.resolveReferences = function(record, model) {
var checkFinished, count, q, rv;
rv = {
id: record.id
};
q = defer();
count = model.length;
checkFinished = function(pname) {
if (--count === 0) {
return q.resolve(rv);
}
};
model.forEach((function(_this) {
return function(property) {
var acount, arr, harr, hcount, resolvedarr, resolvedhash;
if (property.array) {
resolvedarr = [];
arr = record[property.name] || [];
arr = arr.filter(function(el) {
return el && el !== null && el !== 'null' && el !== 'undefined';
});
acount = arr.length;
if (acount === 0) {
rv[property.name] = [];
return checkFinished(property.name);
} else {
return arr.forEach(function(idorobj) {
var id;
id = idorobj;
if (typeof idorobj === 'object') {
id = idorobj.id;
}
return _this.getObjectPullThrough(id, property.type).then(function(o) {
if (o) {
resolvedarr.push(o);
}
if (--acount === 0) {
rv[property.name] = resolvedarr;
return checkFinished(property.name);
}
});
});
}
} else if (property.hashtable) {
if (debug) {
console.log('======================================== going through hashtable property ' + property.name);
}
resolvedhash = {};
if (record[property.name]) {
harr = record[property.name] || [];
if (!harr.length) {
harr = [];
}
if (debug) {
console.dir(harr);
}
if (typeof harr === 'string') {
harr = [harr];
}
hcount = harr.length;
if (!hcount || hcount === 0) {
rv[property.name] = [];
return checkFinished(property.name);
} else {
return harr.forEach(function(id) {
return _this.getObjectPullThrough(id, property.type).then(function(o) {
if (o) {
resolvedhash[o.name] = o;
}
if (--hcount === 0) {
rv[property.name] = resolvedhash;
return checkFinished(property.name);
}
});
});
}
} else {
rv[property.name] = [];
return checkFinished(property.name);
}
} else {
if (property.type && property.value) {
return _this.getObjectPullThrough(record[property.name], property.type).then(function(o) {
rv[property.name] = o;
return checkFinished(property.name);
});
} else {
rv[property.name] = record[property.name];
return checkFinished(property.name);
}
}
};
})(this));
return q;
};
return ObjectManager;
})();
module.exports = ObjectManager;
}).call(this);
//# sourceMappingURL=ObjectManager.js.map