diff --git a/src/apps.js b/src/apps.js index cc79bd466..d4cefa466 100644 --- a/src/apps.js +++ b/src/apps.js @@ -45,6 +45,7 @@ exports = module.exports = { var addons = require('./addons.js'), appdb = require('./appdb.js'), + appstore = require('./appstore.js'), assert = require('assert'), async = require('async'), backups = require('./backups.js'), @@ -64,7 +65,6 @@ var addons = require('./addons.js'), paths = require('./paths.js'), safe = require('safetydance'), semver = require('semver'), - settings = require('./settings.js'), spawn = require('child_process').spawn, split = require('split'), superagent = require('superagent'), @@ -366,99 +366,6 @@ function getAllByUser(user, callback) { }); } -function purchase(appId, appstoreId, callback) { - assert.strictEqual(typeof appId, 'string'); - assert.strictEqual(typeof appstoreId, 'string'); - assert.strictEqual(typeof callback, 'function'); - - if (appstoreId === '') return callback(null); - - function purchaseWithAppstoreConfig(appstoreConfig) { - assert.strictEqual(typeof appstoreConfig.userId, 'string'); - assert.strictEqual(typeof appstoreConfig.cloudronId, 'string'); - assert.strictEqual(typeof appstoreConfig.token, 'string'); - - var url = config.apiServerOrigin() + '/api/v1/users/' + appstoreConfig.userId + '/cloudrons/' + appstoreConfig.cloudronId + '/apps/' + appId; - var data = { appstoreId: appstoreId }; - - superagent.post(url).send(data).query({ accessToken: appstoreConfig.token }).timeout(30 * 1000).end(function (error, result) { - if (error && !error.response) return callback(new AppsError(AppsError.EXTERNAL_ERROR, error)); - if (result.statusCode === 404) return callback(new AppsError(AppsError.NOT_FOUND)); - if (result.statusCode === 403 || result.statusCode === 401) return callback(new AppsError(AppsError.BILLING_REQUIRED)); - if (result.statusCode !== 201 && result.statusCode !== 200) return callback(new AppsError(AppsError.EXTERNAL_ERROR, util.format('App purchase failed. %s %j', result.status, result.body))); - - callback(null); - }); - } - - // Caas Cloudrons do not store appstore credentials in their local database - if (config.provider() === 'caas') { - var url = config.apiServerOrigin() + '/api/v1/exchangeBoxTokenWithUserToken'; - superagent.post(url).query({ token: config.token() }).timeout(30 * 1000).end(function (error, result) { - if (error && !error.response) return callback(new AppsError(AppsError.EXTERNAL_ERROR, error)); - if (result.statusCode !== 201) return callback(new AppsError(AppsError.EXTERNAL_ERROR, util.format('App purchase failed. %s %j', result.status, result.body))); - - purchaseWithAppstoreConfig(result.body); - }); - } else { - settings.getAppstoreConfig(function (error, result) { - if (error) return callback(new AppsError(AppsError.INTERNAL_ERROR, error)); - if (!result.token) return callback(new AppsError(AppsError.BILLING_REQUIRED)); - - purchaseWithAppstoreConfig(result); - }); - } -} - -function unpurchase(appId, appstoreId, callback) { - assert.strictEqual(typeof appId, 'string'); - assert.strictEqual(typeof appstoreId, 'string'); - assert.strictEqual(typeof callback, 'function'); - - if (appstoreId === '') return callback(null); - - function unpurchaseWithAppstoreConfig(appstoreConfig) { - assert.strictEqual(typeof appstoreConfig.userId, 'string'); - assert.strictEqual(typeof appstoreConfig.cloudronId, 'string'); - assert.strictEqual(typeof appstoreConfig.token, 'string'); - - var url = config.apiServerOrigin() + '/api/v1/users/' + appstoreConfig.userId + '/cloudrons/' + appstoreConfig.cloudronId + '/apps/' + appId; - - superagent.get(url).query({ accessToken: appstoreConfig.token }).timeout(30 * 1000).end(function (error, result) { - if (error && !error.response) return callback(new AppsError(AppsError.EXTERNAL_ERROR, error)); - if (result.statusCode === 403 || result.statusCode === 401) return callback(new AppsError(AppsError.BILLING_REQUIRED)); - if (result.statusCode === 404) return callback(null); // was never purchased - if (result.statusCode !== 201 && result.statusCode !== 200) return callback(new AppsError(AppsError.EXTERNAL_ERROR, util.format('App purchase failed. %s %j', result.status, result.body))); - - superagent.del(url).query({ accessToken: appstoreConfig.token }).timeout(30 * 1000).end(function (error, result) { - if (error && !error.response) return callback(new AppsError(AppsError.EXTERNAL_ERROR, error)); - if (result.statusCode === 403 || result.statusCode === 401) return callback(new AppsError(AppsError.BILLING_REQUIRED)); - if (result.statusCode !== 204) return callback(new AppsError(AppsError.EXTERNAL_ERROR, util.format('App unpurchase failed. %s %j', result.status, result.body))); - - callback(null); - }); - }); - } - - // Caas Cloudrons do not store appstore credentials in their local database - if (config.provider() === 'caas') { - var url = config.apiServerOrigin() + '/api/v1/exchangeBoxTokenWithUserToken'; - superagent.post(url).query({ token: config.token() }).timeout(30 * 1000).end(function (error, result) { - if (error && !error.response) return callback(new AppsError(AppsError.EXTERNAL_ERROR, error)); - if (result.statusCode !== 201) return callback(new AppsError(AppsError.EXTERNAL_ERROR, util.format('App unpurchase failed. %s %j', result.status, result.body))); - - unpurchaseWithAppstoreConfig(result.body); - }); - } else { - settings.getAppstoreConfig(function (error, result) { - if (error) return callback(new AppsError(AppsError.INTERNAL_ERROR, error)); - if (!result.token) return callback(new AppsError(AppsError.BILLING_REQUIRED)); - - unpurchaseWithAppstoreConfig(result); - }); - } -} - function downloadManifest(appStoreId, manifest, callback) { if (!appStoreId && !manifest) return callback(new AppsError(AppsError.BAD_FIELD, 'Neither manifest nor appStoreId provided')); @@ -547,7 +454,7 @@ function install(data, auditSource, callback) { debug('Will install app with id : ' + appId); - purchase(appId, appStoreId, function (error) { + appstore.purchase(appId, appStoreId, function (error) { if (error) return callback(error); var data = { @@ -888,7 +795,7 @@ function clone(appId, data, auditSource, callback) { var newAppId = uuid.v4(), appStoreId = app.appStoreId, manifest = restoreConfig.manifest; - purchase(newAppId, appStoreId, function (error) { + appstore.purchase(newAppId, appStoreId, function (error) { if (error) return callback(error); var data = { @@ -926,7 +833,7 @@ function uninstall(appId, auditSource, callback) { get(appId, function (error, result) { if (error) return callback(error); - unpurchase(appId, result.appStoreId, function (error) { + appstore.unpurchase(appId, result.appStoreId, function (error) { if (error) return callback(error); taskmanager.stopAppTask(appId, function () { diff --git a/src/appstore.js b/src/appstore.js new file mode 100644 index 000000000..9b222ba05 --- /dev/null +++ b/src/appstore.js @@ -0,0 +1,106 @@ +'use strict'; + +exports = module.exports = { + purchase: purchase, + unpurchase: unpurchase +}; + +var AppsError = require('./apps.js').AppsError, + assert = require('assert'), + config = require('./config.js'), + settings = require('./settings.js'), + superagent = require('superagent'), + util = require('util'); + +function purchase(appId, appstoreId, callback) { + assert.strictEqual(typeof appId, 'string'); + assert.strictEqual(typeof appstoreId, 'string'); + assert.strictEqual(typeof callback, 'function'); + + if (appstoreId === '') return callback(null); + + function purchaseWithAppstoreConfig(appstoreConfig) { + assert.strictEqual(typeof appstoreConfig.userId, 'string'); + assert.strictEqual(typeof appstoreConfig.cloudronId, 'string'); + assert.strictEqual(typeof appstoreConfig.token, 'string'); + + var url = config.apiServerOrigin() + '/api/v1/users/' + appstoreConfig.userId + '/cloudrons/' + appstoreConfig.cloudronId + '/apps/' + appId; + var data = { appstoreId: appstoreId }; + + superagent.post(url).send(data).query({ accessToken: appstoreConfig.token }).timeout(30 * 1000).end(function (error, result) { + if (error && !error.response) return callback(new AppsError(AppsError.EXTERNAL_ERROR, error)); + if (result.statusCode === 404) return callback(new AppsError(AppsError.NOT_FOUND)); + if (result.statusCode === 403 || result.statusCode === 401) return callback(new AppsError(AppsError.BILLING_REQUIRED)); + if (result.statusCode !== 201 && result.statusCode !== 200) return callback(new AppsError(AppsError.EXTERNAL_ERROR, util.format('App purchase failed. %s %j', result.status, result.body))); + + callback(null); + }); + } + + // Caas Cloudrons do not store appstore credentials in their local database + if (config.provider() === 'caas') { + var url = config.apiServerOrigin() + '/api/v1/exchangeBoxTokenWithUserToken'; + superagent.post(url).query({ token: config.token() }).timeout(30 * 1000).end(function (error, result) { + if (error && !error.response) return callback(new AppsError(AppsError.EXTERNAL_ERROR, error)); + if (result.statusCode !== 201) return callback(new AppsError(AppsError.EXTERNAL_ERROR, util.format('App purchase failed. %s %j', result.status, result.body))); + + purchaseWithAppstoreConfig(result.body); + }); + } else { + settings.getAppstoreConfig(function (error, result) { + if (error) return callback(new AppsError(AppsError.INTERNAL_ERROR, error)); + if (!result.token) return callback(new AppsError(AppsError.BILLING_REQUIRED)); + + purchaseWithAppstoreConfig(result); + }); + } +} + +function unpurchase(appId, appstoreId, callback) { + assert.strictEqual(typeof appId, 'string'); + assert.strictEqual(typeof appstoreId, 'string'); + assert.strictEqual(typeof callback, 'function'); + + if (appstoreId === '') return callback(null); + + function unpurchaseWithAppstoreConfig(appstoreConfig) { + assert.strictEqual(typeof appstoreConfig.userId, 'string'); + assert.strictEqual(typeof appstoreConfig.cloudronId, 'string'); + assert.strictEqual(typeof appstoreConfig.token, 'string'); + + var url = config.apiServerOrigin() + '/api/v1/users/' + appstoreConfig.userId + '/cloudrons/' + appstoreConfig.cloudronId + '/apps/' + appId; + + superagent.get(url).query({ accessToken: appstoreConfig.token }).timeout(30 * 1000).end(function (error, result) { + if (error && !error.response) return callback(new AppsError(AppsError.EXTERNAL_ERROR, error)); + if (result.statusCode === 403 || result.statusCode === 401) return callback(new AppsError(AppsError.BILLING_REQUIRED)); + if (result.statusCode === 404) return callback(null); // was never purchased + if (result.statusCode !== 201 && result.statusCode !== 200) return callback(new AppsError(AppsError.EXTERNAL_ERROR, util.format('App purchase failed. %s %j', result.status, result.body))); + + superagent.del(url).query({ accessToken: appstoreConfig.token }).timeout(30 * 1000).end(function (error, result) { + if (error && !error.response) return callback(new AppsError(AppsError.EXTERNAL_ERROR, error)); + if (result.statusCode === 403 || result.statusCode === 401) return callback(new AppsError(AppsError.BILLING_REQUIRED)); + if (result.statusCode !== 204) return callback(new AppsError(AppsError.EXTERNAL_ERROR, util.format('App unpurchase failed. %s %j', result.status, result.body))); + + callback(null); + }); + }); + } + + // Caas Cloudrons do not store appstore credentials in their local database + if (config.provider() === 'caas') { + var url = config.apiServerOrigin() + '/api/v1/exchangeBoxTokenWithUserToken'; + superagent.post(url).query({ token: config.token() }).timeout(30 * 1000).end(function (error, result) { + if (error && !error.response) return callback(new AppsError(AppsError.EXTERNAL_ERROR, error)); + if (result.statusCode !== 201) return callback(new AppsError(AppsError.EXTERNAL_ERROR, util.format('App unpurchase failed. %s %j', result.status, result.body))); + + unpurchaseWithAppstoreConfig(result.body); + }); + } else { + settings.getAppstoreConfig(function (error, result) { + if (error) return callback(new AppsError(AppsError.INTERNAL_ERROR, error)); + if (!result.token) return callback(new AppsError(AppsError.BILLING_REQUIRED)); + + unpurchaseWithAppstoreConfig(result); + }); + } +}