diff --git a/src/js/index.js b/src/js/index.js
index 177cfc322..f03aca8d5 100644
--- a/src/js/index.js
+++ b/src/js/index.js
@@ -218,7 +218,10 @@ app.filter('selectedDomainFilter', function () {
if (selectedDomain._alldomains) return true; // magic domain for single select, see apps.js ALL_DOMAINS_DOMAIN
if (selectedDomain.domain === app.domain) return true;
- return !!app.alternateDomains.find(function (ad) { return ad.domain === selectedDomain.domain; });
+ if (app.aliasDomains.find(function (ad) { return ad.domain === selectedDomain.domain; })) return true;
+ if (app.alternateDomains.find(function (ad) { return ad.domain === selectedDomain.domain; })) return true;
+
+ return false;
});
};
});
diff --git a/src/theme.scss b/src/theme.scss
index e15d88808..e977227e5 100644
--- a/src/theme.scss
+++ b/src/theme.scss
@@ -484,6 +484,19 @@ multiselect {
}
}
+.alias-domains .col-lg-11 {
+ padding-right: 5px;
+}
+
+.alias-domains .col-lg-1 {
+ padding-left: 0px;
+ padding-right: 0px;
+}
+
+.alias-domains .row {
+ margin-top: 5px;
+}
+
.alternate-domains .col-lg-11 {
padding-right: 5px;
}
diff --git a/src/views/activity.js b/src/views/activity.js
index c77e4e8df..8ef198fa8 100644
--- a/src/views/activity.js
+++ b/src/views/activity.js
@@ -211,6 +211,9 @@ angular.module('Application').controller('ActivityController', ['$scope', '$loca
} else if (!angular.equals(data.alternateDomains, data.app.alternateDomains)) {
var altFqdns = data.alternateDomains.map(function (a) { return a.fqdn; });
return 'Alternate domains of ' + appName(app) + ' was ' + (altFqdns.length ? 'set to ' + altFqdns.join(', ') : 'reset');
+ } else if (!angular.equals(data.aliasDomains, data.app.aliasDomains)) {
+ var aliasDomains = data.aliasDomains.map(function (a) { return a.fqdn; });
+ return 'Alias domains of ' + appName(app) + ' was ' + (aliasDomains.length ? 'set to ' + aliasDomains.join(', ') : 'reset');
} else if (!angular.equals(data.portBindings, data.app.portBindings)) {
return 'Port bindings of ' + appName(app) + ' was changed';
}
diff --git a/src/views/app.html b/src/views/app.html
index 97ff631b4..2b10c9b35 100644
--- a/src/views/app.html
+++ b/src/views/app.html
@@ -106,6 +106,14 @@
+
+
+
+
+
+
+
+
+
{{ location.error.aliasDomains }}
+
+
+
{{ 'app.location.noAliases' | tr }}
+
+
+
{{ location.error.alternateDomains }}
@@ -585,8 +623,8 @@
-
{{ 'appstore.installDialog.userManagementNone' | tr }} {{ 'app.accessControl.userManagement.sftpAccessControl' | tr }}
-
{{ 'appstore.installDialog.configuredForCloudronEmail' | tr:{ emailDocsLink: 'https://docs.cloudron.io/email/' } }}
+
{{ 'appstore.installDialog.userManagementNone' | tr }} {{ 'app.accessControl.userManagement.sftpAccessControl' | tr }}
+
{{ 'appstore.installDialog.configuredForCloudronEmail' | tr:{ emailDocsLink: 'https://docs.cloudron.io/email/' } }}
diff --git a/src/views/app.js b/src/views/app.js
index 9fa1842fb..7d027abb2 100644
--- a/src/views/app.js
+++ b/src/views/app.js
@@ -268,6 +268,7 @@ angular.module('Application').controller('AppController', ['$scope', '$location'
domain: null,
location: '',
alternateDomains: [],
+ aliasDomains: [],
portBindings: {},
portBindingsEnabled: {},
portBindingsInfo: {},
@@ -285,6 +286,19 @@ angular.module('Application').controller('AppController', ['$scope', '$location'
$scope.location.alternateDomains.splice(index, 1);
},
+ addAliasDomain: function (event) {
+ event.preventDefault();
+ $scope.location.aliasDomains.push({
+ domain: $scope.domains.filter(function (d) { return d.domain === $scope.app.domain; })[0], // pre-select app's domain by default
+ subdomain: ''
+ });
+ },
+
+ delAliasDomain: function (event, index) {
+ event.preventDefault();
+ $scope.location.aliasDomains.splice(index, 1);
+ },
+
show: function () {
var app = $scope.app;
@@ -294,6 +308,7 @@ angular.module('Application').controller('AppController', ['$scope', '$location'
$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.alternateDomains = app.alternateDomains.map(function (a) { return { subdomain: a.subdomain, domain: $scope.domains.filter(function (d) { return d.domain === a.domain; })[0] };});
+ $scope.location.aliasDomains = app.aliasDomains.map(function (a) { return { subdomain: a.subdomain, domain: $scope.domains.filter(function (d) { return d.domain === a.domain; })[0] };});
// fill the portBinding structures. There might be holes in the app.portBindings, which signalizes a disabled port
for (var env in $scope.location.portBindingsInfo) {
@@ -327,15 +342,20 @@ angular.module('Application').controller('AppController', ['$scope', '$location'
location: $scope.location.location,
domain: $scope.location.domain.domain,
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 };}),
+ aliasDomains: $scope.location.aliasDomains.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 });
+ if ($scope.app.domain !== data.domain || $scope.app.location !== data.location) domains.push({ subdomain: data.location, domain: data.domain, type: 'main' });
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 });
+ domains.push({ subdomain: a.subdomain, domain: a.domain, type: 'redirect' });
+ });
+ data.aliasDomains.forEach(function (a) {
+ if ($scope.app.aliasDomains.some(function (d) { return d.domain === a.domain && d.subdomain === a.subdomain; })) return;
+ domains.push({ subdomain: a.subdomain, domain: a.domain, type: 'alias' });
});
async.eachSeries(domains, function (domain, callback) {
@@ -344,8 +364,10 @@ angular.module('Application').controller('AppController', ['$scope', '$location'
Client.checkDNSRecords(domain.domain, domain.subdomain, function (error, result) {
if (error) return callback(error);
if (result.error) {
- if (data.domain === domain.domain && data.location === domain.subdomain) {
+ if (domain.type === 'main') {
$scope.location.error.location = domain.domain + ' ' + result.error.message;
+ } else if (domain.type === 'alias') {
+ $scope.location.error.aliasDomains = domain.domain + ' ' + result.error.message;
} else {
$scope.location.error.alternateDomains = domain.domain + ' ' + result.error.message;
}
@@ -374,7 +396,7 @@ angular.module('Application').controller('AppController', ['$scope', '$location'
if (data.domain === error.domain && data.location === error.subdomain) { // the primary
$scope.location.error.location = error.message;
$scope.locationForm.$setPristine();
- } else {
+ } else { // FIXME: check error in aliasDomains
$scope.location.error.alternateDomains = error.message;
}
} else if (error.portName || error.field === 'portBindings') {
@@ -1287,6 +1309,7 @@ angular.module('Application').controller('AppController', ['$scope', '$location'
location: null,
domain: null,
alternateDomains: [],
+ aliasDomains: [],
backups: [],
backupId: '',
@@ -1300,6 +1323,7 @@ angular.module('Application').controller('AppController', ['$scope', '$location'
$scope.repair.location = null;
$scope.repair.domain = null;
$scope.repair.alternateDomains = [];
+ $scope.repair.aliasDomains = [];
$scope.repair.backupId = '';
var app = $scope.app;
@@ -1309,6 +1333,16 @@ angular.module('Application').controller('AppController', ['$scope', '$location'
if (errorState === ISTATES.PENDING_LOCATION_CHANGE) {
$scope.repair.location = app.location;
$scope.repair.domain = $scope.domains.filter(function (d) { return d.domain === app.domain; })[0];
+
+ $scope.repair.aliasDomains = $scope.app.aliasDomains;
+ $scope.repair.aliasDomains = $scope.app.aliasDomains.map(function (aliasDomain) {
+ return {
+ subdomain: aliasDomain.subdomain,
+ enabled: true,
+ domain: $scope.domains.filter(function (d) { return d.domain === aliasDomain.domain; })[0]
+ };
+ });
+
$scope.repair.alternateDomains = $scope.app.alternateDomains;
$scope.repair.alternateDomains = $scope.app.alternateDomains.map(function (altDomain) {
return {
@@ -1351,6 +1385,8 @@ angular.module('Application').controller('AppController', ['$scope', '$location'
case ISTATES.PENDING_LOCATION_CHANGE:
data.location = $scope.repair.location;
data.domain = $scope.repair.domain.domain;
+ data.aliasDomains = $scope.repair.aliasDomains.filter(function (a) { return a.enabled; })
+ .map(function (d) { return { subdomain: d.subdomain, domain: d.domain.domain }; });
data.alternateDomains = $scope.repair.alternateDomains.filter(function (a) { return a.enabled; })
.map(function (d) { return { subdomain: d.subdomain, domain: d.domain.domain }; });
data.overwriteDns = true; // always overwriteDns. user can anyway check and uncheck above