diff --git a/box.js b/box.js index 3192294e8..0f8b147fd 100755 --- a/box.js +++ b/box.js @@ -15,6 +15,7 @@ require('supererror')({ splatchError: true }); let async = require('async'), config = require('./src/config.js'), + constants = require('./constants.js'), ldap = require('./src/ldap.js'), dockerProxy = require('./src/dockerproxy.js'), server = require('./src/server.js'); @@ -25,7 +26,7 @@ console.log(' Cloudron will use the following settings '); console.log('=========================================='); console.log(); console.log(' Environment: ', config.CLOUDRON ? 'CLOUDRON' : 'TEST'); -console.log(' Version: ', config.version()); +console.log(' Version: ', constants.VERSION); console.log(' Admin Origin: ', config.adminOrigin()); console.log(' Appstore API server origin: ', config.apiServerOrigin()); console.log(' Appstore Web server origin: ', config.webServerOrigin()); diff --git a/src/apps.js b/src/apps.js index ca8b2472b..37cb8ce8f 100644 --- a/src/apps.js +++ b/src/apps.js @@ -1224,11 +1224,11 @@ function checkManifestConstraints(manifest) { if (!manifest.dockerImage) return new AppsError(AppsError.BAD_FIELD, 'Missing dockerImage'); // dockerImage is optional in manifest - if (semver.valid(manifest.maxBoxVersion) && semver.gt(config.version(), manifest.maxBoxVersion)) { + if (semver.valid(manifest.maxBoxVersion) && semver.gt(constants.VERSION, manifest.maxBoxVersion)) { return new AppsError(AppsError.BAD_FIELD, 'Box version exceeds Apps maxBoxVersion'); } - if (semver.valid(manifest.minBoxVersion) && semver.gt(manifest.minBoxVersion, config.version())) { + if (semver.valid(manifest.minBoxVersion) && semver.gt(manifest.minBoxVersion, constants.VERSION)) { return new AppsError(AppsError.BAD_FIELD, 'App version requires a new platform version'); } diff --git a/src/appstore.js b/src/appstore.js index 570b27178..a39311f91 100644 --- a/src/appstore.js +++ b/src/appstore.js @@ -28,6 +28,7 @@ var apps = require('./apps.js'), assert = require('assert'), async = require('async'), config = require('./config.js'), + constants = require('./constants.js'), custom = require('./custom.js'), debug = require('debug')('box:appstore'), domains = require('./domains.js'), @@ -279,7 +280,7 @@ function sendAliveStatus(callback) { }; var data = { - version: config.version(), + version: constants.VERSION, adminFqdn: config.adminFqdn(), provider: config.provider(), backendSettings: backendSettings, @@ -317,7 +318,7 @@ function getBoxUpdate(callback) { const url = `${config.apiServerOrigin()}/api/v1/boxupdate`; - superagent.get(url).query({ accessToken: token, boxVersion: config.version() }).timeout(10 * 1000).end(function (error, result) { + superagent.get(url).query({ accessToken: token, boxVersion: constants.VERSION }).timeout(10 * 1000).end(function (error, result) { if (error && !error.response) return callback(new AppstoreError(AppstoreError.EXTERNAL_ERROR, error.message)); if (result.statusCode === 401) return callback(new AppstoreError(AppstoreError.INVALID_TOKEN)); if (result.statusCode === 422) return callback(new AppstoreError(AppstoreError.LICENSE_ERROR, result.body.message)); @@ -326,7 +327,7 @@ function getBoxUpdate(callback) { var updateInfo = result.body; - if (!semver.valid(updateInfo.version) || semver.gt(config.version(), updateInfo.version)) { + if (!semver.valid(updateInfo.version) || semver.gt(constants.VERSION, updateInfo.version)) { return callback(new AppstoreError(AppstoreError.EXTERNAL_ERROR, util.format('Invalid update version: %s %s', result.statusCode, result.text))); } @@ -352,7 +353,7 @@ function getAppUpdate(app, callback) { const url = `${config.apiServerOrigin()}/api/v1/appupdate`; - superagent.get(url).query({ accessToken: token, boxVersion: config.version(), appId: app.appStoreId, appVersion: app.manifest.version }).timeout(10 * 1000).end(function (error, result) { + superagent.get(url).query({ accessToken: token, boxVersion: constants.VERSION, appId: app.appStoreId, appVersion: app.manifest.version }).timeout(10 * 1000).end(function (error, result) { if (error && !error.response) return callback(new AppstoreError(AppstoreError.EXTERNAL_ERROR, error)); if (result.statusCode === 401) return callback(new AppstoreError(AppstoreError.INVALID_TOKEN)); if (result.statusCode === 422) return callback(new AppstoreError(AppstoreError.LICENSE_ERROR, result.body.message)); @@ -488,7 +489,7 @@ function getApps(callback) { settings.getUnstableAppsConfig(function (error, unstable) { if (error) return callback(new AppstoreError(AppstoreError.INTERNAL_ERROR, error)); const url = `${config.apiServerOrigin()}/api/v1/apps`; - superagent.get(url).query({ accessToken: token, boxVersion: config.version(), unstable: unstable }).timeout(10 * 1000).end(function (error, result) { + superagent.get(url).query({ accessToken: token, boxVersion: constants.VERSION, unstable: unstable }).timeout(10 * 1000).end(function (error, result) { if (error && !error.response) return callback(new AppstoreError(AppstoreError.EXTERNAL_ERROR, error.message)); if (result.statusCode === 403 || result.statusCode === 401) return callback(new AppstoreError(AppstoreError.INVALID_TOKEN)); if (result.statusCode === 422) return callback(new AppstoreError(AppstoreError.LICENSE_ERROR, result.body.message)); diff --git a/src/backups.js b/src/backups.js index f8213ab9d..4fbc404f6 100644 --- a/src/backups.js +++ b/src/backups.js @@ -47,6 +47,7 @@ var addons = require('./addons.js'), assert = require('assert'), backupdb = require('./backupdb.js'), config = require('./config.js'), + constants = require('./constants.js'), crypto = require('crypto'), database = require('./database.js'), DatabaseError = require('./databaseerror.js'), @@ -768,12 +769,12 @@ function rotateBoxBackup(backupConfig, tag, appBackupIds, progressCallback, call if (!snapshotInfo) return callback(new BackupsError(BackupsError.INTERNAL_ERROR, 'Snapshot info missing or corrupt')); const snapshotTime = snapshotInfo.timestamp.replace(/[T.]/g, '-').replace(/[:Z]/g,''); // add this to filename to make it unique, so it's easy to download them - const backupId = util.format('%s/box_%s_v%s', tag, snapshotTime, config.version()); + const backupId = util.format('%s/box_%s_v%s', tag, snapshotTime, constants.VERSION); const format = backupConfig.format; debug(`Rotating box backup to id ${backupId}`); - backupdb.add(backupId, { version: config.version(), type: backupdb.BACKUP_TYPE_BOX, dependsOn: appBackupIds, manifest: null, format: format }, function (error) { + backupdb.add(backupId, { version: constants.VERSION, type: backupdb.BACKUP_TYPE_BOX, dependsOn: appBackupIds, manifest: null, format: format }, function (error) { if (error) return callback(new BackupsError(BackupsError.INTERNAL_ERROR, error)); var copy = api(backupConfig.provider).copy(backupConfig, getBackupFilePath(backupConfig, 'snapshot/box', format), getBackupFilePath(backupConfig, backupId, format)); diff --git a/src/cloudron.js b/src/cloudron.js index 0a303c29f..5774219bd 100644 --- a/src/cloudron.js +++ b/src/cloudron.js @@ -169,7 +169,7 @@ function getConfig(callback) { adminDomain: config.adminDomain(), adminFqdn: config.adminFqdn(), mailFqdn: config.mailFqdn(), - version: config.version(), + version: constants.VERSION, isDemo: config.isDemo(), memory: os.totalmem(), provider: config.provider(), diff --git a/src/config.js b/src/config.js index 4caa0b933..cc805b082 100644 --- a/src/config.js +++ b/src/config.js @@ -20,7 +20,6 @@ exports = module.exports = { setFqdn: setAdminDomain, setAdminDomain: setAdminDomain, setAdminFqdn: setAdminFqdn, - version: version, database: database, // these values are derived @@ -178,11 +177,6 @@ function sysadminOrigin() { return 'http://127.0.0.1:' + get('sysadminPort'); } -function version() { - if (exports.TEST) return '3.0.0-test'; - return fs.readFileSync(path.join(__dirname, '../VERSION'), 'utf8').trim(); -} - function database() { return get('database'); } diff --git a/src/constants.js b/src/constants.js index 7c39a44e2..b8024bc85 100644 --- a/src/constants.js +++ b/src/constants.js @@ -1,5 +1,8 @@ 'use strict'; +let fs = require('fs'), + path = require('path'); + exports = module.exports = { SMTP_LOCATION: 'smtp', IMAP_LOCATION: 'imap', @@ -30,6 +33,11 @@ exports = module.exports = { AUTOUPDATE_PATTERN_NEVER: 'never', - SECRET_PLACEHOLDER: String.fromCharCode(0x25CF).repeat(8) + SECRET_PLACEHOLDER: String.fromCharCode(0x25CF).repeat(8), + + CLOUDRON: process.env.BOX_ENV === 'cloudron', + TEST: process.env.BOX_ENV === 'test', + + VERSION: process.env.BOX_ENV === 'cloudron' ? fs.readFileSync(path.join(__dirname, '../VERSION'), 'utf8').trim() : '4.0.0-test' }; diff --git a/src/provision.js b/src/provision.js index d5f485439..187fe7c4a 100644 --- a/src/provision.js +++ b/src/provision.js @@ -252,7 +252,7 @@ function restore(backupConfig, backupId, version, auditSource, callback) { assert.strictEqual(typeof callback, 'function'); if (!semver.valid(version)) return callback(new ProvisionError(ProvisionError.BAD_STATE, 'version is not a valid semver')); - if (semver.major(config.version()) !== semver.major(version) || semver.minor(config.version()) !== semver.minor(version)) return callback(new ProvisionError(ProvisionError.BAD_STATE, `Run cloudron-setup with --version ${version} to restore from this backup`)); + if (semver.major(constants.VERSION) !== semver.major(version) || semver.minor(constants.VERSION) !== semver.minor(version)) return callback(new ProvisionError(ProvisionError.BAD_STATE, `Run cloudron-setup with --version ${version} to restore from this backup`)); if (gProvisionStatus.setup.active || gProvisionStatus.restore.active) return callback(new ProvisionError(ProvisionError.BAD_STATE, 'Already setting up or restoring')); @@ -306,7 +306,7 @@ function getStatus(callback) { if (error) return callback(new ProvisionError(ProvisionError.INTERNAL_ERROR, error)); callback(null, _.extend({ - version: config.version(), + version: constants.VERSION, apiServerOrigin: config.apiServerOrigin(), // used by CaaS tool provider: config.provider(), cloudronName: cloudronName, diff --git a/src/routes/test/appstore-test.js b/src/routes/test/appstore-test.js index 47f40c9c5..290a794d7 100644 --- a/src/routes/test/appstore-test.js +++ b/src/routes/test/appstore-test.js @@ -7,6 +7,7 @@ var async = require('async'), config = require('../../config.js'), + constants = require('../../constants.js'), database = require('../../database.js'), expect = require('expect.js'), nock = require('nock'), @@ -103,7 +104,7 @@ describe('Appstore Apps API', function () { it('can list apps', function (done) { var scope1 = nock(config.apiServerOrigin()) - .get(`/api/v1/apps?accessToken=CLOUDRON_TOKEN&boxVersion=${config.version()}&unstable=false`, () => true) + .get(`/api/v1/apps?accessToken=CLOUDRON_TOKEN&boxVersion=${constants.VERSION}&unstable=false`, () => true) .reply(200, { apps: [] }); superagent.get(SERVER_URL + '/api/v1/appstore/apps') diff --git a/src/routes/test/cloudron-test.js b/src/routes/test/cloudron-test.js index 5fb0f2d9c..601c3b213 100644 --- a/src/routes/test/cloudron-test.js +++ b/src/routes/test/cloudron-test.js @@ -7,6 +7,7 @@ let async = require('async'), config = require('../../config.js'), + constants = require('../../constants.js'), database = require('../../database.js'), expect = require('expect.js'), hat = require('../../hat.js'), @@ -189,7 +190,7 @@ describe('Cloudron', function () { expect(result.body.apiServerOrigin).to.eql('http://localhost:6060'); expect(result.body.webServerOrigin).to.eql(null); expect(result.body.adminFqdn).to.eql(config.adminFqdn()); - expect(result.body.version).to.eql(config.version()); + expect(result.body.version).to.eql(constants.VERSION); expect(result.body.memory).to.eql(os.totalmem()); expect(result.body.cloudronName).to.be.a('string'); diff --git a/src/server.js b/src/server.js index 5d3f368b0..5b60e7bce 100644 --- a/src/server.js +++ b/src/server.js @@ -10,6 +10,7 @@ var accesscontrol = require('./accesscontrol.js'), async = require('async'), cloudron = require('./cloudron.js'), config = require('./config.js'), + constants = require('./constants.js'), database = require('./database.js'), eventlog = require('./eventlog.js'), express = require('express'), @@ -370,7 +371,7 @@ function start(callback) { cloudron.initialize, gHttpServer.listen.bind(gHttpServer, config.get('port'), '127.0.0.1'), gSysadminHttpServer.listen.bind(gSysadminHttpServer, config.get('sysadminPort'), '127.0.0.1'), - eventlog.add.bind(null, eventlog.ACTION_START, { userId: null, username: 'boot' }, { version: config.version() }) + eventlog.add.bind(null, eventlog.ACTION_START, { userId: null, username: 'boot' }, { version: constants.VERSION }) ], callback); } diff --git a/src/test/config-test.js b/src/test/config-test.js index 67e1528e5..001abea37 100644 --- a/src/test/config-test.js +++ b/src/test/config-test.js @@ -6,6 +6,7 @@ 'use strict'; var config = require('../config.js'), + constants = require('../constants.js'), expect = require('expect.js'), fs = require('fs'), path = require('path'); @@ -25,8 +26,8 @@ describe('config', function () { }); it('can get version', function (done) { - expect(config.version()).to.be.ok(); // this gets a dummy text string - expect(config.version().includes('\n')).to.not.be.ok(); + expect(constants.VERSION).to.be.ok(); // this gets a dummy text string + expect(constants.VERSION.includes('\n')).to.not.be.ok(); done(); }); diff --git a/src/test/updatechecker-test.js b/src/test/updatechecker-test.js index b786f6dbd..264ca5feb 100644 --- a/src/test/updatechecker-test.js +++ b/src/test/updatechecker-test.js @@ -46,7 +46,7 @@ var AUDIT_SOURCE = { ip: '1.2.3.4' }; -const UPDATE_VERSION = semver.inc(config.version(), 'major'); +const UPDATE_VERSION = semver.inc(constants.VERSION, 'major'); function checkMails(number, done) { // mails are enqueued async @@ -97,7 +97,7 @@ describe('updatechecker - box - manual (email)', function () { var scope = nock('http://localhost:4444') .get('/api/v1/boxupdate') - .query({ boxVersion: config.version(), accessToken: 'atoken' }) + .query({ boxVersion: constants.VERSION, accessToken: 'atoken' }) .reply(204, { } ); updatechecker.checkBoxUpdates(function (error) { @@ -114,7 +114,7 @@ describe('updatechecker - box - manual (email)', function () { var scope = nock('http://localhost:4444') .get('/api/v1/boxupdate') - .query({ boxVersion: config.version(), accessToken: 'atoken' }) + .query({ boxVersion: constants.VERSION, accessToken: 'atoken' }) .reply(200, { version: UPDATE_VERSION, changelog: [''], sourceTarballUrl: 'box.tar.gz', sourceTarballSigUrl: 'box.tar.gz.sig', boxVersionsUrl: 'box.versions', boxVersionsSigUrl: 'box.versions.sig' } ); updatechecker.checkBoxUpdates(function (error) { @@ -132,7 +132,7 @@ describe('updatechecker - box - manual (email)', function () { var scope = nock('http://localhost:4444') .get('/api/v1/boxupdate') - .query({ boxVersion: config.version(), accessToken: 'atoken' }) + .query({ boxVersion: constants.VERSION, accessToken: 'atoken' }) .reply(404, { version: '2.0.0-pre.0', changelog: [''], sourceTarballUrl: 'box-pre.tar.gz' } ); updatechecker.checkBoxUpdates(function (error) { @@ -170,7 +170,7 @@ describe('updatechecker - box - automatic (no email)', function () { var scope = nock('http://localhost:4444') .get('/api/v1/boxupdate') - .query({ boxVersion: config.version(), accessToken: 'atoken' }) + .query({ boxVersion: constants.VERSION, accessToken: 'atoken' }) .reply(200, { version: UPDATE_VERSION, changelog: [''], sourceTarballUrl: 'box.tar.gz', sourceTarballSigUrl: 'box.tar.gz.sig', boxVersionsUrl: 'box.versions', boxVersionsSigUrl: 'box.versions.sig' } ); updatechecker.checkBoxUpdates(function (error) { @@ -209,7 +209,7 @@ describe('updatechecker - box - automatic free (email)', function () { var scope = nock('http://localhost:4444') .get('/api/v1/boxupdate') - .query({ boxVersion: config.version(), accessToken: 'atoken' }) + .query({ boxVersion: constants.VERSION, accessToken: 'atoken' }) .reply(200, { version: UPDATE_VERSION, changelog: [''], sourceTarballUrl: 'box.tar.gz', sourceTarballSigUrl: 'box.tar.gz.sig', boxVersionsUrl: 'box.versions', boxVersionsSigUrl: 'box.versions.sig' } ); updatechecker.checkBoxUpdates(function (error) { @@ -276,7 +276,7 @@ describe('updatechecker - app - manual (email)', function () { var scope = nock('http://localhost:4444') .get('/api/v1/appupdate') - .query({ boxVersion: config.version(), accessToken: 'atoken', appId: APP_0.appStoreId, appVersion: APP_0.manifest.version }) + .query({ boxVersion: constants.VERSION, accessToken: 'atoken', appId: APP_0.appStoreId, appVersion: APP_0.manifest.version }) .reply(204, { } ); updatechecker.checkAppUpdates(function (error) { @@ -293,7 +293,7 @@ describe('updatechecker - app - manual (email)', function () { var scope = nock('http://localhost:4444') .get('/api/v1/appupdate') - .query({ boxVersion: config.version(), accessToken: 'atoken', appId: APP_0.appStoreId, appVersion: APP_0.manifest.version }) + .query({ boxVersion: constants.VERSION, accessToken: 'atoken', appId: APP_0.appStoreId, appVersion: APP_0.manifest.version }) .reply(500, { update: { manifest: { version: '1.0.0', changelog: '* some changes' } } } ); updatechecker.checkAppUpdates(function (error) { @@ -310,7 +310,7 @@ describe('updatechecker - app - manual (email)', function () { var scope = nock('http://localhost:4444') .get('/api/v1/appupdate') - .query({ boxVersion: config.version(), accessToken: 'atoken', appId: APP_0.appStoreId, appVersion: APP_0.manifest.version }) + .query({ boxVersion: constants.VERSION, accessToken: 'atoken', appId: APP_0.appStoreId, appVersion: APP_0.manifest.version }) .reply(200, { manifest: { version: '2.0.0', changelog: '* some changes' } } ); updatechecker.checkAppUpdates(function (error) { @@ -387,7 +387,7 @@ describe('updatechecker - app - automatic (no email)', function () { var scope = nock('http://localhost:4444') .get('/api/v1/appupdate') - .query({ boxVersion: config.version(), accessToken: 'atoken', appId: APP_0.appStoreId, appVersion: APP_0.manifest.version }) + .query({ boxVersion: constants.VERSION, accessToken: 'atoken', appId: APP_0.appStoreId, appVersion: APP_0.manifest.version }) .reply(200, { manifest: { version: '2.0.0', changelog: 'c' } } ); updatechecker.checkAppUpdates(function (error) { @@ -454,7 +454,7 @@ describe('updatechecker - app - automatic free (email)', function () { var scope = nock('http://localhost:4444') .get('/api/v1/appupdate') - .query({ boxVersion: config.version(), accessToken: 'atoken', appId: APP_0.appStoreId, appVersion: APP_0.manifest.version }) + .query({ boxVersion: constants.VERSION, accessToken: 'atoken', appId: APP_0.appStoreId, appVersion: APP_0.manifest.version }) .reply(200, { manifest: { version: '2.0.0', changelog: 'c' } } ); updatechecker.checkAppUpdates(function (error) { diff --git a/src/updater.js b/src/updater.js index 18e2ab961..5000c7eb6 100644 --- a/src/updater.js +++ b/src/updater.js @@ -13,6 +13,7 @@ var apps = require('./apps.js'), child_process = require('child_process'), backups = require('./backups.js'), config = require('./config.js'), + constants = require('./constants.js'), crypto = require('crypto'), debug = require('debug')('box:updater'), eventlog = require('./eventlog.js'), @@ -123,8 +124,8 @@ function verifyUpdateInfo(versionsFile, updateInfo, callback) { assert.strictEqual(typeof callback, 'function'); var releases = safe.JSON.parse(safe.fs.readFileSync(versionsFile, 'utf8')) || { }; - if (!releases[config.version()] || !releases[config.version()].next) return callback(new UpdaterError(UpdaterError.EXTERNAL_ERROR, 'No version info')); - var nextVersion = releases[config.version()].next; + if (!releases[constants.VERSION] || !releases[constants.VERSION].next) return callback(new UpdaterError(UpdaterError.EXTERNAL_ERROR, 'No version info')); + var nextVersion = releases[constants.VERSION].next; if (typeof releases[nextVersion] !== 'object' || !releases[nextVersion]) return callback(new UpdaterError(UpdaterError.EXTERNAL_ERROR, 'No next version info')); if (releases[nextVersion].sourceTarballUrl !== updateInfo.sourceTarballUrl) return callback(new UpdaterError(UpdaterError.EXTERNAL_ERROR, 'Version info mismatch'));