diff --git a/migrations/20151015232915-clients-add-type.js b/migrations/20151015232915-clients-add-type.js new file mode 100644 index 000000000..c38362bf7 --- /dev/null +++ b/migrations/20151015232915-clients-add-type.js @@ -0,0 +1,17 @@ +dbm = dbm || require('db-migrate'); +var type = dbm.dataType; +var async = require('async'); + +exports.up = function(db, callback) { + async.series([ + db.runSql.bind(db, 'DELETE FROM clients'), + db.runSql.bind(db, 'ALTER TABLE clients ADD COLUMN type VARCHAR(16) NOT NULL'), + ], callback); +}; + +exports.down = function(db, callback) { + db.runSql('ALTER TABLE clients DROP COLUMN type', function (error) { + if (error) console.error(error); + callback(error); + }); +}; diff --git a/migrations/schema.sql b/migrations/schema.sql index 581e49868..a3885c623 100644 --- a/migrations/schema.sql +++ b/migrations/schema.sql @@ -29,8 +29,9 @@ CREATE TABLE IF NOT EXISTS tokens( PRIMARY KEY(accessToken)); CREATE TABLE IF NOT EXISTS clients( - id VARCHAR(128) NOT NULL UNIQUE, - appId VARCHAR(128) NOT NULL, // this is for the form -appId to allow easy clearing of tokens of a type + id VARCHAR(128) NOT NULL UNIQUE, // prefixed with cid- to identify token easily in auth routes + appId VARCHAR(128) NOT NULL, + type VARCHAR(16) NOT NULL, clientSecret VARCHAR(512) NOT NULL, redirectURI VARCHAR(512) NOT NULL, scope VARCHAR(512) NOT NULL, diff --git a/setup/start.sh b/setup/start.sh index 2f710dbaa..e0898aaf9 100755 --- a/setup/start.sh +++ b/setup/start.sh @@ -159,12 +159,12 @@ EOF echo "Add webadmin oauth cient" ADMIN_SCOPES="root,developer,profile,users,apps,settings" mysql -u root -p${mysql_root_password} \ - -e "REPLACE INTO clients (id, appId, clientSecret, redirectURI, scope) VALUES (\"cid-webadmin\", \"webadmin\", \"secret-webadmin\", \"${admin_origin}\", \"${ADMIN_SCOPES}\")" box + -e "REPLACE INTO clients (id, appId, type, clientSecret, redirectURI, scope) VALUES (\"cid-webadmin\", \"webadmin\", \"admin\", \"secret-webadmin\", \"${admin_origin}\", \"${ADMIN_SCOPES}\")" box echo "Add localhost test oauth client" ADMIN_SCOPES="root,developer,profile,users,apps,settings" mysql -u root -p${mysql_root_password} \ - -e "REPLACE INTO clients (id, appId, clientSecret, redirectURI, scope) VALUES (\"cid-test\", \"test\", \"secret-test\", \"http://127.0.0.1:5000\", \"${ADMIN_SCOPES}\")" box + -e "REPLACE INTO clients (id, appId, type, clientSecret, redirectURI, scope) VALUES (\"cid-test\", \"test\", \"test\", \"secret-test\", \"http://127.0.0.1:5000\", \"${ADMIN_SCOPES}\")" box set_progress "80" "Starting Cloudron" systemctl start cloudron.target diff --git a/src/addons.js b/src/addons.js index c0a3b1b5a..8d260f849 100644 --- a/src/addons.js +++ b/src/addons.js @@ -241,18 +241,17 @@ function setupOauth(app, options, callback) { assert.strictEqual(typeof callback, 'function'); var appId = app.id; - var id = 'cid-addon-oauth-' + uuid.v4(); + var id = 'cid-' + uuid.v4(); var clientSecret = hat(256); var redirectURI = 'https://' + config.appFqdn(app.location); var scope = 'profile'; debugApp(app, 'setupOauth: id:%s clientSecret:%s', id, clientSecret); - // ensure 'addon-oauth-' is in sync with oauth.js - clientdb.delByAppId('addon-oauth-' + appId, function (error) { // remove existing creds + clientdb.delByAppIdAndType(appId, clientdb.TYPE_OAUTH, function (error) { // remove existing creds if (error && error.reason !== DatabaseError.NOT_FOUND) return callback(error); - clientdb.add(id, 'addon-oauth-' + appId, clientSecret, redirectURI, scope, function (error) { + clientdb.add(id, appId, clientdb.TYPE_OAUTH, clientSecret, redirectURI, scope, function (error) { if (error) return callback(error); var env = [ @@ -275,7 +274,7 @@ function teardownOauth(app, options, callback) { debugApp(app, 'teardownOauth'); - clientdb.delByAppId('addon-oauth-' + app.id, function (error) { + clientdb.delByAppIdAndType(app.id, clientdb.TYPE_OAUTH, function (error) { if (error && error.reason !== DatabaseError.NOT_FOUND) console.error(error); appdb.unsetAddonConfig(app.id, 'oauth', callback); @@ -288,16 +287,15 @@ function setupSimpleAuth(app, options, callback) { assert.strictEqual(typeof callback, 'function'); var appId = app.id; - var id = 'cid-addon-simpleauth-' + uuid.v4(); + var id = 'cid-' + uuid.v4(); var scope = 'profile'; debugApp(app, 'setupSimpleAuth: id:%s', id); - // ensure 'addon-simpleauth-' is in sync with oauth.js - clientdb.delByAppId('addon-simpleauth-' + appId, function (error) { // remove existing creds + clientdb.delByAppIdAndType(app.id, clientdb.TYPE_SIMPLE_AUTH, function (error) { // remove existing creds if (error && error.reason !== DatabaseError.NOT_FOUND) return callback(error); - clientdb.add(id, 'addon-simpleauth-' + appId, '', '', scope, function (error) { + clientdb.add(id, appId, clientdb.TYPE_SIMPLE_AUTH, '', '', scope, function (error) { if (error) return callback(error); var env = [ @@ -322,7 +320,7 @@ function teardownSimpleAuth(app, options, callback) { debugApp(app, 'teardownSimpleAuth'); - clientdb.delByAppId('addon-simpleauth-' + app.id, function (error) { + clientdb.delByAppIdAndType(app.id, clientdb.TYPE_SIMPLE_AUTH, function (error) { if (error && error.reason !== DatabaseError.NOT_FOUND) console.error(error); appdb.unsetAddonConfig(app.id, 'simpleauth', callback); diff --git a/src/apptask.js b/src/apptask.js index c96e56816..479664702 100644 --- a/src/apptask.js +++ b/src/apptask.js @@ -311,20 +311,19 @@ function allocateOAuthProxyCredentials(app, callback) { if (!app.oauthProxy) return callback(null); - var appId = 'proxy-' + app.id; - var id = 'cid-proxy-' + uuid.v4(); + var id = 'cid-' + uuid.v4(); var clientSecret = hat(256); var redirectURI = 'https://' + config.appFqdn(app.location); var scope = 'profile'; - clientdb.add(id, appId, clientSecret, redirectURI, scope, callback); + clientdb.add(id, app.id, clientdb.TYPE_PROXY, clientSecret, redirectURI, scope, callback); } function removeOAuthProxyCredentials(app, callback) { assert.strictEqual(typeof app, 'object'); assert.strictEqual(typeof callback, 'function'); - clientdb.delByAppId('proxy-' + app.id, function (error) { + clientdb.delByAppIdAndType(app.id, clientdb.TYPE_PROXY, function (error) { if (error && error.reason !== DatabaseError.NOT_FOUND) { debugApp(app, 'Error removing OAuth client id', error); return callback(error); diff --git a/src/clientdb.js b/src/clientdb.js index 2859581b2..5e31ff6a4 100644 --- a/src/clientdb.js +++ b/src/clientdb.js @@ -9,17 +9,27 @@ exports = module.exports = { add: add, del: del, getByAppId: getByAppId, - delByAppId: delByAppId, + getByAppIdAndType: getByAppIdAndType, - _clear: clear + delByAppId: delByAppId, + delByAppIdAndType: delByAppIdAndType, + + _clear: clear, + + TYPE_EXTERNAL: 'external', + TYPE_OAUTH: 'addon-oauth', + TYPE_SIMPLE_AUTH: 'addon-simpleauth', + TYPE_PROXY: 'addon-proxy', + TYPE_TEST: 'test', + TYPE_ADMIN: 'admin' }; var assert = require('assert'), database = require('./database.js'), DatabaseError = require('./databaseerror.js'); -var CLIENTS_FIELDS = [ 'id', 'appId', 'clientSecret', 'redirectURI', 'scope' ].join(','); -var CLIENTS_FIELDS_PREFIXED = [ 'clients.id', 'clients.appId', 'clients.clientSecret', 'clients.redirectURI', 'clients.scope' ].join(','); +var CLIENTS_FIELDS = [ 'id', 'appId', 'type', 'clientSecret', 'redirectURI', 'scope' ].join(','); +var CLIENTS_FIELDS_PREFIXED = [ 'clients.id', 'clients.appId', 'clients.type', 'clients.clientSecret', 'clients.redirectURI', 'clients.scope' ].join(','); function get(id, callback) { assert.strictEqual(typeof id, 'string'); @@ -66,17 +76,31 @@ function getByAppId(appId, callback) { }); } -function add(id, appId, clientSecret, redirectURI, scope, callback) { +function getByAppIdAndType(appId, type, callback) { + assert.strictEqual(typeof appId, 'string'); + assert.strictEqual(typeof type, 'string'); + assert.strictEqual(typeof callback, 'function'); + + database.query('SELECT ' + CLIENTS_FIELDS + ' FROM clients WHERE appId = ? AND type = ? LIMIT 1', [ appId, type ], function (error, result) { + if (error) return callback(new DatabaseError(DatabaseError.INTERNAL_ERROR, error)); + if (result.length === 0) return callback(new DatabaseError(DatabaseError.NOT_FOUND)); + + return callback(null, result[0]); + }); +} + +function add(id, appId, type, clientSecret, redirectURI, scope, callback) { assert.strictEqual(typeof id, 'string'); assert.strictEqual(typeof appId, 'string'); + assert.strictEqual(typeof type, 'string'); assert.strictEqual(typeof clientSecret, 'string'); assert.strictEqual(typeof redirectURI, 'string'); assert.strictEqual(typeof scope, 'string'); assert.strictEqual(typeof callback, 'function'); - var data = [ id, appId, clientSecret, redirectURI, scope ]; + var data = [ id, appId, type, clientSecret, redirectURI, scope ]; - database.query('INSERT INTO clients (id, appId, clientSecret, redirectURI, scope) VALUES (?, ?, ?, ?, ?)', data, function (error, result) { + database.query('INSERT INTO clients (id, appId, type, clientSecret, redirectURI, scope) VALUES (?, ?, ?, ?, ?, ?)', data, function (error, result) { if (error && error.code === 'ER_DUP_ENTRY') return callback(new DatabaseError(DatabaseError.ALREADY_EXISTS)); if (error || result.affectedRows === 0) return callback(new DatabaseError(DatabaseError.INTERNAL_ERROR, error)); @@ -108,6 +132,19 @@ function delByAppId(appId, callback) { }); } +function delByAppIdAndType(appId, type, callback) { + assert.strictEqual(typeof appId, 'string'); + assert.strictEqual(typeof type, 'string'); + assert.strictEqual(typeof callback, 'function'); + + database.query('DELETE FROM clients WHERE appId=? AND type=?', [ appId, type ], function (error, result) { + if (error) return callback(new DatabaseError(DatabaseError.INTERNAL_ERROR, error)); + if (result.affectedRows !== 1) return callback(new DatabaseError(DatabaseError.NOT_FOUND)); + + return callback(null); + }); +} + function clear(callback) { assert.strictEqual(typeof callback, 'function'); diff --git a/src/clients.js b/src/clients.js index da7eeb8d3..978dc0f0f 100644 --- a/src/clients.js +++ b/src/clients.js @@ -54,8 +54,9 @@ function validateScope(scope) { return null; } -function add(appId, redirectURI, scope, callback) { +function add(appId, type, redirectURI, scope, callback) { assert.strictEqual(typeof appId, 'string'); + assert.strictEqual(typeof type, 'string'); assert.strictEqual(typeof redirectURI, 'string'); assert.strictEqual(typeof scope, 'string'); assert.strictEqual(typeof callback, 'function'); @@ -66,12 +67,13 @@ function add(appId, redirectURI, scope, callback) { var id = 'cid-' + uuid.v4(); var clientSecret = hat(256); - clientdb.add(id, appId, clientSecret, redirectURI, scope, function (error) { + clientdb.add(id, appId, type, clientSecret, redirectURI, scope, function (error) { if (error) return callback(error); var client = { id: id, appId: appId, + type: type, clientSecret: clientSecret, redirectURI: redirectURI, scope: scope diff --git a/src/cloudron.js b/src/cloudron.js index 496e8c09c..ce409ec58 100644 --- a/src/cloudron.js +++ b/src/cloudron.js @@ -174,7 +174,7 @@ function activate(username, password, email, name, ip, callback) { if (error && error.reason === UserError.BAD_EMAIL) return callback(new CloudronError(CloudronError.BAD_EMAIL)); if (error) return callback(new CloudronError(CloudronError.INTERNAL_ERROR, error)); - clientdb.getByAppId('webadmin', function (error, result) { + clientdb.getByAppIdAndType('webadmin', clientdb.TYPE_ADMIN, function (error, result) { if (error) return callback(new CloudronError(CloudronError.INTERNAL_ERROR, error)); // Also generate a token so the admin creation can also act as a login diff --git a/src/oauthproxy.js b/src/oauthproxy.js index 652fcda6e..d398f0352 100644 --- a/src/oauthproxy.js +++ b/src/oauthproxy.js @@ -121,7 +121,7 @@ function authenticate(req, res, next) { return res.send(500, 'Unknown app.'); } - clientdb.getByAppId('proxy-' + result.id, function (error, result) { + clientdb.getByAppId(result.id, clientdb.TYPE_PROXY, function (error, result) { if (error) { console.error('Unkonwn OAuth client.', error); return res.send(500, 'Unknown OAuth client.'); diff --git a/src/routes/clients.js b/src/routes/clients.js index f07f9b915..4a0efc686 100644 --- a/src/routes/clients.js +++ b/src/routes/clients.js @@ -12,12 +12,13 @@ exports = module.exports = { }; var assert = require('assert'), - validUrl = require('valid-url'), + clientdb = require('../clientdb.js'), clients = require('../clients.js'), ClientsError = clients.ClientsError, DatabaseError = require('../databaseerror.js'), HttpError = require('connect-lastmile').HttpError, - HttpSuccess = require('connect-lastmile').HttpSuccess; + HttpSuccess = require('connect-lastmile').HttpSuccess, + validUrl = require('valid-url'); function add(req, res, next) { var data = req.body; @@ -28,10 +29,7 @@ function add(req, res, next) { if (typeof data.scope !== 'string' || !data.scope) return next(new HttpError(400, 'scope is required')); if (!validUrl.isWebUri(data.redirectURI)) return next(new HttpError(400, 'redirectURI must be a valid uri')); - // prefix as this route only allows external apps for developers - var appId = 'external-' + data.appId; - - clients.add(appId, data.redirectURI, data.scope, function (error, result) { + clients.add(data.appId, clientdb.TYPE_EXTERNAL, data.redirectURI, data.scope, function (error, result) { if (error && error.reason === ClientsError.INVALID_SCOPE) return next(new HttpError(400, 'Invalid scope')); if (error) return next(new HttpError(500, error)); next(new HttpSuccess(201, result)); diff --git a/src/routes/oauth2.js b/src/routes/oauth2.js index 78fd0223e..12d9bfe6e 100644 --- a/src/routes/oauth2.js +++ b/src/routes/oauth2.js @@ -205,21 +205,14 @@ function loginForm(req, res) { clientdb.get(u.query.client_id, function (error, result) { if (error) return sendError(req, res, 'Unknown OAuth client'); - // Handle our different types of oauth clients - var appId = result.appId; - if (appId === constants.ADMIN_CLIENT_ID) { - return render(constants.ADMIN_NAME, '/api/v1/cloudron/avatar'); - } else if (appId === constants.TEST_CLIENT_ID) { - return render(constants.TEST_NAME, '/api/v1/cloudron/avatar'); - } else if (appId.indexOf('external-') === 0) { - return render('External Application', '/api/v1/cloudron/avatar'); - } else if (appId.indexOf('addon-oauth-') === 0) { - appId = appId.slice('addon-oauth-'.length); - } else if (appId.indexOf('proxy-') === 0) { - appId = appId.slice('proxy-'.length); + switch (result.type) { + case clientdb.TYPE_ADMIN: return render(constants.ADMIN_NAME, '/api/v1/cloudron/avatar'); + case clientdb.TYPE_TEST: return render(constants.TEST_NAME, '/api/v1/cloudron/avatar'); + case clientdb.TYPE_EXTERNAL: return render('External Application', '/api/v1/cloudron/avatar'); + default: break; } - appdb.get(appId, function (error, result) { + appdb.get(result.appId, function (error, result) { if (error) return sendErrorPageOrRedirect(req, res, 'Unknown Application for those OAuth credentials'); var applicationName = result.location || config.fqdn(); diff --git a/src/routes/test/apps-test.js b/src/routes/test/apps-test.js index ecbd109b8..47b179e75 100644 --- a/src/routes/test/apps-test.js +++ b/src/routes/test/apps-test.js @@ -634,9 +634,9 @@ describe('App installation', function () { expect(data.Config.Env).to.contain('WEBADMIN_ORIGIN=' + config.adminOrigin()); expect(data.Config.Env).to.contain('API_ORIGIN=' + config.adminOrigin()); expect(data.Config.Env).to.contain('CLOUDRON=1'); - clientdb.getByAppId('addon-oauth-' + appResult.id, function (error, client) { + clientdb.getByAppIdAndType(appResult.id, clientdb.TYPE_OAUTH, function (error, client) { expect(error).to.not.be.ok(); - expect(client.id.length).to.be(52); // cid-addon-oauth- + 32 hex chars (128 bits) + 4 hyphens + expect(client.id.length).to.be(40); // cid- + 32 hex chars (128 bits) + 4 hyphens expect(client.clientSecret.length).to.be(64); // 32 hex chars (256 bits) expect(data.Config.Env).to.contain('OAUTH_CLIENT_ID=' + client.id); expect(data.Config.Env).to.contain('OAUTH_CLIENT_SECRET=' + client.clientSecret); diff --git a/src/routes/test/oauth2-test.js b/src/routes/test/oauth2-test.js index 91c86365d..c4acd1880 100644 --- a/src/routes/test/oauth2-test.js +++ b/src/routes/test/oauth2-test.js @@ -182,6 +182,7 @@ describe('OAuth2', function () { var CLIENT_0 = { id: 'cid-client0', appId: 'appid-app0', + type: clientdb.TYPE_OAUTH, clientSecret: 'secret0', redirectURI: 'http://redirect0', scope: 'profile' @@ -190,7 +191,8 @@ describe('OAuth2', function () { // unknown app through addon var CLIENT_1 = { id: 'cid-client1', - appId: 'addon-oauth-appid-app1', + appId: 'appid-app1', + type: clientdb.TYPE_OAUTH, clientSecret: 'secret1', redirectURI: 'http://redirect1', scope: 'profile' @@ -200,6 +202,7 @@ describe('OAuth2', function () { var CLIENT_2 = { id: 'cid-client2', appId: APP_0.id, + type: clientdb.TYPE_OAUTH, clientSecret: 'secret2', redirectURI: 'http://redirect2', scope: 'profile' @@ -208,7 +211,8 @@ describe('OAuth2', function () { // known app through addon var CLIENT_3 = { id: 'cid-client3', - appId: 'addon-oauth-' + APP_0.id, + appId: APP_0.id, + type: clientdb.TYPE_OAUTH, clientSecret: 'secret3', redirectURI: 'http://redirect1', scope: 'profile' @@ -217,7 +221,8 @@ describe('OAuth2', function () { // unknown app through proxy var CLIENT_4 = { id: 'cid-client4', - appId: 'proxy-appid-app4', + appId: 'appid-app4', + type: clientdb.TYPE_PROXY, clientSecret: 'secret4', redirectURI: 'http://redirect4', scope: 'profile' @@ -226,7 +231,8 @@ describe('OAuth2', function () { // known app through proxy var CLIENT_5 = { id: 'cid-client5', - appId: 'proxy-' + APP_0.id, + appId: APP_0.id, + type: clientdb.TYPE_PROXY, clientSecret: 'secret5', redirectURI: 'http://redirect5', scope: 'profile' @@ -236,6 +242,7 @@ describe('OAuth2', function () { var CLIENT_6 = { id: 'cid-client6', appId: APP_1.id, + type: clientdb.TYPE_SIMPLE_AUTH, clientSecret: 'secret6', redirectURI: 'http://redirect6', scope: 'profile' @@ -245,6 +252,7 @@ describe('OAuth2', function () { var CLIENT_7 = { id: 'cid-client7', appId: APP_2.id, + type: clientdb.TYPE_SIMPLE_AUTH, clientSecret: 'secret7', redirectURI: 'http://redirect7', scope: 'profile' @@ -260,14 +268,14 @@ describe('OAuth2', function () { async.series([ server.start, database._clear, - clientdb.add.bind(null, CLIENT_0.id, CLIENT_0.appId, CLIENT_0.clientSecret, CLIENT_0.redirectURI, CLIENT_0.scope), - clientdb.add.bind(null, CLIENT_1.id, CLIENT_1.appId, CLIENT_1.clientSecret, CLIENT_1.redirectURI, CLIENT_1.scope), - clientdb.add.bind(null, CLIENT_2.id, CLIENT_2.appId, CLIENT_2.clientSecret, CLIENT_2.redirectURI, CLIENT_2.scope), - clientdb.add.bind(null, CLIENT_3.id, CLIENT_3.appId, CLIENT_3.clientSecret, CLIENT_3.redirectURI, CLIENT_3.scope), - clientdb.add.bind(null, CLIENT_4.id, CLIENT_4.appId, CLIENT_4.clientSecret, CLIENT_4.redirectURI, CLIENT_4.scope), - clientdb.add.bind(null, CLIENT_5.id, CLIENT_5.appId, CLIENT_5.clientSecret, CLIENT_5.redirectURI, CLIENT_5.scope), - clientdb.add.bind(null, CLIENT_6.id, CLIENT_6.appId, CLIENT_6.clientSecret, CLIENT_6.redirectURI, CLIENT_6.scope), - clientdb.add.bind(null, CLIENT_7.id, CLIENT_7.appId, CLIENT_7.clientSecret, CLIENT_7.redirectURI, CLIENT_7.scope), + clientdb.add.bind(null, CLIENT_0.id, CLIENT_0.appId, CLIENT_0.type, CLIENT_0.clientSecret, CLIENT_0.redirectURI, CLIENT_0.scope), + clientdb.add.bind(null, CLIENT_1.id, CLIENT_1.appId, CLIENT_1.type, CLIENT_1.clientSecret, CLIENT_1.redirectURI, CLIENT_1.scope), + clientdb.add.bind(null, CLIENT_2.id, CLIENT_2.appId, CLIENT_2.type, CLIENT_2.clientSecret, CLIENT_2.redirectURI, CLIENT_2.scope), + clientdb.add.bind(null, CLIENT_3.id, CLIENT_3.appId, CLIENT_3.type, CLIENT_3.clientSecret, CLIENT_3.redirectURI, CLIENT_3.scope), + clientdb.add.bind(null, CLIENT_4.id, CLIENT_4.appId, CLIENT_4.type, CLIENT_4.clientSecret, CLIENT_4.redirectURI, CLIENT_4.scope), + clientdb.add.bind(null, CLIENT_5.id, CLIENT_5.appId, CLIENT_5.type, CLIENT_5.clientSecret, CLIENT_5.redirectURI, CLIENT_5.scope), + clientdb.add.bind(null, CLIENT_6.id, CLIENT_6.appId, CLIENT_6.type, CLIENT_6.clientSecret, CLIENT_6.redirectURI, CLIENT_6.scope), + clientdb.add.bind(null, CLIENT_7.id, CLIENT_7.appId, CLIENT_7.type, CLIENT_7.clientSecret, CLIENT_7.redirectURI, CLIENT_7.scope), appdb.add.bind(null, APP_0.id, APP_0.appStoreId, APP_0.manifest, APP_0.location, APP_0.portBindings, APP_0.accessRestriction, APP_0.oauthProxy), appdb.add.bind(null, APP_1.id, APP_1.appStoreId, APP_1.manifest, APP_1.location, APP_1.portBindings, APP_1.accessRestriction, APP_1.oauthProxy), appdb.add.bind(null, APP_2.id, APP_2.appStoreId, APP_2.manifest, APP_2.location, APP_2.portBindings, APP_2.accessRestriction, APP_2.oauthProxy), diff --git a/src/routes/test/simpleauth-test.js b/src/routes/test/simpleauth-test.js index 3e615b3ab..6460cf70a 100644 --- a/src/routes/test/simpleauth-test.js +++ b/src/routes/test/simpleauth-test.js @@ -56,6 +56,7 @@ describe('SimpleAuth API', function () { var CLIENT_0 = { id: 'someclientid', appId: 'someappid', + type: clientdb.TYPE_SIMPLE_AUTH, clientSecret: 'someclientsecret', redirectURI: '', scope: 'user,profile' @@ -64,6 +65,7 @@ describe('SimpleAuth API', function () { var CLIENT_1 = { id: 'someclientid1', appId: APP_0.id, + type: clientdb.TYPE_SIMPLE_AUTH, clientSecret: 'someclientsecret1', redirectURI: '', scope: 'user,profile' @@ -72,6 +74,7 @@ describe('SimpleAuth API', function () { var CLIENT_2 = { id: 'someclientid2', appId: APP_1.id, + type: clientdb.TYPE_SIMPLE_AUTH, clientSecret: 'someclientsecret2', redirectURI: '', scope: 'user,profile' @@ -80,6 +83,7 @@ describe('SimpleAuth API', function () { var CLIENT_3 = { id: 'someclientid3', appId: APP_2.id, + type: clientdb.TYPE_SIMPLE_AUTH, clientSecret: 'someclientsecret3', redirectURI: '', scope: 'user,profile' @@ -110,10 +114,10 @@ describe('SimpleAuth API', function () { }); }, - clientdb.add.bind(null, CLIENT_0.id, CLIENT_0.appId, CLIENT_0.clientSecret, CLIENT_0.redirectURI, CLIENT_0.scope), - clientdb.add.bind(null, CLIENT_1.id, CLIENT_1.appId, CLIENT_1.clientSecret, CLIENT_1.redirectURI, CLIENT_1.scope), - clientdb.add.bind(null, CLIENT_2.id, CLIENT_2.appId, CLIENT_2.clientSecret, CLIENT_2.redirectURI, CLIENT_2.scope), - clientdb.add.bind(null, CLIENT_3.id, CLIENT_3.appId, CLIENT_3.clientSecret, CLIENT_3.redirectURI, CLIENT_3.scope), + clientdb.add.bind(null, CLIENT_0.id, CLIENT_0.appId, CLIENT_0.type, CLIENT_0.clientSecret, CLIENT_0.redirectURI, CLIENT_0.scope), + clientdb.add.bind(null, CLIENT_1.id, CLIENT_1.appId, CLIENT_1.type, CLIENT_1.clientSecret, CLIENT_1.redirectURI, CLIENT_1.scope), + clientdb.add.bind(null, CLIENT_2.id, CLIENT_2.appId, CLIENT_2.type, CLIENT_2.clientSecret, CLIENT_2.redirectURI, CLIENT_2.scope), + clientdb.add.bind(null, CLIENT_3.id, CLIENT_3.appId, CLIENT_3.type, CLIENT_3.clientSecret, CLIENT_3.redirectURI, CLIENT_3.scope), appdb.add.bind(null, APP_0.id, APP_0.appStoreId, APP_0.manifest, APP_0.location, APP_0.portBindings, APP_0.accessRestriction, APP_0.oauthProxy), appdb.add.bind(null, APP_1.id, APP_1.appStoreId, APP_1.manifest, APP_1.location, APP_1.portBindings, APP_1.accessRestriction, APP_1.oauthProxy), appdb.add.bind(null, APP_2.id, APP_2.appStoreId, APP_2.manifest, APP_2.location, APP_2.portBindings, APP_2.accessRestriction, APP_2.oauthProxy) diff --git a/src/test/database-test.js b/src/test/database-test.js index f5a91a46e..c4c0e7f28 100644 --- a/src/test/database-test.js +++ b/src/test/database-test.js @@ -790,6 +790,7 @@ describe('database', function () { var CLIENT_0 = { id: 'cid-0', appId: 'someappid_0', + type: clientdb.TYPE_OAUTH, clientSecret: 'secret-0', redirectURI: 'http://foo.bar', scope: '*' @@ -798,23 +799,17 @@ describe('database', function () { var CLIENT_1 = { id: 'cid-1', appId: 'someappid_1', + type: clientdb.TYPE_OAUTH, clientSecret: 'secret-', redirectURI: 'http://foo.bar', scope: '*' }; - var CLIENT_2 = { - id: 'cid-2', - appId: 'someappid_2', - clientSecret: 'secret-2', - redirectURI: 'http://foo.bar.baz', - scope: 'profile' - }; it('add succeeds', function (done) { - clientdb.add(CLIENT_0.id, CLIENT_0.appId, CLIENT_0.clientSecret, CLIENT_0.redirectURI, CLIENT_0.scope, function (error) { + clientdb.add(CLIENT_0.id, CLIENT_0.appId, CLIENT_0.type, CLIENT_0.clientSecret, CLIENT_0.redirectURI, CLIENT_0.scope, function (error) { expect(error).to.be(null); - clientdb.add(CLIENT_1.id, CLIENT_1.appId, CLIENT_1.clientSecret, CLIENT_1.redirectURI, CLIENT_1.scope, function (error) { + clientdb.add(CLIENT_1.id, CLIENT_1.appId, CLIENT_0.type, CLIENT_1.clientSecret, CLIENT_1.redirectURI, CLIENT_1.scope, function (error) { expect(error).to.be(null); done(); }); @@ -822,7 +817,7 @@ describe('database', function () { }); it('add same client id fails', function (done) { - clientdb.add(CLIENT_0.id, CLIENT_0.appId, CLIENT_0.clientSecret, CLIENT_0.redirectURI, CLIENT_0.scope, function (error) { + clientdb.add(CLIENT_0.id, CLIENT_0.appId, CLIENT_0.type, CLIENT_0.clientSecret, CLIENT_0.redirectURI, CLIENT_0.scope, function (error) { expect(error).to.be.a(DatabaseError); expect(error.reason).to.equal(DatabaseError.ALREADY_EXISTS); done(); @@ -845,6 +840,14 @@ describe('database', function () { }); }); + it('getByAppIdAndType succeeds', function (done) { + clientdb.getByAppIdAndType(CLIENT_0.appId, CLIENT_0.type, function (error, result) { + expect(error).to.be(null); + expect(result).to.eql(CLIENT_0); + done(); + }); + }); + it('getByAppId fails for unknown client id', function (done) { clientdb.getByAppId(CLIENT_0.appId + CLIENT_0.appId, function (error, result) { expect(error).to.be.a(DatabaseError); @@ -865,6 +868,19 @@ describe('database', function () { }); }); + it('delByAppIdAndType succeeds', function (done) { + clientdb.delByAppIdAndType(CLIENT_1.appId, CLIENT_1.type, function (error) { + expect(error).to.be(null); + + clientdb.getByAppIdAndType(CLIENT_1.appId, CLIENT_1.type, function (error, result) { + expect(error).to.be.a(DatabaseError); + expect(error.reason).to.equal(DatabaseError.NOT_FOUND); + expect(result).to.not.be.ok(); + done(); + }); + }); + }); + it('delByAppId succeeds', function (done) { clientdb.delByAppId(CLIENT_0.appId, function (error) { expect(error).to.be(null); diff --git a/src/test/setupTest b/src/test/setupTest index af5dcddaf..9589190a1 100755 --- a/src/test/setupTest +++ b/src/test/setupTest @@ -16,5 +16,5 @@ mkdir -p data/appdata data/box/appicons data/mail data/nginx/cert data/nginx/app webadmin_scopes="root,profile,users,apps,settings" webadmin_origin="https://${ADMIN_LOCATION}-localhost" mysql --user=root --password="" \ - -e "REPLACE INTO clients (id, appId, clientSecret, redirectURI, scope) VALUES (\"cid-webadmin\", \"webadmin\", \"secret-webadmin\", \"${webadmin_origin}\", \"${webadmin_scopes}\")" boxtest + -e "REPLACE INTO clients (id, appId, type, clientSecret, redirectURI, scope) VALUES (\"cid-webadmin\", \"webadmin\", \"admin\", \"secret-webadmin\", \"${webadmin_origin}\", \"${webadmin_scopes}\")" boxtest diff --git a/src/user.js b/src/user.js index 47ac268ee..ae345294d 100644 --- a/src/user.js +++ b/src/user.js @@ -340,7 +340,7 @@ function setPassword(userId, newPassword, callback) { if (error) return callback(new UserError(UserError.INTERNAL_ERROR, error)); // Also generate a token so the new user can get logged in immediately - clientdb.getByAppId('webadmin', function (error, result) { + clientdb.getByAppIdAndType('webadmin', clientdb.TYPE_ADMIN, function (error, result) { if (error) return callback(new UserError(UserError.INTERNAL_ERROR, error)); var token = tokendb.generateToken();