Add pre-flight check for domain collision
This commit is contained in:
@@ -1721,6 +1721,15 @@ angular.module('Application').service('Client', ['$http', '$interval', '$timeout
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Client.prototype.getDNSRecords = function (domain, subdomain, type, callback) {
|
||||||
|
get('/api/v1/domains/' + domain + '/dns?subdomain=' + subdomain + '&type=' + type, null, function (error, data, status) {
|
||||||
|
if (error) return callback(error);
|
||||||
|
if (status !== 200) return callback(new ClientError(status, data));
|
||||||
|
|
||||||
|
callback(null, data.values);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
Client.prototype.addMailDomain = function (domain, callback) {
|
Client.prototype.addMailDomain = function (domain, callback) {
|
||||||
post('/api/v1/mail', { domain: domain }, null, function (error, data, status) {
|
post('/api/v1/mail', { domain: domain }, null, function (error, data, status) {
|
||||||
if (error) return callback(error);
|
if (error) return callback(error);
|
||||||
|
|||||||
@@ -81,6 +81,28 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Modal domain collision -->
|
||||||
|
<div class="modal fade" id="domainCollisionsModal" tabindex="-1" role="dialog">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h4 class="modal-title">Domain Collision</h4>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<p>By default Cloudron does not overwrite DNS records which exist outside of Cloudron.</p>
|
||||||
|
<p>The following domains already exist outside of Cloudron:</p>
|
||||||
|
<ul>
|
||||||
|
<li ng-repeat="domain in location.domainCollisions">{{ domain.subdomain + '.' + domain.domain }}</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
|
||||||
|
<button type="button" class="btn btn-danger" ng-click="location.submit(true)">Overwrite existing DNS Records</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Modal update app -->
|
<!-- Modal update app -->
|
||||||
<div class="modal fade" id="updateModal" tabindex="-1" role="dialog">
|
<div class="modal fade" id="updateModal" tabindex="-1" role="dialog">
|
||||||
<div class="modal-dialog">
|
<div class="modal-dialog">
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
/* global angular */
|
/* global angular */
|
||||||
/* global $ */
|
/* global $ */
|
||||||
/* global asyncSeries */
|
/* global asyncSeries */
|
||||||
|
/* global asyncForEach */
|
||||||
|
|
||||||
|
|
||||||
// TODO use this once we enable custom SSL certificate ui again
|
// TODO use this once we enable custom SSL certificate ui again
|
||||||
@@ -156,7 +157,7 @@ angular.module('Application').controller('AppController', ['$scope', '$location'
|
|||||||
$scope.location = {
|
$scope.location = {
|
||||||
busy: false,
|
busy: false,
|
||||||
error: {},
|
error: {},
|
||||||
success: false,
|
domainCollisions: [],
|
||||||
|
|
||||||
domain: null,
|
domain: null,
|
||||||
location: '',
|
location: '',
|
||||||
@@ -182,6 +183,7 @@ angular.module('Application').controller('AppController', ['$scope', '$location'
|
|||||||
var app = $scope.app;
|
var app = $scope.app;
|
||||||
|
|
||||||
$scope.location.error = {};
|
$scope.location.error = {};
|
||||||
|
$scope.location.domainCollisions = [];
|
||||||
$scope.location.location = app.location;
|
$scope.location.location = app.location;
|
||||||
$scope.location.domain = $scope.domains.filter(function (d) { return d.domain === app.domain; })[0];
|
$scope.location.domain = $scope.domains.filter(function (d) { return d.domain === app.domain; })[0];
|
||||||
$scope.location.portBindingsInfo = angular.extend({}, app.manifest.tcpPorts, app.manifest.udpPorts); // Portbinding map only for information
|
$scope.location.portBindingsInfo = angular.extend({}, app.manifest.tcpPorts, app.manifest.udpPorts); // Portbinding map only for information
|
||||||
@@ -199,9 +201,12 @@ angular.module('Application').controller('AppController', ['$scope', '$location'
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
submit: function () {
|
submit: function (overwriteDns) {
|
||||||
|
$('#domainCollisionsModal').modal('hide');
|
||||||
|
|
||||||
$scope.location.busy = true;
|
$scope.location.busy = true;
|
||||||
$scope.location.error = {};
|
$scope.location.error = {};
|
||||||
|
$scope.location.domainCollisions = [];
|
||||||
|
|
||||||
// only use enabled ports from portBindings
|
// only use enabled ports from portBindings
|
||||||
var portBindings = {};
|
var portBindings = {};
|
||||||
@@ -212,12 +217,43 @@ angular.module('Application').controller('AppController', ['$scope', '$location'
|
|||||||
}
|
}
|
||||||
|
|
||||||
var data = {
|
var data = {
|
||||||
|
overwriteDns: !!overwriteDns,
|
||||||
location: $scope.location.location,
|
location: $scope.location.location,
|
||||||
domain: $scope.location.domain.domain,
|
domain: $scope.location.domain.domain,
|
||||||
portBindings: portBindings,
|
portBindings: portBindings,
|
||||||
alternateDomains: $scope.location.alternateDomains.map(function (a) { return { subdomain: a.subdomain, domain: a.domain.domain };})
|
alternateDomains: $scope.location.alternateDomains.map(function (a) { return { subdomain: a.subdomain, domain: a.domain.domain };})
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// pre-flight only for changed domains
|
||||||
|
var domains = [];
|
||||||
|
if ($scope.app.domain !== data.domain || $scope.app.location !== data.location) domains.push({ subdomain: data.location, domain: data.domain });
|
||||||
|
data.alternateDomains.forEach(function (a) {
|
||||||
|
if ($scope.app.alternateDomains.some(function (d) { return d.domain === a.domain && d.subdomain === a.subdomain; })) return;
|
||||||
|
domains.push({ subdomain: a.subdomain, domain: a.domain });
|
||||||
|
});
|
||||||
|
|
||||||
|
asyncForEach(domains, function (domain, callback) {
|
||||||
|
if (overwriteDns) return callback();
|
||||||
|
|
||||||
|
Client.getDNSRecords(domain.domain, domain.subdomain, 'A', function (error, result) {
|
||||||
|
// TODO handle credential errors
|
||||||
|
if (error) return callback(error);
|
||||||
|
|
||||||
|
if (result.length) $scope.location.domainCollisions.push(domain);
|
||||||
|
|
||||||
|
callback();
|
||||||
|
});
|
||||||
|
}, function (error) {
|
||||||
|
if (error) {
|
||||||
|
$scope.location.busy = false;
|
||||||
|
return Client.error(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($scope.location.domainCollisions.length) {
|
||||||
|
$scope.location.busy = false;
|
||||||
|
return $('#domainCollisionsModal').modal('show');
|
||||||
|
}
|
||||||
|
|
||||||
Client.configureApp($scope.app.id, 'location', data, function (error) {
|
Client.configureApp($scope.app.id, 'location', data, function (error) {
|
||||||
if (error && (error.statusCode === 409 || error.statusCode === 400)) {
|
if (error && (error.statusCode === 409 || error.statusCode === 400)) {
|
||||||
if ((error.location && error.domain) || error.field === 'location') {
|
if ((error.location && error.domain) || error.field === 'location') {
|
||||||
@@ -232,11 +268,12 @@ angular.module('Application').controller('AppController', ['$scope', '$location'
|
|||||||
}
|
}
|
||||||
if (error) return Client.error(error);
|
if (error) return Client.error(error);
|
||||||
|
|
||||||
$scope.location.success = true;
|
$scope.locationForm.$setPristine();
|
||||||
$scope.location.busy = false;
|
$scope.location.busy = false;
|
||||||
|
|
||||||
refreshApp();
|
refreshApp();
|
||||||
});
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user