From 2134e3b4d11bf2b714e6b1e1623e777e4e8cfd2c Mon Sep 17 00:00:00 2001 From: Julien Fontanet Date: Wed, 10 Jul 2013 12:25:55 +0200 Subject: [PATCH] Various updates. --- src/api.js | 88 +++++++++++++++++++++++++++++++++++++++++------ src/collection.js | 15 +++++--- src/main.js | 29 ++++++++-------- src/model.js | 34 +++++++++++++----- src/session.js | 8 ++++- src/xapi.js | 6 ++++ 6 files changed, 140 insertions(+), 40 deletions(-) diff --git a/src/api.js b/src/api.js index 2636550..0513438 100644 --- a/src/api.js +++ b/src/api.js @@ -143,20 +143,24 @@ Api.fn.session = { throw Api.err.ALREADY_AUTHENTICATED; } - var user = this.users.findWhere({'email': p_email}); - if (!user) - { - throw Api.err.INVALID_CREDENTIAL; - } + return this.users.findWhere({'email': p_email}).then(function (user) { - return user.checkPassword(p_pass).then(function (success) { - if (!success) + console.log(user); + + if (!user) { throw Api.err.INVALID_CREDENTIAL; } - session.set('user_id', user.get('id')); - return true; + return user.checkPassword(p_pass).then(function (success) { + if (!success) + { + throw Api.err.INVALID_CREDENTIAL; + } + + session.set('user_id', user.get('id')); + return true; + }); }); }, @@ -236,8 +240,70 @@ Api.fn.user = { throw Api.err.NOT_IMPLEMENTED; }, - 'set': function () { - throw Api.err.NOT_IMPLEMENTED; + 'set': function (session, request) { + var user_id = session.get('user_id'); + if (undefined === user_id) + { + throw Api.err.UNAUTHORIZED; + } + + var p_email, p_password, p_permission; + + var users = this.users; + + return users.get(user_id).then(function (user) { + // Get the current user to check its permission. + + if (!user.hasPermission('admin')) + { + throw Api.err.UNAUTHORIZED; + } + + var p_id = request.params.id; + p_email = request.params.email; + p_password = request.params.password; + p_permission = request.params.permission; + + /* jshint laxbreak: true */ + if ((undefined === p_id) + || ((undefined === p_email) + && (undefined === p_password) + && (undefined === p_permission))) + { + throw Api.err.INVALID_PARAMS; + } + + // @todo Check there are no invalid parameter. + + return users.get(p_id); + }).then(function (user) { + // Gets the user to update. + + // @todo Check undefined value are ignored. + user.set({ + 'email': p_email, + 'permission': p_permission, + }); + + if (p_password) + { + return user.setPassword(p_password).then(user); + } + + return user; + }).then(function (user) { + // Save the updated user. + + return users.update(user); + }).then( + function () { + return true; + }, + function () { + // @todo Find a better error. + return Api.err.INVALID_PARAMS; + } + ); }, }; diff --git a/src/collection.js b/src/collection.js index 8788395..777daaa 100644 --- a/src/collection.js +++ b/src/collection.js @@ -1,6 +1,8 @@ var _ = require('underscore'); var Q = require('q'); +////////////////////////////////////////////////////////////////////// + // @todo Add events. function Collection(items) { @@ -34,7 +36,7 @@ Collection.prototype.add = function (items) { _.each(items, function (item, i) { if ( !(item instanceof this.model) ) { - item = new this.model(item); + item = new (this.model)(item); items[i] = item; } @@ -59,8 +61,8 @@ Collection.prototype.add = function (items) { return Q.reject('cannot add existing items!'); } - this.items[id] = item; - }); + this.items[id] = item.properties; + }, this); /* jshint newcap: false */ return Q(array ? items : items[0]); @@ -77,7 +79,9 @@ Collection.prototype.exists = function (id) { * */ Collection.prototype.findWhere = function (properties) { - return _.findWhere(this.items, properties); + /* jshint newcap: false */ + + return Q(_.findWhere(this.items, properties)); }; /** @@ -155,5 +159,6 @@ Collection.prototype.set = function (/*items*/) { Collection.extend = require('extendable'); -// Export. +////////////////////////////////////////////////////////////////////// + module.exports = Collection; diff --git a/src/main.js b/src/main.js index 4f42ed6..2bae68d 100644 --- a/src/main.js +++ b/src/main.js @@ -72,23 +72,24 @@ function json_api_call(session, message) ////////////////////////////////////////////////////////////////////// // @todo Port should be configurable. -require('socket.io').listen(8080).sockets.on('connection', function (socket) { - var session = new Session(xo); - session.once('close', function () { - socket.disconnect(); - }); +require('socket.io').listen(8080, {'log level': 0}).sockets + .on('connection', function (socket) { + var session = new Session(xo); + session.once('close', function () { + socket.disconnect(); + }); - socket.on('message', function (request) { - json_api_call(session, request).then(function (response) { - socket.send(response); - }).done(); - }); + socket.on('message', function (request) { + json_api_call(session, request).then(function (response) { + socket.send(response); + }).done(); + }); - // @todo Ugly inter dependency. - socket.once('disconnect', function () { - session.close(); + // @todo Ugly inter dependency. + socket.once('disconnect', function () { + session.close(); + }); }); -}); ////////////////////////////////////////////////////////////////////// // JSON-RPC over TCP. diff --git a/src/model.js b/src/model.js index 875746d..582b126 100644 --- a/src/model.js +++ b/src/model.js @@ -1,11 +1,13 @@ var _ = require('underscore'); +////////////////////////////////////////////////////////////////////// + function Model(properties) { // Parent constructor. Model.super_.call(this); - this.properties = {}; + this.properties = this['default']; if (properties) { @@ -37,12 +39,6 @@ Model.prototype.get = function (property, def) { return prop; } - prop = this['default'][property]; - if (undefined !== prop) - { - return prop; - } - return def; }; @@ -64,17 +60,36 @@ Model.prototype.set = function (properties, value) { properties[property] = value; } + var previous = {}; + var model = this; _.each(properties, function (value, key) { - //model.properties = + var prev = model.get(key); + + // New value. + if (value !== prev) + { + previous[key] = prev; + model.properties[key] = value; + } }); + + if (!_.isEmpty(previous)) + { + this.emit('change', previous); + + _.each(previous, function (previous, property) { + this.emit('change:'+ property, previous); + }, this); + } }; /** * Unsets properties. */ Model.prototype.unset = function (properties) { + // @todo Events. this.properties = _.omit(this.properties, properties); }; @@ -87,5 +102,6 @@ Model.prototype['default'] = {}; Model.extend = require('extendable'); -// Export. +////////////////////////////////////////////////////////////////////// + module.exports = Model; diff --git a/src/session.js b/src/session.js index bcf9d5f..7d57b90 100644 --- a/src/session.js +++ b/src/session.js @@ -1,6 +1,8 @@ var Model = require('./model'); -module.exports = Model.extend({ +////////////////////////////////////////////////////////////////////// + +var Session = Model.extend({ 'constructor': function (xo) { Model.call(this); @@ -45,3 +47,7 @@ module.exports = Model.extend({ this.emit('close'); }, }); + +////////////////////////////////////////////////////////////////////// + +module.exports = Session; diff --git a/src/xapi.js b/src/xapi.js index 74b0ebf..b44957d 100644 --- a/src/xapi.js +++ b/src/xapi.js @@ -1,6 +1,8 @@ var Q = require('q'); var xmlrpc = require('xmlrpc'); +////////////////////////////////////////////////////////////////////// + function Xapi(host) { // Parent constructor. @@ -48,3 +50,7 @@ Xapi.prototype.connect = function (username, password) { self.sessionId = session_id; }); }; + +////////////////////////////////////////////////////////////////////// + +module.exports = Xapi;