diff --git a/src/apptask.js b/src/apptask.js index 62278fbaf..79919b4e0 100644 --- a/src/apptask.js +++ b/src/apptask.js @@ -39,6 +39,7 @@ var addons = require('./addons.js'), debug = require('debug')('box:apptask'), docker = require('./docker.js'), domains = require('./domains.js'), + DomainError = domains.DomainError, ejs = require('ejs'), fs = require('fs'), manifestFormat = require('cloudron-manifestformat'), @@ -49,7 +50,6 @@ var addons = require('./addons.js'), paths = require('./paths.js'), safe = require('safetydance'), shell = require('./shell.js'), - SubdomainError = require('./subdomains.js').SubdomainError, superagent = require('superagent'), sysinfo = require('./sysinfo.js'), tld = require('tldjs'), @@ -263,7 +263,7 @@ function registerSubdomain(app, overwrite, callback) { if (config.isCustomDomain() && values.length !== 0 && !overwrite) return retryCallback(null, new Error('DNS Record already exists')); domains.upsertDNSRecords(app.location, 'A', [ ip ], function (error, changeId) { - if (error && (error.reason === SubdomainError.STILL_BUSY || error.reason === SubdomainError.EXTERNAL_ERROR)) return retryCallback(error); // try again + if (error && (error.reason === DomainError.STILL_BUSY || error.reason === DomainError.EXTERNAL_ERROR)) return retryCallback(error); // try again retryCallback(null, error || changeId); }); @@ -300,7 +300,7 @@ function unregisterSubdomain(app, location, callback) { debugApp(app, 'Unregistering subdomain: %s', location); domains.removeDNSRecords(location, 'A', [ ip ], function (error) { - if (error && (error.reason === SubdomainError.STILL_BUSY || error.reason === SubdomainError.EXTERNAL_ERROR)) return retryCallback(error); // try again + if (error && (error.reason === DomainError.STILL_BUSY || error.reason === DomainError.EXTERNAL_ERROR)) return retryCallback(error); // try again retryCallback(null, error); }); diff --git a/src/dns/caas.js b/src/dns/caas.js index 518b9ee36..dd870998e 100644 --- a/src/dns/caas.js +++ b/src/dns/caas.js @@ -11,7 +11,7 @@ exports = module.exports = { var assert = require('assert'), config = require('../config.js'), debug = require('debug')('box:dns/caas'), - SubdomainError = require('../subdomains.js').SubdomainError, + DomainError = require('../domains.js').DomainError, superagent = require('superagent'), util = require('util'); @@ -38,10 +38,10 @@ function add(dnsConfig, zoneName, subdomain, type, values, callback) { .send(data) .timeout(30 * 1000) .end(function (error, result) { - if (error && !error.response) return callback(new SubdomainError(SubdomainError.EXTERNAL_ERROR, util.format('Network error %s', error.message))); - if (result.statusCode === 400) return callback(new SubdomainError(SubdomainError.BAD_FIELD, result.body.message)); - if (result.statusCode === 420) return callback(new SubdomainError(SubdomainError.STILL_BUSY)); - if (result.statusCode !== 201) return callback(new SubdomainError(SubdomainError.EXTERNAL_ERROR, util.format('%s %j', result.statusCode, result.body))); + if (error && !error.response) return callback(new DomainError(DomainError.EXTERNAL_ERROR, util.format('Network error %s', error.message))); + if (result.statusCode === 400) return callback(new DomainError(DomainError.BAD_FIELD, result.body.message)); + if (result.statusCode === 420) return callback(new DomainError(DomainError.STILL_BUSY)); + if (result.statusCode !== 201) return callback(new DomainError(DomainError.EXTERNAL_ERROR, util.format('%s %j', result.statusCode, result.body))); return callback(null, result.body.changeId); }); @@ -63,8 +63,8 @@ function get(dnsConfig, zoneName, subdomain, type, callback) { .query({ token: dnsConfig.token, type: type }) .timeout(30 * 1000) .end(function (error, result) { - if (error && !error.response) return callback(new SubdomainError(SubdomainError.EXTERNAL_ERROR, util.format('Network error %s', error.message))); - if (result.statusCode !== 200) return callback(new SubdomainError(SubdomainError.EXTERNAL_ERROR, util.format('%s %j', result.statusCode, result.body))); + if (error && !error.response) return callback(new DomainError(DomainError.EXTERNAL_ERROR, util.format('Network error %s', error.message))); + if (result.statusCode !== 200) return callback(new DomainError(DomainError.EXTERNAL_ERROR, util.format('%s %j', result.statusCode, result.body))); return callback(null, result.body.values); }); @@ -102,11 +102,11 @@ function del(dnsConfig, zoneName, subdomain, type, values, callback) { .send(data) .timeout(30 * 1000) .end(function (error, result) { - if (error && !error.response) return callback(new SubdomainError(SubdomainError.EXTERNAL_ERROR, util.format('Network error %s', error.message))); - if (result.statusCode === 400) return callback(new SubdomainError(SubdomainError.BAD_FIELD, result.body.message)); - if (result.statusCode === 420) return callback(new SubdomainError(SubdomainError.STILL_BUSY)); - if (result.statusCode === 404) return callback(new SubdomainError(SubdomainError.NOT_FOUND)); - if (result.statusCode !== 204) return callback(new SubdomainError(SubdomainError.EXTERNAL_ERROR, util.format('%s %j', result.statusCode, result.body))); + if (error && !error.response) return callback(new DomainError(DomainError.EXTERNAL_ERROR, util.format('Network error %s', error.message))); + if (result.statusCode === 400) return callback(new DomainError(DomainError.BAD_FIELD, result.body.message)); + if (result.statusCode === 420) return callback(new DomainError(DomainError.STILL_BUSY)); + if (result.statusCode === 404) return callback(new DomainError(DomainError.NOT_FOUND)); + if (result.statusCode !== 204) return callback(new DomainError(DomainError.EXTERNAL_ERROR, util.format('%s %j', result.statusCode, result.body))); return callback(null); }); diff --git a/src/dns/cloudflare.js b/src/dns/cloudflare.js index 48bebc20c..c78343de2 100644 --- a/src/dns/cloudflare.js +++ b/src/dns/cloudflare.js @@ -10,12 +10,12 @@ exports = module.exports = { var assert = require('assert'), async = require('async'), - dns = require('dns'), - _ = require('underscore'), - SubdomainError = require('../subdomains.js').SubdomainError, - superagent = require('superagent'), debug = require('debug')('box:dns/cloudflare'), - util = require('util'); + dns = require('dns'), + DomainError = require('../domains.js').DomainError, + superagent = require('superagent'), + util = require('util'), + _ = require('underscore'); // we are using latest v4 stable API https://api.cloudflare.com/#getting-started-endpoints var CLOUDFLARE_ENDPOINT = 'https://api.cloudflare.com/client/v4'; @@ -24,8 +24,8 @@ function translateRequestError(result, callback) { assert.strictEqual(typeof result, 'object'); assert.strictEqual(typeof callback, 'function'); - if (result.statusCode === 404) return callback(new SubdomainError(SubdomainError.NOT_FOUND, util.format('%s %j', result.statusCode, 'API does not exist'))); - if (result.statusCode === 422) return callback(new SubdomainError(SubdomainError.BAD_FIELD, result.body.message)); + if (result.statusCode === 404) return callback(new DomainError(DomainError.NOT_FOUND, util.format('%s %j', result.statusCode, 'API does not exist'))); + if (result.statusCode === 422) return callback(new DomainError(DomainError.BAD_FIELD, result.body.message)); if ((result.statusCode === 400 || result.statusCode === 401 || result.statusCode === 403) && result.body.errors.length > 0) { let error = result.body.errors[0]; let message = error.message; @@ -34,10 +34,10 @@ function translateRequestError(result, callback) { else message = 'Invalid credentials'; } - return callback(new SubdomainError(SubdomainError.ACCESS_DENIED, message)); + return callback(new DomainError(DomainError.ACCESS_DENIED, message)); } - callback(new SubdomainError(SubdomainError.EXTERNAL_ERROR, util.format('%s %j', result.statusCode, result.body))); + callback(new DomainError(DomainError.EXTERNAL_ERROR, util.format('%s %j', result.statusCode, result.body))); } function getZoneByName(dnsConfig, zoneName, callback) { @@ -52,7 +52,7 @@ function getZoneByName(dnsConfig, zoneName, callback) { .end(function (error, result) { if (error && !error.response) return callback(error); if (result.statusCode !== 200 || result.body.success !== true) return translateRequestError(result, callback); - if (!result.body.result.length) return callback(new SubdomainError(SubdomainError.NOT_FOUND, util.format('%s %j', result.statusCode, result.body))); + if (!result.body.result.length) return callback(new DomainError(DomainError.NOT_FOUND, util.format('%s %j', result.statusCode, result.body))); callback(null, result.body.result[0]); }); @@ -233,8 +233,8 @@ function verifyDnsConfig(dnsConfig, fqdn, zoneName, ip, callback) { assert.strictEqual(typeof ip, 'string'); assert.strictEqual(typeof callback, 'function'); - if (!dnsConfig.token || typeof dnsConfig.token !== 'string') return callback(new SubdomainError(SubdomainError.BAD_FIELD, 'token must be a non-empty string')); - if (!dnsConfig.email || typeof dnsConfig.email !== 'string') return callback(new SubdomainError(SubdomainError.BAD_FIELD, 'email must be a non-empty string')); + if (!dnsConfig.token || typeof dnsConfig.token !== 'string') return callback(new DomainError(DomainError.BAD_FIELD, 'token must be a non-empty string')); + if (!dnsConfig.email || typeof dnsConfig.email !== 'string') return callback(new DomainError(DomainError.BAD_FIELD, 'email must be a non-empty string')); var credentials = { provider: dnsConfig.provider, @@ -245,15 +245,15 @@ function verifyDnsConfig(dnsConfig, fqdn, zoneName, ip, callback) { if (process.env.BOX_ENV === 'test') return callback(null, credentials); // this shouldn't be here dns.resolveNs(zoneName, function (error, nameservers) { - if (error && error.code === 'ENOTFOUND') return callback(new SubdomainError(SubdomainError.BAD_FIELD, 'Unable to resolve nameservers for this domain')); - if (error || !nameservers) return callback(new SubdomainError(SubdomainError.BAD_FIELD, error ? error.message : 'Unable to get nameservers')); + if (error && error.code === 'ENOTFOUND') return callback(new DomainError(DomainError.BAD_FIELD, 'Unable to resolve nameservers for this domain')); + if (error || !nameservers) return callback(new DomainError(DomainError.BAD_FIELD, error ? error.message : 'Unable to get nameservers')); getZoneByName(dnsConfig, zoneName, function(error, result) { if (error) return callback(error); if (!_.isEqual(result.name_servers.sort(), nameservers.sort())) { debug('verifyDnsConfig: %j and %j do not match', nameservers, result.name_servers); - return callback(new SubdomainError(SubdomainError.BAD_FIELD, 'Domain nameservers are not set to Cloudflare')); + return callback(new DomainError(DomainError.BAD_FIELD, 'Domain nameservers are not set to Cloudflare')); } upsert(credentials, zoneName, 'my', 'A', [ ip ], function (error, changeId) { diff --git a/src/dns/digitalocean.js b/src/dns/digitalocean.js index 464d77cd2..e8ed1b8a0 100644 --- a/src/dns/digitalocean.js +++ b/src/dns/digitalocean.js @@ -13,8 +13,8 @@ var assert = require('assert'), config = require('../config.js'), debug = require('debug')('box:dns/digitalocean'), dns = require('dns'), + DomainError = require('../domains.js').DomainError, safe = require('safetydance'), - SubdomainError = require('../subdomains.js').SubdomainError, superagent = require('superagent'), util = require('util'); @@ -40,10 +40,10 @@ function getInternal(dnsConfig, zoneName, subdomain, type, callback) { .set('Authorization', 'Bearer ' + dnsConfig.token) .timeout(30 * 1000) .end(function (error, result) { - if (error && !error.response) return callback(new SubdomainError(SubdomainError.EXTERNAL_ERROR, util.format('Network error %s', error.message))); - if (result.statusCode === 404) return callback(new SubdomainError(SubdomainError.NOT_FOUND, formatError(result))); - if (result.statusCode === 403 || result.statusCode === 401) return callback(new SubdomainError(SubdomainError.ACCESS_DENIED, formatError(result))); - if (result.statusCode !== 200) return callback(new SubdomainError(SubdomainError.EXTERNAL_ERROR, formatError(result))); + if (error && !error.response) return callback(new DomainError(DomainError.EXTERNAL_ERROR, util.format('Network error %s', error.message))); + if (result.statusCode === 404) return callback(new DomainError(DomainError.NOT_FOUND, formatError(result))); + if (result.statusCode === 403 || result.statusCode === 401) return callback(new DomainError(DomainError.ACCESS_DENIED, formatError(result))); + if (result.statusCode !== 200) return callback(new DomainError(DomainError.EXTERNAL_ERROR, formatError(result))); matchingRecords = matchingRecords.concat(result.body.domain_records.filter(function (record) { return (record.type === type && record.name === subdomain); @@ -102,10 +102,10 @@ function upsert(dnsConfig, zoneName, subdomain, type, values, callback) { .send(data) .timeout(30 * 1000) .end(function (error, result) { - if (error && !error.response) return callback(new SubdomainError(SubdomainError.EXTERNAL_ERROR, util.format('Network error %s', error.message))); - if (result.statusCode === 403 || result.statusCode === 401) return callback(new SubdomainError(SubdomainError.ACCESS_DENIED, formatError(result))); - if (result.statusCode === 422) return callback(new SubdomainError(SubdomainError.BAD_FIELD, result.body.message)); - if (result.statusCode !== 201) return callback(new SubdomainError(SubdomainError.EXTERNAL_ERROR, formatError(result))); + if (error && !error.response) return callback(new DomainError(DomainError.EXTERNAL_ERROR, util.format('Network error %s', error.message))); + if (result.statusCode === 403 || result.statusCode === 401) return callback(new DomainError(DomainError.ACCESS_DENIED, formatError(result))); + if (result.statusCode === 422) return callback(new DomainError(DomainError.BAD_FIELD, result.body.message)); + if (result.statusCode !== 201) return callback(new DomainError(DomainError.EXTERNAL_ERROR, formatError(result))); recordIds.push(safe.query(result.body, 'domain_record.id')); @@ -120,10 +120,10 @@ function upsert(dnsConfig, zoneName, subdomain, type, values, callback) { // increment, as we have consumed the record ++i; - if (error && !error.response) return callback(new SubdomainError(SubdomainError.EXTERNAL_ERROR, util.format('Network error %s', error.message))); - if (result.statusCode === 403 || result.statusCode === 401) return callback(new SubdomainError(SubdomainError.ACCESS_DENIED, formatError(result))); - if (result.statusCode === 422) return callback(new SubdomainError(SubdomainError.BAD_FIELD, result.body.message)); - if (result.statusCode !== 200) return callback(new SubdomainError(SubdomainError.EXTERNAL_ERROR, formatError(result))); + if (error && !error.response) return callback(new DomainError(DomainError.EXTERNAL_ERROR, util.format('Network error %s', error.message))); + if (result.statusCode === 403 || result.statusCode === 401) return callback(new DomainError(DomainError.ACCESS_DENIED, formatError(result))); + if (result.statusCode === 422) return callback(new DomainError(DomainError.BAD_FIELD, result.body.message)); + if (result.statusCode !== 200) return callback(new DomainError(DomainError.EXTERNAL_ERROR, formatError(result))); recordIds.push(safe.query(result.body, 'domain_record.id')); @@ -186,10 +186,10 @@ function del(dnsConfig, zoneName, subdomain, type, values, callback) { .set('Authorization', 'Bearer ' + dnsConfig.token) .timeout(30 * 1000) .end(function (error, result) { - if (error && !error.response) return callback(new SubdomainError(SubdomainError.EXTERNAL_ERROR, util.format('Network error %s', error.message))); + if (error && !error.response) return callback(new DomainError(DomainError.EXTERNAL_ERROR, util.format('Network error %s', error.message))); if (result.statusCode === 404) return callback(null); - if (result.statusCode === 403 || result.statusCode === 401) return callback(new SubdomainError(SubdomainError.ACCESS_DENIED, formatError(result))); - if (result.statusCode !== 204) return callback(new SubdomainError(SubdomainError.EXTERNAL_ERROR, formatError(result))); + if (result.statusCode === 403 || result.statusCode === 401) return callback(new DomainError(DomainError.ACCESS_DENIED, formatError(result))); + if (result.statusCode !== 204) return callback(new DomainError(DomainError.EXTERNAL_ERROR, formatError(result))); debug('del: done'); @@ -213,12 +213,12 @@ function verifyDnsConfig(dnsConfig, fqdn, zoneName, ip, callback) { if (process.env.BOX_ENV === 'test') return callback(null, credentials); // this shouldn't be here dns.resolveNs(zoneName, function (error, nameservers) { - if (error && error.code === 'ENOTFOUND') return callback(new SubdomainError(SubdomainError.BAD_FIELD, 'Unable to resolve nameservers for this domain')); - if (error || !nameservers) return callback(new SubdomainError(SubdomainError.BAD_FIELD, error ? error.message : 'Unable to get nameservers')); + if (error && error.code === 'ENOTFOUND') return callback(new DomainError(DomainError.BAD_FIELD, 'Unable to resolve nameservers for this domain')); + if (error || !nameservers) return callback(new DomainError(DomainError.BAD_FIELD, error ? error.message : 'Unable to get nameservers')); if (nameservers.map(function (n) { return n.toLowerCase(); }).indexOf('ns1.digitalocean.com') === -1) { debug('verifyDnsConfig: %j does not contains DO NS', nameservers); - return callback(new SubdomainError(SubdomainError.BAD_FIELD, 'Domain nameservers are not set to Digital Ocean')); + return callback(new DomainError(DomainError.BAD_FIELD, 'Domain nameservers are not set to Digital Ocean')); } const name = config.adminLocation() + (fqdn === zoneName ? '' : '.' + fqdn.slice(0, - zoneName.length - 1)); diff --git a/src/dns/gcdns.js b/src/dns/gcdns.js index 5199469eb..6b06c8bbe 100644 --- a/src/dns/gcdns.js +++ b/src/dns/gcdns.js @@ -12,8 +12,8 @@ var assert = require('assert'), config = require('../config.js'), debug = require('debug')('box:dns/gcdns'), dns = require('dns'), + DomainError = require('../domains.js').DomainError, GCDNS = require('@google-cloud/dns'), - SubdomainError = require('../subdomains.js').SubdomainError, util = require('util'), _ = require('underscore'); @@ -44,20 +44,20 @@ function getZoneByName(dnsConfig, zoneName, callback) { var gcdns = GCDNS(getDnsCredentials(dnsConfig)); gcdns.getZones(function (error, zones) { - if (error && error.message === 'invalid_grant') return callback(new SubdomainError(SubdomainError.ACCESS_DENIED, 'The key was probably revoked')); - if (error && error.reason === 'No such domain') return callback(new SubdomainError(SubdomainError.NOT_FOUND, error.message)); - if (error && error.code === 403) return callback(new SubdomainError(SubdomainError.ACCESS_DENIED, error.message)); - if (error && error.code === 404) return callback(new SubdomainError(SubdomainError.NOT_FOUND, error.message)); + if (error && error.message === 'invalid_grant') return callback(new DomainError(DomainError.ACCESS_DENIED, 'The key was probably revoked')); + if (error && error.reason === 'No such domain') return callback(new DomainError(DomainError.NOT_FOUND, error.message)); + if (error && error.code === 403) return callback(new DomainError(DomainError.ACCESS_DENIED, error.message)); + if (error && error.code === 404) return callback(new DomainError(DomainError.NOT_FOUND, error.message)); if (error) { debug('gcdns.getZones', error); - return callback(new SubdomainError(SubdomainError.EXTERNAL_ERROR, error)); + return callback(new DomainError(DomainError.EXTERNAL_ERROR, error)); } var zone = zones.filter(function (zone) { return zone.metadata.dnsName.slice(0, -1) === zoneName; // the zone name contains a '.' at the end })[0]; - if (!zone) return callback(new SubdomainError(SubdomainError.NOT_FOUND, 'no such zone')); + if (!zone) return callback(new DomainError(DomainError.NOT_FOUND, 'no such zone')); callback(null, zone); //zone.metadata ~= {name="", dnsName="", nameServers:[]} }); @@ -79,10 +79,10 @@ function upsert(dnsConfig, zoneName, subdomain, type, values, callback) { var domain = (subdomain ? subdomain + '.' : '') + zoneName + '.'; zone.getRecords({ type: type, name: domain }, function (error, oldRecords) { - if (error && error.code === 403) return callback(new SubdomainError(SubdomainError.ACCESS_DENIED, error.message)); + if (error && error.code === 403) return callback(new DomainError(DomainError.ACCESS_DENIED, error.message)); if (error) { debug('upsert->zone.getRecords', error); - return callback(new SubdomainError(SubdomainError.EXTERNAL_ERROR, error.message)); + return callback(new DomainError(DomainError.EXTERNAL_ERROR, error.message)); } var newRecord = zone.record(type, { @@ -92,11 +92,11 @@ function upsert(dnsConfig, zoneName, subdomain, type, values, callback) { }); zone.createChange({ delete: oldRecords, add: newRecord }, function(error, change) { - if (error && error.code === 403) return callback(new SubdomainError(SubdomainError.ACCESS_DENIED, error.message)); - if (error && error.code === 412) return callback(new SubdomainError(SubdomainError.STILL_BUSY, error.message)); + if (error && error.code === 403) return callback(new DomainError(DomainError.ACCESS_DENIED, error.message)); + if (error && error.code === 412) return callback(new DomainError(DomainError.STILL_BUSY, error.message)); if (error) { debug('upsert->zone.createChange', error); - return callback(new SubdomainError(SubdomainError.EXTERNAL_ERROR, error.message)); + return callback(new DomainError(DomainError.EXTERNAL_ERROR, error.message)); } callback(null, change.id); @@ -121,8 +121,8 @@ function get(dnsConfig, zoneName, subdomain, type, callback) { }; zone.getRecords(params, function (error, records) { - if (error && error.code === 403) return callback(new SubdomainError(SubdomainError.ACCESS_DENIED, error.message)); - if (error) return callback(new SubdomainError(SubdomainError.EXTERNAL_ERROR, error)); + if (error && error.code === 403) return callback(new DomainError(DomainError.ACCESS_DENIED, error.message)); + if (error) return callback(new DomainError(DomainError.EXTERNAL_ERROR, error)); if (records.length === 0) return callback(null, [ ]); return callback(null, records[0].data); @@ -144,18 +144,18 @@ function del(dnsConfig, zoneName, subdomain, type, values, callback) { var domain = (subdomain ? subdomain + '.' : '') + zoneName + '.'; zone.getRecords({ type: type, name: domain }, function(error, oldRecords) { - if (error && error.code === 403) return callback(new SubdomainError(SubdomainError.ACCESS_DENIED, error.message)); + if (error && error.code === 403) return callback(new DomainError(DomainError.ACCESS_DENIED, error.message)); if (error) { debug('del->zone.getRecords', error); - return callback(new SubdomainError(SubdomainError.EXTERNAL_ERROR, error.message)); + return callback(new DomainError(DomainError.EXTERNAL_ERROR, error.message)); } zone.deleteRecords(oldRecords, function (error, change) { - if (error && error.code === 403) return callback(new SubdomainError(SubdomainError.ACCESS_DENIED, error.message)); - if (error && error.code === 412) return callback(new SubdomainError(SubdomainError.STILL_BUSY, error.message)); + if (error && error.code === 403) return callback(new DomainError(DomainError.ACCESS_DENIED, error.message)); + if (error && error.code === 412) return callback(new DomainError(DomainError.STILL_BUSY, error.message)); if (error) { debug('del->zone.createChange', error); - return callback(new SubdomainError(SubdomainError.EXTERNAL_ERROR, error.message)); + return callback(new DomainError(DomainError.EXTERNAL_ERROR, error.message)); } callback(null, change.id); @@ -175,8 +175,8 @@ function verifyDnsConfig(dnsConfig, fqdn, zoneName, ip, callback) { if (process.env.BOX_ENV === 'test') return callback(null, credentials); // this shouldn't be here dns.resolveNs(zoneName, function (error, resolvedNS) { - if (error && error.code === 'ENOTFOUND') return callback(new SubdomainError(SubdomainError.BAD_FIELD, 'Unable to resolve nameservers for this domain')); - if (error || !resolvedNS) return callback(new SubdomainError(SubdomainError.BAD_FIELD, error ? error.message : 'Unable to get nameservers')); + if (error && error.code === 'ENOTFOUND') return callback(new DomainError(DomainError.BAD_FIELD, 'Unable to resolve nameservers for this domain')); + if (error || !resolvedNS) return callback(new DomainError(DomainError.BAD_FIELD, error ? error.message : 'Unable to get nameservers')); getZoneByName(credentials, zoneName, function (error, zone) { if (error) return callback(error); @@ -184,7 +184,7 @@ function verifyDnsConfig(dnsConfig, fqdn, zoneName, ip, callback) { var definedNS = zone.metadata.nameServers.sort().map(function(r) { return r.replace(/\.$/, ''); }); if (!_.isEqual(definedNS, resolvedNS.sort())) { debug('verifyDnsConfig: %j and %j do not match', resolvedNS, definedNS); - return callback(new SubdomainError(SubdomainError.BAD_FIELD, 'Domain nameservers are not set to Google Cloud DNS')); + return callback(new DomainError(DomainError.BAD_FIELD, 'Domain nameservers are not set to Google Cloud DNS')); } const name = config.adminLocation() + (fqdn === zoneName ? '' : '.' + fqdn.slice(0, - zoneName.length - 1)); diff --git a/src/dns/interface.js b/src/dns/interface.js index ac6b5ae40..15aeb0a80 100644 --- a/src/dns/interface.js +++ b/src/dns/interface.js @@ -15,7 +15,7 @@ exports = module.exports = { }; var assert = require('assert'), - SubdomainError = require('../subdomains.js').SubdomainError, + DomainError = require('../domains.js').DomainError, util = require('util'); function upsert(dnsConfig, zoneName, subdomain, type, values, callback) { diff --git a/src/dns/manual.js b/src/dns/manual.js index 4f6ef1860..4dcbea9ac 100644 --- a/src/dns/manual.js +++ b/src/dns/manual.js @@ -14,7 +14,7 @@ var assert = require('assert'), debug = require('debug')('box:dns/manual'), dig = require('../dig.js'), dns = require('dns'), - SubdomainError = require('../subdomains.js').SubdomainError, + DomainError = require('../domains.js').DomainError, util = require('util'); function upsert(dnsConfig, zoneName, subdomain, type, values, callback) { @@ -61,13 +61,13 @@ function verifyDnsConfig(dnsConfig, domain, zoneName, ip, callback) { var adminDomain = config.adminLocation() + '.' + domain; dns.resolveNs(zoneName, function (error, nameservers) { - if (error || !nameservers) return callback(new SubdomainError(SubdomainError.BAD_FIELD, 'Unable to get nameservers')); + if (error || !nameservers) return callback(new DomainError(DomainError.BAD_FIELD, 'Unable to get nameservers')); async.every(nameservers, function (nameserver, everyNsCallback) { // ns records cannot have cname dns.resolve4(nameserver, function (error, nsIps) { if (error || !nsIps || nsIps.length === 0) { - return everyNsCallback(new SubdomainError(SubdomainError.BAD_FIELD, 'Unable to resolve nameservers for this domain')); + return everyNsCallback(new DomainError(DomainError.BAD_FIELD, 'Unable to resolve nameservers for this domain')); } async.every(nsIps, function (nsIp, everyIpCallback) { @@ -99,7 +99,7 @@ function verifyDnsConfig(dnsConfig, domain, zoneName, ip, callback) { }); }, function (error, success) { if (error) return callback(error); - if (!success) return callback(new SubdomainError(SubdomainError.BAD_FIELD, 'The domain ' + adminDomain + ' does not resolve to the server\'s IP ' + ip)); + if (!success) return callback(new DomainError(DomainError.BAD_FIELD, 'The domain ' + adminDomain + ' does not resolve to the server\'s IP ' + ip)); callback(null, { provider: dnsConfig.provider, wildcard: !!dnsConfig.wildcard }); }); diff --git a/src/dns/route53.js b/src/dns/route53.js index 80b01a663..3c9b7140a 100644 --- a/src/dns/route53.js +++ b/src/dns/route53.js @@ -16,7 +16,7 @@ var assert = require('assert'), config = require('../config.js'), debug = require('debug')('box:dns/route53'), dns = require('dns'), - SubdomainError = require('../subdomains.js').SubdomainError, + DomainError = require('../domains.js').DomainError, util = require('util'), _ = require('underscore'); @@ -41,15 +41,15 @@ function getZoneByName(dnsConfig, zoneName, callback) { var route53 = new AWS.Route53(getDnsCredentials(dnsConfig)); route53.listHostedZones({}, function (error, result) { - if (error && error.code === 'AccessDenied') return callback(new SubdomainError(SubdomainError.ACCESS_DENIED, error.message)); - if (error && error.code === 'InvalidClientTokenId') return callback(new SubdomainError(SubdomainError.ACCESS_DENIED, error.message)); - if (error) return callback(new SubdomainError(SubdomainError.EXTERNAL_ERROR, error.message)); + if (error && error.code === 'AccessDenied') return callback(new DomainError(DomainError.ACCESS_DENIED, error.message)); + if (error && error.code === 'InvalidClientTokenId') return callback(new DomainError(DomainError.ACCESS_DENIED, error.message)); + if (error) return callback(new DomainError(DomainError.EXTERNAL_ERROR, error.message)); var zone = result.HostedZones.filter(function (zone) { return zone.Name.slice(0, -1) === zoneName; // aws zone name contains a '.' at the end })[0]; - if (!zone) return callback(new SubdomainError(SubdomainError.NOT_FOUND, 'no such zone')); + if (!zone) return callback(new DomainError(DomainError.NOT_FOUND, 'no such zone')); callback(null, zone); }); @@ -65,9 +65,9 @@ function getHostedZone(dnsConfig, zoneName, callback) { var route53 = new AWS.Route53(getDnsCredentials(dnsConfig)); route53.getHostedZone({ Id: zone.Id }, function (error, result) { - if (error && error.code === 'AccessDenied') return callback(new SubdomainError(SubdomainError.ACCESS_DENIED, error.message)); - if (error && error.code === 'InvalidClientTokenId') return callback(new SubdomainError(SubdomainError.ACCESS_DENIED, error.message)); - if (error) return callback(new SubdomainError(SubdomainError.EXTERNAL_ERROR, error.message)); + if (error && error.code === 'AccessDenied') return callback(new DomainError(DomainError.ACCESS_DENIED, error.message)); + if (error && error.code === 'InvalidClientTokenId') return callback(new DomainError(DomainError.ACCESS_DENIED, error.message)); + if (error) return callback(new DomainError(DomainError.EXTERNAL_ERROR, error.message)); callback(null, result); }); @@ -107,11 +107,11 @@ function add(dnsConfig, zoneName, subdomain, type, values, callback) { var route53 = new AWS.Route53(getDnsCredentials(dnsConfig)); route53.changeResourceRecordSets(params, function(error, result) { - if (error && error.code === 'AccessDenied') return callback(new SubdomainError(SubdomainError.ACCESS_DENIED, error.message)); - if (error && error.code === 'InvalidClientTokenId') return callback(new SubdomainError(SubdomainError.ACCESS_DENIED, error.message)); - if (error && error.code === 'PriorRequestNotComplete') return callback(new SubdomainError(SubdomainError.STILL_BUSY, error.message)); - if (error && error.code === 'InvalidChangeBatch') return callback(new SubdomainError(SubdomainError.BAD_FIELD, error.message)); - if (error) return callback(new SubdomainError(SubdomainError.EXTERNAL_ERROR, error.message)); + if (error && error.code === 'AccessDenied') return callback(new DomainError(DomainError.ACCESS_DENIED, error.message)); + if (error && error.code === 'InvalidClientTokenId') return callback(new DomainError(DomainError.ACCESS_DENIED, error.message)); + if (error && error.code === 'PriorRequestNotComplete') return callback(new DomainError(DomainError.STILL_BUSY, error.message)); + if (error && error.code === 'InvalidChangeBatch') return callback(new DomainError(DomainError.BAD_FIELD, error.message)); + if (error) return callback(new DomainError(DomainError.EXTERNAL_ERROR, error.message)); callback(null, result.ChangeInfo.Id); }); @@ -148,9 +148,9 @@ function get(dnsConfig, zoneName, subdomain, type, callback) { var route53 = new AWS.Route53(getDnsCredentials(dnsConfig)); route53.listResourceRecordSets(params, function (error, result) { - if (error && error.code === 'AccessDenied') return callback(new SubdomainError(SubdomainError.ACCESS_DENIED, error.message)); - if (error && error.code === 'InvalidClientTokenId') return callback(new SubdomainError(SubdomainError.ACCESS_DENIED, error.message)); - if (error) return callback(new SubdomainError(SubdomainError.EXTERNAL_ERROR, error.message)); + if (error && error.code === 'AccessDenied') return callback(new DomainError(DomainError.ACCESS_DENIED, error.message)); + if (error && error.code === 'InvalidClientTokenId') return callback(new DomainError(DomainError.ACCESS_DENIED, error.message)); + if (error) return callback(new DomainError(DomainError.EXTERNAL_ERROR, error.message)); if (result.ResourceRecordSets.length === 0) return callback(null, [ ]); if (result.ResourceRecordSets[0].Name !== params.StartRecordName || result.ResourceRecordSets[0].Type !== params.StartRecordType) return callback(null, [ ]); @@ -194,23 +194,23 @@ function del(dnsConfig, zoneName, subdomain, type, values, callback) { var route53 = new AWS.Route53(getDnsCredentials(dnsConfig)); route53.changeResourceRecordSets(params, function(error, result) { - if (error && error.code === 'AccessDenied') return callback(new SubdomainError(SubdomainError.ACCESS_DENIED, error.message)); - if (error && error.code === 'InvalidClientTokenId') return callback(new SubdomainError(SubdomainError.ACCESS_DENIED, error.message)); + if (error && error.code === 'AccessDenied') return callback(new DomainError(DomainError.ACCESS_DENIED, error.message)); + if (error && error.code === 'InvalidClientTokenId') return callback(new DomainError(DomainError.ACCESS_DENIED, error.message)); if (error && error.message && error.message.indexOf('it was not found') !== -1) { debug('del: resource record set not found.', error); - return callback(new SubdomainError(SubdomainError.NOT_FOUND, error.message)); + return callback(new DomainError(DomainError.NOT_FOUND, error.message)); } else if (error && error.code === 'NoSuchHostedZone') { debug('del: hosted zone not found.', error); - return callback(new SubdomainError(SubdomainError.NOT_FOUND, error.message)); + return callback(new DomainError(DomainError.NOT_FOUND, error.message)); } else if (error && error.code === 'PriorRequestNotComplete') { debug('del: resource is still busy', error); - return callback(new SubdomainError(SubdomainError.STILL_BUSY, error.message)); + return callback(new DomainError(DomainError.STILL_BUSY, error.message)); } else if (error && error.code === 'InvalidChangeBatch') { debug('del: invalid change batch. No such record to be deleted.'); - return callback(new SubdomainError(SubdomainError.NOT_FOUND, error.message)); + return callback(new DomainError(DomainError.NOT_FOUND, error.message)); } else if (error) { debug('del: error', error); - return callback(new SubdomainError(SubdomainError.EXTERNAL_ERROR, error.message)); + return callback(new DomainError(DomainError.EXTERNAL_ERROR, error.message)); } callback(null); @@ -236,15 +236,15 @@ function verifyDnsConfig(dnsConfig, fqdn, zoneName, ip, callback) { if (process.env.BOX_ENV === 'test') return callback(null, credentials); // this shouldn't be here dns.resolveNs(zoneName, function (error, nameservers) { - if (error && error.code === 'ENOTFOUND') return callback(new SubdomainError(SubdomainError.BAD_FIELD, 'Unable to resolve nameservers for this domain')); - if (error || !nameservers) return callback(new SubdomainError(SubdomainError.BAD_FIELD, error ? error.message : 'Unable to get nameservers')); + if (error && error.code === 'ENOTFOUND') return callback(new DomainError(DomainError.BAD_FIELD, 'Unable to resolve nameservers for this domain')); + if (error || !nameservers) return callback(new DomainError(DomainError.BAD_FIELD, error ? error.message : 'Unable to get nameservers')); getHostedZone(credentials, zoneName, function (error, zone) { if (error) return callback(error); if (!_.isEqual(zone.DelegationSet.NameServers.sort(), nameservers.sort())) { debug('verifyDnsConfig: %j and %j do not match', nameservers, zone.DelegationSet.NameServers); - return callback(new SubdomainError(SubdomainError.BAD_FIELD, 'Domain nameservers are not set to Route53')); + return callback(new DomainError(DomainError.BAD_FIELD, 'Domain nameservers are not set to Route53')); } const name = config.adminLocation() + (fqdn === zoneName ? '' : '.' + fqdn.slice(0, - zoneName.length - 1)); diff --git a/src/dns/waitfordns.js b/src/dns/waitfordns.js index 3e2dc2365..5d1a3287d 100644 --- a/src/dns/waitfordns.js +++ b/src/dns/waitfordns.js @@ -7,7 +7,7 @@ var assert = require('assert'), debug = require('debug')('box:dns/waitfordns'), dig = require('../dig.js'), dns = require('dns'), - SubdomainError = require('../subdomains.js').SubdomainError, + DomainError = require('../domains.js').DomainError, util = require('util'); function isChangeSynced(domain, value, type, nameserver, callback) { @@ -79,12 +79,12 @@ function waitForDns(domain, zoneName, value, type, options, callback) { debug('waitForDNS: %s attempt %s.', domain, attempt++); dns.resolveNs(zoneName, function (error, nameservers) { - if (error || !nameservers) return retryCallback(error || new SubdomainError(SubdomainError.EXTERNAL_ERROR, 'Unable to get nameservers')); + if (error || !nameservers) return retryCallback(error || new DomainError(DomainError.EXTERNAL_ERROR, 'Unable to get nameservers')); async.every(nameservers, isChangeSynced.bind(null, domain, value, type), function (error, synced) { debug('waitForIp: %s %s ns: %j', domain, synced ? 'done' : 'not done', nameservers); - retryCallback(synced ? null : new SubdomainError(SubdomainError.EXTERNAL_ERROR, 'ETRYAGAIN')); + retryCallback(synced ? null : new DomainError(DomainError.EXTERNAL_ERROR, 'ETRYAGAIN')); }); }); }, function retryDone(error) { diff --git a/src/domains.js b/src/domains.js index 42414097a..3ac1e2b24 100644 --- a/src/domains.js +++ b/src/domains.js @@ -19,7 +19,6 @@ module.exports = exports = { var assert = require('assert'), DatabaseError = require('./databaseerror.js'), domaindb = require('./domaindb.js'), - SubdomainError = require('./subdomains.js').SubdomainError, sysinfo = require('./sysinfo.js'), tld = require('tldjs'), util = require('util'); @@ -69,7 +68,7 @@ function api(provider) { } } -// TODO make it return a DomainError instead of SubdomainError +// TODO make it return a DomainError instead of DomainError function verifyDnsConfig(config, domain, zoneName, ip, callback) { assert(config && typeof config === 'object'); // the dns config to test with assert(typeof config.provider === 'string'); @@ -79,7 +78,7 @@ function verifyDnsConfig(config, domain, zoneName, ip, callback) { assert.strictEqual(typeof callback, 'function'); var backend = api(config.provider); - if (!backend) return callback(new SubdomainError(SubdomainError.INVALID_PROVIDER)); + if (!backend) return callback(new DomainError(DomainError.INVALID_PROVIDER)); api(config.provider).verifyDnsConfig(config, domain, zoneName, ip, callback); } @@ -98,11 +97,11 @@ function add(domain, zoneName, config, callback) { if (error) return callback(new DomainError(DomainError.INTERNAL_ERROR, 'Error getting IP:' + error.message)); verifyDnsConfig(config, domain, zoneName, ip, function (error, result) { - if (error && error.reason === SubdomainError.ACCESS_DENIED) return callback(new DomainError(DomainError.BAD_FIELD, 'Error adding A record. Access denied')); - if (error && error.reason === SubdomainError.NOT_FOUND) return callback(new DomainError(DomainError.BAD_FIELD, 'Zone not found')); - if (error && error.reason === SubdomainError.EXTERNAL_ERROR) return callback(new DomainError(DomainError.BAD_FIELD, 'Error adding A record:' + error.message)); - if (error && error.reason === SubdomainError.BAD_FIELD) return callback(new DomainError(DomainError.BAD_FIELD, error.message)); - if (error && error.reason === SubdomainError.INVALID_PROVIDER) return callback(new DomainError(DomainError.BAD_FIELD, error.message)); + if (error && error.reason === DomainError.ACCESS_DENIED) return callback(new DomainError(DomainError.BAD_FIELD, 'Error adding A record. Access denied')); + if (error && error.reason === DomainError.NOT_FOUND) return callback(new DomainError(DomainError.BAD_FIELD, 'Zone not found')); + if (error && error.reason === DomainError.EXTERNAL_ERROR) return callback(new DomainError(DomainError.BAD_FIELD, 'Error adding A record:' + error.message)); + if (error && error.reason === DomainError.BAD_FIELD) return callback(new DomainError(DomainError.BAD_FIELD, error.message)); + if (error && error.reason === DomainError.INVALID_PROVIDER) return callback(new DomainError(DomainError.BAD_FIELD, error.message)); if (error) return callback(new DomainError(DomainError.INTERNAL_ERROR, error)); domaindb.add(domain, zoneName, result, function (error) { @@ -150,11 +149,11 @@ function update(domain, config, callback) { if (error) return callback(new DomainError(DomainError.INTERNAL_ERROR, 'Error getting IP:' + error.message)); verifyDnsConfig(config, domain, result.zoneName, ip, function (error, result) { - if (error && error.reason === SubdomainError.ACCESS_DENIED) return callback(new DomainError(DomainError.BAD_FIELD, 'Error adding A record. Access denied')); - if (error && error.reason === SubdomainError.NOT_FOUND) return callback(new DomainError(DomainError.BAD_FIELD, 'Zone not found')); - if (error && error.reason === SubdomainError.EXTERNAL_ERROR) return callback(new DomainError(DomainError.BAD_FIELD, 'Error adding A record:' + error.message)); - if (error && error.reason === SubdomainError.BAD_FIELD) return callback(new DomainError(DomainError.BAD_FIELD, error.message)); - if (error && error.reason === SubdomainError.INVALID_PROVIDER) return callback(new DomainError(DomainError.BAD_FIELD, error.message)); + if (error && error.reason === DomainError.ACCESS_DENIED) return callback(new DomainError(DomainError.BAD_FIELD, 'Error adding A record. Access denied')); + if (error && error.reason === DomainError.NOT_FOUND) return callback(new DomainError(DomainError.BAD_FIELD, 'Zone not found')); + if (error && error.reason === DomainError.EXTERNAL_ERROR) return callback(new DomainError(DomainError.BAD_FIELD, 'Error adding A record:' + error.message)); + if (error && error.reason === DomainError.BAD_FIELD) return callback(new DomainError(DomainError.BAD_FIELD, error.message)); + if (error && error.reason === DomainError.INVALID_PROVIDER) return callback(new DomainError(DomainError.BAD_FIELD, error.message)); if (error) return callback(new DomainError(DomainError.INTERNAL_ERROR, error)); domaindb.update(domain, result, function (error) { @@ -234,7 +233,7 @@ function removeDNSRecords(fqdn, type, values, callback) { if (error) return callback(new DomainError(DomainError.INTERNAL_ERROR, error)); api(result.config.provider).del(result.config, result.zoneName, subdomain, type, values, function (error) { - if (error && error.reason !== SubdomainError.NOT_FOUND) return callback(error); + if (error && error.reason !== DomainError.NOT_FOUND) return callback(error); callback(null); }); diff --git a/src/settings.js b/src/settings.js index e28bb7fde..e55721e7e 100644 --- a/src/settings.js +++ b/src/settings.js @@ -95,7 +95,6 @@ var assert = require('assert'), EmailError = email.EmailError, safe = require('safetydance'), settingsdb = require('./settingsdb.js'), - SubdomainError = require('./subdomains.js').SubdomainError, superagent = require('superagent'), util = require('util'), _ = require('underscore'); @@ -315,11 +314,11 @@ function setDnsConfig(dnsConfig, domain, zoneName, callback) { assert.strictEqual(typeof callback, 'function'); function done(error) { - if (error && error.reason === SubdomainError.ACCESS_DENIED) return callback(new SettingsError(SettingsError.BAD_FIELD, 'Error adding A record. Access denied')); - if (error && error.reason === SubdomainError.NOT_FOUND) return callback(new SettingsError(SettingsError.BAD_FIELD, 'Zone not found')); - if (error && error.reason === SubdomainError.EXTERNAL_ERROR) return callback(new SettingsError(SettingsError.BAD_FIELD, 'Error adding A record:' + error.message)); - if (error && error.reason === SubdomainError.BAD_FIELD) return callback(new SettingsError(SettingsError.BAD_FIELD, error.message)); - if (error && error.reason === SubdomainError.INVALID_PROVIDER) return callback(new SettingsError(SettingsError.BAD_FIELD, error.message)); + if (error && error.reason === DomainError.ACCESS_DENIED) return callback(new SettingsError(SettingsError.BAD_FIELD, 'Error adding A record. Access denied')); + if (error && error.reason === DomainError.NOT_FOUND) return callback(new SettingsError(SettingsError.BAD_FIELD, 'Zone not found')); + if (error && error.reason === DomainError.EXTERNAL_ERROR) return callback(new SettingsError(SettingsError.BAD_FIELD, 'Error adding A record:' + error.message)); + if (error && error.reason === DomainError.BAD_FIELD) return callback(new SettingsError(SettingsError.BAD_FIELD, error.message)); + if (error && error.reason === DomainError.INVALID_PROVIDER) return callback(new SettingsError(SettingsError.BAD_FIELD, error.message)); if (error) return callback(new SettingsError(SettingsError.INTERNAL_ERROR, error)); cloudron.configureWebadmin(NOOP_CALLBACK); // do not block diff --git a/src/subdomains.js b/src/subdomains.js deleted file mode 100644 index 36b8f6ecd..000000000 --- a/src/subdomains.js +++ /dev/null @@ -1,157 +0,0 @@ -'use strict'; - -module.exports = exports = { - remove: remove, - upsert: upsert, - get: get, - waitForDns: waitForDns, - verifyDnsConfig: verifyDnsConfig, - - SubdomainError: SubdomainError -}; - -var assert = require('assert'), - config = require('./config.js'), - settings = require('./settings.js'), - tld = require('tldjs'), - util = require('util'); - -function SubdomainError(reason, errorOrMessage) { - assert.strictEqual(typeof reason, 'string'); - assert(errorOrMessage instanceof Error || typeof errorOrMessage === 'string' || typeof errorOrMessage === 'undefined'); - - Error.call(this); - Error.captureStackTrace(this, this.constructor); - - this.name = this.constructor.name; - this.reason = reason; - if (typeof errorOrMessage === 'undefined') { - this.message = reason; - } else if (typeof errorOrMessage === 'string') { - this.message = errorOrMessage; - } else { - this.message = 'Internal error'; - this.nestedError = errorOrMessage; - } -} -util.inherits(SubdomainError, Error); - -SubdomainError.NOT_FOUND = 'No such domain'; -SubdomainError.ALREADY_EXISTS = 'Domain already exists'; -SubdomainError.EXTERNAL_ERROR = 'External error'; -SubdomainError.BAD_FIELD = 'Bad Field'; -SubdomainError.STILL_BUSY = 'Still busy'; -SubdomainError.INTERNAL_ERROR = 'Internal error'; -SubdomainError.ACCESS_DENIED = 'Access denied'; -SubdomainError.INVALID_PROVIDER = 'provider must be route53, gcdns, digitalocean, cloudflare, noop, manual or caas'; - -// choose which subdomain backend we use for test purpose we use route53 -function api(provider) { - assert.strictEqual(typeof provider, 'string'); - - switch (provider) { - case 'caas': return require('./dns/caas.js'); - case 'cloudflare': return require('./dns/cloudflare.js'); - case 'route53': return require('./dns/route53.js'); - case 'gcdns': return require('./dns/gcdns.js'); - case 'digitalocean': return require('./dns/digitalocean.js'); - case 'noop': return require('./dns/noop.js'); - case 'manual': return require('./dns/manual.js'); - default: return null; - } -} - -function getName(subdomain) { - // support special caas domains - if (!config.isCustomDomain()) return subdomain; - - if (config.fqdn() === config.zoneName()) return subdomain; - - var part = config.fqdn().slice(0, -config.zoneName().length - 1); - - return subdomain === '' ? part : subdomain + '.' + part; -} - -function get(subdomain, type, callback) { - assert.strictEqual(typeof subdomain, 'string'); - assert.strictEqual(typeof type, 'string'); - assert.strictEqual(typeof callback, 'function'); - - settings.getDnsConfig(function (error, dnsConfig) { - if (error) return callback(new SubdomainError(SubdomainError.INTERNAL_ERROR, error)); - - api(dnsConfig.provider).get(dnsConfig, config.zoneName(), getName(subdomain), type, function (error, values) { - if (error) return callback(error); - - callback(null, values); - }); - }); -} - -function upsert(subdomain, type, values, callback) { - assert.strictEqual(typeof subdomain, 'string'); - assert.strictEqual(typeof type, 'string'); - assert(util.isArray(values)); - assert.strictEqual(typeof callback, 'function'); - - settings.getDnsConfig(function (error, dnsConfig) { - if (error) return callback(new SubdomainError(SubdomainError.INTERNAL_ERROR, error)); - - api(dnsConfig.provider).upsert(dnsConfig, config.zoneName(), getName(subdomain), type, values, function (error, changeId) { - if (error) return callback(error); - - callback(null, changeId); - }); - }); -} - -function remove(subdomain, type, values, callback) { - assert.strictEqual(typeof subdomain, 'string'); - assert.strictEqual(typeof type, 'string'); - assert(util.isArray(values)); - assert.strictEqual(typeof callback, 'function'); - - settings.getDnsConfig(function (error, dnsConfig) { - if (error) return callback(new SubdomainError(SubdomainError.INTERNAL_ERROR, error)); - - api(dnsConfig.provider).del(dnsConfig, config.zoneName(), getName(subdomain), type, values, function (error) { - if (error && error.reason !== SubdomainError.NOT_FOUND) return callback(error); - - callback(null); - }); - }); -} - -function waitForDns(domain, value, type, options, callback) { - assert.strictEqual(typeof domain, 'string'); - assert(typeof value === 'string' || util.isRegExp(value)); - assert(type === 'A' || type === 'CNAME' || type === 'TXT'); - assert(options && typeof options === 'object'); // { interval: 5000, times: 50000 } - assert.strictEqual(typeof callback, 'function'); - - settings.getDnsConfig(function (error, dnsConfig) { - if (error) return callback(new SubdomainError(SubdomainError.INTERNAL_ERROR, error)); - - var zoneName = config.zoneName(); - - // if the domain is on another zone in case of external domain, use the correct zone - if (!domain.endsWith(zoneName)) zoneName = tld.getDomain(domain); - - api(dnsConfig.provider).waitForDns(domain, zoneName, value, type, options, callback); - }); -} - -// TODO move to domains.js -function verifyDnsConfig(dnsConfig, domain, zoneName, ip, callback) { - assert(dnsConfig && typeof dnsConfig === 'object'); // the dns config to test with - assert(typeof dnsConfig.provider === 'string'); - assert.strictEqual(typeof domain, 'string'); - assert.strictEqual(typeof zoneName, 'string'); - assert.strictEqual(typeof ip, 'string'); - assert.strictEqual(typeof callback, 'function'); - - var backend = api(dnsConfig.provider); - if (!backend) return callback(new SubdomainError(SubdomainError.INVALID_PROVIDER)); - - api(dnsConfig.provider).verifyDnsConfig(dnsConfig, domain, zoneName, ip, callback); -}