2015-07-20 00:09:47 -07:00
|
|
|
'use strict';
|
|
|
|
|
|
2016-04-02 12:31:10 +02:00
|
|
|
angular.module('Application').controller('AppsController', ['$scope', '$location', '$timeout', 'Client', 'AppStore', function ($scope, $location, $timeout, Client, AppStore) {
|
2015-07-20 00:09:47 -07:00
|
|
|
$scope.HOST_PORT_MIN = 1024;
|
|
|
|
|
$scope.HOST_PORT_MAX = 65535;
|
|
|
|
|
|
|
|
|
|
$scope.installedApps = Client.getInstalledApps();
|
|
|
|
|
$scope.config = Client.getConfig();
|
|
|
|
|
$scope.user = Client.getUserInfo();
|
2017-01-10 13:11:37 +01:00
|
|
|
$scope.dnsConfig = {};
|
2016-02-11 14:14:51 +01:00
|
|
|
$scope.groups = [];
|
2016-04-02 12:31:10 +02:00
|
|
|
$scope.users = [];
|
2016-12-06 15:31:21 +01:00
|
|
|
$scope.restartAppBusy = false;
|
2015-07-20 00:09:47 -07:00
|
|
|
|
|
|
|
|
$scope.appConfigure = {
|
|
|
|
|
busy: false,
|
|
|
|
|
error: {},
|
|
|
|
|
app: {},
|
|
|
|
|
location: '',
|
2016-04-25 19:26:13 -07:00
|
|
|
usingAltDomain: false,
|
2016-09-05 13:51:29 +02:00
|
|
|
advancedVisible: false,
|
2015-07-20 00:09:47 -07:00
|
|
|
password: '',
|
|
|
|
|
portBindings: {},
|
|
|
|
|
portBindingsEnabled: {},
|
|
|
|
|
portBindingsInfo: {},
|
2015-10-27 18:02:41 +01:00
|
|
|
certificateFile: null,
|
|
|
|
|
certificateFileName: '',
|
|
|
|
|
keyFile: null,
|
2016-02-05 14:56:46 +01:00
|
|
|
keyFileName: '',
|
2016-09-12 08:51:05 -07:00
|
|
|
memoryLimit: 0,
|
|
|
|
|
memoryTicks: [],
|
|
|
|
|
|
2016-09-06 17:56:31 -07:00
|
|
|
accessRestrictionOption: 'any',
|
2016-02-19 18:02:51 +01:00
|
|
|
accessRestriction: { users: [], groups: [] },
|
2016-07-14 17:15:25 +02:00
|
|
|
xFrameOptions: '',
|
2016-11-12 06:37:55 +05:30
|
|
|
customAuth: false,
|
2016-02-19 18:02:51 +01:00
|
|
|
|
|
|
|
|
isAccessRestrictionValid: function () {
|
|
|
|
|
var tmp = $scope.appConfigure.accessRestriction;
|
|
|
|
|
return !!(tmp.users.length || tmp.groups.length);
|
|
|
|
|
}
|
2015-07-20 00:09:47 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
$scope.appUninstall = {
|
|
|
|
|
busy: false,
|
|
|
|
|
error: {},
|
|
|
|
|
app: {},
|
|
|
|
|
password: ''
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
$scope.appRestore = {
|
|
|
|
|
busy: false,
|
|
|
|
|
error: {},
|
|
|
|
|
app: {},
|
|
|
|
|
password: ''
|
|
|
|
|
};
|
|
|
|
|
|
2016-09-07 12:07:49 -07:00
|
|
|
$scope.appPostInstall = {
|
2016-09-07 01:44:14 -07:00
|
|
|
app: {},
|
2016-09-07 12:07:49 -07:00
|
|
|
message: ''
|
2016-09-07 01:44:14 -07:00
|
|
|
};
|
|
|
|
|
|
2015-12-14 18:56:15 -08:00
|
|
|
$scope.appError = {
|
|
|
|
|
app: {}
|
|
|
|
|
};
|
|
|
|
|
|
2015-07-20 00:09:47 -07:00
|
|
|
$scope.appUpdate = {
|
|
|
|
|
busy: false,
|
|
|
|
|
error: {},
|
|
|
|
|
app: {},
|
|
|
|
|
password: '',
|
|
|
|
|
manifest: {},
|
|
|
|
|
portBindings: {}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
$scope.reset = function () {
|
|
|
|
|
// reset configure dialog
|
|
|
|
|
$scope.appConfigure.error = {};
|
|
|
|
|
$scope.appConfigure.app = {};
|
|
|
|
|
$scope.appConfigure.location = '';
|
2016-09-05 13:51:29 +02:00
|
|
|
$scope.appConfigure.advancedVisible = false;
|
2016-04-25 19:26:13 -07:00
|
|
|
$scope.appConfigure.usingAltDomain = false;
|
2015-07-20 00:09:47 -07:00
|
|
|
$scope.appConfigure.password = '';
|
2015-10-27 18:02:41 +01:00
|
|
|
$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 = '';
|
2016-09-12 08:51:05 -07:00
|
|
|
$scope.appConfigure.memoryLimit = 0;
|
|
|
|
|
$scope.appConfigure.memoryTicks = [];
|
2016-09-06 17:56:31 -07:00
|
|
|
$scope.appConfigure.accessRestrictionOption = 'any';
|
2016-02-11 14:14:51 +01:00
|
|
|
$scope.appConfigure.accessRestriction = { users: [], groups: [] };
|
2016-07-14 17:15:25 +02:00
|
|
|
$scope.appConfigure.xFrameOptions = '';
|
2016-11-12 06:37:55 +05:30
|
|
|
$scope.appConfigure.customAuth = false;
|
2015-07-20 00:09:47 -07:00
|
|
|
|
|
|
|
|
$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.password = '';
|
|
|
|
|
$scope.appUpdate.manifest = {};
|
|
|
|
|
$scope.appUpdate.portBindings = {};
|
|
|
|
|
|
|
|
|
|
$scope.appUpdateForm.$setPristine();
|
|
|
|
|
$scope.appUpdateForm.$setUntouched();
|
|
|
|
|
|
|
|
|
|
// reset restore dialog
|
|
|
|
|
$scope.appRestore.error = {};
|
|
|
|
|
$scope.appRestore.app = {};
|
|
|
|
|
$scope.appRestore.password = '';
|
|
|
|
|
|
|
|
|
|
$scope.appRestoreForm.$setPristine();
|
|
|
|
|
$scope.appRestoreForm.$setUntouched();
|
|
|
|
|
};
|
|
|
|
|
|
2015-10-27 18:02:41 +01:00
|
|
|
document.getElementById('appConfigureCertificateFileInput').onchange = function (event) {
|
|
|
|
|
$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]);
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
document.getElementById('appConfigureKeyFileInput').onchange = function (event) {
|
|
|
|
|
$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]);
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
2016-02-11 14:14:51 +01:00
|
|
|
$scope.appConfigureToggleGroup = function (group) {
|
|
|
|
|
var groups = $scope.appConfigure.accessRestriction.groups;
|
|
|
|
|
var pos = groups.indexOf(group.id);
|
|
|
|
|
|
|
|
|
|
if (pos === -1) groups.push(group.id);
|
|
|
|
|
else groups.splice(pos, 1);
|
|
|
|
|
};
|
|
|
|
|
|
2016-04-25 19:26:13 -07:00
|
|
|
$scope.useAltDomain = function (use) {
|
|
|
|
|
$scope.appConfigure.usingAltDomain = use;
|
|
|
|
|
|
|
|
|
|
if (use) {
|
|
|
|
|
$scope.appConfigure.location = '';
|
|
|
|
|
} else {
|
|
|
|
|
$scope.appConfigure.location = $scope.appConfigure.app.location;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2015-07-20 00:09:47 -07:00
|
|
|
$scope.showConfigure = function (app) {
|
|
|
|
|
$scope.reset();
|
|
|
|
|
|
2015-10-27 18:02:41 +01:00
|
|
|
// fill relevant info from the app
|
2015-07-20 00:09:47 -07:00
|
|
|
$scope.appConfigure.app = app;
|
2016-04-25 19:26:13 -07:00
|
|
|
$scope.appConfigure.location = app.altDomain || app.location;
|
|
|
|
|
$scope.appConfigure.usingAltDomain = !!app.altDomain;
|
2015-07-20 00:09:47 -07:00
|
|
|
$scope.appConfigure.portBindingsInfo = app.manifest.tcpPorts || {}; // Portbinding map only for information
|
2016-09-06 17:56:31 -07:00
|
|
|
$scope.appConfigure.accessRestrictionOption = app.accessRestriction ? 'groups' : 'any';
|
2016-02-11 14:14:51 +01:00
|
|
|
$scope.appConfigure.accessRestriction = app.accessRestriction || { users: [], groups: [] };
|
2016-09-13 16:52:03 -07:00
|
|
|
$scope.appConfigure.memoryLimit = app.memoryLimit || app.manifest.memoryLimit || (256 * 1024 * 1024);
|
2016-07-14 17:15:25 +02:00
|
|
|
$scope.appConfigure.xFrameOptions = app.xFrameOptions.indexOf('ALLOW-FROM') === 0 ? app.xFrameOptions.split(' ')[1] : '';
|
2016-11-12 06:37:55 +05:30
|
|
|
$scope.appConfigure.customAuth = !(app.manifest.addons['simpleauth'] || app.manifest.addons['ldap'] || app.manifest.addons['oauth']);
|
2015-07-20 00:09:47 -07:00
|
|
|
|
2016-09-12 08:51:05 -07:00
|
|
|
// create ticks starting from manifest memory limit
|
|
|
|
|
$scope.appConfigure.memoryTicks = [
|
|
|
|
|
256 * 1024 * 1024,
|
|
|
|
|
512 * 1024 * 1024,
|
|
|
|
|
1024 * 1024 * 1024,
|
|
|
|
|
2048 * 1024 * 1024,
|
|
|
|
|
4096 * 1024 * 1024
|
|
|
|
|
].filter(function (t) { return t >= (app.manifest.memoryLimit || 0); });
|
|
|
|
|
if (app.manifest.memoryLimit && $scope.appConfigure.memoryTicks[0] !== app.manifest.memoryLimit) {
|
|
|
|
|
$scope.appConfigure.memoryTicks.unshift(app.manifest.memoryLimit);
|
|
|
|
|
}
|
|
|
|
|
|
2016-11-11 22:30:18 +05:30
|
|
|
$scope.appConfigure.accessRestrictionOption = app.accessRestriction ? 'groups' : 'any';
|
2016-09-06 17:56:31 -07:00
|
|
|
|
2015-07-20 00:09:47 -07:00
|
|
|
// 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');
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
$scope.doConfigure = function () {
|
|
|
|
|
$scope.appConfigure.busy = true;
|
|
|
|
|
$scope.appConfigure.error.other = null;
|
|
|
|
|
$scope.appConfigure.error.location = null;
|
|
|
|
|
$scope.appConfigure.error.password = null;
|
2016-07-15 11:45:41 +02:00
|
|
|
$scope.appConfigure.error.xFrameOptions = null;
|
2015-07-20 00:09:47 -07: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];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-19 10:29:51 +02:00
|
|
|
var data = {
|
2016-04-25 19:26:13 -07:00
|
|
|
location: $scope.appConfigure.usingAltDomain ? $scope.appConfigure.app.location : $scope.appConfigure.location,
|
|
|
|
|
altDomain: $scope.appConfigure.usingAltDomain ? $scope.appConfigure.location : null,
|
2015-10-19 10:29:51 +02:00
|
|
|
portBindings: finalPortBindings,
|
2016-09-06 17:56:31 -07:00
|
|
|
accessRestriction: $scope.appConfigure.accessRestrictionOption === 'groups' ? $scope.appConfigure.accessRestriction : null,
|
2015-10-27 18:02:41 +01:00
|
|
|
cert: $scope.appConfigure.certificateFile,
|
2016-07-14 17:15:25 +02:00
|
|
|
key: $scope.appConfigure.keyFile,
|
2016-09-04 11:45:56 -07:00
|
|
|
xFrameOptions: $scope.appConfigure.xFrameOptions ? ('ALLOW-FROM ' + $scope.appConfigure.xFrameOptions) : 'SAMEORIGIN',
|
2016-11-11 22:30:18 +05:30
|
|
|
memoryLimit: $scope.appConfigure.memoryLimit === $scope.appConfigure.memoryTicks[0] ? 0 : $scope.appConfigure.memoryLimit
|
2015-10-19 10:29:51 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Client.configureApp($scope.appConfigure.app.id, $scope.appConfigure.password, data, function (error) {
|
2015-07-20 00:09:47 -07:00
|
|
|
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;
|
|
|
|
|
} else if (error.statusCode === 409) {
|
|
|
|
|
$scope.appConfigure.error.location = 'This name is already taken.';
|
|
|
|
|
$scope.appConfigureForm.location.$setPristine();
|
|
|
|
|
$('#appConfigureLocationInput').focus();
|
|
|
|
|
} else if (error.statusCode === 403) {
|
2016-01-21 15:03:51 +01:00
|
|
|
$scope.appConfigure.error.password = true;
|
2015-07-20 00:09:47 -07:00
|
|
|
$scope.appConfigure.password = '';
|
2016-01-21 15:03:51 +01:00
|
|
|
$scope.appConfigureForm.password.$setPristine();
|
2015-07-20 00:09:47 -07:00
|
|
|
$('#appConfigurePasswordInput').focus();
|
2015-10-28 22:21:20 +01:00
|
|
|
} else if (error.statusCode === 400 && error.message.indexOf('cert') !== -1 ) {
|
2015-10-28 20:30:15 +01:00
|
|
|
$scope.appConfigure.error.cert = error.message;
|
|
|
|
|
$scope.appConfigure.certificateFileName = '';
|
|
|
|
|
$scope.appConfigure.certificateFile = null;
|
|
|
|
|
$scope.appConfigure.keyFileName = '';
|
|
|
|
|
$scope.appConfigure.keyFile = null;
|
2016-07-15 11:45:41 +02:00
|
|
|
} else if (error.statusCode === 400 && error.message.indexOf('xFrameOptions') !== -1 ) {
|
|
|
|
|
$scope.appConfigure.error.xFrameOptions = error.message;
|
|
|
|
|
$scope.appConfigureForm.xFrameOptions.$setPristine();
|
|
|
|
|
$('#appConfigureXFrameOptionsInput').focus();
|
2015-07-20 00:09:47 -07:00
|
|
|
} else {
|
|
|
|
|
$scope.appConfigure.error.other = error.message;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$scope.appConfigure.busy = false;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$scope.appConfigure.busy = false;
|
|
|
|
|
|
|
|
|
|
$('#appConfigureModal').modal('hide');
|
|
|
|
|
|
|
|
|
|
$scope.reset();
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
2016-09-07 12:07:49 -07:00
|
|
|
$scope.showPostInstall = function (app) {
|
2016-09-07 01:44:14 -07:00
|
|
|
$scope.reset();
|
|
|
|
|
|
2016-09-07 12:07:49 -07:00
|
|
|
$scope.appPostInstall.app = app;
|
|
|
|
|
$scope.appPostInstall.message = app.manifest.postInstallMessage;
|
2016-09-07 01:44:14 -07:00
|
|
|
|
2016-09-07 12:07:49 -07:00
|
|
|
$('#appPostInstallModal').modal('show');
|
2016-09-07 01:44:14 -07:00
|
|
|
|
|
|
|
|
return false; // prevent propagation and default
|
|
|
|
|
};
|
|
|
|
|
|
2015-12-14 17:57:58 -08:00
|
|
|
$scope.showError = function (app) {
|
|
|
|
|
$scope.reset();
|
|
|
|
|
|
|
|
|
|
$scope.appError.app = app;
|
|
|
|
|
|
|
|
|
|
$('#appErrorModal').modal('show');
|
2015-12-14 18:56:15 -08:00
|
|
|
|
|
|
|
|
return false; // prevent propagation and default
|
2015-12-14 17:57:58 -08:00
|
|
|
};
|
|
|
|
|
|
2015-07-20 00:09:47 -07:00
|
|
|
$scope.showRestore = function (app) {
|
|
|
|
|
$scope.reset();
|
|
|
|
|
|
|
|
|
|
$scope.appRestore.app = app;
|
|
|
|
|
|
|
|
|
|
$('#appRestoreModal').modal('show');
|
2016-09-07 01:44:14 -07:00
|
|
|
|
|
|
|
|
return false; // prevent propagation and default
|
2015-07-20 00:09:47 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
$scope.doRestore = function () {
|
|
|
|
|
$scope.appRestore.busy = true;
|
|
|
|
|
$scope.appRestore.error.password = null;
|
|
|
|
|
|
2016-06-13 10:13:54 -07:00
|
|
|
Client.restoreApp($scope.appRestore.app.id, $scope.appRestore.app.lastBackupId, $scope.appRestore.password, function (error) {
|
2015-07-20 00:09:47 -07:00
|
|
|
if (error && error.statusCode === 403) {
|
|
|
|
|
$scope.appRestore.password = '';
|
|
|
|
|
$scope.appRestore.error.password = true;
|
2016-01-21 15:06:22 +01:00
|
|
|
$scope.appRestoreForm.password.$setPristine();
|
2015-07-20 00:09:47 -07:00
|
|
|
$('#appRestorePasswordInput').focus();
|
|
|
|
|
} else if (error) {
|
|
|
|
|
Client.error(error);
|
|
|
|
|
} else {
|
|
|
|
|
$('#appRestoreModal').modal('hide');
|
|
|
|
|
$scope.reset();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$scope.appRestore.busy = false;
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
$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;
|
2016-01-21 15:09:22 +01:00
|
|
|
$scope.appUninstallForm.password.$setPristine();
|
2015-07-20 00:09:47 -07:00
|
|
|
$('#appUninstallPasswordInput').focus();
|
|
|
|
|
} else if (error) {
|
|
|
|
|
Client.error(error);
|
|
|
|
|
} else {
|
|
|
|
|
$('#appUninstallModal').modal('hide');
|
|
|
|
|
$scope.reset();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$scope.appUninstall.busy = false;
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
$scope.showUpdate = function (app) {
|
|
|
|
|
$scope.reset();
|
|
|
|
|
|
|
|
|
|
$scope.appUpdate.app = app;
|
|
|
|
|
|
|
|
|
|
AppStore.getManifest(app.appStoreId, function (error, manifest) {
|
|
|
|
|
if (error) return console.error(error);
|
|
|
|
|
|
2015-08-03 21:17:58 -07:00
|
|
|
$scope.appUpdate.manifest = angular.copy(manifest);
|
2015-07-20 00:09:47 -07:00
|
|
|
|
|
|
|
|
// ensure we always operate on objects here
|
|
|
|
|
app.portBindings = app.portBindings || {};
|
|
|
|
|
app.manifest.tcpPorts = app.manifest.tcpPorts || {};
|
|
|
|
|
manifest.tcpPorts = manifest.tcpPorts || {};
|
|
|
|
|
|
|
|
|
|
// Activate below two lines for testing the UI
|
|
|
|
|
// manifest.tcpPorts['TEST_HTTP'] = { defaultValue: 1337, description: 'HTTP server'};
|
|
|
|
|
// app.manifest.tcpPorts['TEST_FOOBAR'] = { defaultValue: 1338, description: 'FOOBAR server'};
|
|
|
|
|
// app.portBindings['TEST_SSH'] = 1339;
|
|
|
|
|
|
|
|
|
|
var portBindingsInfo = {}; // Portbinding map only for information
|
|
|
|
|
var portBindings = {}; // This is the actual model holding the env:port pair
|
|
|
|
|
var portBindingsEnabled = {}; // This is the actual model holding the enabled/disabled flag
|
|
|
|
|
var obsoletePortBindings = {}; // Info map for obsolete port bindings, this is for display use only and thus not in the model
|
|
|
|
|
var portsChanged = false;
|
|
|
|
|
var env;
|
|
|
|
|
|
|
|
|
|
// detect new portbindings and copy all from manifest.tcpPorts
|
|
|
|
|
for (env in manifest.tcpPorts) {
|
|
|
|
|
portBindingsInfo[env] = manifest.tcpPorts[env];
|
|
|
|
|
if (!app.manifest.tcpPorts[env]) {
|
|
|
|
|
portBindingsInfo[env].isNew = true;
|
|
|
|
|
portBindingsEnabled[env] = true;
|
|
|
|
|
|
|
|
|
|
// use default integer port value in model
|
|
|
|
|
portBindings[env] = manifest.tcpPorts[env].defaultValue || 0;
|
|
|
|
|
|
|
|
|
|
portsChanged = true;
|
|
|
|
|
} else {
|
|
|
|
|
// detect if the port binding was enabled
|
|
|
|
|
if (app.portBindings[env]) {
|
|
|
|
|
portBindings[env] = app.portBindings[env];
|
|
|
|
|
portBindingsEnabled[env] = true;
|
|
|
|
|
} else {
|
|
|
|
|
portBindings[env] = manifest.tcpPorts[env].defaultValue || 0;
|
|
|
|
|
portBindingsEnabled[env] = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// detect obsolete portbindings (mappings in app.portBindings, but not anymore in manifest.tcpPorts)
|
|
|
|
|
for (env in app.manifest.tcpPorts) {
|
|
|
|
|
// only list the port if it is not in the new manifest and was enabled previously
|
|
|
|
|
if (!manifest.tcpPorts[env] && app.portBindings[env]) {
|
|
|
|
|
obsoletePortBindings[env] = app.portBindings[env];
|
|
|
|
|
portsChanged = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// now inject the maps into the $scope, we only show those if ports have changed
|
|
|
|
|
$scope.appUpdate.portBindings = portBindings; // always inject the model, so it gets used in the actual update call
|
|
|
|
|
$scope.appUpdate.portBindingsEnabled = portBindingsEnabled; // always inject the model, so it gets used in the actual update call
|
|
|
|
|
|
|
|
|
|
if (portsChanged) {
|
|
|
|
|
$scope.appUpdate.portBindingsInfo = portBindingsInfo;
|
|
|
|
|
$scope.appUpdate.obsoletePortBindings = obsoletePortBindings;
|
|
|
|
|
} else {
|
|
|
|
|
$scope.appUpdate.portBindingsInfo = {};
|
|
|
|
|
$scope.appUpdate.obsoletePortBindings = {};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$('#appUpdateModal').modal('show');
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
$scope.doUpdate = function (form) {
|
|
|
|
|
$scope.appUpdate.error.password = null;
|
|
|
|
|
$scope.appUpdate.busy = true;
|
|
|
|
|
|
|
|
|
|
// only use enabled ports from portBindings
|
|
|
|
|
var finalPortBindings = {};
|
|
|
|
|
for (var env in $scope.appUpdate.portBindings) {
|
|
|
|
|
if ($scope.appUpdate.portBindingsEnabled[env]) {
|
|
|
|
|
finalPortBindings[env] = $scope.appUpdate.portBindings[env];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Client.updateApp($scope.appUpdate.app.id, $scope.appUpdate.manifest, finalPortBindings, $scope.appUpdate.password, function (error) {
|
|
|
|
|
if (error && error.statusCode === 403) {
|
|
|
|
|
$scope.appUpdate.password = '';
|
|
|
|
|
$scope.appUpdate.error.password = true;
|
|
|
|
|
} else if (error) {
|
|
|
|
|
Client.error(error);
|
|
|
|
|
} else {
|
|
|
|
|
$scope.appUpdate.app = {};
|
|
|
|
|
$scope.appUpdate.password = '';
|
|
|
|
|
|
|
|
|
|
form.$setPristine();
|
|
|
|
|
form.$setUntouched();
|
|
|
|
|
|
|
|
|
|
$('#appUpdateModal').modal('hide');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$scope.appUpdate.busy = false;
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
2016-04-02 12:55:14 +02: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;
|
|
|
|
|
};
|
|
|
|
|
|
2015-07-20 00:09:47 -07:00
|
|
|
$scope.cancel = function () {
|
|
|
|
|
window.history.back();
|
|
|
|
|
};
|
|
|
|
|
|
2016-09-07 12:07:49 -07:00
|
|
|
$scope.hasPostInstallMessage = function (app) {
|
|
|
|
|
return app.manifest && app.manifest.postInstallMessage;
|
2016-09-07 02:34:17 -07:00
|
|
|
};
|
|
|
|
|
|
2016-11-24 13:02:20 +01:00
|
|
|
$scope.hasConfigurePath = function (app) {
|
|
|
|
|
return app.manifest && app.manifest.configurePath;
|
|
|
|
|
};
|
|
|
|
|
|
2016-12-06 15:31:21 +01:00
|
|
|
$scope.restartApp = function (app) {
|
|
|
|
|
$scope.restartAppBusy = true;
|
|
|
|
|
|
|
|
|
|
function waitUntilStopped(callback) {
|
|
|
|
|
Client.refreshInstalledApps(function (error) {
|
|
|
|
|
if (error) return callback(error);
|
|
|
|
|
|
|
|
|
|
Client.getApp(app.id, function (error, result) {
|
|
|
|
|
if (error) return callback(error);
|
|
|
|
|
|
|
|
|
|
if (result.runState === 'stopped') return callback();
|
|
|
|
|
setTimeout(waitUntilStopped.bind(null, callback), 2000);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Client.stopApp(app.id, function (error) {
|
|
|
|
|
$scope.restartAppBusy = false;
|
|
|
|
|
|
|
|
|
|
if (error) return console.error('Failed to stop app.', error);
|
|
|
|
|
|
|
|
|
|
// close dialog to allow user see the app restarting
|
|
|
|
|
$('#appConfigureModal').modal('hide');
|
|
|
|
|
$scope.reset();
|
|
|
|
|
|
|
|
|
|
waitUntilStopped(function (error) {
|
|
|
|
|
if (error) return console.error('Failed to get app status.', error);
|
|
|
|
|
|
|
|
|
|
Client.startApp(app.id, function (error) {
|
|
|
|
|
if (error) console.error('Failed to start app.', error);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
2016-04-02 12:31:10 +02:00
|
|
|
function fetchUsers() {
|
|
|
|
|
Client.getUsers(function (error, users) {
|
|
|
|
|
if (error) {
|
|
|
|
|
console.error(error);
|
|
|
|
|
return $timeout(fetchUsers, 5000);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$scope.users = users;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function fetchGroups() {
|
|
|
|
|
Client.getGroups(function (error, groups) {
|
|
|
|
|
if (error) {
|
|
|
|
|
console.error(error);
|
|
|
|
|
return $timeout(fetchUsers, 5000);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$scope.groups = groups;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2017-01-10 13:11:37 +01:00
|
|
|
function fetchDnsConfig() {
|
|
|
|
|
Client.getDnsConfig(function (error, result) {
|
|
|
|
|
if (error) {
|
|
|
|
|
console.error(error);
|
|
|
|
|
return $timeout(fetchDnsConfig, 5000);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$scope.dnsConfig = result;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-27 16:34:36 +02:00
|
|
|
Client.onReady(function () {
|
|
|
|
|
Client.refreshUserInfo(function (error) {
|
|
|
|
|
if (error) return console.error(error);
|
2016-04-02 12:55:14 +02:00
|
|
|
|
2016-07-27 16:34:36 +02:00
|
|
|
if ($scope.user.admin) {
|
|
|
|
|
fetchUsers();
|
|
|
|
|
fetchGroups();
|
2017-01-10 13:11:37 +01:00
|
|
|
fetchDnsConfig();
|
2016-07-27 16:34:36 +02:00
|
|
|
}
|
|
|
|
|
});
|
2016-04-02 12:55:14 +02:00
|
|
|
});
|
2016-02-11 14:14:51 +01:00
|
|
|
|
2015-07-20 00:09:47 -07:00
|
|
|
// setup all the dialog focus handling
|
2015-08-12 14:35:51 +02:00
|
|
|
['appConfigureModal', 'appUninstallModal', 'appUpdateModal', 'appRestoreModal'].forEach(function (id) {
|
2015-07-20 00:09:47 -07:00
|
|
|
$('#' + id).on('shown.bs.modal', function () {
|
|
|
|
|
$(this).find("[autofocus]:first").focus();
|
|
|
|
|
});
|
|
|
|
|
});
|
2016-11-21 13:22:56 +01:00
|
|
|
|
|
|
|
|
$('.modal-backdrop').remove();
|
2015-07-20 00:09:47 -07:00
|
|
|
}]);
|