486 lines
20 KiB
JavaScript
486 lines
20 KiB
JavaScript
'use strict';
|
|
|
|
/* global angular:false */
|
|
/* global $:false */
|
|
|
|
angular.module('Application').controller('ActivityController', ['$scope', '$location', 'Client', function ($scope, $location, Client) {
|
|
Client.onReady(function () { if (!Client.getUserInfo().isAtLeastAdmin) $location.path('/'); });
|
|
|
|
$scope.config = Client.getConfig();
|
|
|
|
$scope.busy = false;
|
|
$scope.busyRefresh = false;
|
|
$scope.eventLogs = [];
|
|
$scope.activeEventLog = null;
|
|
|
|
// TODO sync this with the eventlog filter
|
|
$scope.actions = [
|
|
{ name: '-- All app events --', value: 'app.' },
|
|
{ name: '-- All user events --', value: 'user.' },
|
|
{ name: 'app.configure', value: 'app.configure' },
|
|
{ name: 'app.install', value: 'app.install' },
|
|
{ name: 'app.restore', value: 'app.restore' },
|
|
{ name: 'app.uninstall', value: 'app.uninstall' },
|
|
{ name: 'app.update', value: 'app.update' },
|
|
{ name: 'app.update.finish', value: 'app.update.finish' },
|
|
{ name: 'app.login', value: 'app.login' },
|
|
{ name: 'app.oom', value: 'app.oom' },
|
|
{ name: 'app.down', value: 'app.down' },
|
|
{ name: 'app.up', value: 'app.up' },
|
|
{ name: 'app.start', value: 'app.start' },
|
|
{ name: 'app.stop', value: 'app.stop' },
|
|
{ name: 'app.restart', value: 'app.restart' },
|
|
{ name: 'Apptask Crash', value: 'app.task.crash' },
|
|
{ name: 'backup.cleanup', value: 'backup.cleanup.start' },
|
|
{ name: 'backup.cleanup.finish', value: 'backup.cleanup.finish' },
|
|
{ name: 'backup.finish', value: 'backup.finish' },
|
|
{ name: 'backup.start', value: 'backup.start' },
|
|
{ name: 'certificate.new', value: 'certificate.new' },
|
|
{ name: 'certificate.renew', value: 'certificate.renew' },
|
|
{ name: 'cloudron.activate', value: 'cloudron.activate' },
|
|
{ name: 'cloudron.provision', value: 'cloudron.provision' },
|
|
{ name: 'cloudron.restore', value: 'cloudron.restore' },
|
|
{ name: 'cloudron.start', value: 'cloudron.start' },
|
|
{ name: 'cloudron.update', value: 'cloudron.update' },
|
|
{ name: 'cloudron.update.finish', value: 'cloudron.update.finish' },
|
|
{ name: 'dashboard.domain.update', value: 'dashboard.domain.update' },
|
|
{ name: 'dyndns.update', value: 'dyndns.update' },
|
|
{ name: 'domain.add', value: 'domain.add' },
|
|
{ name: 'domain.update', value: 'domain.update' },
|
|
{ name: 'domain.remove', value: 'domain.remove' },
|
|
{ name: 'mail.location', value: 'mail.location' },
|
|
{ name: 'mail.enabled', value: 'mail.enabled' },
|
|
{ name: 'mail.box.add', value: 'mail.box.add' },
|
|
{ name: 'mail.box.update', value: 'mail.box.update' },
|
|
{ name: 'mail.box.remove', value: 'mail.box.remove' },
|
|
{ name: 'mail.list.add', value: 'mail.list.add' },
|
|
{ name: 'mail.list.update', value: 'mail.list.update' },
|
|
{ name: 'mail.list.remove', value: 'mail.list.remove' },
|
|
{ name: 'support.ticket', value: 'support.ticket' },
|
|
{ name: 'support.ssh', value: 'support.ssh' },
|
|
{ name: 'user.add', value: 'user.add' },
|
|
{ name: 'user.login', value: 'user.login' },
|
|
{ name: 'user.remove', value: 'user.remove' },
|
|
{ name: 'user.transfer', value: 'user.transfer' },
|
|
{ name: 'user.update', value: 'user.update' },
|
|
{ name: 'volume.add', value: 'volume.add' },
|
|
{ name: 'volume.update', value: 'volume.update' },
|
|
{ name: 'volume.remove', value: 'volume.update' },
|
|
{ name: 'System Crash', value: 'system.crash' }
|
|
];
|
|
|
|
$scope.pageItemCount = [
|
|
{ name: 'Show 20 per page', value: 20 },
|
|
{ name: 'Show 50 per page', value: 50 },
|
|
{ name: 'Show 100 per page', value: 100 }
|
|
];
|
|
|
|
$scope.currentPage = 1;
|
|
$scope.pageItems = $scope.pageItemCount[0];
|
|
$scope.action = '';
|
|
$scope.selectedActions = [];
|
|
$scope.search = '';
|
|
|
|
function eventLogDetails(eventLog) {
|
|
var ACTION_ACTIVATE = 'cloudron.activate';
|
|
var ACTION_PROVISION = 'cloudron.provision';
|
|
var ACTION_RESTORE = 'cloudron.restore';
|
|
|
|
var ACTION_APP_CLONE = 'app.clone';
|
|
var ACTION_APP_REPAIR = 'app.repair';
|
|
var ACTION_APP_CONFIGURE = 'app.configure';
|
|
var ACTION_APP_INSTALL = 'app.install';
|
|
var ACTION_APP_RESTORE = 'app.restore';
|
|
var ACTION_APP_UNINSTALL = 'app.uninstall';
|
|
var ACTION_APP_UPDATE = 'app.update';
|
|
var ACTION_APP_UPDATE_FINISH = 'app.update.finish';
|
|
var ACTION_APP_LOGIN = 'app.login';
|
|
var ACTION_APP_OOM = 'app.oom';
|
|
var ACTION_APP_UP = 'app.up';
|
|
var ACTION_APP_DOWN = 'app.down';
|
|
var ACTION_APP_START = 'app.start';
|
|
var ACTION_APP_STOP = 'app.stop';
|
|
var ACTION_APP_RESTART = 'app.restart';
|
|
|
|
var ACTION_BACKUP_FINISH = 'backup.finish';
|
|
var ACTION_BACKUP_START = 'backup.start';
|
|
var ACTION_BACKUP_CLEANUP_START = 'backup.cleanup.start';
|
|
var ACTION_BACKUP_CLEANUP_FINISH = 'backup.cleanup.finish';
|
|
var ACTION_CERTIFICATE_NEW = 'certificate.new';
|
|
var ACTION_CERTIFICATE_RENEWAL = 'certificate.renew';
|
|
|
|
var ACTION_DASHBOARD_DOMAIN_UPDATE = 'dashboard.domain.update';
|
|
|
|
var ACTION_DOMAIN_ADD = 'domain.add';
|
|
var ACTION_DOMAIN_UPDATE = 'domain.update';
|
|
var ACTION_DOMAIN_REMOVE = 'domain.remove';
|
|
|
|
var ACTION_START = 'cloudron.start';
|
|
var ACTION_UPDATE = 'cloudron.update';
|
|
var ACTION_UPDATE_FINISH = 'cloudron.update.finish';
|
|
var ACTION_USER_ADD = 'user.add';
|
|
var ACTION_USER_LOGIN = 'user.login';
|
|
var ACTION_USER_REMOVE = 'user.remove';
|
|
var ACTION_USER_UPDATE = 'user.update';
|
|
var ACTION_USER_TRANSFER = 'user.transfer';
|
|
|
|
var ACTION_MAIL_LOCATION = 'mail.location';
|
|
var ACTION_MAIL_ENABLED = 'mail.enabled';
|
|
var ACTION_MAIL_DISABLED = 'mail.disabled';
|
|
var ACTION_MAIL_MAILBOX_ADD = 'mail.box.add';
|
|
var ACTION_MAIL_MAILBOX_UPDATE = 'mail.box.update';
|
|
var ACTION_MAIL_MAILBOX_REMOVE = 'mail.box.remove';
|
|
var ACTION_MAIL_LIST_ADD = 'mail.list.add';
|
|
var ACTION_MAIL_LIST_UPDATE = 'mail.list.update';
|
|
var ACTION_MAIL_LIST_REMOVE = 'mail.list.remove';
|
|
|
|
var ACTION_SUPPORT_TICKET = 'support.ticket';
|
|
var ACTION_SUPPORT_SSH = 'support.ssh';
|
|
|
|
var ACTION_VOLUME_ADD = 'volume.add';
|
|
var ACTION_VOLUME_UPDATE = 'volume.update';
|
|
var ACTION_VOLUME_REMOVE = 'volume.remove';
|
|
|
|
var ACTION_DYNDNS_UPDATE = 'dyndns.update';
|
|
|
|
var ACTION_SYSTEM_CRASH = 'system.crash';
|
|
|
|
var data = eventLog.data;
|
|
var errorMessage = data.errorMessage;
|
|
var details, app;
|
|
|
|
function appName(app) {
|
|
return (app.label || app.fqdn || app.location) + ' (' + app.manifest.title + ')';
|
|
}
|
|
|
|
switch (eventLog.action) {
|
|
case ACTION_ACTIVATE:
|
|
return 'Cloudron was activated';
|
|
|
|
case ACTION_PROVISION:
|
|
return 'Cloudron was setup';
|
|
|
|
case ACTION_RESTORE:
|
|
return 'Cloudron was restored using backup ' + data.backupId;
|
|
|
|
case ACTION_APP_CONFIGURE: {
|
|
if (!data.app) return '';
|
|
app = data.app;
|
|
|
|
var q = function (x) {
|
|
return '"' + x + '"';
|
|
};
|
|
|
|
if ('accessRestriction' in data) { // since it can be null
|
|
return 'Access restriction of ' + appName(app) + ' was changed';
|
|
} else if (data.label) {
|
|
return 'Label of ' + appName(app) + ' was set to ' + q(data.label);
|
|
} else if (data.tags) {
|
|
return 'Tags of ' + appName(app) + ' was set to ' + q(data.tags.join(','));
|
|
} else if (data.icon) {
|
|
return 'Icon of ' + appName(app) + ' was changed';
|
|
} else if (data.memoryLimit) {
|
|
return 'Memory limit of ' + appName(app) + ' was set to ' + data.memoryLimit;
|
|
} else if (data.cpuShares) {
|
|
return 'CPU shares of ' + appName(app) + ' was set to ' + Math.round((data.cpuShares * 100)/1024) + '%';
|
|
} else if (data.env) {
|
|
return 'Env vars of ' + appName(app) + ' was changed';
|
|
} else if ('debugMode' in data) { // since it can be null
|
|
if (data.debugMode) {
|
|
return appName(app) + ' was placed in repair mode';
|
|
} else {
|
|
return appName(app) + ' was taken out of repair mode';
|
|
}
|
|
} else if ('enableBackup' in data) {
|
|
return 'Automatic backups of ' + appName(app) + ' was ' + (data.enableBackup ? 'enabled' : 'disabled');
|
|
} else if ('enableAutomaticUpdate' in data) {
|
|
return 'Automatic updates of ' + appName(app) + ' was ' + (data.enableAutomaticUpdate ? 'enabled' : 'disabled');
|
|
} else if ('reverseProxyConfig' in data) {
|
|
return 'Reverse proxy configuration of ' + appName(app) + ' was updated';
|
|
} else if ('cert' in data) {
|
|
if (data.cert) {
|
|
return 'Custom certificate was set for ' + appName(app);
|
|
} else {
|
|
return 'Certificate of ' + appName(app) + ' was reset';
|
|
}
|
|
} else if (data.location) {
|
|
if (data.fqdn !== data.app.fqdn) {
|
|
return 'Location of ' + appName(app) + ' was changed to ' + data.fqdn;
|
|
} 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.portBindings, data.app.portBindings)) {
|
|
return 'Port bindings of ' + appName(app) + ' was changed';
|
|
}
|
|
} else if ('dataDir' in data) {
|
|
if (data.dataDir) {
|
|
return 'Data directory of ' + appName(app) + ' was set ' + data.dataDir;
|
|
} else {
|
|
return 'Data directory of ' + appName(app) + ' was reset';
|
|
}
|
|
} else if ('icon' in data) {
|
|
if (data.icon) {
|
|
return 'Icon of ' + appName(app) + ' was set';
|
|
} else {
|
|
return 'Icon of ' + appName(app) + ' was reset';
|
|
}
|
|
} else if (('mailboxName' in data) && data.mailboxName !== data.app.mailboxName) {
|
|
if (data.mailboxName) {
|
|
return 'Mailbox of ' + appName(app) + ' was set to ' + q(data.mailboxName);
|
|
} else {
|
|
return 'Mailbox of ' + appName(app) + ' was reset';
|
|
}
|
|
}
|
|
|
|
return appName(app) + ' was re-configured';
|
|
}
|
|
|
|
case ACTION_APP_INSTALL:
|
|
if (!data.app) return '';
|
|
return data.app.manifest.title + ' (package v' + data.app.manifest.version + ') was installed at ' + (data.app.fqdn || data.app.location);
|
|
|
|
case ACTION_APP_RESTORE:
|
|
if (!data.app) return '';
|
|
details = data.app.manifest.title + ' was restored at ' + (data.app.fqdn || data.app.location);
|
|
// older versions (<3.5) did not have these fields
|
|
if (data.fromManifest) details += ' from version ' + data.fromManifest.version;
|
|
if (data.toManifest) details += ' to version ' + data.toManifest.version;
|
|
if (data.backupId) details += ' using backup ' + data.backupId;
|
|
return details;
|
|
|
|
case ACTION_APP_UNINSTALL:
|
|
if (!data.app) return '';
|
|
return data.app.manifest.title + ' (package v' + data.app.manifest.version + ') was uninstalled at ' + (data.app.fqdn || data.app.location);
|
|
|
|
case ACTION_APP_UPDATE:
|
|
if (!data.app) return '';
|
|
return 'Update of ' + data.app.manifest.title + ' at ' + (data.app.fqdn || data.app.location) + ' started from v' + data.fromManifest.version + ' to v' + data.toManifest.version;
|
|
|
|
case ACTION_APP_UPDATE_FINISH:
|
|
if (!data.app) return '';
|
|
return data.app.manifest.title + ' at ' + (data.app.fqdn || data.app.location) + ' was updated to v' + data.app.manifest.version;
|
|
|
|
case ACTION_APP_CLONE:
|
|
return data.newApp.manifest.title + ' at ' + (data.newApp.fqdn || data.newApp.location) + ' was cloned from ' + (data.oldApp.fqdn || data.oldApp.location) + ' using backup ' + data.backupId + ' with v' + data.oldApp.manifest.version;
|
|
|
|
case ACTION_APP_REPAIR:
|
|
return 'App ' + appName(data.app) + ' was re-configured'; // re-configure of email apps is more common?
|
|
|
|
case ACTION_APP_LOGIN: {
|
|
app = Client.getCachedAppSync(data.appId);
|
|
if (!app) return '';
|
|
return 'App ' + app.fqdn + ' logged in';
|
|
}
|
|
|
|
case ACTION_APP_OOM:
|
|
if (!data.app) return '';
|
|
return appName(data.app) + ' ran out of memory';
|
|
|
|
case ACTION_APP_DOWN:
|
|
if (!data.app) return '';
|
|
return appName(data.app) + ' is down';
|
|
|
|
case ACTION_APP_UP:
|
|
if (!data.app) return '';
|
|
return appName(data.app) + ' is back online';
|
|
|
|
case ACTION_APP_START:
|
|
if (!data.app) return '';
|
|
return appName(data.app) + ' was started';
|
|
|
|
case ACTION_APP_STOP:
|
|
if (!data.app) return '';
|
|
return appName(data.app) + ' was stopped';
|
|
|
|
case ACTION_APP_RESTART:
|
|
if (!data.app) return '';
|
|
return appName(data.app) + ' was restarted';
|
|
|
|
case ACTION_BACKUP_START:
|
|
return 'Backup started';
|
|
|
|
case ACTION_BACKUP_FINISH:
|
|
if (!errorMessage) {
|
|
return 'Cloudron backup created with Id ' + data.backupId;
|
|
} else {
|
|
return 'Cloudron backup errored with error: ' + errorMessage;
|
|
}
|
|
|
|
case ACTION_BACKUP_CLEANUP_START:
|
|
return 'Backup cleaner started';
|
|
|
|
case ACTION_BACKUP_CLEANUP_FINISH:
|
|
return data.errorMessage ? 'Backup cleaner errored: ' + data.errorMessage : 'Backup cleaner removed ' + (data.removedBoxBackups ? data.removedBoxBackups.length : '0') + ' backups';
|
|
|
|
case ACTION_CERTIFICATE_NEW:
|
|
return 'Certificate install for ' + data.domain + (errorMessage ? ' failed' : ' succeeded');
|
|
|
|
case ACTION_CERTIFICATE_RENEWAL:
|
|
return 'Certificate renewal for ' + data.domain + (errorMessage ? ' failed' : ' succeeded');
|
|
|
|
case ACTION_DASHBOARD_DOMAIN_UPDATE:
|
|
return 'Dashboard domain set to ' + data.fqdn;
|
|
|
|
case ACTION_DOMAIN_ADD:
|
|
return 'Domain ' + data.domain + ' with ' + data.provider + ' provider was added';
|
|
|
|
case ACTION_DOMAIN_UPDATE:
|
|
return 'Domain ' + data.domain + ' with ' + data.provider + ' provider was updated';
|
|
|
|
case ACTION_DOMAIN_REMOVE:
|
|
return 'Domain ' + data.domain + ' was removed';
|
|
|
|
case ACTION_MAIL_LOCATION:
|
|
return 'Mail server location was changed to ' + data.subdomain + (data.subdomain ? '.' : '') + data.domain;
|
|
|
|
case ACTION_MAIL_ENABLED:
|
|
return 'Mail was enabled for domain ' + data.domain;
|
|
|
|
case ACTION_MAIL_DISABLED:
|
|
return 'Mail was disabled for domain ' + data.domain;
|
|
|
|
case ACTION_MAIL_MAILBOX_ADD:
|
|
return 'Mailbox with name ' + data.name + ' was added in domain ' + data.domain;
|
|
|
|
case ACTION_MAIL_MAILBOX_UPDATE:
|
|
return 'Mailbox with name ' + data.name + ' was updated in domain ' + data.domain;
|
|
|
|
case ACTION_MAIL_MAILBOX_REMOVE:
|
|
return 'Mailbox with name ' + data.name + ' was removed in domain ' + data.domain;
|
|
|
|
case ACTION_MAIL_LIST_ADD:
|
|
return 'Mail list with name ' + data.name + ' was added in domain ' + data.domain;
|
|
|
|
case ACTION_MAIL_LIST_UPDATE:
|
|
return 'Mail list with name ' + data.name + ' was updated in domain ' + data.domain;
|
|
|
|
case ACTION_MAIL_LIST_REMOVE:
|
|
return 'Mail list with name ' + data.name + ' was removed in domain ' + data.domain;
|
|
|
|
case ACTION_START:
|
|
return 'Cloudron started with version ' + data.version;
|
|
|
|
case ACTION_UPDATE:
|
|
return 'Cloudron update to version ' + data.boxUpdateInfo.version + ' was started';
|
|
|
|
case ACTION_UPDATE_FINISH:
|
|
if (data.errorMessage) {
|
|
return 'Cloudron update errored. Error: ' + data.errorMessage;
|
|
} else {
|
|
return 'Cloudron updated to version ' + data.newVersion;
|
|
}
|
|
|
|
case ACTION_USER_ADD:
|
|
return data.email + (data.user.username ? ' (' + data.user.username + ')' : '') + ' was added';
|
|
|
|
case ACTION_USER_UPDATE:
|
|
return (data.user ? (data.user.email + (data.user.username ? ' (' + data.user.username + ')' : '')) : data.userId) + ' was updated';
|
|
|
|
case ACTION_USER_REMOVE:
|
|
return (data.user ? (data.user.email + (data.user.username ? ' (' + data.user.username + ')' : '')) : data.userId) + ' was removed';
|
|
|
|
case ACTION_USER_TRANSFER:
|
|
return 'Apps of ' + data.oldOwnerId + ' was transferred to ' + data.newOwnerId;
|
|
|
|
case ACTION_USER_LOGIN:
|
|
return (data.user ? data.user.username : data.userId) + ' logged in';
|
|
|
|
case ACTION_DYNDNS_UPDATE:
|
|
return 'DNS was updated from ' + data.fromIp + ' to ' + data.toIp;
|
|
|
|
case ACTION_SUPPORT_SSH:
|
|
return 'Remote Support was ' + (data.enable ? 'enabled' : 'disabled');
|
|
|
|
case ACTION_SUPPORT_TICKET:
|
|
return 'Support ticket was created';
|
|
|
|
case ACTION_SYSTEM_CRASH:
|
|
return 'A system process crashed';
|
|
|
|
case ACTION_VOLUME_ADD:
|
|
return 'Volume "' + data.volume.name + '" was added';
|
|
|
|
case ACTION_VOLUME_UPDATE:
|
|
return 'Volme "' + data.volume.name + '" was updated';
|
|
|
|
case ACTION_VOLUME_REMOVE:
|
|
return 'Volume "' + data.volume.name + '" was removed';
|
|
|
|
default: return eventLog.action;
|
|
}
|
|
}
|
|
|
|
function eventLogSource(eventLog) {
|
|
var source = eventLog.source;
|
|
var line = '';
|
|
|
|
line = source.username || source.userId || source.mailboxId || source.authType || 'system';
|
|
if (source.appId) {
|
|
var app = Client.getCachedAppSync(source.appId);
|
|
line += ' - ' + (app ? app.fqdn : source.appId);
|
|
} else if (source.ip) {
|
|
line += ' - ' + source.ip;
|
|
}
|
|
|
|
return line;
|
|
}
|
|
|
|
function fetchEventLogs(background, callback) {
|
|
callback = callback || function (error) { if (error) console.error(error); };
|
|
background = background || false;
|
|
|
|
if (!background) $scope.busy = true;
|
|
|
|
var actions = $scope.selectedActions.map(function (a) { return a.value; }).join(', ');
|
|
|
|
Client.getEventLogs(actions, $scope.search || null, $scope.currentPage, $scope.pageItems.value, function (error, result) {
|
|
$scope.busy = false;
|
|
|
|
if (error) return callback(error);
|
|
|
|
$scope.eventLogs = [];
|
|
result.forEach(function (e) {
|
|
$scope.eventLogs.push({ raw: e, details: eventLogDetails(e), source: eventLogSource(e) });
|
|
});
|
|
|
|
callback();
|
|
});
|
|
}
|
|
|
|
$scope.refresh = function () {
|
|
$scope.busyRefresh = true;
|
|
|
|
fetchEventLogs(true, function () {
|
|
$scope.busyRefresh = false;
|
|
});
|
|
};
|
|
|
|
$scope.showNextPage = function () {
|
|
$scope.currentPage++;
|
|
fetchEventLogs();
|
|
};
|
|
|
|
$scope.showPrevPage = function () {
|
|
if ($scope.currentPage > 1) $scope.currentPage--;
|
|
else $scope.currentPage = 1;
|
|
|
|
fetchEventLogs();
|
|
};
|
|
|
|
$scope.updateFilter = function (fresh) {
|
|
if (fresh) $scope.currentPage = 1;
|
|
fetchEventLogs();
|
|
};
|
|
|
|
$scope.showEventLogDetails = function (eventLog) {
|
|
if ($scope.activeEventLog === eventLog) $scope.activeEventLog = null;
|
|
else $scope.activeEventLog = eventLog;
|
|
};
|
|
|
|
Client.onReady(function () {
|
|
fetchEventLogs();
|
|
});
|
|
|
|
$('.modal-backdrop').remove();
|
|
}]);
|