diff --git a/src/docker.js b/src/docker.js index d8731cc06..f916a4f70 100644 --- a/src/docker.js +++ b/src/docker.js @@ -2,7 +2,13 @@ exports = module.exports = { connection: connectionInstance(), + + testRegistryConfig: testRegistryConfig, setRegistryConfig: setRegistryConfig, + injectPrivateFields: injectPrivateFields, + removePrivateFields: removePrivateFields, + + SECRET_PLACEHOLDER: String.fromCharCode(0x25CF).repeat(8), ping: ping, @@ -58,6 +64,25 @@ function debugApp(app) { debug(app.fqdn + ' ' + util.format.apply(util, Array.prototype.slice.call(arguments, 1))); } +function testRegistryConfig(auth, callback) { + assert.strictEqual(typeof auth, 'object'); + assert.strictEqual(typeof callback, 'function'); + + return callback(null); +} + +function injectPrivateFields(newConfig, currentConfig) { + if (newConfig.password === exports.SECRET_PLACEHOLDER) newConfig.password = currentConfig.password; +} + +function removePrivateFields(registryConfig) { + assert.strictEqual(typeof registryConfig, 'object'); + + if (registryConfig.password) registryConfig.password = exports.SECRET_PLACEHOLDER; + + return registryConfig; +} + function setRegistryConfig(auth, callback) { assert.strictEqual(typeof auth, 'object'); assert.strictEqual(typeof callback, 'function'); @@ -65,7 +90,7 @@ function setRegistryConfig(auth, callback) { const isLogin = !!auth.password; // currently, auth info is not stashed in the db but maybe it should for restore to work? - const cmd = isLogin ? `docker login ${auth.serveraddress} --username ${auth.username} --password ${auth.password}` : `docker logout ${auth.serveraddress}`; + const cmd = isLogin ? `docker login ${auth.serverAddress} --username ${auth.username} --password ${auth.password}` : `docker logout ${auth.serverAddress}`; child_process.exec(cmd, { }, function (error /*, stdout, stderr */) { if (error) return callback(new BoxError(BoxError.ACCESS_DENIED, error.message)); diff --git a/src/routes/settings.js b/src/routes/settings.js index 9c4503047..365fc4cc5 100644 --- a/src/routes/settings.js +++ b/src/routes/settings.js @@ -269,14 +269,22 @@ function setUnstableAppsConfig(req, res, next) { }); } +function getRegistryConfig(req, res, next) { + settings.getRegistryConfig(function (error, registryConfig) { + if (error) return next(toHttpError(error)); + + next(new HttpSuccess(200, docker.removePrivateFields(registryConfig))); + }); +} + function setRegistryConfig(req, res, next) { assert.strictEqual(typeof req.body, 'object'); - if (typeof req.body.serveraddress !== 'string') return next(new HttpError(400, 'serveraddress is required')); + if (typeof req.body.serverAddress !== 'string') return next(new HttpError(400, 'serverAddress is required')); if ('username' in req.body && typeof req.body.username !== 'string') return next(new HttpError(400, 'username is required')); if ('password' in req.body && typeof req.body.password !== 'string') return next(new HttpError(400, 'password is required')); - docker.setRegistryConfig(req.body, function (error) { + settings.setRegistryConfig(req.body, function (error) { if (error) return next(toHttpError(error)); next(new HttpSuccess(200)); @@ -292,6 +300,7 @@ function get(req, res, next) { case settings.PLATFORM_CONFIG_KEY: return getPlatformConfig(req, res, next); case settings.EXTERNAL_LDAP_KEY: return getExternalLdapConfig(req, res, next); case settings.UNSTABLE_APPS_KEY: return getUnstableAppsConfig(req, res, next); + case settings.REGISTRY_CONFIG_KEY: return getRegistryConfig(req, res, next); case settings.APP_AUTOUPDATE_PATTERN_KEY: return getAppAutoupdatePattern(req, res, next); case settings.BOX_AUTOUPDATE_PATTERN_KEY: return getBoxAutoupdatePattern(req, res, next); @@ -313,6 +322,7 @@ function set(req, res, next) { case settings.PLATFORM_CONFIG_KEY: return setPlatformConfig(req, res, next); case settings.EXTERNAL_LDAP_KEY: return setExternalLdapConfig(req, res, next); case settings.UNSTABLE_APPS_KEY: return setUnstableAppsConfig(req, res, next); + case settings.REGISTRY_CONFIG_KEY: return setRegistryConfig(req, res, next); case settings.APP_AUTOUPDATE_PATTERN_KEY: return setAppAutoupdatePattern(req, res, next); case settings.BOX_AUTOUPDATE_PATTERN_KEY: return setBoxAutoupdatePattern(req, res, next); diff --git a/src/settings.js b/src/settings.js index 4374358e5..a9c4289b1 100644 --- a/src/settings.js +++ b/src/settings.js @@ -31,6 +31,9 @@ exports = module.exports = { getExternalLdapConfig: getExternalLdapConfig, setExternalLdapConfig: setExternalLdapConfig, + getRegistryConfig: getRegistryConfig, + setRegistryConfig: setRegistryConfig, + getLicenseKey: getLicenseKey, setLicenseKey: setLicenseKey, @@ -65,6 +68,7 @@ exports = module.exports = { BACKUP_CONFIG_KEY: 'backup_config', PLATFORM_CONFIG_KEY: 'platform_config', EXTERNAL_LDAP_KEY: 'external_ldap_config', + REGISTRY_CONFIG_KEY: 'registry_config', // strings APP_AUTOUPDATE_PATTERN_KEY: 'app_autoupdate_pattern', @@ -97,6 +101,7 @@ var addons = require('./addons.js'), CronJob = require('cron').CronJob, DatabaseError = require('./databaseerror.js'), debug = require('debug')('box:settings'), + docker = require('./docker.js'), externalldap = require('./externalldap.js'), ExternalLdapError = externalldap.ExternalLdapError, moment = require('moment-timezone'), @@ -127,6 +132,7 @@ let gDefaults = (function () { }; result[exports.PLATFORM_CONFIG_KEY] = {}; result[exports.EXTERNAL_LDAP_KEY] = {}; + result[exports.REGISTRY_CONFIG_KEY] = {}; result[exports.ADMIN_DOMAIN_KEY] = ''; result[exports.ADMIN_FQDN_KEY] = ''; result[exports.API_SERVER_ORIGIN_KEY] = 'https://api.cloudron.io'; @@ -423,6 +429,40 @@ function setExternalLdapConfig(externalLdapConfig, callback) { }); } +function getRegistryConfig(callback) { + assert.strictEqual(typeof callback, 'function'); + + settingsdb.get(exports.REGISTRY_CONFIG_KEY, function (error, value) { + if (error && error.reason === DatabaseError.NOT_FOUND) return callback(null, gDefaults[exports.REGISTRY_CONFIG_KEY]); + if (error) return callback(new BoxError(BoxError.DATABASE_ERROR, error)); + + callback(null, JSON.parse(value)); + }); +} + +function setRegistryConfig(registryConfig, callback) { + assert.strictEqual(typeof registryConfig, 'object'); + assert.strictEqual(typeof callback, 'function'); + + getRegistryConfig(function (error, curentConfig) { + if (error) return callback(error); + + docker.injectPrivateFields(registryConfig, curentConfig); + + docker.testRegistryConfig(registryConfig, function (error) { + if (error) return callback(error); + + settingsdb.set(exports.REGISTRY_CONFIG_KEY, JSON.stringify(registryConfig), function (error) { + if (error) return callback(new BoxError(BoxError.DATABASE_ERROR, error)); + + notifyChange(exports.REGISTRY_CONFIG_KEY, registryConfig); + + callback(null); + }); + }); + }); +} + function getLicenseKey(callback) { assert.strictEqual(typeof callback, 'function'); @@ -510,7 +550,7 @@ function getAll(callback) { result[exports.DEMO_KEY] = !!result[exports.DEMO_KEY]; // convert JSON objects - [exports.BACKUP_CONFIG_KEY, exports.PLATFORM_CONFIG_KEY, exports.EXTERNAL_LDAP_KEY ].forEach(function (key) { + [exports.BACKUP_CONFIG_KEY, exports.PLATFORM_CONFIG_KEY, exports.EXTERNAL_LDAP_KEY, exports.REGISTRY_CONFIG_KEY ].forEach(function (key) { result[key] = typeof result[key] === 'object' ? result[key] : safe.JSON.parse(result[key]); });