Add clients business logic

This commit is contained in:
Johannes Zellner
2015-03-31 10:47:57 +02:00
parent d3049c90a4
commit fc040b6b54
3 changed files with 277 additions and 0 deletions
+53
View File
@@ -0,0 +1,53 @@
'use strict';
var assert = require('assert'),
hat = require('hat'),
debug = require('debug')('box:clients'),
clientdb = require('./clientdb.js'),
DatabaseError = require('./databaseerror.js'),
uuid = require('node-uuid');
exports = module.exports = {
add: add,
get: get,
update: update
};
function add(appIdentifier, redirectURI, scope, callback) {
assert(typeof appIdentifier === 'string');
assert(typeof redirectURI === 'string');
assert(typeof scope === 'string');
assert(typeof callback === 'function');
var id = 'cid-' + uuid.v4();
var clientSecret = hat();
clientdb.add(id, appIdentifier, clientSecret, redirectURI, scope, function (error, result) {
if (error) return callback(error);
callback(null, result);
});
}
function get(id, callback) {
assert(typeof id === 'string');
assert(typeof callback === 'function');
clientdb.get(id, function (error, result) {
if (error && error.reason !== DatabaseError.NOT_FOUND) return callback(error);
callback(null, result);
});
}
function update(id, appIdentifier, clientSecret, redirectURI, scope, callback) {
assert(typeof id === 'string');
assert(typeof appIdentifier === 'string');
assert(typeof clientSecret === 'string');
assert(typeof redirectURI === 'string');
assert(typeof scope === 'string');
assert(typeof callback === 'function');
clientdb.update(id, appIdentifier, clientSecret, redirectURI, scope, function (error, result) {
if (error) return callback(error);
callback(null, result);
});
}
+56
View File
@@ -0,0 +1,56 @@
/* jslint node:true */
'use strict';
var assert = require('assert'),
debug = require('debug')('box:routes/clients'),
clients = require('../clients.js'),
DatabaseError = require('../databaseerror.js'),
HttpError = require('connect-lastmile').HttpError,
HttpSuccess = require('connect-lastmile').HttpSuccess;
exports = module.exports = {
add: add,
get: get,
update: update
};
function add(req, res, next) {
var data = req.body;
if (!data) return next(new HttpError(400, 'Cannot parse data field'));
if (typeof data.appId !== 'string' || !data.appId) return next(new HttpError(400, 'appId is required'));
if (typeof data.redirectURI !== 'string' || !data.redirectURI) return next(new HttpError(400, 'redirectURI is required'));
// prefix as this route only allows external apps for developers
var appId = 'external-' + data.appId;
clients.add(appId, data.redirectURI, 'profile,users', function (error, result) {
if (error) return next(new HttpError(500, error));
next(new HttpSuccess(201, result));
});
}
function get(req, res, next) {
assert(typeof req.param.clientId === 'string');
clients.get(req.param.clientId, function (error, result) {
if (error) return next(new HttpError(500, error));
next(new HttpSuccess(200, result));
});
}
function update(req, res, next) {
assert(typeof req.param.clientId === 'string');
var data = req.body;
if (!data) return next(new HttpError(400, 'Cannot parse data field'));
if (typeof data.appId !== 'string' || !data.appId) return next(new HttpError(400, 'appId is required'));
if (typeof data.redirectURI !== 'string' || !data.redirectURI) return next(new HttpError(400, 'redirectURI is required'));
clients.update(req.param.clientId, data.appId, data.redirectURI, data.scope, function (error, result) {
if (error) return next(new HttpError(500, error));
next(new HttpSuccess(200, result));
});
}
+168
View File
@@ -0,0 +1,168 @@
'use strict';
/* jslint node:true */
/* global it:false */
/* global describe:false */
/* global before:false */
/* global after:false */
var async = require('async'),
config = require('../../../config.js'),
database = require('../../database.js'),
expect = require('expect.js'),
nock = require('nock'),
request = require('superagent'),
server = require('../../server.js');
var SERVER_URL = 'http://localhost:' + config.get('port');
var USERNAME = 'admin', PASSWORD = 'password', EMAIL ='silly@me.com';
var token = null; // authentication token
var server;
function setup(done) {
server.start(done);
}
function cleanup(done) {
database._clear(function (error) {
expect(error).to.not.be.ok();
server.stop(done);
});
}
describe('OAuth Clients API', function () {
describe('add', function () {
before(function (done) {
async.series([
setup,
function (callback) {
var scope1 = nock(config.apiServerOrigin()).get('/api/v1/boxes/' + config.fqdn() + '/setup/verify?setupToken=somesetuptoken').reply(200, {});
var scope2 = nock(config.apiServerOrigin()).post('/api/v1/boxes/' + config.fqdn() + '/setup/done?setupToken=somesetuptoken').reply(201, {});
request.post(SERVER_URL + '/api/v1/cloudron/activate')
.query({ setupToken: 'somesetuptoken' })
.send({ username: USERNAME, password: PASSWORD, email: EMAIL })
.end(function (error, result) {
expect(error).to.not.be.ok();
expect(result).to.be.ok();
expect(scope1.isDone()).to.be.ok();
expect(scope2.isDone()).to.be.ok();
// stash token for further use
token = result.body.token;
callback();
});
},
], done);
});
after(cleanup);
it('fails without token', function (done) {
config.set('developerMode', true);
request.post(SERVER_URL + '/api/v1/oauth/clients')
.send({ appId: 'someApp', redirectURI: 'http://foobar.com' })
.end(function (error, result) {
expect(error).to.not.be.ok();
expect(result.statusCode).to.equal(401);
done();
});
});
it('fails if not in developerMode', function (done) {
config.set('developerMode', false);
request.post(SERVER_URL + '/api/v1/oauth/clients')
.query({ access_token: token })
.send({ appId: 'someApp', redirectURI: 'http://foobar.com' })
.end(function (error, result) {
expect(error).to.not.be.ok();
expect(result.statusCode).to.equal(412);
done();
});
});
it('fails without appId', function (done) {
config.set('developerMode', true);
request.post(SERVER_URL + '/api/v1/oauth/clients')
.query({ access_token: token })
.send({ redirectURI: 'http://foobar.com' })
.end(function (error, result) {
expect(error).to.not.be.ok();
expect(result.statusCode).to.equal(400);
done();
});
});
it('fails with empty appId', function (done) {
config.set('developerMode', true);
request.post(SERVER_URL + '/api/v1/oauth/clients')
.query({ access_token: token })
.send({ appId: '', redirectURI: 'http://foobar.com' })
.end(function (error, result) {
expect(error).to.not.be.ok();
expect(result.statusCode).to.equal(400);
done();
});
});
it('fails without callbackURI', function (done) {
config.set('developerMode', true);
request.post(SERVER_URL + '/api/v1/oauth/clients')
.query({ access_token: token })
.send({ appId: 'someApp' })
.end(function (error, result) {
expect(error).to.not.be.ok();
expect(result.statusCode).to.equal(400);
done();
});
});
it('fails with empty callbackURI', function (done) {
config.set('developerMode', true);
request.post(SERVER_URL + '/api/v1/oauth/clients')
.query({ access_token: token })
.send({ appId: 'someApp', redirectURI: '' })
.end(function (error, result) {
expect(error).to.not.be.ok();
expect(result.statusCode).to.equal(400);
done();
});
});
xit('fails with malformed callbackURI', function (done) {
config.set('developerMode', true);
request.post(SERVER_URL + '/api/v1/oauth/clients')
.query({ access_token: token })
.send({ appId: 'someApp', redirectURI: 'foobar' })
.end(function (error, result) {
expect(error).to.not.be.ok();
expect(result.statusCode).to.equal(400);
done();
});
});
it('succeeds', function (done) {
config.set('developerMode', true);
request.post(SERVER_URL + '/api/v1/oauth/clients')
.query({ access_token: token })
.send({ appId: 'someApp', redirectURI: 'http://foobar.com' })
.end(function (error, result) {
expect(error).to.not.be.ok();
expect(result.statusCode).to.equal(201);
done();
});
});
});
});