2018-01-22 13:01:38 -08:00
|
|
|
'use strict';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
angular.module('Application').controller('AppsController', ['$scope', '$location', '$timeout', '$interval', 'Client', 'ngTld', 'AppStore', function ($scope, $location, $timeout, $interval, Client, ngTld, AppStore) {
|
|
|
|
|
$scope.HOST_PORT_MIN = 1024;
|
|
|
|
|
$scope.HOST_PORT_MAX = 65535;
|
|
|
|
|
$scope.installedApps = Client.getInstalledApps();
|
|
|
|
|
$scope.config = Client.getConfig();
|
|
|
|
|
$scope.user = Client.getUserInfo();
|
|
|
|
|
$scope.domains = [];
|
|
|
|
|
$scope.groups = [];
|
|
|
|
|
$scope.users = [];
|
|
|
|
|
$scope.backupConfig = {};
|
|
|
|
|
|
|
|
|
|
$scope.appConfigure = {
|
|
|
|
|
busy: false,
|
|
|
|
|
error: {},
|
|
|
|
|
app: {},
|
|
|
|
|
domain: '',
|
|
|
|
|
location: '',
|
|
|
|
|
advancedVisible: false,
|
|
|
|
|
portBindings: {},
|
|
|
|
|
portBindingsEnabled: {},
|
|
|
|
|
portBindingsInfo: {},
|
|
|
|
|
robotsTxt: '',
|
|
|
|
|
certificateFile: null,
|
|
|
|
|
certificateFileName: '',
|
|
|
|
|
keyFile: null,
|
|
|
|
|
keyFileName: '',
|
|
|
|
|
memoryLimit: 0,
|
|
|
|
|
memoryTicks: [],
|
2018-05-24 15:40:26 -07:00
|
|
|
mailboxName: '',
|
2018-01-22 13:01:38 -08:00
|
|
|
|
|
|
|
|
accessRestrictionOption: 'any',
|
|
|
|
|
accessRestriction: { users: [], groups: [] },
|
|
|
|
|
xFrameOptions: '',
|
2018-05-25 13:59:53 -07:00
|
|
|
ssoAuth: false,
|
2018-01-22 13:01:38 -08:00
|
|
|
|
|
|
|
|
isAccessRestrictionValid: function () {
|
|
|
|
|
var tmp = $scope.appConfigure.accessRestriction;
|
|
|
|
|
return !!(tmp.users.length || tmp.groups.length);
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
show: function (app) {
|
|
|
|
|
$scope.reset();
|
|
|
|
|
|
|
|
|
|
// fill relevant info from the app
|
|
|
|
|
$scope.appConfigure.app = app;
|
2018-02-08 09:44:35 +01:00
|
|
|
$scope.appConfigure.location = app.location;
|
2018-01-22 13:01:38 -08:00
|
|
|
$scope.appConfigure.domain = $scope.domains.filter(function (d) { return d.domain === app.domain; })[0];
|
|
|
|
|
$scope.appConfigure.portBindingsInfo = app.manifest.tcpPorts || {}; // Portbinding map only for information
|
|
|
|
|
$scope.appConfigure.memoryLimit = app.memoryLimit || app.manifest.memoryLimit || (256 * 1024 * 1024);
|
|
|
|
|
$scope.appConfigure.xFrameOptions = app.xFrameOptions.indexOf('ALLOW-FROM') === 0 ? app.xFrameOptions.split(' ')[1] : '';
|
|
|
|
|
$scope.appConfigure.robotsTxt = app.robotsTxt;
|
|
|
|
|
$scope.appConfigure.enableBackup = app.enableBackup;
|
2018-05-24 15:40:26 -07:00
|
|
|
$scope.appConfigure.mailboxName = app.mailboxName || '';
|
2018-01-22 13:01:38 -08:00
|
|
|
|
2018-05-25 13:59:53 -07:00
|
|
|
$scope.appConfigure.ssoAuth = (app.manifest.addons['ldap'] || app.manifest.addons['oauth']) && app.sso;
|
|
|
|
|
|
2018-01-22 13:01:38 -08:00
|
|
|
// create ticks starting from manifest memory limit. the memory limit here is currently split into ram+swap (and thus *2 below)
|
|
|
|
|
// TODO: the *2 will overallocate since 4GB is max swap that cloudron itself allocates
|
|
|
|
|
$scope.appConfigure.memoryTicks = [ ];
|
|
|
|
|
var npow2 = Math.pow(2, Math.ceil(Math.log($scope.config.memory)/Math.log(2)));
|
|
|
|
|
for (var i = 256; i <= (npow2*2/1024/1024); i *= 2) {
|
|
|
|
|
if (i >= (app.manifest.memoryLimit/1024/1024 || 0)) $scope.appConfigure.memoryTicks.push(i * 1024 * 1024);
|
|
|
|
|
}
|
|
|
|
|
if (app.manifest.memoryLimit && $scope.appConfigure.memoryTicks[0] !== app.manifest.memoryLimit) {
|
|
|
|
|
$scope.appConfigure.memoryTicks.unshift(app.manifest.memoryLimit);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$scope.appConfigure.accessRestrictionOption = app.accessRestriction ? 'groups' : 'any';
|
|
|
|
|
$scope.appConfigure.accessRestriction = { users: [], groups: [] };
|
|
|
|
|
|
|
|
|
|
if (app.accessRestriction) {
|
|
|
|
|
var userSet = { };
|
|
|
|
|
app.accessRestriction.users.forEach(function (uid) { userSet[uid] = true; });
|
|
|
|
|
$scope.users.forEach(function (u) { if (userSet[u.id] === true) $scope.appConfigure.accessRestriction.users.push(u); });
|
|
|
|
|
|
|
|
|
|
var groupSet = { };
|
|
|
|
|
app.accessRestriction.groups.forEach(function (gid) { groupSet[gid] = true; });
|
|
|
|
|
$scope.groups.forEach(function (g) { if (groupSet[g.id] === true) $scope.appConfigure.accessRestriction.groups.push(g); });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// fill the portBinding structures. There might be holes in the app.portBindings, which signalizes a disabled port
|
|
|
|
|
for (var env in $scope.appConfigure.portBindingsInfo) {
|
|
|
|
|
if (app.portBindings && app.portBindings[env]) {
|
|
|
|
|
$scope.appConfigure.portBindings[env] = app.portBindings[env];
|
|
|
|
|
$scope.appConfigure.portBindingsEnabled[env] = true;
|
|
|
|
|
} else {
|
|
|
|
|
$scope.appConfigure.portBindings[env] = $scope.appConfigure.portBindingsInfo[env].defaultValue || 0;
|
|
|
|
|
$scope.appConfigure.portBindingsEnabled[env] = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$('#appConfigureModal').modal('show');
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
submit: function () {
|
|
|
|
|
$scope.appConfigure.busy = true;
|
|
|
|
|
$scope.appConfigure.error.other = null;
|
|
|
|
|
$scope.appConfigure.error.location = null;
|
|
|
|
|
$scope.appConfigure.error.xFrameOptions = null;
|
2018-05-24 15:40:26 -07:00
|
|
|
$scope.appConfigure.error.mailboxName = null;
|
2018-01-22 13:01:38 -08:00
|
|
|
|
|
|
|
|
// only use enabled ports from portBindings
|
|
|
|
|
var finalPortBindings = {};
|
|
|
|
|
for (var env in $scope.appConfigure.portBindings) {
|
|
|
|
|
if ($scope.appConfigure.portBindingsEnabled[env]) {
|
|
|
|
|
finalPortBindings[env] = $scope.appConfigure.portBindings[env];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var finalAccessRestriction = null;
|
|
|
|
|
if ($scope.appConfigure.accessRestrictionOption === 'groups') {
|
|
|
|
|
finalAccessRestriction = { users: [], groups: [] };
|
|
|
|
|
finalAccessRestriction.users = $scope.appConfigure.accessRestriction.users.map(function (u) { return u.id; });
|
|
|
|
|
finalAccessRestriction.groups = $scope.appConfigure.accessRestriction.groups.map(function (g) { return g.id; });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var data = {
|
2018-02-08 09:44:35 +01:00
|
|
|
location: $scope.appConfigure.location,
|
|
|
|
|
domain: $scope.appConfigure.domain.domain,
|
2018-01-22 13:01:38 -08:00
|
|
|
portBindings: finalPortBindings,
|
|
|
|
|
accessRestriction: finalAccessRestriction,
|
|
|
|
|
cert: $scope.appConfigure.certificateFile,
|
|
|
|
|
key: $scope.appConfigure.keyFile,
|
|
|
|
|
xFrameOptions: $scope.appConfigure.xFrameOptions ? ('ALLOW-FROM ' + $scope.appConfigure.xFrameOptions) : 'SAMEORIGIN',
|
|
|
|
|
memoryLimit: $scope.appConfigure.memoryLimit === $scope.appConfigure.memoryTicks[0] ? 0 : $scope.appConfigure.memoryLimit,
|
|
|
|
|
robotsTxt: $scope.appConfigure.robotsTxt,
|
|
|
|
|
enableBackup: $scope.appConfigure.enableBackup
|
|
|
|
|
};
|
|
|
|
|
|
2018-05-24 16:29:36 -07:00
|
|
|
if ($scope.appConfigure.mailboxName !== $scope.appConfigure.app.mailboxName) data.mailboxName = $scope.appConfigure.mailboxName;
|
2018-05-24 15:40:26 -07:00
|
|
|
|
2018-01-22 13:01:38 -08:00
|
|
|
Client.configureApp($scope.appConfigure.app.id, data, function (error) {
|
|
|
|
|
if (error) {
|
|
|
|
|
if (error.statusCode === 409 && (error.message.indexOf('is reserved') !== -1 || error.message.indexOf('is already in use') !== -1)) {
|
|
|
|
|
$scope.appConfigure.error.port = error.message;
|
2018-05-24 20:15:08 -07:00
|
|
|
} else if (error.statusCode === 409 && error.message.indexOf('mailbox') !== -1 ) {
|
|
|
|
|
$scope.appConfigure.error.mailboxName = error.message;
|
|
|
|
|
$scope.appConfigureForm.mailboxName.$setPristine();
|
|
|
|
|
$('#appConfigureMailboxNameInput').focus();
|
2018-01-22 13:01:38 -08:00
|
|
|
} else if (error.statusCode === 409) {
|
2018-06-26 17:35:37 -07:00
|
|
|
$scope.appConfigure.error.location = error.message;
|
2018-01-22 13:01:38 -08:00
|
|
|
$scope.appConfigureForm.location.$setPristine();
|
|
|
|
|
$('#appConfigureLocationInput').focus();
|
|
|
|
|
} else if (error.statusCode === 400 && error.message.indexOf('cert') !== -1 ) {
|
|
|
|
|
$scope.appConfigure.error.cert = error.message;
|
|
|
|
|
$scope.appConfigure.certificateFileName = '';
|
|
|
|
|
$scope.appConfigure.certificateFile = null;
|
|
|
|
|
$scope.appConfigure.keyFileName = '';
|
|
|
|
|
$scope.appConfigure.keyFile = null;
|
|
|
|
|
} else if (error.statusCode === 400 && error.message.indexOf('xFrameOptions') !== -1 ) {
|
|
|
|
|
$scope.appConfigure.error.xFrameOptions = error.message;
|
|
|
|
|
$scope.appConfigureForm.xFrameOptions.$setPristine();
|
|
|
|
|
$('#appConfigureXFrameOptionsInput').focus();
|
|
|
|
|
} else {
|
|
|
|
|
$scope.appConfigure.error.other = error.message;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$scope.appConfigure.busy = false;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$scope.appConfigure.busy = false;
|
|
|
|
|
|
2018-06-26 08:49:43 -07:00
|
|
|
Client.refreshAppCache($scope.appConfigure.app.id); // reflect the new app state immediately
|
2018-01-22 13:01:38 -08:00
|
|
|
|
|
|
|
|
$('#appConfigureModal').modal('hide');
|
|
|
|
|
|
|
|
|
|
$scope.reset();
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
$scope.appUninstall = {
|
|
|
|
|
busy: false,
|
|
|
|
|
error: {},
|
|
|
|
|
app: {},
|
|
|
|
|
password: ''
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
$scope.appRestore = {
|
|
|
|
|
busy: false,
|
|
|
|
|
busyFetching: false,
|
|
|
|
|
error: {},
|
|
|
|
|
app: {},
|
|
|
|
|
password: '',
|
|
|
|
|
backups: [ ],
|
|
|
|
|
selectedBackup: null,
|
|
|
|
|
|
2018-05-28 00:47:53 -07:00
|
|
|
// from clone
|
|
|
|
|
location: '',
|
|
|
|
|
domain: null,
|
|
|
|
|
portBindings: {},
|
|
|
|
|
portBindingsInfo: {},
|
|
|
|
|
portBindingsEnabled: {},
|
|
|
|
|
|
2018-05-28 10:00:12 -07:00
|
|
|
action: 'restore',
|
|
|
|
|
|
2018-01-22 13:01:38 -08:00
|
|
|
selectBackup: function (backup) {
|
|
|
|
|
$scope.appRestore.selectedBackup = backup;
|
|
|
|
|
},
|
|
|
|
|
|
2018-05-23 20:36:54 -07:00
|
|
|
createBackup: function () {
|
|
|
|
|
Client.backupApp($scope.appRestore.app.id, function (error) {
|
2018-05-29 22:05:18 +02:00
|
|
|
if (error) Client.error(error);
|
|
|
|
|
|
|
|
|
|
function waitForBackupFinish() {
|
|
|
|
|
if ($scope.appRestore.app.installationState === 'pending_backup') return $timeout(waitForBackupFinish, 1000);
|
|
|
|
|
|
|
|
|
|
// we are done, refresh the backup list
|
|
|
|
|
Client.getAppBackups($scope.appRestore.app.id, function (error, backups) {
|
|
|
|
|
if (error) return Client.error(error);
|
|
|
|
|
|
|
|
|
|
$scope.appRestore.backups = backups;
|
|
|
|
|
if (backups.length) $scope.appRestore.selectedBackup = backups[0]; // pre-select first backup
|
|
|
|
|
});
|
2018-05-23 20:36:54 -07:00
|
|
|
}
|
|
|
|
|
|
2018-05-29 22:05:18 +02:00
|
|
|
// reflect the new app state immediately
|
2018-06-26 08:49:43 -07:00
|
|
|
Client.refreshAppCache($scope.appRestore.app.id, waitForBackupFinish);
|
2018-05-23 20:36:54 -07:00
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
2018-05-28 00:47:53 -07:00
|
|
|
clone: function () {
|
2018-05-29 22:53:51 +02:00
|
|
|
$scope.appRestore.busy = true;
|
|
|
|
|
|
2018-05-28 00:47:53 -07:00
|
|
|
var data = {
|
|
|
|
|
location: $scope.appRestore.location,
|
|
|
|
|
domain: $scope.appRestore.domain.domain,
|
|
|
|
|
portBindings: $scope.appRestore.portBindings,
|
|
|
|
|
backupId: $scope.appRestore.selectedBackup.id
|
|
|
|
|
};
|
|
|
|
|
|
2018-06-26 08:49:43 -07:00
|
|
|
Client.cloneApp($scope.appRestore.app.id, data, function (error, clonedApp) {
|
2018-05-29 22:53:51 +02:00
|
|
|
$scope.appRestore.busy = false;
|
|
|
|
|
|
2018-05-28 00:47:53 -07:00
|
|
|
if (error) {
|
|
|
|
|
if (error.statusCode === 409 && (error.message.indexOf('is reserved') !== -1 || error.message.indexOf('is already in use') !== -1)) {
|
|
|
|
|
$scope.appRestore.error.port = error.message;
|
|
|
|
|
} else if (error.statusCode === 409) {
|
|
|
|
|
$scope.appRestore.error.location = 'This name is already taken.';
|
|
|
|
|
$scope.appCloneForm.location.$setPristine();
|
|
|
|
|
$('#appRestoreLocationInput').focus();
|
|
|
|
|
} else {
|
|
|
|
|
Client.error(error);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
$('#appRestoreModal').modal('hide');
|
|
|
|
|
}
|
|
|
|
|
|
2018-06-26 08:49:43 -07:00
|
|
|
Client.refreshAppCache(clonedApp.id); // reflect the new app state immediately
|
2018-05-28 00:47:53 -07:00
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
2018-01-22 13:01:38 -08:00
|
|
|
show: function (app) {
|
|
|
|
|
$scope.reset();
|
|
|
|
|
|
|
|
|
|
$scope.appRestore.app = app;
|
|
|
|
|
$scope.appRestore.busyFetching = true;
|
|
|
|
|
|
2018-05-28 00:47:53 -07:00
|
|
|
$scope.appRestore.domain = $scope.domains.find(function (d) { return app.domain === d.domain; }); // pre-select the app's domain
|
|
|
|
|
$scope.appRestore.portBindingsInfo = $scope.appRestore.app.manifest.tcpPorts || {}; // Portbinding map only for information
|
|
|
|
|
// set default ports
|
|
|
|
|
for (var env in $scope.appRestore.app.manifest.tcpPorts) {
|
|
|
|
|
$scope.appRestore.portBindings[env] = $scope.appRestore.app.manifest.tcpPorts[env].defaultValue || 0;
|
|
|
|
|
$scope.appRestore.portBindingsEnabled[env] = true;
|
|
|
|
|
}
|
|
|
|
|
|
2018-05-28 10:00:12 -07:00
|
|
|
$scope.appRestore.action = 'restore';
|
|
|
|
|
|
2018-01-22 13:01:38 -08:00
|
|
|
$('#appRestoreModal').modal('show');
|
|
|
|
|
|
|
|
|
|
Client.getAppBackups(app.id, function (error, backups) {
|
|
|
|
|
if (error) {
|
|
|
|
|
Client.error(error);
|
|
|
|
|
} else {
|
|
|
|
|
$scope.appRestore.backups = backups;
|
|
|
|
|
if (backups.length) $scope.appRestore.selectedBackup = backups[0]; // pre-select first backup
|
|
|
|
|
$scope.appRestore.busyFetching = false;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return false; // prevent propagation and default
|
|
|
|
|
},
|
|
|
|
|
|
2018-05-23 20:36:54 -07:00
|
|
|
restore: function () {
|
2018-01-22 13:01:38 -08:00
|
|
|
$scope.appRestore.busy = true;
|
|
|
|
|
$scope.appRestore.error.password = null;
|
|
|
|
|
|
|
|
|
|
Client.restoreApp($scope.appRestore.app.id, $scope.appRestore.selectedBackup.id, $scope.appRestore.password, function (error) {
|
2018-06-18 18:57:00 -07:00
|
|
|
if (error && error.statusCode === 403) {
|
2018-01-22 13:01:38 -08:00
|
|
|
$scope.appRestore.password = '';
|
|
|
|
|
$scope.appRestore.error.password = true;
|
|
|
|
|
$('#appRestorePasswordInput').focus();
|
|
|
|
|
} else if (error) {
|
|
|
|
|
Client.error(error);
|
|
|
|
|
} else {
|
|
|
|
|
$('#appRestoreModal').modal('hide');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$scope.appRestore.busy = false;
|
|
|
|
|
|
2018-06-26 08:49:43 -07:00
|
|
|
Client.refreshAppCache($scope.appRestore.app.id); // reflect the new app state immediately
|
2018-01-22 13:01:38 -08:00
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
$scope.appInfo = {
|
|
|
|
|
app: {},
|
|
|
|
|
message: ''
|
|
|
|
|
};
|
|
|
|
|
|
2018-06-14 15:46:55 +02:00
|
|
|
$scope.appPostInstallConfirm = {
|
|
|
|
|
app: {},
|
|
|
|
|
message: '',
|
|
|
|
|
confirmed: false,
|
|
|
|
|
|
|
|
|
|
show: function (app) {
|
|
|
|
|
$scope.reset();
|
|
|
|
|
|
|
|
|
|
$scope.appPostInstallConfirm.app = app;
|
|
|
|
|
$scope.appPostInstallConfirm.message = app.manifest.postInstallMessage;
|
|
|
|
|
|
|
|
|
|
$('#appPostInstallConfirmModal').modal('show');
|
|
|
|
|
|
|
|
|
|
return false; // prevent propagation and default
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
submit: function () {
|
2018-06-15 13:39:30 +02:00
|
|
|
if (!$scope.appPostInstallConfirm.confirmed) return;
|
|
|
|
|
|
2018-06-14 15:46:55 +02:00
|
|
|
$scope.appPostInstallConfirm.app.pendingPostInstallConfirmation = false;
|
|
|
|
|
delete localStorage['confirmPostInstall_' + $scope.appPostInstallConfirm.app.id];
|
|
|
|
|
|
|
|
|
|
$('#appPostInstallConfirmModal').modal('hide');
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2018-01-22 13:01:38 -08:00
|
|
|
$scope.appError = {
|
|
|
|
|
app: {}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
$scope.appUpdate = {
|
|
|
|
|
busy: false,
|
|
|
|
|
error: {},
|
|
|
|
|
app: {},
|
|
|
|
|
manifest: {},
|
|
|
|
|
portBindings: {}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
$scope.reset = function () {
|
|
|
|
|
// close all dialogs
|
|
|
|
|
$('#appErrorModal').modal('hide');
|
|
|
|
|
$('#appConfigureModal').modal('hide');
|
|
|
|
|
$('#appRestoreModal').modal('hide');
|
|
|
|
|
$('#appUpdateModal').modal('hide');
|
|
|
|
|
$('#appInfoModal').modal('hide');
|
|
|
|
|
$('#appUninstallModal').modal('hide');
|
2018-06-14 15:46:55 +02:00
|
|
|
$('#appPostInstallConfirmModal').modal('hide');
|
2018-01-22 13:01:38 -08:00
|
|
|
|
|
|
|
|
// reset configure dialog
|
|
|
|
|
$scope.appConfigure.error = {};
|
|
|
|
|
$scope.appConfigure.app = {};
|
|
|
|
|
$scope.appConfigure.domain = null;
|
|
|
|
|
$scope.appConfigure.location = '';
|
|
|
|
|
$scope.appConfigure.advancedVisible = false;
|
|
|
|
|
$scope.appConfigure.portBindings = {}; // This is the actual model holding the env:port pair
|
|
|
|
|
$scope.appConfigure.portBindingsEnabled = {}; // This is the actual model holding the enabled/disabled flag
|
|
|
|
|
$scope.appConfigure.certificateFile = null;
|
|
|
|
|
$scope.appConfigure.certificateFileName = '';
|
|
|
|
|
$scope.appConfigure.keyFile = null;
|
|
|
|
|
$scope.appConfigure.keyFileName = '';
|
|
|
|
|
$scope.appConfigure.memoryLimit = 0;
|
|
|
|
|
$scope.appConfigure.memoryTicks = [];
|
|
|
|
|
$scope.appConfigure.accessRestrictionOption = 'any';
|
|
|
|
|
$scope.appConfigure.accessRestriction = { users: [], groups: [] };
|
|
|
|
|
$scope.appConfigure.xFrameOptions = '';
|
2018-05-25 13:59:53 -07:00
|
|
|
$scope.appConfigure.ssoAuth = false;
|
2018-01-22 13:01:38 -08:00
|
|
|
$scope.appConfigure.robotsTxt = '';
|
|
|
|
|
$scope.appConfigure.enableBackup = true;
|
|
|
|
|
|
|
|
|
|
$scope.appConfigureForm.$setPristine();
|
|
|
|
|
$scope.appConfigureForm.$setUntouched();
|
|
|
|
|
|
|
|
|
|
// reset uninstall dialog
|
|
|
|
|
$scope.appUninstall.app = {};
|
|
|
|
|
$scope.appUninstall.error = {};
|
|
|
|
|
$scope.appUninstall.password = '';
|
|
|
|
|
|
|
|
|
|
$scope.appUninstallForm.$setPristine();
|
|
|
|
|
$scope.appUninstallForm.$setUntouched();
|
|
|
|
|
|
|
|
|
|
// reset update dialog
|
|
|
|
|
$scope.appUpdate.error = {};
|
|
|
|
|
$scope.appUpdate.app = {};
|
|
|
|
|
$scope.appUpdate.manifest = {};
|
|
|
|
|
|
|
|
|
|
// reset restore dialog
|
|
|
|
|
$scope.appRestore.error = {};
|
|
|
|
|
$scope.appRestore.app = {};
|
|
|
|
|
$scope.appRestore.password = '';
|
|
|
|
|
$scope.appRestore.selectedBackup = null;
|
|
|
|
|
$scope.appRestore.backups = [];
|
2018-05-28 00:47:53 -07:00
|
|
|
$scope.appRestore.location = '';
|
|
|
|
|
$scope.appRestore.domain = null;
|
|
|
|
|
$scope.appRestore.portBindings = {};
|
|
|
|
|
$scope.appRestore.portBindingsInfo = {};
|
|
|
|
|
$scope.appRestore.portBindingsEnabled = {};
|
2018-05-28 10:00:12 -07:00
|
|
|
$scope.appRestore.action = 'restore';
|
2018-06-14 15:46:55 +02:00
|
|
|
|
|
|
|
|
// post install confirmation dialog
|
|
|
|
|
$scope.appPostInstallConfirm.app = {};
|
|
|
|
|
$scope.appPostInstallConfirm.message = '';
|
|
|
|
|
$scope.appPostInstallConfirm.confirmed = false;
|
2018-01-22 13:01:38 -08:00
|
|
|
};
|
|
|
|
|
|
2018-05-24 13:53:30 -07:00
|
|
|
$scope.readCertificate = function (event) {
|
2018-01-22 13:01:38 -08:00
|
|
|
$scope.$apply(function () {
|
|
|
|
|
$scope.appConfigure.certificateFile = null;
|
|
|
|
|
$scope.appConfigure.certificateFileName = event.target.files[0].name;
|
|
|
|
|
|
|
|
|
|
var reader = new FileReader();
|
|
|
|
|
reader.onload = function (result) {
|
|
|
|
|
if (!result.target || !result.target.result) return console.error('Unable to read local file');
|
|
|
|
|
$scope.appConfigure.certificateFile = result.target.result;
|
|
|
|
|
};
|
|
|
|
|
reader.readAsText(event.target.files[0]);
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
2018-05-24 13:53:30 -07:00
|
|
|
$scope.readKey = function (event) {
|
2018-01-22 13:01:38 -08:00
|
|
|
$scope.$apply(function () {
|
|
|
|
|
$scope.appConfigure.keyFile = null;
|
|
|
|
|
$scope.appConfigure.keyFileName = event.target.files[0].name;
|
|
|
|
|
|
|
|
|
|
var reader = new FileReader();
|
|
|
|
|
reader.onload = function (result) {
|
|
|
|
|
if (!result.target || !result.target.result) return console.error('Unable to read local file');
|
|
|
|
|
$scope.appConfigure.keyFile = result.target.result;
|
|
|
|
|
};
|
|
|
|
|
reader.readAsText(event.target.files[0]);
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
$scope.showInformation = function (app) {
|
|
|
|
|
$scope.reset();
|
|
|
|
|
|
|
|
|
|
$scope.appInfo.app = app;
|
|
|
|
|
$scope.appInfo.message = app.manifest.postInstallMessage;
|
|
|
|
|
|
|
|
|
|
$('#appInfoModal').modal('show');
|
|
|
|
|
|
|
|
|
|
return false; // prevent propagation and default
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
$scope.showError = function (app) {
|
|
|
|
|
$scope.reset();
|
|
|
|
|
|
|
|
|
|
$scope.appError.app = app;
|
|
|
|
|
|
|
|
|
|
$('#appErrorModal').modal('show');
|
|
|
|
|
|
|
|
|
|
return false; // prevent propagation and default
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
$scope.showUninstall = function (app) {
|
|
|
|
|
$scope.reset();
|
|
|
|
|
|
|
|
|
|
$scope.appUninstall.app = app;
|
|
|
|
|
|
|
|
|
|
$('#appUninstallModal').modal('show');
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
$scope.doUninstall = function () {
|
|
|
|
|
$scope.appUninstall.busy = true;
|
|
|
|
|
$scope.appUninstall.error.password = null;
|
|
|
|
|
|
|
|
|
|
Client.uninstallApp($scope.appUninstall.app.id, $scope.appUninstall.password, function (error) {
|
|
|
|
|
if (error && error.statusCode === 403) {
|
|
|
|
|
$scope.appUninstall.password = '';
|
|
|
|
|
$scope.appUninstall.error.password = true;
|
|
|
|
|
$scope.appUninstallForm.password.$setPristine();
|
|
|
|
|
$('#appUninstallPasswordInput').focus();
|
|
|
|
|
} else if (error && error.statusCode === 402) { // unpurchase failed
|
|
|
|
|
Client.error('Relogin to Cloudron App Store');
|
|
|
|
|
} else if (error) {
|
|
|
|
|
Client.error(error);
|
|
|
|
|
} else {
|
|
|
|
|
$('#appUninstallModal').modal('hide');
|
2018-06-26 19:47:39 -07:00
|
|
|
Client.refreshAppCache($scope.appUninstall.app.id); // reflect the new app state immediately
|
2018-01-22 13:01:38 -08:00
|
|
|
$scope.reset();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$scope.appUninstall.busy = false;
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
$scope.showUpdate = function (app, updateManifest) {
|
|
|
|
|
$scope.reset();
|
|
|
|
|
|
|
|
|
|
$scope.appUpdate.app = app;
|
|
|
|
|
$scope.appUpdate.manifest = angular.copy(updateManifest);
|
|
|
|
|
|
|
|
|
|
$('#appUpdateModal').modal('show');
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
$scope.doUpdate = function () {
|
|
|
|
|
$scope.appUpdate.busy = true;
|
|
|
|
|
|
|
|
|
|
Client.updateApp($scope.appUpdate.app.id, $scope.appUpdate.manifest, function (error) {
|
|
|
|
|
if (error) {
|
|
|
|
|
Client.error(error);
|
|
|
|
|
} else {
|
|
|
|
|
$scope.appUpdate.app = {};
|
|
|
|
|
$('#appUpdateModal').modal('hide');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$scope.appUpdate.busy = false;
|
|
|
|
|
|
2018-06-26 08:49:43 -07:00
|
|
|
Client.refreshAppCache($scope.appUpdate.app.id); // reflect the new app state immediately
|
2018-01-22 13:01:38 -08:00
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
$scope.renderAccessRestrictionUser = function (userId) {
|
|
|
|
|
var user = $scope.users.filter(function (u) { return u.id === userId; })[0];
|
|
|
|
|
|
|
|
|
|
// user not found
|
|
|
|
|
if (!user) return userId;
|
|
|
|
|
|
|
|
|
|
return user.username ? user.username : user.email;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
$scope.cancel = function () {
|
|
|
|
|
window.history.back();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
function fetchUsers() {
|
|
|
|
|
Client.getUsers(function (error, users) {
|
|
|
|
|
if (error) {
|
|
|
|
|
console.error(error);
|
|
|
|
|
return $timeout(fetchUsers, 5000);
|
|
|
|
|
}
|
|
|
|
|
|
2018-03-05 12:14:20 +01:00
|
|
|
// ensure we have something to work with in the access restriction dropdowns
|
|
|
|
|
users.forEach(function (user) { user.display = user.username || user.email; });
|
|
|
|
|
|
2018-01-22 13:01:38 -08:00
|
|
|
$scope.users = users;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function fetchGroups() {
|
|
|
|
|
Client.getGroups(function (error, groups) {
|
|
|
|
|
if (error) {
|
|
|
|
|
console.error(error);
|
|
|
|
|
return $timeout(fetchUsers, 5000);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$scope.groups = groups;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getDomains() {
|
|
|
|
|
Client.getDomains(function (error, result) {
|
|
|
|
|
if (error) {
|
|
|
|
|
console.error(error);
|
|
|
|
|
return $timeout(getDomains, 5000);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$scope.domains = result;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getBackupConfig() {
|
|
|
|
|
Client.getBackupConfig(function (error, backupConfig) {
|
|
|
|
|
if (error) return console.error(error);
|
|
|
|
|
|
|
|
|
|
$scope.backupConfig = backupConfig;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Client.onReady(function () {
|
2018-06-26 10:19:50 -07:00
|
|
|
Client.refreshInstalledApps(); // refresh the new list immediately when switching from another view (appstore)
|
|
|
|
|
|
2018-06-25 18:06:17 -07:00
|
|
|
if ($scope.user.caps.apps) {
|
|
|
|
|
fetchUsers();
|
|
|
|
|
fetchGroups();
|
|
|
|
|
getDomains();
|
|
|
|
|
getBackupConfig();
|
|
|
|
|
}
|
2018-01-22 13:01:38 -08:00
|
|
|
|
2018-06-25 18:06:17 -07:00
|
|
|
var refreshAppsTimer = $interval(Client.refreshInstalledApps.bind(Client), 5000);
|
2018-01-22 13:01:38 -08:00
|
|
|
|
2018-06-25 18:06:17 -07:00
|
|
|
$scope.$on('$destroy', function () {
|
|
|
|
|
$interval.cancel(refreshAppsTimer);
|
2018-01-22 13:01:38 -08:00
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// setup all the dialog focus handling
|
|
|
|
|
['appConfigureModal', 'appUninstallModal', 'appUpdateModal', 'appRestoreModal', 'appInfoModal', 'appErrorModal'].forEach(function (id) {
|
|
|
|
|
$('#' + id).on('shown.bs.modal', function () {
|
|
|
|
|
$(this).find("[autofocus]:first").focus();
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
$('.modal-backdrop').remove();
|
|
|
|
|
}]);
|