Various updates.

This commit is contained in:
Julien Fontanet 2013-07-05 13:09:20 +02:00
parent 22ce37c0cd
commit ddf259f8b7
4 changed files with 170 additions and 108 deletions

View File

@ -13,7 +13,7 @@
},
"main": "src/main.js",
"dependencies": {
"backbone": ">=1.0.0",
"extendable": ">=0.0.3",
"hashy": ">=0.1.0",
"underscore": ">=1.4.4"
},

View File

@ -2,6 +2,17 @@ var _ = require('underscore');
//////////////////////////////////////////////////////////////////////
function deprecated(fn)
{
return function (session, req, res) {
console.warn(req.method +' is deprecated!');
return fn.call(this, session, req, res);
};
}
//////////////////////////////////////////////////////////////////////
function Api(xo)
{
this.xo = xo;
@ -41,9 +52,19 @@ Api.prototype.get = function (name) {
)
{}
return _.isFunction(current)
? current
: undefined
// Method found.
if (_.isFunction(current))
{
return current;
}
// It's a (deprecated) alias.
if (_.isString(current))
{
return deprecated(this.get(current));
}
return undefined;
;
};
@ -64,14 +85,14 @@ function err(code, message)
Api.err = {
//////////////////////////////////////////////////////////////////
// JSON errors.
// JSON-RPC errors.
//////////////////////////////////////////////////////////////////
'INVALID_JSON': err(-32700, 'invalid JSON'),
'INVALID_REQUEST': err(-32600, 'invalid JSON-RPC request'),
'INVALID_METHOD': err(-326001, 'method not found'),
'INVALID_METHOD': err(-32601, 'method not found'),
'INVALID_PARAMS': err(-32602, 'invalid parameter(s)'),
@ -100,6 +121,7 @@ Api.fn.api = {
},
};
// Session management
Api.fn.session = {
'signInWithPassword': function (session, req, res) {
var p_email = req.params.email;
@ -161,7 +183,7 @@ Api.fn.session = {
return true;
},
'getUser': function (session, req, res) {
'getUser': deprecated(function (session, req, res) {
var user_id = session.get('user_id');
if (undefined === user_id)
{
@ -169,36 +191,18 @@ Api.fn.session = {
}
return _.pick(users.get(user_id), 'id', 'email');
});
'getUserId': function (session, req, res) {
return session.get('user_id', null);
};
'createToken': function (session, req, res) {
var user_id = session.get('user_id');
if ((undefined === user_id)
|| session.has('token_id'))
{
throw Api.err.UNAUTHORIZED;
}
'createToken': 'token.create'
// @todo Ugly.
var token = this.tokens.model.generate(user_id);
this.tokens.add(token);
return token.id;
},
'destroyToken': function (session, req, res) {
var p_token = req.params.token;
if (!this.tokens.get(p_token))
{
throw Api.err.INVALID_PARAMS;
}
this.tokens.remove(p_token);
return true;
},
'destroyToken': 'token.delete',
};
// User management.
Api.fn.user = {
'create': function (session, req, res) {
var p_email = req.params.email;
@ -220,7 +224,9 @@ Api.fn.user = {
},
'delete': function (session, req, res) {
var p_id = req.params.id;
var user
},
'changePassword': function (session, req, res) {
@ -235,3 +241,38 @@ Api.fn.user = {
},
};
// Token management.
Api.fn.token = {
'create': function (session, req, res) {
var user_id = session.get('user_id');
if ((undefined === user_id)
|| session.has('token_id'))
{
throw Api.err.UNAUTHORIZED;
}
// @todo Ugly.
var token = this.tokens.model.generate(user_id);
this.tokens.add(token);
return token.id;
},
'delete': function (session, req, res) {
var p_token = req.params.token;
if (!this.tokens.get(p_token))
{
throw Api.err.INVALID_PARAMS;
}
this.tokens.remove(p_token);
return true;
},
};
// VM
Api.fn.vm = {
};

View File

@ -1,5 +1,6 @@
var events = require('events');
var EventEmitter = require('events').EventEmitter;
var util = require('util');
var Session = require('session');
//--------------------------------------
@ -8,34 +9,6 @@ var api = require('./api')(xo);
//////////////////////////////////////////////////////////////////////
function Session()
{
this.data = {};
}
util.inherits(Session, events.EventEmitter);
Session.prototype.close = function () {
session.emit('close');
};
Session.prototype.get = function (name, def) {
if (undefined !== this.data[name])
{
return this.data[name];
}
return def;
};
Session.prototype.has = function (name) {
return (undefined !== this.data[name]);
};
Session.prototype.set = function (name, value) {
this.data[name] = value;
};
//////////////////////////////////////////////////////////////////////
function Response(transport, id)
@ -70,22 +43,8 @@ Response.prototype.sendError = function (error)
//////////////////////////////////////////////////////////////////////
require('socket.io')
.listen(8080)
.sockets.on('connection', function (socket) {
// @todo comment
var transport = function (message) {
socket.send(data);
};
var session = new Session();
session.on('close', function () {
socket.disconnect();
});
// When a message is received.
socket.on('message', function (message) {
function json_api_call(session, transport, message)
{
try
{
var req = JSON.parse(message.toString());
@ -117,6 +76,65 @@ require('socket.io')
},
new Response(transport, req.id)
);
}
//////////////////////////////////////////////////////////////////////
// JSON-RPC over WebSocket.
//////////////////////////////////////////////////////////////////////
require('socket.io').listen(8080).sockets.on('connection', function (socket) {
var transport = function (message) {
socket.send(data);
};
var session = new Session();
session.on('close', function () {
socket.disconnect();
});
})
;
socket.on('message', function (message) {
json_api_call(session, transport, message);
});
});
//////////////////////////////////////////////////////////////////////
// JSON-RPC over TCP.
//////////////////////////////////////////////////////////////////////
require('net').createServer(function (socket) {
var transport = function (message) {
socket.write(message); // @todo Handle long messages.
};
var session = new Session();
session.on('close', function () {
socket.end(); // @todo Check it is enough.
});
var length = null; // Expected message length.
var buffer = new Buffer();
socket.on('data', function (data) {
data.copy(buffer);
// Read the message length.
if (!length)
{
var i = _.indexOf(buffer, 10);
if (-1 === i)
{
return;
}
length = +buffer.toString('ascii', 0, i); // @todo Handle NaN.
buffer = buffer.slice(i + 1);
}
// We do not have received everything.
if (buffer.length < length)
{
return;
}
json_api_call(session, transport, buffer.toString());
});
}).listen('<path>'); // @todo

View File

@ -1,8 +1,9 @@
var _ = require('underscore');
var Backbone = require('backbone');
var crypto = require('crypto');
var hashy = require('hashy');
var Q = require('q');
var Collection = require('collection');
var Model = require('model');
//////////////////////////////////////////////////////////////////////
@ -33,7 +34,7 @@ var check = function () {
// @todo We could also give a permission level to tokens (<=
// user.permission).
var Token = Backbone.Model.extend({
var Token = Model.extend({
// Validates model attributes.
'validate': function (attr) {
check(attr.id).len(10);
@ -52,7 +53,9 @@ var Token = Backbone.Model.extend({
},
});
var User = Backbone.Model.extend({
user.set('password', '123');
var User = Model.extend({
'default': {
'permission': 'none',
},
@ -102,11 +105,11 @@ var User = Backbone.Model.extend({
// Collections
//////////////////////////////////////////////////////////////////////
var Tokens = Backbone.Collection.extend({
var Tokens = Collection.extend({
'model': Token,
});
var Users = Backbone.Collection.extend({
var Users = Collection.extend({
'model': User,
});