archives: add listing
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
|
||||
/* global $, angular, TASK_TYPES, SECRET_PLACEHOLDER, STORAGE_PROVIDERS, BACKUP_FORMATS, APP_TYPES */
|
||||
/* global REGIONS_S3, REGIONS_WASABI, REGIONS_DIGITALOCEAN, REGIONS_EXOSCALE, REGIONS_SCALEWAY, REGIONS_LINODE, REGIONS_OVH, REGIONS_IONOS, REGIONS_UPCLOUD, REGIONS_VULTR , REGIONS_CONTABO, REGIONS_HETZNER */
|
||||
/* global document, window, FileReader */
|
||||
/* global async, ERROR */
|
||||
|
||||
angular.module('Application').controller('BackupsController', ['$scope', '$location', '$rootScope', '$timeout', 'Client', function ($scope, $location, $rootScope, $timeout, Client) {
|
||||
Client.onReady(function () { if (!Client.getUserInfo().isAtLeastAdmin) $location.path('/'); });
|
||||
@@ -23,6 +23,8 @@ angular.module('Application').controller('BackupsController', ['$scope', '$locat
|
||||
$scope.backupTasks = [];
|
||||
$scope.cleanupTasks = [];
|
||||
|
||||
$scope.domains = [];
|
||||
|
||||
$scope.s3Regions = REGIONS_S3;
|
||||
$scope.wasabiRegions = REGIONS_WASABI;
|
||||
$scope.doSpacesRegions = REGIONS_DIGITALOCEAN;
|
||||
@@ -266,7 +268,171 @@ angular.module('Application').controller('BackupsController', ['$scope', '$locat
|
||||
}
|
||||
};
|
||||
|
||||
$scope.listBackups = {
|
||||
$scope.listArchives = {
|
||||
ready: false,
|
||||
archives: [],
|
||||
|
||||
fetch: function () {
|
||||
Client.listArchives(function (error, archives) {
|
||||
if (error) Client.error(error);
|
||||
$scope.listArchives.archives = archives;
|
||||
$scope.listArchives.ready = true;
|
||||
});
|
||||
},
|
||||
|
||||
delete: function (archive) {
|
||||
Client.deleteArchive(archive.id, function (error) {
|
||||
if (error) Client.error(error);
|
||||
$scope.listArchives.fetch();
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
// keep in sync with app.js
|
||||
$scope.clone = {
|
||||
busy: false,
|
||||
error: {},
|
||||
|
||||
archive: null,
|
||||
subdomain: '',
|
||||
domain: null,
|
||||
secondaryDomains: {},
|
||||
needsOverwrite: false,
|
||||
overwriteDns: false,
|
||||
ports: {},
|
||||
portsEnabled: {},
|
||||
portInfo: {},
|
||||
|
||||
init: function () {
|
||||
Client.getDomains(function (error, domains) {
|
||||
if (error) return console.error('Unable to get domain listing.', error);
|
||||
$scope.domains = domains;
|
||||
});
|
||||
},
|
||||
|
||||
show: function (archive) {
|
||||
$scope.clone.error = {};
|
||||
$scope.clone.archive = archive;
|
||||
const app = archive.appConfig;
|
||||
const manifest = archive.appConfig.manifest;
|
||||
$scope.clone.domain = $scope.domains.find(function (d) { return app.domain === d.domain; }); // pre-select the app's domain
|
||||
|
||||
$scope.clone.needsOverwrite = false;
|
||||
$scope.clone.overwriteDns = false;
|
||||
|
||||
$scope.clone.secondaryDomains = {};
|
||||
|
||||
var httpPorts = manifest.httpPorts || {};
|
||||
for (var env2 in httpPorts) {
|
||||
$scope.clone.secondaryDomains[env2] = {
|
||||
subdomain: httpPorts[env2].defaultValue || '',
|
||||
domain: $scope.clone.domain
|
||||
};
|
||||
}
|
||||
|
||||
$scope.clone.portInfo = angular.extend({}, manifest.tcpPorts, manifest.udpPorts); // Portbinding map only for information
|
||||
// set default ports
|
||||
for (var env in $scope.clone.portInfo) {
|
||||
$scope.clone.ports[env] = $scope.clone.portInfo[env].defaultValue || 0;
|
||||
$scope.clone.portsEnabled[env] = true;
|
||||
}
|
||||
|
||||
$('#appCloneModal').modal('show');
|
||||
},
|
||||
|
||||
submit: function () {
|
||||
$scope.clone.busy = true;
|
||||
|
||||
var secondaryDomains = {};
|
||||
for (var env2 in $scope.clone.secondaryDomains) {
|
||||
secondaryDomains[env2] = {
|
||||
subdomain: $scope.clone.secondaryDomains[env2].subdomain,
|
||||
domain: $scope.clone.secondaryDomains[env2].domain.domain
|
||||
};
|
||||
}
|
||||
|
||||
// only use enabled ports
|
||||
var finalPorts = {};
|
||||
for (var env in $scope.clone.ports) {
|
||||
if ($scope.clone.portsEnabled[env]) {
|
||||
finalPorts[env] = $scope.clone.ports[env];
|
||||
}
|
||||
}
|
||||
|
||||
var data = {
|
||||
subdomain: $scope.clone.subdomain,
|
||||
domain: $scope.clone.domain.domain,
|
||||
secondaryDomains: secondaryDomains,
|
||||
ports: finalPorts,
|
||||
backupId: $scope.clone.archive.backupId,
|
||||
overwriteDns: $scope.clone.overwriteDns
|
||||
};
|
||||
|
||||
var allDomains = [{ domain: data.domain, subdomain: data.subdomain }].concat(Object.keys(secondaryDomains).map(function (k) {
|
||||
return {
|
||||
domain: secondaryDomains[k].domain,
|
||||
subdomain: secondaryDomains[k].subdomain
|
||||
};
|
||||
}));
|
||||
async.eachSeries(allDomains, function (domain, callback) {
|
||||
if ($scope.clone.overwriteDns) return callback();
|
||||
|
||||
Client.checkDNSRecords(domain.domain, domain.subdomain, function (error, result) {
|
||||
if (error) return callback(error);
|
||||
|
||||
var fqdn = domain.subdomain + '.' + domain.domain;
|
||||
|
||||
if (result.error) {
|
||||
if (result.error.reason === ERROR.ACCESS_DENIED) return callback({ type: 'provider', fqdn: fqdn, message: 'DNS credentials for ' + domain.domain + ' are invalid. Update it in Domains & Certs view' });
|
||||
return callback({ type: 'provider', fqdn: fqdn, message: result.error.message });
|
||||
}
|
||||
if (result.needsOverwrite) {
|
||||
$scope.clone.needsOverwrite = true;
|
||||
$scope.clone.overwriteDns = true;
|
||||
return callback({ type: 'externally_exists', fqdn: fqdn, message: 'DNS Record already exists. Confirm that the domain is not in use for services external to Cloudron' });
|
||||
}
|
||||
|
||||
callback();
|
||||
});
|
||||
}, function (error) {
|
||||
if (error) {
|
||||
if (error.type) {
|
||||
$scope.clone.error.location = error;
|
||||
$scope.clone.busy = false;
|
||||
} else {
|
||||
Client.error(error);
|
||||
}
|
||||
|
||||
$scope.clone.error.location = error;
|
||||
$scope.clone.busy = false;
|
||||
return;
|
||||
}
|
||||
|
||||
const app = $scope.clone.archive.appConfig;
|
||||
|
||||
Client.installApp(app.manifest.id, app.manifest, data, function (error/*, clonedApp */) {
|
||||
$scope.clone.busy = false;
|
||||
|
||||
if (error) {
|
||||
var errorMessage = error.message.toLowerCase();
|
||||
if (errorMessage.indexOf('port') !== -1) {
|
||||
$scope.clone.error.port = error.message;
|
||||
} else if (error.message.indexOf('location') !== -1 || error.message.indexOf('subdomain') !== -1) {
|
||||
// TODO extract fqdn from error message, currently we just set it always to the main location
|
||||
$scope.clone.error.location = { type: 'internally_exists', fqdn: data.subdomain + '.' + data.domain, message: error.message };
|
||||
$('#cloneLocationInput').focus();
|
||||
} else {
|
||||
Client.error(error);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
$('#appCloneModal').modal('hide');
|
||||
|
||||
$location.path('/apps');
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
$scope.s3like = function (provider) {
|
||||
@@ -860,12 +1026,15 @@ angular.module('Application').controller('BackupsController', ['$scope', '$locat
|
||||
fetchBackups();
|
||||
getBackupConfig();
|
||||
|
||||
$scope.listArchives.fetch();
|
||||
|
||||
$scope.manualBackupApps = Client.getInstalledApps().filter(function (app) { return app.type !== APP_TYPES.LINK && !app.enableBackup; });
|
||||
|
||||
// show backup status
|
||||
$scope.createBackup.init();
|
||||
$scope.cleanupBackups.init();
|
||||
$scope.backupPolicy.init();
|
||||
$scope.clone.init();
|
||||
|
||||
getBackupTasks();
|
||||
getCleanupTasks();
|
||||
|
||||
Reference in New Issue
Block a user