diff --git a/src/config.js b/src/config.js index a7e65ed14..87341ec47 100644 --- a/src/config.js +++ b/src/config.js @@ -43,6 +43,7 @@ exports = module.exports = { isSpacesEnabled: isSpacesEnabled, allowHyphenatedSubdomains: allowHyphenatedSubdomains, allowOperatorActions: allowOperatorActions, + isAdminDomainLocked: isAdminDomainLocked, // for testing resets to defaults _reset: _reset @@ -240,6 +241,10 @@ function allowOperatorActions() { return get('edition') !== 'hostingprovider'; } +function isAdminDomainLocked() { + return get('edition') === 'hostingprovider'; +} + function provider() { return get('provider'); } diff --git a/src/domains.js b/src/domains.js index a78f155fa..63f46a459 100644 --- a/src/domains.js +++ b/src/domains.js @@ -6,6 +6,7 @@ module.exports = exports = { getAll: getAll, update: update, del: del, + isLocked: isLocked, fqdn: fqdn, setAdmin: setAdmin, @@ -205,6 +206,10 @@ function add(domain, zoneName, provider, dnsConfig, fallbackCertificate, tlsConf }); } +function isLocked(domain) { + return domain === config.adminDomain() && config.isAdminDomainLocked(); +} + function get(domain, callback) { assert.strictEqual(typeof domain, 'string'); assert.strictEqual(typeof callback, 'function'); @@ -214,6 +219,8 @@ function get(domain, callback) { if (error && error.reason === DatabaseError.NOT_FOUND) return callback(new DomainsError(DomainsError.NOT_FOUND)); if (error) return callback(new DomainsError(DomainsError.INTERNAL_ERROR, error)); + result.locked = isLocked(domain); + reverseProxy.getFallbackCertificate(domain, function (error, bundle) { if (error && error.reason !== ReverseProxyError.NOT_FOUND) return callback(new DomainsError(DomainsError.INTERNAL_ERROR, error)); @@ -235,6 +242,8 @@ function getAll(callback) { domaindb.getAll(function (error, result) { if (error) return callback(new DomainsError(DomainsError.INTERNAL_ERROR, error)); + result.forEach(function (r) { r.locked = isLocked(r.domain); }); + return callback(null, result); }); } @@ -429,17 +438,17 @@ function setAdmin(domain, callback) { // removes all fields that are strictly private and should never be returned by API calls function removePrivateFields(domain) { - var result = _.pick(domain, 'domain', 'zoneName', 'provider', 'config', 'tlsConfig', 'fallbackCertificate'); + var result = _.pick(domain, 'domain', 'zoneName', 'provider', 'config', 'tlsConfig', 'fallbackCertificate', 'locked'); if (result.fallbackCertificate) delete result.fallbackCertificate.key; // do not return the 'key'. in caas, this is private return result; } // removes all fields that are not accessible by a normal user function removeRestrictedFields(domain) { - var result = _.pick(domain, 'domain', 'zoneName', 'provider'); + var result = _.pick(domain, 'domain', 'zoneName', 'provider', 'locked'); // always ensure config object result.config = { hyphenatedSubdomains: !!domain.config.hyphenatedSubdomains }; return result; -} \ No newline at end of file +} diff --git a/src/routes/domains.js b/src/routes/domains.js index 48e913c7d..0f419e0ff 100644 --- a/src/routes/domains.js +++ b/src/routes/domains.js @@ -5,7 +5,9 @@ exports = module.exports = { get: get, getAll: getAll, update: update, - del: del + del: del, + + verifyDomainLock: verifyDomainLock }; var assert = require('assert'), @@ -14,6 +16,14 @@ var assert = require('assert'), HttpError = require('connect-lastmile').HttpError, HttpSuccess = require('connect-lastmile').HttpSuccess; +function verifyDomainLock(req, res, next) { + assert.strictEqual(typeof req.params.domain, 'string'); + + if (domains.isLocked(req.params.domain)) return next(new HttpError(423, 'This domain is locked')); + + next(); +} + function add(req, res, next) { assert.strictEqual(typeof req.body, 'object'); diff --git a/src/server.js b/src/server.js index 27c7d6905..149fbbc68 100644 --- a/src/server.js +++ b/src/server.js @@ -103,6 +103,7 @@ function initializeExpressSync() { var appstoreScope = routes.accesscontrol.scope(accesscontrol.SCOPE_APPSTORE); const verifyOperator = routes.accesscontrol.verifyOperator; + const verifyDomainLock = routes.domains.verifyDomainLock; // csrf protection var csrf = routes.oauth2.csrf(); @@ -272,9 +273,9 @@ function initializeExpressSync() { // domain routes router.post('/api/v1/domains', domainsManageScope, routes.domains.add); router.get ('/api/v1/domains', domainsReadScope, routes.domains.getAll); - router.get ('/api/v1/domains/:domain', domainsManageScope, routes.domains.get); // this is manage scope because it returns non-restricted fields - router.put ('/api/v1/domains/:domain', domainsManageScope, routes.domains.update); - router.del ('/api/v1/domains/:domain', domainsManageScope, routes.users.verifyPassword, routes.domains.del); + router.get ('/api/v1/domains/:domain', domainsManageScope, verifyDomainLock, routes.domains.get); // this is manage scope because it returns non-restricted fields + router.put ('/api/v1/domains/:domain', domainsManageScope, verifyDomainLock, routes.domains.update); + router.del ('/api/v1/domains/:domain', domainsManageScope, verifyDomainLock, routes.users.verifyPassword, routes.domains.del); // caas routes router.get('/api/v1/caas/config', cloudronScope, routes.caas.getConfig);