mirror of
https://github.com/mclueppers/xo-server.git
synced 2025-07-27 16:04:49 +02:00
Various updates.
This commit is contained in:
parent
2134e3b4d1
commit
16667e0d40
53
src/api.js
53
src/api.js
@ -144,9 +144,6 @@ Api.fn.session = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return this.users.findWhere({'email': p_email}).then(function (user) {
|
return this.users.findWhere({'email': p_email}).then(function (user) {
|
||||||
|
|
||||||
console.log(user);
|
|
||||||
|
|
||||||
if (!user)
|
if (!user)
|
||||||
{
|
{
|
||||||
throw Api.err.INVALID_CREDENTIAL;
|
throw Api.err.INVALID_CREDENTIAL;
|
||||||
@ -177,15 +174,17 @@ Api.fn.session = {
|
|||||||
throw Api.err.ALREADY_AUTHENTICATED;
|
throw Api.err.ALREADY_AUTHENTICATED;
|
||||||
}
|
}
|
||||||
|
|
||||||
var token = this.tokens.get(p_token);
|
return this.tokens.get(p_token).then(function (token) {
|
||||||
if (!token)
|
if (!token)
|
||||||
{
|
{
|
||||||
throw Api.err.INVALID_CREDENTIAL;
|
throw Api.err.INVALID_CREDENTIAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
session.set('token_id', token.id);
|
session.set('token_id', token.get('id'));
|
||||||
session.set('user_id', token.user_id);
|
session.set('user_id', token.get('user_id'));
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
'getUser': deprecated(function (session) {
|
'getUser': deprecated(function (session) {
|
||||||
@ -195,7 +194,9 @@ Api.fn.session = {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return _.pick(this.users.get(user_id), 'id', 'email');
|
return this.users.get(user_id).then(function (user) {
|
||||||
|
return _.pick(user.properties, 'id', 'email');
|
||||||
|
});
|
||||||
}),
|
}),
|
||||||
|
|
||||||
'getUserId': function (session) {
|
'getUserId': function (session) {
|
||||||
@ -296,13 +297,8 @@ Api.fn.user = {
|
|||||||
|
|
||||||
return users.update(user);
|
return users.update(user);
|
||||||
}).then(
|
}).then(
|
||||||
function () {
|
true,
|
||||||
return true;
|
Q.reject(Api.err.INVALID_PARAMS)
|
||||||
},
|
|
||||||
function () {
|
|
||||||
// @todo Find a better error.
|
|
||||||
return Api.err.INVALID_PARAMS;
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -320,7 +316,7 @@ Api.fn.token = {
|
|||||||
|
|
||||||
// @todo Token permission.
|
// @todo Token permission.
|
||||||
|
|
||||||
this.tokens.generate(user_id).then(function (token) {
|
return this.tokens.generate(user_id).then(function (token) {
|
||||||
return token.get('id');
|
return token.get('id');
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@ -328,13 +324,14 @@ Api.fn.token = {
|
|||||||
'delete': function (session, req) {
|
'delete': function (session, req) {
|
||||||
var p_token = req.params.token;
|
var p_token = req.params.token;
|
||||||
|
|
||||||
if (!this.tokens.get(p_token))
|
var tokens = this.tokens;
|
||||||
{
|
return tokens.get(p_token).then(function (token) {
|
||||||
throw Api.err.INVALID_PARAMS;
|
if (!token)
|
||||||
}
|
{
|
||||||
|
throw Api.err.INVALID_PARAMS;
|
||||||
|
}
|
||||||
|
|
||||||
return this.tokens.remove(p_token).then(function () {
|
return tokens.remove(p_token).then(true);
|
||||||
return true;
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -398,9 +395,7 @@ Api.fn.server = {
|
|||||||
|
|
||||||
// @todo Disconnect the server.
|
// @todo Disconnect the server.
|
||||||
|
|
||||||
return this.servers.remove(p_id).then(function () {
|
return this.servers.remove(p_id).then(true);
|
||||||
return true;
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
'connect': function () {
|
'connect': function () {
|
||||||
|
@ -4,18 +4,18 @@ var Q = require('q');
|
|||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// @todo Add events.
|
// @todo Add events.
|
||||||
function Collection(items)
|
function Collection(models)
|
||||||
{
|
{
|
||||||
// Parent constructor.
|
// Parent constructor.
|
||||||
Collection.super_.call(this);
|
Collection.super_.call(this);
|
||||||
|
|
||||||
this.items = [];
|
this.models = [];
|
||||||
|
|
||||||
this.next_id = 0;
|
this.next_id = 0;
|
||||||
|
|
||||||
if (items)
|
if (models)
|
||||||
{
|
{
|
||||||
this.add(items);
|
this.add(models);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
require('util').inherits(Collection, require('events').EventEmitter);
|
require('util').inherits(Collection, require('events').EventEmitter);
|
||||||
@ -23,56 +23,69 @@ require('util').inherits(Collection, require('events').EventEmitter);
|
|||||||
Collection.prototype.model = require('./model');
|
Collection.prototype.model = require('./model');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds new items to this collection.
|
* Adds new models to this collection.
|
||||||
*/
|
*/
|
||||||
Collection.prototype.add = function (items) {
|
Collection.prototype.add = function (models) {
|
||||||
var array = true;
|
var array = true;
|
||||||
if (!_.isArray(items))
|
if (!_.isArray(models))
|
||||||
{
|
{
|
||||||
items = [items];
|
models = [models];
|
||||||
array = false;
|
array = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_.each(items, function (item, i) {
|
_.each(models, function (model, i) {
|
||||||
if ( !(item instanceof this.model) )
|
if ( !(model instanceof this.model) )
|
||||||
{
|
{
|
||||||
item = new (this.model)(item);
|
model = new this.model(model);
|
||||||
items[i] = item;
|
models[i] = model;
|
||||||
}
|
}
|
||||||
|
|
||||||
var error = item.validate();
|
var error = model.validate();
|
||||||
if (undefined !== error)
|
if (undefined !== error)
|
||||||
{
|
{
|
||||||
// @todo Better system inspired by Backbone.js.
|
// @todo Better system inspired by Backbone.js.
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
|
|
||||||
var id = item.get('id');
|
var id = model.get('id');
|
||||||
|
|
||||||
if (undefined === id)
|
if (undefined === id)
|
||||||
{
|
{
|
||||||
id = this.next_id++;
|
id = this.next_id++;
|
||||||
item.set('id', id);
|
model.set('id', id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Existing items are ignored.
|
// Existing models are ignored.
|
||||||
if (this.items[id])
|
if (this.models[id])
|
||||||
{
|
{
|
||||||
return Q.reject('cannot add existing items!');
|
return Q.reject('cannot add existing models!');
|
||||||
}
|
}
|
||||||
|
|
||||||
this.items[id] = item.properties;
|
this.models[id] = model.properties;
|
||||||
}, this);
|
}, this);
|
||||||
|
|
||||||
/* jshint newcap: false */
|
/* jshint newcap: false */
|
||||||
return Q(array ? items : items[0]);
|
return Q(array ? models : models[0]);
|
||||||
|
};
|
||||||
|
|
||||||
|
Collection.prototype.get = function (id) {
|
||||||
|
/* jshint newcap:false */
|
||||||
|
|
||||||
|
var model = this.models[id];
|
||||||
|
|
||||||
|
if (!model)
|
||||||
|
{
|
||||||
|
return Q(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Q(new this.model(model));
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
Collection.prototype.exists = function (id) {
|
Collection.prototype.exists = function (id) {
|
||||||
return (undefined !== this.items[id]);
|
return (undefined !== this.models[id]);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -81,11 +94,13 @@ Collection.prototype.exists = function (id) {
|
|||||||
Collection.prototype.findWhere = function (properties) {
|
Collection.prototype.findWhere = function (properties) {
|
||||||
/* jshint newcap: false */
|
/* jshint newcap: false */
|
||||||
|
|
||||||
return Q(_.findWhere(this.items, properties));
|
var model = _.findWhere(this.models, properties);
|
||||||
|
|
||||||
|
return Q(model ? new this.model(model) : null);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes items from this collection.
|
* Removes models from this collection.
|
||||||
*/
|
*/
|
||||||
Collection.prototype.remove = function (ids) {
|
Collection.prototype.remove = function (ids) {
|
||||||
if (!_.isArray(ids))
|
if (!_.isArray(ids))
|
||||||
@ -94,8 +109,8 @@ Collection.prototype.remove = function (ids) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_.each(ids, function (id) {
|
_.each(ids, function (id) {
|
||||||
delete this.items[id];
|
delete this.models[id];
|
||||||
});
|
}, this);
|
||||||
|
|
||||||
// @todo Maybe return a more meaningful value.
|
// @todo Maybe return a more meaningful value.
|
||||||
/* jshint newcap: false */
|
/* jshint newcap: false */
|
||||||
@ -103,24 +118,25 @@ Collection.prototype.remove = function (ids) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates existing items.
|
* Updates existing models.
|
||||||
*/
|
*/
|
||||||
Collection.prototype.update = function (items) {
|
Collection.prototype.update = function (models) {
|
||||||
var array = true;
|
var array = true;
|
||||||
if (!_.isArray(items))
|
if (!_.isArray(models))
|
||||||
{
|
{
|
||||||
items = [items];
|
models = [models];
|
||||||
array = false;
|
array = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_.each(items, function (properties, i) {
|
// @todo Rewrite.
|
||||||
|
_.each(models, function (properties, i) {
|
||||||
if (properties instanceof this.model)
|
if (properties instanceof this.model)
|
||||||
{
|
{
|
||||||
properties = properties.properties;
|
properties = properties.properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
// @todo
|
// @todo
|
||||||
// var error = item.validate();
|
// var error = model.validate();
|
||||||
// if (undefined !== error)
|
// if (undefined !== error)
|
||||||
// {
|
// {
|
||||||
// // @todo Better system inspired by Backbone.js.
|
// // @todo Better system inspired by Backbone.js.
|
||||||
@ -129,31 +145,31 @@ Collection.prototype.update = function (items) {
|
|||||||
|
|
||||||
var id = properties.id;
|
var id = properties.id;
|
||||||
|
|
||||||
var item = this.items[id];
|
var model = this.models[id];
|
||||||
|
|
||||||
// Missing items are ignored.
|
// Missing models are ignored.
|
||||||
if (!item)
|
if (!model)
|
||||||
{
|
{
|
||||||
return Q.reject('missing item!');
|
return Q.reject('missing model!');
|
||||||
}
|
}
|
||||||
|
|
||||||
item.set(properties);
|
_.extend(model.properties, model);
|
||||||
|
|
||||||
items[i] = item;
|
models[i] = model;
|
||||||
});
|
});
|
||||||
|
|
||||||
/* jshint newcap: false */
|
/* jshint newcap: false */
|
||||||
return Q(array ? items : items[0]);
|
return Q(array ? models : models[0]);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Smartly updates the collection.
|
* Smartly updates the collection.
|
||||||
*
|
*
|
||||||
* - Adds new items.
|
* - Adds new models.
|
||||||
* - Updates existing items.
|
* - Updates existing models.
|
||||||
* - Removes missing items.
|
* - Removes missing models.
|
||||||
*/
|
*/
|
||||||
Collection.prototype.set = function (/*items*/) {
|
Collection.prototype.set = function (/*models*/) {
|
||||||
throw 'not implemented';
|
throw 'not implemented';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
12
src/main.js
12
src/main.js
@ -63,7 +63,15 @@ function json_api_call(session, message)
|
|||||||
'id': req.id,
|
'id': req.id,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
format_error
|
function (error) {
|
||||||
|
if (error instanceof Error)
|
||||||
|
{
|
||||||
|
console.error(error);
|
||||||
|
return format_error(Api.err.SERVER_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
return format_error(error);
|
||||||
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,4 +157,4 @@ require('net').createServer(function (socket) {
|
|||||||
socket.once('close', function () {
|
socket.once('close', function () {
|
||||||
session.close();
|
session.close();
|
||||||
});
|
});
|
||||||
}).listen(__dirname +'/../socket'); // @todo Should be configurable.
|
}).listen(8081); // @todo Should be configurable.
|
||||||
|
@ -7,7 +7,7 @@ function Model(properties)
|
|||||||
// Parent constructor.
|
// Parent constructor.
|
||||||
Model.super_.call(this);
|
Model.super_.call(this);
|
||||||
|
|
||||||
this.properties = this['default'];
|
this.properties = _.extend({}, this['default']);
|
||||||
|
|
||||||
if (properties)
|
if (properties)
|
||||||
{
|
{
|
||||||
|
57
src/xo.js
57
src/xo.js
@ -35,12 +35,12 @@ var check = function () {
|
|||||||
// user.permission).
|
// user.permission).
|
||||||
var Token = Model.extend({
|
var Token = Model.extend({
|
||||||
// Validates model attributes.
|
// Validates model attributes.
|
||||||
'validate': function (attr) {
|
// 'validate': function (attr) {
|
||||||
check(attr.id).len(10);
|
// check(attr.id).len(10);
|
||||||
check(attr.user_id).isInt();
|
// check(attr.user_id).isInt();
|
||||||
|
|
||||||
return check.pop();
|
// return check.pop();
|
||||||
},
|
// },
|
||||||
}, {
|
}, {
|
||||||
'generate': function (user_id) {
|
'generate': function (user_id) {
|
||||||
return Q.ninvoke(crypto, 'randomBytes', 32).then(function (buf) {
|
return Q.ninvoke(crypto, 'randomBytes', 32).then(function (buf) {
|
||||||
@ -57,26 +57,21 @@ var User = Model.extend({
|
|||||||
'permission': 'none',
|
'permission': 'none',
|
||||||
},
|
},
|
||||||
|
|
||||||
'initialize': function ()
|
|
||||||
{
|
|
||||||
this.on('change:password', function (model, password) {
|
|
||||||
this.unset('password', {'silent': true});
|
|
||||||
|
|
||||||
var user = this;
|
|
||||||
hashy.hash(password).then(function (hash) {
|
|
||||||
user.set('pw_hash', hash);
|
|
||||||
}).done();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
// Validates model attributes.
|
// Validates model attributes.
|
||||||
'validate': function (attr) {
|
// 'validate': function (attr) {
|
||||||
check(attr.id).isInt();
|
// check(attr.id).isInt();
|
||||||
check(attr.email).isEmail();
|
// check(attr.email).isEmail();
|
||||||
check(attr.pw_hash).len(40);
|
// check(attr.pw_hash).len(40);
|
||||||
check(attr.permission).isIn('none', 'read', 'write', 'admin');
|
// check(attr.permission).isIn('none', 'read', 'write', 'admin');
|
||||||
|
|
||||||
return check.pop();
|
// return check.pop();
|
||||||
|
// },
|
||||||
|
|
||||||
|
'setPassword': function (password) {
|
||||||
|
var self = this;
|
||||||
|
return hashy.hash(password).then(function (hash) {
|
||||||
|
self.set('pw_hash', hash);
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
// Checks and updates the hash if necessary.
|
// Checks and updates the hash if necessary.
|
||||||
@ -92,8 +87,10 @@ var User = Model.extend({
|
|||||||
|
|
||||||
if (hashy.needsRehash(hash))
|
if (hashy.needsRehash(hash))
|
||||||
{
|
{
|
||||||
user.set('password', password);
|
return user.setPassword(password).then(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -122,8 +119,10 @@ var Tokens = Collection.extend({
|
|||||||
'model': Token,
|
'model': Token,
|
||||||
|
|
||||||
'generate': function (user_id) {
|
'generate': function (user_id) {
|
||||||
return this.model.generate(user_id).then(function (token) {
|
var self = this;
|
||||||
return this.add(token);
|
|
||||||
|
return Token.generate(user_id).then(function (token) {
|
||||||
|
return self.add(token);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -143,6 +142,10 @@ function Xo()
|
|||||||
this.servers = new Servers();
|
this.servers = new Servers();
|
||||||
this.tokens = new Tokens();
|
this.tokens = new Tokens();
|
||||||
this.users = new Users();
|
this.users = new Users();
|
||||||
|
this.users.add({
|
||||||
|
'email': 'bob@gmail.com',
|
||||||
|
'pw_hash': '$2a$10$PsSOXflmnNMEOd0I5ohJQ.cLty0R29koYydD0FBKO9Rb7.jvCelZq',
|
||||||
|
}).done();
|
||||||
|
|
||||||
// This events are used to automatically close connections if the
|
// This events are used to automatically close connections if the
|
||||||
// associated credentials are invalidated.
|
// associated credentials are invalidated.
|
||||||
@ -157,7 +160,7 @@ function Xo()
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
require('util').inherits(Collection, require('events').EventEmitter);
|
require('util').inherits(Xo, require('events').EventEmitter);
|
||||||
|
|
||||||
module.exports = function () {
|
module.exports = function () {
|
||||||
return new Xo();
|
return new Xo();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user