зеркало из https://github.com/mozilla/gombot.git
WIP persistence layer and stage account api
This commit is contained in:
Родитель
add29d59f5
Коммит
41657124dc
14
bin/api
14
bin/api
|
@ -24,11 +24,21 @@ server.on('bound', function(host, port) {
|
||||||
console.log("running on http://" + host + ":" + port);
|
console.log("running on http://" + host + ":" + port);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// TODO seperate config
|
||||||
|
var dbConfig = {
|
||||||
|
hosts: [ 'localhost:8091' ],
|
||||||
|
username: 'admin',
|
||||||
|
password: null,
|
||||||
|
bucket: 'default'
|
||||||
|
};
|
||||||
|
|
||||||
// now load up api handlers
|
// now load up api handlers
|
||||||
apiLoader(server, function(err) {
|
apiLoader(server, function(err) {
|
||||||
if (err) fatal(err);
|
if (err) fatal(err);
|
||||||
// Start the server
|
db.connect(dbConfig, function() {
|
||||||
server.start();
|
// Start the server
|
||||||
|
server.start();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
process.on('SIGTERM', function() {
|
process.on('SIGTERM', function() {
|
||||||
|
|
102
client/client.js
102
client/client.js
|
@ -1,39 +1,79 @@
|
||||||
GombotClient = (function() {
|
;(function() {
|
||||||
var xhr = typeof jQuery !== 'undefined' ? jQuery.ajax : require('xhrequest');
|
|
||||||
|
|
||||||
function request(args, cb) {
|
GombotClient = function(host, port) {
|
||||||
var url = args.scheme ? args.scheme : 'http';
|
this.host = host;
|
||||||
var method = args.method.toUpperCase();
|
this.port = port;
|
||||||
url += "://" + args.host;
|
};
|
||||||
if (args.port) url += ":" + args.port;
|
|
||||||
url += args.path;
|
|
||||||
|
|
||||||
console.log('sending xhr');
|
var xhr = typeof jQuery !== 'undefined' ? jQuery.ajax : require('xhrequest');
|
||||||
xhr(url, {
|
|
||||||
method: method,
|
if (typeof GombotCrypto === 'undefined') {
|
||||||
success: function (data, res, status) {
|
var GombotCrypto = require('./crypto.js');
|
||||||
try {
|
}
|
||||||
var body = JSON.parse(data);
|
|
||||||
body.session_context = {};
|
function request(args, cb) {
|
||||||
cb(null, body);
|
var url = args.scheme ? args.scheme : 'http';
|
||||||
} catch (e) {
|
var method = args.method.toUpperCase();
|
||||||
cb('Invalid JSON response: '+e);
|
url += '://' + args.host;
|
||||||
}
|
if (args.port) url += ':' + args.port;
|
||||||
},
|
url += args.path;
|
||||||
error: function (data, res, status) {
|
|
||||||
cb('Error: '+data+'\nStatus: '+status);
|
var req = {
|
||||||
|
url: url,
|
||||||
|
method: method,
|
||||||
|
data: args.data,
|
||||||
|
headers: {},
|
||||||
|
success: function(data, res, status) {
|
||||||
|
try {
|
||||||
|
var body = JSON.parse(data);
|
||||||
|
} catch (e) {
|
||||||
|
return cb('Invalid JSON response: ' + e);
|
||||||
}
|
}
|
||||||
});
|
body.session_context = {};
|
||||||
}
|
cb(null, body);
|
||||||
|
},
|
||||||
return {
|
error: function(data, res, status) {
|
||||||
// get "session context" from the server
|
cb('Error: ' + data + '\nStatus: ' + status);
|
||||||
context: function(args, cb) {
|
|
||||||
args.method = 'get';
|
|
||||||
args.path = '/v1/context';
|
|
||||||
request(args, cb);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
if (method == 'PUT' || method == 'POST') {
|
||||||
|
req.headers['Content-Type'] = 'application/json';
|
||||||
|
}
|
||||||
|
xhr(url, req);
|
||||||
|
}
|
||||||
|
|
||||||
|
GombotClient.prototype = {
|
||||||
|
// get "session context" from the server
|
||||||
|
context: function(args, cb) {
|
||||||
|
if (typeof args === 'function') {
|
||||||
|
cb = args;
|
||||||
|
args = {};
|
||||||
|
}
|
||||||
|
args.host = args.host || this.host;
|
||||||
|
args.port = args.port || this.port;
|
||||||
|
args.method = 'get';
|
||||||
|
args.path = '/v1/context';
|
||||||
|
|
||||||
|
request(args, cb);
|
||||||
|
},
|
||||||
|
account: function(args, cb) {
|
||||||
|
args.host = args.host || this.host;
|
||||||
|
args.port = args.port || this.port;
|
||||||
|
args.method = 'put';
|
||||||
|
args.path = '/v1/account';
|
||||||
|
|
||||||
|
// compute the authKey
|
||||||
|
var keys = GombotCrypto.derive({
|
||||||
|
email: args.email,
|
||||||
|
password: args.password
|
||||||
|
}, function(err, r) {
|
||||||
|
args.data = JSON.stringify({email: args.email, pass: r.authKey});
|
||||||
|
// send request with authKey as the password
|
||||||
|
request(args, cb);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
|
||||||
if (typeof module != 'undefined' && module.exports) {
|
if (typeof module != 'undefined' && module.exports) {
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
var crypto = require('crypto'),
|
||||||
|
Hapi = require('hapi'),
|
||||||
|
db = require('../../db');
|
||||||
|
|
||||||
|
var B = Hapi.Types.Boolean,
|
||||||
|
S = Hapi.Types.String;
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
method: 'PUT',
|
||||||
|
handler: handler,
|
||||||
|
config: {
|
||||||
|
auth: false,
|
||||||
|
description: 'Stage a new account',
|
||||||
|
schema: {
|
||||||
|
email: B(),
|
||||||
|
pass: S()
|
||||||
|
},
|
||||||
|
response: {
|
||||||
|
success: B()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function handler(request) {
|
||||||
|
console.log('$$$$$$$$$$');
|
||||||
|
db.stageAccount(request.payload, function(err) {
|
||||||
|
if (err) request.reply(Hapi.Error.internal("error staging account"));
|
||||||
|
request.reply({
|
||||||
|
success: true
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
|
@ -5,7 +5,7 @@ const API_BASE_PATH = path.join(__dirname, 'api');
|
||||||
|
|
||||||
function addRouteFromFile(hapiServer, apiPath) {
|
function addRouteFromFile(hapiServer, apiPath) {
|
||||||
// hack off ext
|
// hack off ext
|
||||||
var route = apiPath.substr(0,apiPath.length - 3);
|
var route = apiPath.substr(0, apiPath.length - 3);
|
||||||
var route = path.relative(API_BASE_PATH, route);
|
var route = path.relative(API_BASE_PATH, route);
|
||||||
var impl = require(apiPath);
|
var impl = require(apiPath);
|
||||||
impl.path = '/' + route;
|
impl.path = '/' + route;
|
||||||
|
@ -23,7 +23,7 @@ module.exports = function(hapiServer, cb) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
addRouteFromFile(hapiServer, apiPath);
|
addRouteFromFile(hapiServer, apiPath);
|
||||||
} catch(e) {
|
} catch (e) {
|
||||||
walker.end();
|
walker.end();
|
||||||
cb('error while loading API handler ("' + apiPath + '") ' +
|
cb('error while loading API handler ("' + apiPath + '") ' +
|
||||||
e.toString());
|
e.toString());
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
|
||||||
|
// TODO select driver based on config
|
||||||
|
module.exports = require('./db/json');
|
|
@ -0,0 +1,29 @@
|
||||||
|
var couchbase = require('couchbase');
|
||||||
|
|
||||||
|
var db;
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
connect: function(options, cb) {
|
||||||
|
console.error('options', options);
|
||||||
|
couchbase.connect(options, function(err, bucket) {
|
||||||
|
console.error('connection fail!!!', err);
|
||||||
|
if (err) cb(err);
|
||||||
|
db = bucket;
|
||||||
|
cb(null);
|
||||||
|
});
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
stageAccount: function(data, cb) {
|
||||||
|
var account = {
|
||||||
|
pass: data.pass,
|
||||||
|
email: data.email,
|
||||||
|
staged: true
|
||||||
|
};
|
||||||
|
db.set(data.email, account, function (err, meta) {
|
||||||
|
console.log('meta', meta);
|
||||||
|
if (err) cb(err);
|
||||||
|
else cb(null, meta);
|
||||||
|
});
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
};
|
|
@ -0,0 +1,23 @@
|
||||||
|
var db;
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
connect: function(options, cb) {
|
||||||
|
setTimeout(function() {
|
||||||
|
if (db) return;
|
||||||
|
db = {};
|
||||||
|
cb(null);
|
||||||
|
}, 0);
|
||||||
|
},
|
||||||
|
stageAccount: function(data, cb) {
|
||||||
|
var account = {
|
||||||
|
pass: data.pass,
|
||||||
|
email: data.email,
|
||||||
|
staged: true
|
||||||
|
};
|
||||||
|
setTimeout(function() {
|
||||||
|
db[data.email] = account;
|
||||||
|
cb(null);
|
||||||
|
}, 0);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
};
|
|
@ -6,6 +6,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"hapi": "git://github.com/lloyd/hapi#b12270",
|
"hapi": "git://github.com/lloyd/hapi#b12270",
|
||||||
"walkdir": "0.0.5",
|
"walkdir": "0.0.5",
|
||||||
|
"couchbase": "0.0.4",
|
||||||
"express": "3.0.2",
|
"express": "3.0.2",
|
||||||
"nunjucks": "0.1.5"
|
"nunjucks": "0.1.5"
|
||||||
},
|
},
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
const
|
||||||
|
should = require('should'),
|
||||||
|
runner = require('./lib/runner.js'),
|
||||||
|
Client = require('../client/client.js');
|
||||||
|
|
||||||
|
var servers;
|
||||||
|
var client;
|
||||||
|
|
||||||
|
describe('the servers', function() {
|
||||||
|
it('should start up', function(done) {
|
||||||
|
runner(function(err, r) {
|
||||||
|
should.not.exist(err);
|
||||||
|
should.exist(r);
|
||||||
|
servers = r;
|
||||||
|
client = new Client(servers.host, servers.port);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('/api/v1/account', function() {
|
||||||
|
it('staging should return success', function(done) {
|
||||||
|
client.account({
|
||||||
|
email: 'foo',
|
||||||
|
password: 'bar'
|
||||||
|
}, function(err, r) {
|
||||||
|
should.not.exist(err);
|
||||||
|
should.exist(r);
|
||||||
|
(r.success).should.be.true;
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('the servers', function() {
|
||||||
|
it('should stop', function(done) {
|
||||||
|
servers.stop(function(err) {
|
||||||
|
should.not.exist(err);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -1,9 +1,10 @@
|
||||||
const
|
const
|
||||||
should = require('should'),
|
should = require('should'),
|
||||||
runner = require('./lib/runner.js'),
|
runner = require('./lib/runner.js'),
|
||||||
client = require('../client/client.js');
|
Client = require('../client/client.js');
|
||||||
|
|
||||||
var servers;
|
var servers;
|
||||||
|
var client;
|
||||||
|
|
||||||
describe('the servers', function() {
|
describe('the servers', function() {
|
||||||
it('should start up', function(done) {
|
it('should start up', function(done) {
|
||||||
|
@ -11,6 +12,7 @@ describe('the servers', function() {
|
||||||
should.not.exist(err);
|
should.not.exist(err);
|
||||||
should.exist(r);
|
should.exist(r);
|
||||||
servers = r;
|
servers = r;
|
||||||
|
client = new Client(servers.host, servers.port);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -18,10 +20,7 @@ describe('the servers', function() {
|
||||||
|
|
||||||
describe("/api/v1/context", function() {
|
describe("/api/v1/context", function() {
|
||||||
it ("should return an object with two keys", function(done) {
|
it ("should return an object with two keys", function(done) {
|
||||||
client.context({
|
client.context(function(err, r) {
|
||||||
host: servers.host,
|
|
||||||
port: servers.port
|
|
||||||
}, function(err, r) {
|
|
||||||
should.not.exist(err);
|
should.not.exist(err);
|
||||||
should.exist(r);
|
should.exist(r);
|
||||||
should.exist(r.session_context);
|
should.exist(r.session_context);
|
||||||
|
|
|
@ -19,7 +19,7 @@ module.exports = function(cb) {
|
||||||
if (!s.started) {
|
if (!s.started) {
|
||||||
// we parse app output to determine when the process has really
|
// we parse app output to determine when the process has really
|
||||||
data.toString().split("\n").forEach(function(line) {
|
data.toString().split("\n").forEach(function(line) {
|
||||||
var m = /^bound to ([a-zA-Z0-9_.]+):([0-9]+)$/.exec(line);
|
var m = /running on http:\/\/([a-zA-Z0-9_.]+):([0-9]+)$/.exec(line);
|
||||||
if (m) {
|
if (m) {
|
||||||
s.started = true;
|
s.started = true;
|
||||||
s.host = m[1];
|
s.host = m[1];
|
||||||
|
@ -28,6 +28,9 @@ module.exports = function(cb) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if (process.env.LOG_TO_CONSOLE) {
|
||||||
|
process.stdout.write(data);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
s.server.stderr.on('data', function (data) {
|
s.server.stderr.on('data', function (data) {
|
||||||
|
|
Загрузка…
Ссылка в новой задаче