Files
cloudron-box/src/js/client.js

3585 lines
130 KiB
JavaScript
Raw Normal View History

2018-01-22 13:01:38 -08:00
'use strict';
2020-06-03 23:17:06 +02:00
/* global $ */
/* global angular */
/* global EventSource */
/* global async */
2018-01-22 13:01:38 -08:00
// keep in sync with box/src/apps.js
var ISTATES = {
PENDING_INSTALL: 'pending_install',
PENDING_CLONE: 'pending_clone',
PENDING_CONFIGURE: 'pending_configure',
PENDING_UNINSTALL: 'pending_uninstall',
PENDING_RESTORE: 'pending_restore',
2021-05-26 09:32:17 -07:00
PENDING_IMPORT: 'pending_import',
PENDING_UPDATE: 'pending_update',
PENDING_BACKUP: 'pending_backup',
PENDING_RECREATE_CONTAINER: 'pending_recreate_container', // env change or addon change
PENDING_LOCATION_CHANGE: 'pending_location_change',
PENDING_DATA_DIR_MIGRATION: 'pending_data_dir_migration',
PENDING_RESIZE: 'pending_resize',
PENDING_DEBUG: 'pending_debug',
PENDING_START: 'pending_start',
PENDING_STOP: 'pending_stop',
PENDING_RESTART: 'pending_restart',
ERROR: 'error',
INSTALLED: 'installed'
};
var HSTATES = {
HEALTHY: 'healthy',
UNHEALTHY: 'unhealthy',
ERROR: 'error',
DEAD: 'dead'
};
var RSTATES ={
RUNNING: 'running',
STOPPED: 'stopped'
};
var ERROR = {
ACCESS_DENIED: 'Access Denied',
ALREADY_EXISTS: 'Already Exists',
BAD_FIELD: 'Bad Field',
COLLECTD_ERROR: 'Collectd Error',
CONFLICT: 'Conflict',
DATABASE_ERROR: 'Database Error',
DNS_ERROR: 'DNS Error',
DOCKER_ERROR: 'Docker Error',
EXTERNAL_ERROR: 'External Error',
FS_ERROR: 'FileSystem Error',
INTERNAL_ERROR: 'Internal Error',
LOGROTATE_ERROR: 'Logrotate Error',
NETWORK_ERROR: 'Network Error',
NOT_FOUND: 'Not found',
REVERSEPROXY_ERROR: 'ReverseProxy Error',
TASK_ERROR: 'Task Error',
UNKNOWN_ERROR: 'Unknown Error' // only used for portin,
};
2020-02-21 16:52:37 -08:00
var ROLES = {
OWNER: 'owner',
ADMIN: 'admin',
MAIL_MANAGER: 'mailmanager',
2020-02-21 16:52:37 -08:00
USER_MANAGER: 'usermanager',
USER: 'user'
};
2020-09-01 16:31:09 +02:00
// sync up with tasks.js
var TASK_TYPES = {
TASK_APP: 'app',
TASK_BACKUP: 'backup',
TASK_UPDATE: 'update',
TASK_RENEW_CERTS: 'renewcerts',
TASK_SETUP_DNS_AND_CERT: 'setupDnsAndCert',
TASK_CLEAN_BACKUPS: 'cleanBackups',
TASK_SYNC_EXTERNAL_LDAP: 'syncExternalLdap',
TASK_CHANGE_MAIL_LOCATION: 'changeMailLocation',
2021-02-24 22:18:39 -08:00
TASK_SYNC_DNS_RECORDS: 'syncDnsRecords',
2020-09-01 16:31:09 +02:00
};
var SECRET_PLACEHOLDER = String.fromCharCode(0x25CF).repeat(8);
// ----------------------------------------------
// Helper to ensure loading a fallback app icon on first load failure
// ----------------------------------------------
function imageErrorHandler(elem) {
elem.src = elem.getAttribute('fallback-icon');
elem.onerror = null; // avoid retry after default icon cannot be loaded
}
2020-06-02 14:34:38 +02:00
// ----------------------------------------------
// Shared Angular Filters
// ----------------------------------------------
// binary units (non SI) 1024 based
function prettyByteSize(size, fallback) {
if (!size) return fallback || 0;
var i = Math.floor(Math.log(size) / Math.log(1024));
return (size / Math.pow(1024, i)).toFixed(2) * 1 + ' ' + ['B', 'kB', 'MB', 'GB', 'TB'][i];
2021-01-29 11:15:33 +01:00
}
2020-06-02 14:34:38 +02:00
angular.module('Application').filter('prettyByteSize', function () {
2021-01-29 11:15:33 +01:00
return function (size, fallback) { return prettyByteSize(size, fallback) || '0 kb'; };
2020-06-02 14:34:38 +02:00
});
angular.module('Application').filter('prettyDiskSize', function () {
2021-01-29 11:15:33 +01:00
return function (size, fallback) { return prettyByteSize(size, fallback) || 'Not available yet'; };
2020-06-02 14:34:38 +02:00
});
angular.module('Application').filter('trKeyFromPeriod', function () {
return function (period) {
if (period === 6) return 'app.graphs.period.6h';
if (period === 12) return 'app.graphs.period.12h';
if (period === 24) return 'app.graphs.period.24h';
if (period === 24*7) return 'app.graphs.period.7d';
if (period === 24*30) return 'app.graphs.period.30d';
return '';
};
});
2021-04-01 17:04:46 +02:00
angular.module('Application').filter('prettyDate', function ($translate) {
// http://ejohn.org/files/pretty.js
return function prettyDate(utc) {
var date = new Date(utc), // this converts utc into browser timezone and not cloudron timezone!
diff = (((new Date()).getTime() - date.getTime()) / 1000) + 30, // add 30seconds for clock skew
day_diff = Math.floor(diff / 86400);
2021-04-01 17:04:46 +02:00
if (isNaN(day_diff) || day_diff < 0) return $translate.instant('main.prettyDate.justNow', {});
return day_diff === 0 && (
2021-04-01 17:04:46 +02:00
diff < 60 && $translate.instant('main.prettyDate.justNow', {}) ||
diff < 120 && $translate.instant('main.prettyDate.minutesAgo', { m: 1 }) ||
diff < 3600 && $translate.instant('main.prettyDate.minutesAgo', { m: Math.floor( diff / 60 ) }) ||
diff < 7200 && $translate.instant('main.prettyDate.hoursAgo', { h: 1 }) ||
diff < 86400 && $translate.instant('main.prettyDate.hoursAgo', { h: Math.floor( diff / 3600 ) })
) ||
day_diff === 1 && $translate.instant('main.prettyDate.yeserday', {}) ||
day_diff < 7 && $translate.instant('main.prettyDate.daysAgo', { d: day_diff }) ||
day_diff < 31 && $translate.instant('main.prettyDate.weeksAgo', { w: Math.ceil( day_diff / 7 ) }) ||
day_diff < 365 && $translate.instant('main.prettyDate.monthsAgo', { m: Math.round( day_diff / 30 ) }) ||
$translate.instant('main.prettyDate.yearsAgo', { m: Math.round( day_diff / 365 ) });
};
});
angular.module('Application').filter('prettyLongDate', function () {
return function prettyLongDate(utc) {
return moment(utc).format('MMMM Do YYYY, h:mm:ss a'); // this converts utc into browser timezone and not cloudron timezone!
};
});
angular.module('Application').filter('prettyShortDate', function () {
return function prettyShortDate(utc) {
return moment(utc).format('MMMM Do YYYY'); // this converts utc into browser timezone and not cloudron timezone!
};
});
angular.module('Application').filter('markdown2html', function () {
var converter = new showdown.Converter({
simplifiedAutoLink: true,
strikethrough: true,
tables: true,
openLinksInNewWindow: true
});
// without this cache, the code runs into some infinite loop (https://github.com/angular/angular.js/issues/3980)
var cache = {};
return function (text) {
if (cache[text]) return cache[text];
cache[text] = converter.makeHtml(text);
return cache[text];
};
});
angular.module('Application').config(['$translateProvider', function ($translateProvider) {
$translateProvider.useStaticFilesLoader({
prefix: 'translation/',
suffix: '.json?' + '<%= revision %>'
});
$translateProvider.useLocalStorage();
$translateProvider.preferredLanguage('en');
$translateProvider.fallbackLanguage('en');
}]);
// Add shorthand "tr" filter to avoid having ot use "translate"
// This is a copy of the code at https://github.com/angular-translate/angular-translate/blob/master/src/filter/translate.js
// If we find out how to get that function handle somehow dynamically we can use that, otherwise the copy is required
function translateFilterFactory($parse, $translate) {
var translateFilter = function (translationId, interpolateParams, interpolation, forceLanguage) {
if (!angular.isObject(interpolateParams)) {
var ctx = this || {
'__SCOPE_IS_NOT_AVAILABLE': 'More info at https://github.com/angular/angular.js/commit/8863b9d04c722b278fa93c5d66ad1e578ad6eb1f'
};
interpolateParams = $parse(interpolateParams)(ctx);
}
return $translate.instant(translationId, interpolateParams, interpolation, forceLanguage);
};
if ($translate.statefulFilter()) {
translateFilter.$stateful = true;
}
return translateFilter;
}
translateFilterFactory.displayName = 'translateFilterFactory';
angular.module('Application').filter('tr', translateFilterFactory);
2020-06-02 14:34:38 +02:00
// ----------------------------------------------
// Cloudron REST API wrapper
// ----------------------------------------------
angular.module('Application').service('Client', ['$http', '$interval', '$timeout', 'md5', 'Notification', function ($http, $interval, $timeout, md5, Notification) {
2018-01-22 13:01:38 -08:00
var client = null;
// variable available only here to avoid this._property pattern
var token = null;
function ClientError(statusCode, messageOrObject) {
Error.call(this);
this.name = this.constructor.name;
this.statusCode = statusCode;
if (messageOrObject === null || typeof messageOrObject === 'undefined') {
this.message = 'Empty message or object';
} else if (typeof messageOrObject === 'string') {
this.message = messageOrObject;
} else if (messageOrObject) {
angular.extend(this, messageOrObject); // status, message, reason and other properties
2018-01-22 13:01:38 -08:00
}
}
function defaultErrorHandler(callback) {
function handleServerOffline() {
if (client.offline) return;
client.offline = true;
(function onlineCheck() {
$http.get(client.apiOrigin + '/api/v1/cloudron/status', {}).success(function (data, status) {
client.offline = false;
client._reconnectListener.forEach(function (handler) { handler(); });
}).error(function (data, status) {
$timeout(onlineCheck, 5000);
});
})();
}
2018-01-22 13:01:38 -08:00
return function (data, status) {
// handle request killed by browser (eg. cors issue)
if (data === null && status === -1) {
handleServerOffline();
return callback(new ClientError('Request cancelled by browser'));
}
// re-login will make the code get a new token
if (status === 401) return client.login();
if (status === 500 || status === 501) {
// actual internal server error, most likely a bug or timeout log to console only to not alert the user
if (!client.offline) {
console.error(status, data);
console.log('------\nCloudron Internal Error\n\nIf you see this, please send a mail with above log to support@cloudron.io\n------\n');
}
} else if (status === 502 || status === 503 || status === 504) {
// This means the box service is not reachable. We just show offline banner for now
}
if (status >= 502) {
handleServerOffline();
2018-01-22 13:01:38 -08:00
return callback(new ClientError(status, data));
}
var obj = data;
try {
obj = JSON.parse(data);
} catch (e) {}
2018-01-22 13:01:38 -08:00
callback(new ClientError(status, obj));
};
}
function defaultSuccessHandler(callback) {
return function (data, status) {
return callback(null, data, status);
2019-05-05 09:05:06 -07:00
};
}
2018-01-22 13:01:38 -08:00
// XHR wrapper to set the auth header
function get(url, config, callback) {
if (arguments.length !== 3) {
console.error('GET', arguments);
throw('Wrong number of arguments');
}
2018-01-22 13:01:38 -08:00
config = config || {};
config.headers = config.headers || {};
config.headers.Authorization = 'Bearer ' + token;
return $http.get(client.apiOrigin + url, config)
.success(defaultSuccessHandler(callback))
.error(defaultErrorHandler(callback));
2018-01-22 13:01:38 -08:00
}
function head(url, config, callback) {
if (arguments.length !== 3) {
console.error('HEAD', arguments);
throw('Wrong number of arguments');
}
2018-01-22 13:01:38 -08:00
config = config || {};
config.headers = config.headers || {};
config.headers.Authorization = 'Bearer ' + token;
return $http.head(client.apiOrigin + url, config)
.success(defaultSuccessHandler(callback))
.error(defaultErrorHandler(callback));
2018-01-22 13:01:38 -08:00
}
function post(url, data, config, callback) {
if (arguments.length !== 4) {
console.error('POST', arguments);
throw('Wrong number of arguments');
}
2018-01-22 13:01:38 -08:00
data = data || {};
config = config || {};
config.headers = config.headers || {};
config.headers.Authorization = 'Bearer ' + token;
return $http.post(client.apiOrigin + url, data, config)
.success(defaultSuccessHandler(callback))
.error(defaultErrorHandler(callback));
2018-01-22 13:01:38 -08:00
}
function put(url, data, config, callback) {
if (arguments.length !== 4) {
console.error('PUT', arguments);
throw('Wrong number of arguments');
}
2018-01-22 13:01:38 -08:00
data = data || {};
config = config || {};
config.headers = config.headers || {};
config.headers.Authorization = 'Bearer ' + token;
return $http.put(client.apiOrigin + url, data, config)
.success(defaultSuccessHandler(callback))
.error(defaultErrorHandler(callback));
2018-01-22 13:01:38 -08:00
}
function del(url, config, callback) {
if (arguments.length !== 3) {
console.error('DEL', arguments);
throw('Wrong number of arguments');
}
2018-01-22 13:01:38 -08:00
config = config || {};
config.headers = config.headers || {};
config.headers.Authorization = 'Bearer ' + token;
return $http.delete(client.apiOrigin + url, config)
.success(defaultSuccessHandler(callback))
.error(defaultErrorHandler(callback));
2018-01-22 13:01:38 -08:00
}
function Client() {
this.offline = false;
2018-01-22 13:01:38 -08:00
this._ready = false;
this._configListener = [];
this._readyListener = [];
this._reconnectListener = [];
2018-01-22 13:01:38 -08:00
this._userInfo = {
id: null,
username: null,
email: null,
twoFactorAuthenticationEnabled: false,
source: null,
avatarUrl: null
2018-01-22 13:01:38 -08:00
};
this._config = {
apiServerOrigin: null,
webServerOrigin: null,
fqdn: null,
ip: null,
revision: null,
update: { box: null, apps: null },
progress: {},
region: null,
2019-12-20 10:02:01 -08:00
size: null
2018-01-22 13:01:38 -08:00
};
this._installedApps = [];
this._installedAppsById = {};
2019-04-12 11:06:56 +02:00
this._appTags = [];
2018-01-22 13:01:38 -08:00
// window.location fallback for websocket connections which do not have relative uris
this.apiOrigin = '<%= apiOrigin %>' || window.location.origin;
2018-01-22 13:01:38 -08:00
this.avatar = '';
this._availableLanguages = ['en'];
2019-05-04 18:15:33 -07:00
this._appstoreAppCache = [];
2018-01-22 13:01:38 -08:00
this.resetAvatar();
this.setToken(localStorage.token);
}
Client.prototype.error = function (error, action) {
2018-01-22 13:01:38 -08:00
var message = '';
console.error(error);
2018-01-22 13:01:38 -08:00
if (typeof error === 'object') {
message = error.message || error;
} else {
message = error;
}
// give more info in case the error was a request which failed with empty response body,
// this happens mostly if the box crashes
if (message === 'Empty message or object') {
2021-01-29 11:15:33 +01:00
message = 'Got empty response. Click to check the server logs.';
action = action || '/logs.html?id=box';
}
this.notify('Cloudron Error', message, true, 'error', action);
2018-01-22 13:01:38 -08:00
};
// handles application startup errors, mostly only when dashboard is loaded and api endpoint is down
Client.prototype.initError = function (error, initFunction) {
console.error('Application startup error', error);
$timeout(initFunction, 5000); // we will try to re-init the app
};
Client.prototype.clearNotifications = function () {
Notification.clearAll();
};
2018-01-22 13:01:38 -08:00
/*
If `action` is a non-empty string, it will be treated as a url, if it is a function, that function will be exectued on click
2018-01-22 13:01:38 -08:00
*/
Client.prototype.notify = function (title, message, persistent, type, action) {
2018-01-22 13:01:38 -08:00
var options = { title: title, message: message};
if (persistent) options.delay = 'never'; // any non Number means never timeout
2018-01-22 13:01:38 -08:00
if (action) {
options.onClick = function (/* params */) {
// if action is a string, we assume it is a link
if (typeof action === 'string' && action !== '') window.location = action;
else if (typeof action === 'function') action();
else console.warn('Notification action is not supported.', action);
};
2018-01-22 13:01:38 -08:00
}
if (type === 'error') Notification.error(options);
else if (type === 'success') Notification.success(options);
else if (type === 'info') Notification.info(options);
else if (type === 'warning') Notification.warning(options);
else throw('Invalid notification type "' + type + '"');
};
Client.prototype.setReady = function () {
if (this._ready) return;
this._ready = true;
this._readyListener.forEach(function (callback) {
callback();
});
// clear the listeners, we only callback once!
this._readyListener = [];
};
Client.prototype.onReady = function (callback) {
if (this._ready) callback();
else this._readyListener.push(callback);
};
Client.prototype.onConfig = function (callback) {
this._configListener.push(callback);
if (this._config && this._config.apiServerOrigin) callback(this._config);
};
Client.prototype.onReconnect = function (callback) {
if (this._ready) callback();
else this._reconnectListener.push(callback);
};
2018-01-22 13:01:38 -08:00
Client.prototype.resetAvatar = function () {
this.avatar = this.apiOrigin + '/api/v1/cloudron/avatar?' + String(Math.random()).slice(2);
var favicon = $('#favicon');
if (favicon) favicon.attr('href', this.avatar);
};
Client.prototype.setUserInfo = function (userInfo) {
// In order to keep the angular bindings alive, set each property individually
this._userInfo.id = userInfo.id;
this._userInfo.username = userInfo.username;
this._userInfo.email = userInfo.email;
this._userInfo.fallbackEmail = userInfo.fallbackEmail;
this._userInfo.displayName = userInfo.displayName;
2018-04-26 15:12:29 +02:00
this._userInfo.twoFactorAuthenticationEnabled = userInfo.twoFactorAuthenticationEnabled;
2020-02-24 12:56:13 +01:00
this._userInfo.role = userInfo.role;
this._userInfo.source = userInfo.source;
this._userInfo.avatarUrl = userInfo.avatarUrl + '?s=128&default=mp&ts=' + Date.now(); // we add the timestamp to avoid caching
2020-02-24 12:56:13 +01:00
this._userInfo.isAtLeastOwner = [ ROLES.OWNER ].indexOf(userInfo.role) !== -1;
this._userInfo.isAtLeastAdmin = [ ROLES.OWNER, ROLES.ADMIN ].indexOf(userInfo.role) !== -1;
this._userInfo.isAtLeastMailManager = [ ROLES.OWNER, ROLES.ADMIN, ROLES.MAIL_MANAGER ].indexOf(userInfo.role) !== -1;
this._userInfo.isAtLeastUserManager = [ ROLES.OWNER, ROLES.ADMIN, ROLES.MAIL_MANAGER, ROLES.USER_MANAGER ].indexOf(userInfo.role) !== -1;
2018-01-22 13:01:38 -08:00
};
Client.prototype.setConfig = function (config) {
var that = this;
angular.copy(config, this._config);
<% if (appstore.webOrigin) { -%>
this._config.webServerOrigin = '<%= appstore.webOrigin %>';
<% } -%>
<% if (appstore.ApiOrigin) { -%>
2019-08-06 10:22:00 +02:00
this._config.apiServerOrigin = '<%= appstore.apiOrigin %>';
<% } -%>
2020-02-14 20:44:27 +01:00
// => This is just for easier testing
// this._config.features.userMaxCount = 5;
// this._config.features.userRoles = false;
// this._config.features.userGroups = false;
// this._config.features.domainMaxCount = 1;
2020-02-14 20:44:27 +01:00
// this._config.features.externalLdap = false;
// this._config.features.privateDockerRegistry = false;
2020-03-09 14:19:12 -07:00
// this._config.features.branding = true;
2020-03-06 01:08:55 -08:00
// this._config.features.support = true;
// this._config.features.profileConfig = true;
2020-07-16 18:51:29 +02:00
// this._config.features.mailboxMaxCount = 5;
// this._config.features.emailPremium = false;
2020-02-14 20:44:27 +01:00
2018-01-22 13:01:38 -08:00
this._configListener.forEach(function (callback) {
callback(that._config);
});
};
Client.prototype.getInstalledApps = function () {
return this._installedApps;
};
2019-04-12 11:06:56 +02:00
Client.prototype.getAppTags = function () {
return this._appTags;
};
2018-01-22 13:01:38 -08:00
Client.prototype.getUserInfo = function () {
return this._userInfo;
};
Client.prototype.getConfig = function () {
return this._config;
};
Client.prototype.getAvailableLanguages = function () {
return this._availableLanguages;
};
2018-01-22 13:01:38 -08:00
Client.prototype.setToken = function (accessToken) {
if (!accessToken) localStorage.removeItem('token');
else localStorage.token = accessToken;
// set the token closure
token = accessToken;
};
Client.prototype.getToken = function () {
return token;
};
Client.prototype.makeURL = function (url) {
if (url.indexOf('?') === -1) {
return this.apiOrigin + url + '?access_token=' + token;
} else {
return this.apiOrigin + url + '&access_token=' + token;
}
};
2018-01-22 13:01:38 -08:00
/*
* Rest API wrappers
*/
Client.prototype.config = function (callback) {
get('/api/v1/config', null, function (error, data, status) {
if (error) return callback(error);
2018-01-22 13:01:38 -08:00
if (status !== 200 || typeof data !== 'object') return callback(new ClientError(status, data));
callback(null, data);
});
2018-01-22 13:01:38 -08:00
};
Client.prototype.userInfo = function (callback) {
get('/api/v1/profile', null, function (error, data, status) {
if (error) return callback(error);
2018-01-22 13:01:38 -08:00
if (status !== 200 || typeof data !== 'object') return callback(new ClientError(status, data));
callback(null, data);
});
2018-01-22 13:01:38 -08:00
};
Client.prototype.changeCloudronAvatar = function (avatarFile, callback) {
var fd = new FormData();
fd.append('avatar', avatarFile);
var config = {
2018-01-22 13:01:38 -08:00
headers: { 'Content-Type': undefined },
transformRequest: angular.identity
};
2020-03-18 21:31:51 -07:00
post('/api/v1/branding/cloudron_avatar', fd, config, function (error, data, status) {
if (error) return callback(error);
2018-01-22 13:01:38 -08:00
if (status !== 202) return callback(new ClientError(status, data));
callback(null);
});
2018-01-22 13:01:38 -08:00
};
Client.prototype.changeCloudronName = function (name, callback) {
var data = {
name: name
};
2020-03-18 21:31:51 -07:00
post('/api/v1/branding/cloudron_name', data, null, function (error, data, status) {
if (error) return callback(error);
2018-01-22 13:01:38 -08:00
if (status !== 202) return callback(new ClientError(status, data));
callback(null);
});
2018-01-22 13:01:38 -08:00
};
Client.prototype.installApp = function (id, manifest, title, config, callback) {
var that = this;
var data = {
appStoreId: id + '@' + manifest.version,
2022-01-16 18:29:32 -08:00
subdomain: config.subdomain,
2018-01-22 13:01:38 -08:00
domain: config.domain,
portBindings: config.portBindings,
accessRestriction: config.accessRestriction,
cert: config.cert,
key: config.key,
2019-09-24 00:21:01 +02:00
sso: config.sso,
overwriteDns: config.overwriteDns
2018-01-22 13:01:38 -08:00
};
post('/api/v1/apps/install', data, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 202) return callback(new ClientError(status, data));
2018-01-22 13:01:38 -08:00
callback(null, data.id);
});
2018-01-22 13:01:38 -08:00
};
2018-05-28 00:47:53 -07:00
Client.prototype.cloneApp = function (appId, config, callback) {
var data = {
2022-01-16 18:29:32 -08:00
subdomain: config.subdomain,
2018-05-28 00:47:53 -07:00
domain: config.domain,
portBindings: config.portBindings,
backupId: config.backupId
};
post('/api/v1/apps/' + appId + '/clone', data, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 201) return callback(new ClientError(status, data));
2018-05-28 00:47:53 -07:00
2018-06-26 08:33:04 -07:00
callback(null, data);
});
2018-05-28 00:47:53 -07:00
};
Client.prototype.restoreApp = function (appId, backupId, callback) {
var data = { backupId: backupId };
post('/api/v1/apps/' + appId + '/restore', data, null, function (error, data, status) {
if (error) return callback(error);
2018-01-22 13:01:38 -08:00
if (status !== 202) return callback(new ClientError(status, data));
2018-01-22 13:01:38 -08:00
callback(null);
});
2018-01-22 13:01:38 -08:00
};
Client.prototype.backupApp = function (appId, callback) {
var data = {};
post('/api/v1/apps/' + appId + '/backup', data, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 202) return callback(new ClientError(status, data));
callback(null);
});
};
Client.prototype.uninstallApp = function (appId, callback) {
var data = {};
post('/api/v1/apps/' + appId + '/uninstall', data, null, function (error, data, status) {
if (error) return callback(error);
2018-01-22 13:01:38 -08:00
if (status !== 202) return callback(new ClientError(status, data));
2018-01-22 13:01:38 -08:00
callback(null);
});
2018-01-22 13:01:38 -08:00
};
Client.prototype.configureApp = function (id, setting, data, callback) {
post('/api/v1/apps/' + id + '/configure/' + setting, data, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200 && status !== 202) return callback(new ClientError(status, data));
callback(null, data);
});
};
Client.prototype.repairApp = function (id, data, callback) {
2019-12-06 11:44:33 -08:00
post('/api/v1/apps/' + id + '/repair', data, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200 && status !== 202) return callback(new ClientError(status, data));
callback(null, data);
});
2018-01-22 13:01:38 -08:00
};
Client.prototype.updateApp = function (id, manifest, options, callback) {
2018-01-22 13:01:38 -08:00
var data = {
appStoreId: manifest.id + '@' + manifest.version,
skipBackup: !!options.skipBackup
2018-01-22 13:01:38 -08:00
};
post('/api/v1/apps/' + id + '/update', data, null, function (error, data, status) {
if (error) return callback(error);
2018-01-22 13:01:38 -08:00
if (status !== 202) return callback(new ClientError(status, data));
2019-09-23 15:50:41 -07:00
callback(null, data);
});
2018-01-22 13:01:38 -08:00
};
Client.prototype.startApp = function (id, callback) {
post('/api/v1/apps/' + id + '/start', {}, null, function (error, data, status) {
if (error) return callback(error);
2018-01-22 13:01:38 -08:00
if (status !== 202) return callback(new ClientError(status, data));
2019-09-23 15:50:41 -07:00
callback(null, data);
});
2018-01-22 13:01:38 -08:00
};
Client.prototype.stopApp = function (id, callback) {
post('/api/v1/apps/' + id + '/stop', {}, null, function (error, data, status) {
if (error) return callback(error);
2018-01-22 13:01:38 -08:00
if (status !== 202) return callback(new ClientError(status, data));
2019-09-23 15:50:41 -07:00
callback(null, data);
});
2018-01-22 13:01:38 -08:00
};
Client.prototype.restartApp = function (id, callback) {
2020-01-06 16:38:48 +01:00
post('/api/v1/apps/' + id + '/restart', {}, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 202) return callback(new ClientError(status, data));
callback(null, data);
});
};
2018-01-22 13:01:38 -08:00
Client.prototype.debugApp = function (id, state, callback) {
var data = {
debugMode: state ? {
readonlyRootfs: false,
2018-01-22 13:01:38 -08:00
cmd: [ '/bin/bash', '-c', 'echo "Repair mode. Use the webterminal or cloudron exec to repair. Sleeping" && sleep infinity' ]
} : null
};
2019-09-19 17:30:24 -07:00
post('/api/v1/apps/' + id + '/configure/debug_mode', data, null, function (error, data, status) {
if (error) return callback(error);
2018-01-22 13:01:38 -08:00
if (status !== 202) return callback(new ClientError(status, data));
2018-01-22 13:01:38 -08:00
callback(null);
});
2018-01-22 13:01:38 -08:00
};
Client.prototype.version = function (callback) {
get('/api/v1/cloudron/status', null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
2018-01-22 13:01:38 -08:00
callback(null, data);
2019-09-05 21:52:26 +02:00
});
2018-01-22 13:01:38 -08:00
};
Client.prototype.getStatus = function (callback) {
get('/api/v1/cloudron/status', null, function (error, data, status) {
if (error) return callback(error);
2018-01-22 13:01:38 -08:00
if (status !== 200 || typeof data !== 'object') return callback(new ClientError(status, data));
callback(null, data);
2019-09-05 21:52:26 +02:00
});
2018-01-22 13:01:38 -08:00
};
Client.prototype.setBackupConfig = function (backupConfig, callback) {
post('/api/v1/settings/backup_config', backupConfig, null, function (error, data, status) {
if (error) return callback(error);
2018-01-22 13:01:38 -08:00
if (status !== 200) return callback(new ClientError(status, data));
2018-01-22 13:01:38 -08:00
callback(null);
});
2018-01-22 13:01:38 -08:00
};
Client.prototype.getBackupConfig = function (callback) {
get('/api/v1/settings/backup_config', null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
callback(null, data);
});
};
Client.prototype.remountBackupStorage = function (callback) {
post('/api/v1/backups/remount', {}, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 202) return callback(new ClientError(status, data));
callback(null);
});
};
2020-02-05 14:15:46 -08:00
Client.prototype.getSupportConfig = function (callback) {
get('/api/v1/settings/support_config', null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
callback(null, data);
});
};
2019-08-29 09:59:57 +02:00
Client.prototype.setExternalLdapConfig = function (config, callback) {
post('/api/v1/settings/external_ldap_config', config, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
callback(null);
});
};
Client.prototype.getExternalLdapConfig = function (callback) {
get('/api/v1/settings/external_ldap_config', null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
2020-07-09 21:51:51 -07:00
callback(null, data);
});
};
Client.prototype.setProfileConfig = function (config, callback) {
post('/api/v1/settings/profile_config', config, null, function (error, data, status) {
2020-07-09 21:51:51 -07:00
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
callback(null);
});
};
Client.prototype.getProfileConfig = function (callback) {
get('/api/v1/settings/profile_config', null, function (error, data, status) {
2020-07-09 21:51:51 -07:00
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
2019-08-29 09:59:57 +02:00
callback(null, data);
});
};
Client.prototype.setUserDirectoryConfig = function (config, callback) {
post('/api/v1/settings/user_directory_config', config, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
callback(null);
});
};
Client.prototype.getUserDirectoryConfig = function (callback) {
get('/api/v1/settings/user_directory_config', null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
callback(null, data);
});
};
2020-08-31 21:45:56 -07:00
// network
2019-10-31 19:33:05 -07:00
Client.prototype.setSysinfoConfig = function (config, callback) {
post('/api/v1/settings/sysinfo_config', config, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
callback(null);
});
};
2019-11-07 10:41:24 -08:00
Client.prototype.getServerIp = function (callback) {
get('/api/v1/cloudron/server_ip', null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
2022-01-06 12:51:08 -08:00
callback(null, data);
2019-11-07 10:41:24 -08:00
});
};
2019-10-31 19:33:05 -07:00
Client.prototype.getSysinfoConfig = function (callback) {
get('/api/v1/settings/sysinfo_config', null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
callback(null, data);
});
};
2020-08-31 21:45:56 -07:00
Client.prototype.getBlocklist = function (callback) {
var config = {};
get('/api/v1/network/blocklist', config, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
callback(null, data.blocklist);
});
};
Client.prototype.setBlocklist = function (blocklist, callback) {
post('/api/v1/network/blocklist', { blocklist: blocklist }, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
callback(null);
});
};
2018-10-31 16:03:09 +01:00
Client.prototype.setDynamicDnsConfig = function (enabled, callback) {
post('/api/v1/settings/dynamic_dns', { enabled: enabled }, null, function (error, data, status) {
if (error) return callback(error);
2018-10-31 16:03:09 +01:00
if (status !== 200) return callback(new ClientError(status, data));
callback(null);
});
2018-10-31 16:03:09 +01:00
};
Client.prototype.getDynamicDnsConfig = function (callback) {
get('/api/v1/settings/dynamic_dns', null, function (error, data, status) {
if (error) return callback(error);
2018-10-31 16:03:09 +01:00
if (status !== 200) return callback(new ClientError(status, data));
2018-10-31 16:03:09 +01:00
callback(null, data.enabled);
});
2018-10-31 16:03:09 +01:00
};
2022-01-06 21:50:23 -08:00
Client.prototype.setIPv6Config = function (enabled, callback) {
post('/api/v1/settings/ipv6', { enabled: enabled }, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
callback(null);
});
};
Client.prototype.getIPv6Config = function (callback) {
get('/api/v1/settings/ipv6', null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
callback(null, data.enabled);
});
};
2020-08-31 21:45:56 -07:00
// branding
2020-02-14 15:34:44 +01:00
Client.prototype.setFooter = function (footer, callback) {
2020-03-18 17:53:50 -07:00
post('/api/v1/branding/footer', { footer: footer }, null, function (error, data, status) {
2020-02-14 15:34:44 +01:00
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
callback(null);
});
};
Client.prototype.getFooter = function (callback) {
2020-03-18 17:53:50 -07:00
get('/api/v1/branding/footer', null, function (error, data, status) {
2020-02-14 15:34:44 +01:00
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
callback(null, data.footer);
});
};
Client.prototype.setUnstableAppsConfig = function (enabled, callback) {
post('/api/v1/settings/unstable_apps', { enabled: enabled }, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
callback(null);
});
};
Client.prototype.getUnstableAppsConfig = function (callback) {
get('/api/v1/settings/unstable_apps', null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
callback(null, data.enabled);
});
};
2019-10-22 22:31:38 -07:00
Client.prototype.setRegistryConfig = function (rc, callback) {
post('/api/v1/settings/registry_config', rc, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
callback(null);
});
};
Client.prototype.getRegistryConfig = function (callback) {
get('/api/v1/settings/registry_config', null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
callback(null, data);
});
};
Client.prototype.getUpdateInfo = function (callback) {
if (!this._userInfo.isAtLeastAdmin) return callback(new Error('Not allowed'));
get('/api/v1/cloudron/update', null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
callback(null, data);
});
};
2018-01-22 13:01:38 -08:00
Client.prototype.checkForUpdates = function (callback) {
post('/api/v1/cloudron/check_for_updates', {}, null, function (error, data, status) {
if (error) return callback(error);
2018-01-22 13:01:38 -08:00
if (status !== 200) return callback(new ClientError(status, data));
client.refreshConfig(callback);
});
2018-01-22 13:01:38 -08:00
};
Client.prototype.checkForAppUpdates = function (appId, callback) {
post('/api/v1/apps/' + appId + '/check_for_updates', {}, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
client.refreshConfig(callback);
});
};
Client.prototype.setAutoupdatePattern = function (pattern, callback) {
post('/api/v1/settings/autoupdate_pattern', { pattern: pattern }, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
callback(null);
});
};
Client.prototype.getAutoupdatePattern = function (callback) {
get('/api/v1/settings/autoupdate_pattern', null, function (error, data, status) {
if (error) return callback(error);
2018-01-22 13:01:38 -08:00
if (status !== 200) return callback(new ClientError(status, data));
2018-01-22 13:01:38 -08:00
callback(null, data);
});
2018-01-22 13:01:38 -08:00
};
2020-01-07 21:41:45 +01:00
Client.prototype.setTimeZone = function (timeZone, callback) {
post('/api/v1/settings/time_zone', { timeZone: timeZone }, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
callback(null);
});
};
Client.prototype.getTimeZone = function (callback) {
get('/api/v1/settings/time_zone', null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
callback(null, data.timeZone);
});
};
2020-11-18 00:10:29 +01:00
Client.prototype.setLanguage = function (language, callback) {
post('/api/v1/settings/language', { language: language }, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
callback(null);
});
};
Client.prototype.getLanguage = function (callback) {
get('/api/v1/settings/language', null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
callback(null, data.language);
});
};
Client.prototype.getRemoteSupport = function (callback) {
get('/api/v1/support/remote_support', null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
callback(null, data.enabled);
});
2018-01-22 13:01:38 -08:00
};
Client.prototype.enableRemoteSupport = function (enable, callback) {
post('/api/v1/support/remote_support', { enable: enable }, null, function (error, data, status) {
if (error) return callback(error);
2018-01-22 13:01:38 -08:00
if (status !== 202) return callback(new ClientError(status, data));
2018-01-22 13:01:38 -08:00
callback(null);
});
2018-01-22 13:01:38 -08:00
};
Client.prototype.getBackups = function (callback) {
get('/api/v1/backups', null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
2018-01-22 13:01:38 -08:00
callback(null, data.backups);
});
2018-01-22 13:01:38 -08:00
};
2018-12-08 20:21:11 -08:00
Client.prototype.getLatestTaskByType = function (type, callback) {
get('/api/v1/tasks?page=1&per_page=1&type=' + type, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
2019-01-06 14:52:36 -08:00
callback(null, data.tasks.length ? data.tasks[0] : null);
});
2018-12-08 20:21:11 -08:00
};
Client.prototype.getTask = function (taskId, callback) {
get('/api/v1/tasks/' + taskId, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
2018-11-19 17:34:14 -08:00
callback(null, data);
});
2018-11-19 17:34:14 -08:00
};
2018-12-08 21:45:49 -08:00
Client.prototype.getTaskLogs = function (taskId, follow, lines, callback) {
if (follow) {
var eventSource = new EventSource(client.apiOrigin + '/api/v1/tasks/' + taskId + '/logstream?lines=' + lines + '&access_token=' + token);
callback(null, eventSource);
} else {
2019-01-08 13:12:37 -08:00
get('/api/v1/services/' + taskId + '/logs?lines=' + lines, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
2018-12-08 21:45:49 -08:00
callback(null, data);
});
2018-12-08 21:45:49 -08:00
}
};
2018-11-17 19:55:37 -08:00
Client.prototype.startBackup = function (callback) {
2019-04-13 18:09:51 -07:00
post('/api/v1/backups/create', {}, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 202) return callback(new ClientError(status, data));
callback(null, data.taskId);
});
};
Client.prototype.cleanupBackups = function (callback) {
post('/api/v1/backups/cleanup', {}, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 202) return callback(new ClientError(status, data));
2018-12-08 20:21:11 -08:00
callback(null, data.taskId);
});
2018-11-17 19:55:37 -08:00
};
2018-11-19 17:34:14 -08:00
Client.prototype.stopTask = function (taskId, callback) {
post('/api/v1/tasks/' + taskId + '/stop', {}, null, function (error, data, status) {
if (error) return callback(error);
2019-01-06 14:52:36 -08:00
if (status !== 204) return callback(new ClientError(status, data));
2018-01-22 13:01:38 -08:00
callback(null, data);
});
2018-01-22 13:01:38 -08:00
};
2021-02-24 15:16:29 -08:00
Client.prototype.restore = function (backupConfig, backupId, version, sysinfoConfig, skipDnsSetup, callback) {
2018-01-22 13:01:38 -08:00
var data = {
backupConfig: backupConfig,
backupId: backupId,
2019-11-11 11:07:52 -08:00
version: version,
2021-02-24 15:16:29 -08:00
sysinfoConfig: sysinfoConfig,
skipDnsSetup: skipDnsSetup
2018-01-22 13:01:38 -08:00
};
post('/api/v1/cloudron/restore', data, null, function (error, data, status) {
if (error) return callback(error);
2018-01-22 13:01:38 -08:00
if (status !== 200) return callback(new ClientError(status));
2018-01-22 13:01:38 -08:00
callback(null);
});
2018-01-22 13:01:38 -08:00
};
2020-02-06 16:08:22 -08:00
Client.prototype.importBackup = function (appId, backupId, backupFormat, backupConfig, callback) {
var data = {
backupId: backupId,
backupFormat: backupFormat,
backupConfig: backupConfig,
};
post('/api/v1/apps/' + appId + '/import', data, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 202) return callback(new ClientError(status));
callback(null);
});
};
Client.prototype.getNotifications = function (options, page, perPage, callback) {
var config = {
params: {
page: page,
per_page: perPage
}
};
if (typeof options.acknowledged === 'boolean') config.params.acknowledged = options.acknowledged;
get('/api/v1/notifications', config, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
callback(null, data.notifications);
});
};
Client.prototype.ackNotification = function (notificationId, acknowledged, callback) {
post('/api/v1/notifications/' + notificationId, { acknowledged: acknowledged }, null, function (error, data, status) {
2019-01-07 18:04:52 +01:00
if (error) return callback(error);
if (status !== 204) return callback(new ClientError(status));
callback(null);
});
};
2019-01-23 16:44:57 +01:00
Client.prototype.getEvent = function (eventId, callback) {
get('/api/v1/cloudron/eventlog/' + eventId, {}, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
callback(null, data.event);
});
};
Client.prototype.getEventLogs = function (actions, search, page, perPage, callback) {
2018-01-22 13:01:38 -08:00
var config = {
params: {
actions: actions,
2018-01-22 13:01:38 -08:00
search: search,
page: page,
per_page: perPage
}
};
2018-12-11 19:03:35 +01:00
get('/api/v1/cloudron/eventlog', config, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
2018-01-22 13:01:38 -08:00
callback(null, data.eventlogs);
});
2018-01-22 13:01:38 -08:00
};
2018-06-11 20:10:57 +02:00
Client.prototype.getPlatformLogs = function (unit, follow, lines, callback) {
2018-01-22 13:01:38 -08:00
if (follow) {
2018-06-11 20:10:57 +02:00
var eventSource = new EventSource(client.apiOrigin + '/api/v1/cloudron/logstream/' + unit + '?lines=' + lines + '&access_token=' + token);
2018-01-22 13:01:38 -08:00
callback(null, eventSource);
} else {
2019-01-08 13:12:37 -08:00
get('/api/v1/cloudron/logs/' + unit + '?lines=' + lines, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
2018-01-22 13:01:38 -08:00
callback(null, data);
});
2018-01-22 13:01:38 -08:00
}
};
2018-12-02 18:07:11 -08:00
Client.prototype.getServiceLogs = function (serviceName, follow, lines, callback) {
2018-11-26 14:49:50 +01:00
if (follow) {
2018-12-02 18:07:11 -08:00
var eventSource = new EventSource(client.apiOrigin + '/api/v1/services/' + serviceName + '/logstream?lines=' + lines + '&access_token=' + token);
2018-11-26 14:49:50 +01:00
callback(null, eventSource);
} else {
2019-01-08 13:12:37 -08:00
get('/api/v1/services/' + serviceName + '/logs?lines=' + lines, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
2018-11-26 14:49:50 +01:00
callback(null, data);
});
2018-11-26 14:49:50 +01:00
}
};
2018-01-22 13:01:38 -08:00
Client.prototype.getApps = function (callback) {
2020-06-08 17:20:18 -07:00
var that = this;
get('/api/v1/apps', null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
2020-06-08 17:20:18 -07:00
var apps = data.apps;
for (var i = 0; i < apps.length; i++) {
that._appPostProcess(apps[i]); // this will also set the correct iconUrl
}
callback(null, apps);
});
2018-01-22 13:01:38 -08:00
};
Client.prototype.getAppLogs = function (appId, follow, lines, callback) {
if (follow) {
var eventSource = new EventSource(client.apiOrigin + '/api/v1/apps/' + appId + '/logstream?lines=' + lines + '&access_token=' + token);
callback(null, eventSource);
} else {
get('/api/v1/apps/' + appId + '/logs', null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
2018-01-22 13:01:38 -08:00
callback(null, data);
});
2018-01-22 13:01:38 -08:00
}
};
Client.prototype.getAppBackups = function (appId, callback) {
get('/api/v1/apps/' + appId + '/backups', null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
2018-01-22 13:01:38 -08:00
callback(null, data.backups);
});
2018-01-22 13:01:38 -08:00
};
2018-12-02 18:07:11 -08:00
Client.prototype.getServices = function (callback) {
get('/api/v1/services', null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
2018-12-02 18:07:11 -08:00
callback(null, data.services);
});
2018-11-15 19:59:24 +01:00
};
2018-12-02 18:07:11 -08:00
Client.prototype.getService = function (serviceName, callback) {
get('/api/v1/services/' + serviceName, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
2018-12-02 18:07:11 -08:00
callback(null, data.service);
});
2018-11-15 19:59:24 +01:00
};
Client.prototype.configureService = function (serviceName, data, callback) {
post('/api/v1/services/' + serviceName, data, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 202) return callback(new ClientError(status, data));
callback(null);
});
2018-11-20 16:53:42 +01:00
};
2018-12-02 18:07:11 -08:00
Client.prototype.restartService = function (serviceName, callback) {
post('/api/v1/services/' + serviceName + '/restart', {}, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 202) return callback(new ClientError(status, data));
callback(null);
});
};
2021-01-21 17:41:16 -08:00
Client.prototype.rebuildService = function (serviceName, callback) {
post('/api/v1/services/' + serviceName + '/rebuild', {}, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 202) return callback(new ClientError(status, data));
callback(null);
});
};
Client.prototype.getUsers = function (search, page, perPage, callback) {
if (typeof search === 'function') {
callback = search;
search = '';
page = 1;
perPage = 5000;
}
var config = {
params: {
page: page,
per_page: perPage
}
};
if (search) config.params.search = search;
get('/api/v1/users', config, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
2018-01-22 13:01:38 -08:00
callback(null, data.users);
});
2018-01-22 13:01:38 -08:00
};
Client.prototype.getUser = function (userId, callback) {
get('/api/v1/users/' + userId, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
callback(null, data);
});
};
2018-01-22 13:01:38 -08:00
Client.prototype.getGroups = function (callback) {
get('/api/v1/groups', null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
2018-01-22 13:01:38 -08:00
callback(null, data.groups);
});
2018-01-22 13:01:38 -08:00
};
Client.prototype.setGroups = function (userId, groupIds, callback) {
put('/api/v1/users/' + userId + '/groups', { groupIds: groupIds }, null, function (error, data, status) {
if (error) return callback(error);
2018-01-22 13:01:38 -08:00
if (status !== 204) return callback(new ClientError(status, data));
2018-01-22 13:01:38 -08:00
callback(null);
});
2018-01-22 13:01:38 -08:00
};
Client.prototype.getGroup = function (groupId, callback) {
get('/api/v1/groups/' + groupId, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
2018-01-22 13:01:38 -08:00
callback(null, data);
});
2018-01-22 13:01:38 -08:00
};
2018-07-26 11:38:20 -07:00
Client.prototype.createGroup = function (name, callback) {
2018-01-22 13:01:38 -08:00
var data = {
2018-07-26 11:38:20 -07:00
name: name
2018-01-22 13:01:38 -08:00
};
post('/api/v1/groups', data, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 201) return callback(new ClientError(status, data));
2018-01-22 13:01:38 -08:00
callback(null, data);
});
2018-01-22 13:01:38 -08:00
};
2018-07-26 11:38:20 -07:00
Client.prototype.updateGroup = function (id, name, callback) {
var data = {
2018-07-26 11:38:20 -07:00
name: name
};
post('/api/v1/groups/' + id, data, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
callback(null, data);
});
};
Client.prototype.setGroupMembers = function (id, userIds, callback) {
var data = {
userIds: userIds
};
put('/api/v1/groups/' + id + '/members', data, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
callback(null, data);
});
};
Client.prototype.removeGroup = function (groupId, callback) {
2018-01-22 13:01:38 -08:00
var config = {
data: {},
2018-01-22 13:01:38 -08:00
headers: {
'Content-Type': 'application/json'
}
};
del('/api/v1/groups/' + groupId, config, function (error, data, status) {
if (error) return callback(error);
2018-01-22 13:01:38 -08:00
if (status !== 204) return callback(new ClientError(status, data));
2018-01-22 13:01:38 -08:00
callback(null, data);
});
2018-01-22 13:01:38 -08:00
};
Client.prototype.getApp = function (appId, callback) {
var that = this;
get('/api/v1/apps/' + appId, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
that._appPostProcess(data);
2018-06-25 18:55:07 -07:00
callback(null, data);
});
2018-06-25 18:55:07 -07:00
};
Client.prototype.getAppTask = function (appId, callback) {
get('/api/v1/apps/' + appId + '/task', null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
callback(null, data);
});
};
Client.prototype.getAppLimits = function (appId, callback) {
get('/api/v1/apps/' + appId + '/limits', null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
callback(null, data.limits);
});
};
Client.prototype.getAppWithTask = function (appId, callback) {
var that = this;
this.getApp(appId, function (error, app) {
if (error) return callback(error);
if (!app.taskId) return callback(null, app);
that.getAppTask(appId, function (error, task) {
if (error) return callback(error);
if (task) {
app.progress = task.percent;
app.message = task.message;
app.taskMinutesActive = moment.duration(moment.utc().diff(moment.utc(task.creationTime))).asMinutes();
} else {
app.progress = 0;
app.message = '';
app.taskMinutesActive = 0;
}
callback(null, app);
});
});
};
Client.prototype.getCachedAppSync = function (appId) {
var appFound = null;
this._installedApps.some(function (app) {
if (app.id === appId) {
appFound = app;
return true;
} else {
return false;
}
});
return appFound;
};
2021-04-14 20:58:43 -07:00
Client.prototype.disableTwoFactorAuthenticationByUserId = function (userId, callback) {
post('/api/v1/users/' + userId + '/twofactorauthentication_disable', {}, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
callback(null, data);
});
};
Client.prototype.setup = function (data, callback) {
post('/api/v1/cloudron/setup', data, null, function (error, data, status) {
if (error) return callback(error);
2018-01-22 13:01:38 -08:00
if (status !== 200) return callback(new ClientError(status, data));
2018-01-22 13:01:38 -08:00
callback(null);
});
2018-01-22 13:01:38 -08:00
};
Client.prototype.createAdmin = function (data, callback) {
2018-01-22 13:01:38 -08:00
var that = this;
post('/api/v1/cloudron/activate', data, null, function (error, result, status) {
if (error) return callback(error);
if (status !== 201) return callback(new ClientError(status, result));
2018-01-22 13:01:38 -08:00
that.setToken(result.token);
that.setUserInfo({ username: data.username, email: data.email, admin: true, twoFactorAuthenticationEnabled: false, source: '', avatarUrl: null });
2018-01-22 13:01:38 -08:00
callback(null, result.activated);
});
2018-01-22 13:01:38 -08:00
};
2020-02-07 16:42:35 +01:00
Client.prototype.getTokens = function (callback) {
get('/api/v1/tokens/', null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
callback(null, data.tokens);
});
};
Client.prototype.createToken = function (name, callback) {
var data = {
name: name
};
post('/api/v1/tokens', data, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 201) return callback(new ClientError(status, data));
2021-06-04 13:11:06 -07:00
callback(null, data);
2020-02-07 16:42:35 +01:00
});
};
// FIXME clashes with existing getToken()
// Client.prototype.getToken = function (id, callback) {
// get('/api/v1/tokens/' + id, null, function (error, data, status) {
// if (error) return callback(error);
// if (status !== 200) return callback(new ClientError(status, data));
// callback(null, data.token);
// });
// };
Client.prototype.delToken = function (tokenId, callback) {
del('/api/v1/tokens/' + tokenId, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 204) return callback(new ClientError(status, data));
callback(null);
});
};
2020-02-01 10:04:09 -08:00
Client.prototype.addAppPassword = function (identifier, name, callback) {
var data = {
identifier: identifier,
name: name
};
post('/api/v1/app_passwords', data, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 201) return callback(new ClientError(status, data));
callback(null, data);
});
};
Client.prototype.getAppPasswords = function (callback) {
get('/api/v1/app_passwords', null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
callback(null, data);
});
};
Client.prototype.delAppPassword = function (id, callback) {
del('/api/v1/app_passwords/' + id, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 204) return callback(new ClientError(status, data));
callback(null);
});
};
2019-05-12 13:08:40 -07:00
Client.prototype.update = function (options, callback) {
var data = {
skipBackup: !!options.skipBackup
};
2018-01-22 13:01:38 -08:00
post('/api/v1/cloudron/update', data, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 202) return callback(new ClientError(status, data));
2018-12-08 20:21:11 -08:00
callback(null, data.taskId);
});
2018-01-22 13:01:38 -08:00
};
Client.prototype.isRebootRequired = function (callback) {
get('/api/v1/cloudron/reboot', null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
callback(null, data.rebootRequired);
});
};
2018-01-22 13:01:38 -08:00
Client.prototype.reboot = function (callback) {
post('/api/v1/cloudron/reboot', {}, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 202) return callback(new ClientError(status, data));
2018-01-22 13:01:38 -08:00
callback(null, data);
});
2018-01-22 13:01:38 -08:00
};
Client.prototype.setCertificate = function (certificateFile, keyFile, callback) {
var data = {
cert: certificateFile,
key: keyFile
};
post('/api/v1/settings/certificate', data, null, function (error, data, status) {
if (error) return callback(error);
2018-01-22 13:01:38 -08:00
if (status !== 202) return callback(new ClientError(status, data));
2018-01-22 13:01:38 -08:00
callback(null);
});
2018-01-22 13:01:38 -08:00
};
Client.prototype.disks = function (callback) {
get('/api/v1/cloudron/disks', null, function (error, data, status) {
2019-11-21 13:22:24 -08:00
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
callback(null, data);
});
};
Client.prototype.memory = function (callback) {
get('/api/v1/cloudron/memory', null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
2018-01-22 13:01:38 -08:00
callback(null, data);
});
2018-01-22 13:01:38 -08:00
};
2019-08-20 19:38:32 -07:00
Client.prototype.graphs = function (targets, from, options, callback) {
// if we have a lot of apps, targets can be very large. node will just disconnect since it exceeds header size
var size = 10, chunks = [];
for (var i = 0; i < targets.length; i += size) {
chunks.push(targets.slice(i, i+size));
}
2018-01-22 13:01:38 -08:00
var result = [];
2020-06-03 23:17:06 +02:00
async.eachSeries(chunks, function (chunk, iteratorCallback) {
var config = {
params: {
target: chunk,
format: 'json',
2020-05-22 17:16:37 +02:00
from: from,
until: 'now'
}
};
2019-08-20 19:38:32 -07:00
if (options.noNullPoints) config.params.noNullPoints = true;
2021-09-21 21:50:44 -07:00
get(options.appId ? '/api/v1/apps/' + options.appId + '/graphs' : '/api/v1/cloudron/graphs', config, function (error, data, status) {
if (error) return iteratorCallback(error);
if (status !== 200) return iteratorCallback(new ClientError(status, data));
// the datapoint returned here is an [value, timestamp]
result = result.concat(data);
iteratorCallback(null);
});
}, function iteratorDone(error) {
callback(error, result);
});
2018-01-22 13:01:38 -08:00
};
Client.prototype.createTicket = function (ticket, callback) {
// just to be eplicit here
2018-01-22 13:01:38 -08:00
var data = {
enableSshSupport: !!ticket.enableSshSupport,
type: ticket.type,
subject: ticket.subject,
description: ticket.description,
appId: ticket.appId || undefined,
altEmail: ticket.altEmail || undefined
2018-01-22 13:01:38 -08:00
};
2019-05-07 11:36:12 -07:00
post('/api/v1/support/ticket', data, null, function (error, data, status) {
if (error) return callback(error);
2018-01-22 13:01:38 -08:00
if (status !== 201) return callback(new ClientError(status, data));
2019-05-28 10:04:18 -07:00
callback(null, data);
});
2018-01-22 13:01:38 -08:00
};
2021-08-10 13:53:28 -07:00
Client.prototype.addUser = function (user, callback) {
2018-01-22 13:01:38 -08:00
var data = {
2018-07-26 15:52:06 -07:00
email: user.email,
fallbackEmail: user.fallbackEmail,
2018-07-26 15:52:06 -07:00
displayName: user.displayName,
role: user.role
2018-01-22 13:01:38 -08:00
};
2018-07-26 15:52:06 -07:00
if (user.username !== null) data.username = user.username;
if (user.password !== null) data.password = user.password;
2018-01-22 13:01:38 -08:00
post('/api/v1/users', data, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 201) return callback(new ClientError(status, data));
2021-08-10 13:53:28 -07:00
callback(null, data.id);
});
2018-01-22 13:01:38 -08:00
};
Client.prototype.updateUser = function (user, callback) {
var data = {
email: user.email,
displayName: user.displayName,
2018-07-26 15:45:52 -07:00
fallbackEmail: user.fallbackEmail,
2020-02-17 14:05:26 +01:00
active: user.active,
role: user.role
2018-01-22 13:01:38 -08:00
};
if (user.username) data.username = user.username;
2018-01-22 13:01:38 -08:00
post('/api/v1/users/' + user.id, data, null, function (error, data, status) {
if (error) return callback(error);
2018-01-22 13:01:38 -08:00
if (status !== 204) return callback(new ClientError(status, data));
2018-01-22 13:01:38 -08:00
callback(null);
});
2018-01-22 13:01:38 -08:00
};
2021-01-15 14:28:52 +01:00
Client.prototype.changeOwnership = function (userId, callback) {
post('/api/v1/users/' + userId + '/make_owner', {}, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 204) return callback(new ClientError(status, data));
callback(null);
});
};
Client.prototype.removeUser = function (userId, callback) {
2018-01-22 13:01:38 -08:00
var config = {
data: {},
2018-01-22 13:01:38 -08:00
headers: {
'Content-Type': 'application/json'
}
};
del('/api/v1/users/' + userId, config, function (error, data, status) {
if (error) return callback(error);
2018-01-22 13:01:38 -08:00
if (status !== 204) return callback(new ClientError(status, data));
2018-01-22 13:01:38 -08:00
callback(null);
});
2018-01-22 13:01:38 -08:00
};
Client.prototype.updateProfile = function (data, callback) {
post('/api/v1/profile', data, null, function (error, data, status) {
if (error) return callback(error);
2018-01-22 13:01:38 -08:00
if (status !== 204) return callback(new ClientError(status, data));
2018-01-22 13:01:38 -08:00
callback(null, data);
});
2018-01-22 13:01:38 -08:00
};
Client.prototype.changeAvatar = function (avatarFileOrType, callback) {
// Blob type if object
if (typeof avatarFileOrType === 'object') {
var fd = new FormData();
fd.append('avatar', avatarFileOrType);
var config = {
headers: { 'Content-Type': undefined },
transformRequest: angular.identity
};
post('/api/v1/profile/avatar', fd, config, function (error, data, status) {
if (error) return callback(error);
if (status !== 202) return callback(new ClientError(status, data));
callback(null);
});
} else {
post('/api/v1/profile/avatar', { avatar: avatarFileOrType === 'gravatar' ? 'gravatar' : '' }, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 202) return callback(new ClientError(status, data));
callback(null);
});
}
};
2018-01-22 13:01:38 -08:00
Client.prototype.changePassword = function (currentPassword, newPassword, callback) {
var data = {
password: currentPassword,
newPassword: newPassword
};
post('/api/v1/profile/password', data, null, function (error, data, status) {
if (error) return callback(error);
2018-01-22 13:01:38 -08:00
if (status !== 204) return callback(new ClientError(status, data));
2018-01-22 13:01:38 -08:00
callback(null, data);
});
2018-01-22 13:01:38 -08:00
};
Client.prototype.getPasswordResetLink = function (userId, callback) {
get('/api/v1/users/' + userId + '/password_reset_link', null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
callback(null, data);
});
};
Client.prototype.sendPasswordResetEmail = function (userId, email, callback) {
post('/api/v1/users/' + userId + '/send_password_reset_email', { email }, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 202) return callback(new ClientError(status, data));
2021-09-16 14:35:17 +02:00
callback(null, data);
});
};
Client.prototype.sendSelfPasswordReset = function (identifier, callback) {
post('/api/v1/cloudron/password_reset_request', { identifier }, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 202) return callback(new ClientError(status, data));
callback(null, data);
});
};
2021-10-27 19:57:57 +02:00
Client.prototype.getInviteLink = function (userId, callback) {
get('/api/v1/users/' + userId + '/invite_link', null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
callback(null, data);
});
};
Client.prototype.sendInviteEmail = function (userId, email, callback) {
post('/api/v1/users/' + userId + '/send_invite_email', { email }, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 202) return callback(new ClientError(status, data));
callback(null, data);
});
};
2018-04-26 15:12:29 +02:00
Client.prototype.setTwoFactorAuthenticationSecret = function (callback) {
var data = {};
2021-04-14 20:00:31 -07:00
post('/api/v1/profile/twofactorauthentication_secret', data, null, function (error, data, status) {
if (error) return callback(error);
2018-04-26 15:12:29 +02:00
if (status !== 201) return callback(new ClientError(status, data));
2018-04-26 15:12:29 +02:00
callback(null, data);
});
2018-04-26 15:12:29 +02:00
};
Client.prototype.enableTwoFactorAuthentication = function (totpToken, callback) {
var data = {
totpToken: totpToken
};
2021-04-14 20:00:31 -07:00
post('/api/v1/profile/twofactorauthentication_enable', data, null, function (error, data, status) {
if (error) return callback(error);
2018-04-26 15:12:29 +02:00
if (status !== 202) return callback(new ClientError(status, data));
2018-04-26 15:12:29 +02:00
callback(null);
});
2018-04-26 15:12:29 +02:00
};
Client.prototype.disableTwoFactorAuthentication = function (password, callback) {
var data = {
password: password
};
2021-04-14 20:00:31 -07:00
post('/api/v1/profile/twofactorauthentication_disable', data, null, function (error, data, status) {
if (error) return callback(error);
2018-04-26 15:12:29 +02:00
if (status !== 202) return callback(new ClientError(status, data));
2018-04-26 15:12:29 +02:00
callback(null);
});
2018-04-26 15:12:29 +02:00
};
2021-09-17 15:53:11 +02:00
Client.prototype.setGhost = function (userId, password, expiresAt, callback) {
var data = { password };
if (expiresAt) data.expiresAt = expiresAt;
post('/api/v1/users/' + userId + '/ghost', data, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 204) return callback(new ClientError(status, data));
callback(null);
});
};
Client.prototype.startExternalLdapSync = function (callback) {
post('/api/v1/cloudron/sync_external_ldap', {}, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 202) return callback(new ClientError(status, data));
2019-08-29 23:19:34 +02:00
callback(null, data.taskId);
});
};
2019-08-08 07:39:43 -07:00
Client.prototype.setUserActive = function (userId, active, callback) {
var data = {
active: active
};
post('/api/v1/users/' + userId + '/active', data, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
callback(null);
});
};
2018-01-22 13:01:38 -08:00
Client.prototype.refreshUserInfo = function (callback) {
var that = this;
callback = typeof callback === 'function' ? callback : function () {};
this.userInfo(function (error, result) {
if (error) return callback(error);
that.setUserInfo(result);
callback(null);
});
};
Client.prototype.refreshConfig = function (callback) {
var that = this;
callback = typeof callback === 'function' ? callback : function () {};
this.config(function (error, result) {
if (error) return callback(error);
that.getUpdateInfo(function (error, info) { // note: non-admin users may get access denied for this
if (!error) result.update = info.update; // attach update information to config object
2018-01-22 13:01:38 -08:00
that.setConfig(result);
callback(null);
});
2018-01-22 13:01:38 -08:00
});
};
Client.prototype.refreshAvailableLanguages = function (callback) {
var that = this;
get('/api/v1/cloudron/languages', null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
angular.copy(data.languages, that._availableLanguages);
callback(null, data.languages);
});
};
Client.prototype._appPostProcess = function (app) {
// calculate the icon paths
app.iconUrl = app.iconUrl ? (this.apiOrigin + app.iconUrl + '?access_token=' + token + '&ts=' + app.ts) : null;
2018-01-22 13:01:38 -08:00
// amend the post install confirm state
app.pendingPostInstallConfirmation = !!localStorage['confirmPostInstall_' + app.id];
if (app.manifest.upstreamVersion) {
app.upstreamVersion = app.manifest.upstreamVersion;
} else if (app.manifest.description) { // can be empty for dev apps
var tmp = app.manifest.description.match(/\<upstream\>(.*)\<\/upstream\>/i);
app.upstreamVersion = (tmp && tmp[1]) ? tmp[1] : '';
} else {
app.upstreamVersion = '';
}
if (!app.manifest.title) app.manifest.title = 'Untitled';
if (app.manifest.postInstallMessage) {
var text= app.manifest.postInstallMessage;
// we chose - because underscore has special meaning in markdown
2022-01-16 18:29:32 -08:00
text = text.replace(/\$CLOUDRON-APP-LOCATION/g, app.subdomain);
2021-05-25 11:32:53 -07:00
text = text.replace(/\$CLOUDRON-APP-DOMAIN/g, app.domain);
text = text.replace(/\$CLOUDRON-APP-FQDN/g, app.fqdn);
2020-08-08 22:02:31 -07:00
text = text.replace(/\$CLOUDRON-APP-ORIGIN/g, 'https://' + app.fqdn);
text = text.replace(/\$CLOUDRON-API-DOMAIN/g, this._config.adminFqdn);
text = text.replace(/\$CLOUDRON-API-ORIGIN/g, 'https://' + this._config.adminFqdn);
text = text.replace(/\$CLOUDRON-USERNAME/g, this._userInfo.username);
text = text.replace(/\$CLOUDRON-APP-ID/g, app.id);
// [^] matches even newlines. '?' makes it non-greedy
if (app.sso) text = text.replace(/<nosso>[^]*?<\/nosso>/g, '');
else text = text.replace(/<sso>[^]*?<\/sso>/g, '');
app.manifest.postInstallMessage = text;
}
2018-01-22 13:01:38 -08:00
return app;
};
2018-06-26 17:12:55 -07:00
function binarySearch(array, pred) {
var lo = -1, hi = array.length;
while (1 + lo !== hi) {
var mi = lo + ((hi - lo) >> 1);
if (pred(array[mi])) {
hi = mi;
} else {
lo = mi;
}
}
return hi;
}
2018-06-26 08:41:25 -07:00
Client.prototype._updateAppCache = function (app) {
var tmp = {};
angular.copy(app, tmp);
var foundIndex = this._installedApps.findIndex(function (a) { return a.id === app.id; });
// we replace new data into the existing reference to keep angular bindings
if (foundIndex !== -1) {
angular.copy(tmp, this._installedApps[foundIndex]);
2018-06-26 08:41:25 -07:00
} else {
this._installedApps.push(tmp);
2018-06-26 08:41:25 -07:00
}
// add reference to object map with appId keys
this._installedAppsById[app.id] = this._installedApps[foundIndex];
2019-04-12 11:06:56 +02:00
// TODO this not very elegant
// update app tags
tmp = this._installedApps
.map(function (app) { return app.tags || []; }) // return array of arrays
.reduce(function (a, i) { return a.concat(i); }, []) // merge all arrays into one
2019-05-16 09:42:34 -07:00
.filter(function (v, i, self) { return self.indexOf(v) === i; }) // filter duplicates
.sort(function (a, b) { return a.localeCompare(b); }); // sort
2019-04-12 11:06:56 +02:00
// keep tag array references
angular.copy(tmp, this._appTags);
2018-06-26 08:41:25 -07:00
};
2018-01-22 13:01:38 -08:00
Client.prototype.refreshInstalledApps = function (callback) {
callback = callback || function (error) { if (error) console.error(error); };
2018-01-22 13:01:38 -08:00
var that = this;
this.getApps(function (error, apps) {
2018-01-22 13:01:38 -08:00
if (error) return callback(error);
2020-06-03 23:38:00 +02:00
async.eachLimit(apps, 20, function (app, iteratorCallback) {
app.ssoAuth = (app.manifest.addons['ldap'] || app.manifest.addons['proxyAuth']) && app.sso;
if (app.accessLevel !== 'operator' && app.accessLevel !== 'admin') { // only fetch if we have permissions
2021-02-24 17:12:18 +01:00
app.progress = 0;
app.message = '';
app.taskMinutesActive = 0;
that._updateAppCache(app);
return iteratorCallback();
}
var getTaskFunc = app.taskId ? that.getAppTask.bind(null, app.id) : function (next) { return next(); };
getTaskFunc(function (error, task) {
if (error) return iteratorCallback(error);
if (task) {
app.progress = task.percent;
app.message = task.message;
app.taskMinutesActive = moment.duration(moment.utc().diff(moment.utc(task.creationTime))).asMinutes();
} else {
app.progress = 0;
app.message = '';
app.taskMinutesActive = 0;
}
2018-01-22 13:01:38 -08:00
that._updateAppCache(app);
2018-01-22 13:01:38 -08:00
2021-02-24 17:12:18 +01:00
iteratorCallback();
});
}, function iteratorDone(error) {
if (error) return callback(error);
// filter out old apps, going backwards to allow splicing
for (var i = that._installedApps.length - 1; i >= 0; --i) {
if (!apps.some(function (elem) { return (elem.id === that._installedApps[i].id); })) {
var removed = that._installedApps.splice(i, 1);
delete that._installedAppsById[removed[0].id];
}
}
callback(null);
});
2018-01-22 13:01:38 -08:00
});
};
Client.prototype.login = function () {
this.setToken(null);
window.location.href = '/login.html?returnTo=/' + encodeURIComponent(window.location.hash);
2018-01-22 13:01:38 -08:00
};
Client.prototype.logout = function () {
var token = this.getToken();
2018-01-22 13:01:38 -08:00
this.setToken(null);
// invalidates the token
window.location.href = client.apiOrigin + '/api/v1/cloudron/logout?access_token=' + token;
2018-01-22 13:01:38 -08:00
};
2021-09-21 19:46:18 -07:00
Client.prototype.getAppEventLog = function (appId, page, perPage, callback) {
var config = {
params: {
page: page,
per_page: perPage
}
};
get('/api/v1/apps/' + appId + '/eventlog', config, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
callback(null, data.eventlogs);
});
};
2018-01-22 13:01:38 -08:00
Client.prototype.uploadFile = function (appId, file, progressCallback, callback) {
var fd = new FormData();
fd.append('file', file);
var config = {
2018-01-22 13:01:38 -08:00
headers: { 'Content-Type': undefined },
transformRequest: angular.identity,
uploadEventHandlers: {
progress: progressCallback
}
};
2019-03-04 11:54:41 -08:00
post('/api/v1/apps/' + appId + '/upload?file=' + encodeURIComponent('/tmp/' + file.name), fd, config, function (error, data, status) {
if (error) return callback(error);
2018-01-22 13:01:38 -08:00
if (status !== 202) return callback(new ClientError(status, data));
2018-01-22 13:01:38 -08:00
callback(null);
});
2018-01-22 13:01:38 -08:00
};
Client.prototype.checkDownloadableFile = function (appId, filePath, callback) {
var config = {
2018-01-22 13:01:38 -08:00
headers: { 'Content-Type': undefined }
};
head('/api/v1/apps/' + appId + '/download?file=' + encodeURIComponent(filePath), config, function (error, data, status) {
if (error) return callback(error);
2018-01-22 13:01:38 -08:00
if (status !== 200) return callback(new ClientError(status, data));
2018-01-22 13:01:38 -08:00
callback(null);
});
2018-01-22 13:01:38 -08:00
};
2018-01-23 16:10:09 -08:00
Client.prototype.sendTestMail = function (domain, to, callback) {
2018-01-22 13:01:38 -08:00
var data = {
2018-01-23 16:10:09 -08:00
to: to
2018-01-22 13:01:38 -08:00
};
post('/api/v1/mail/' + domain + '/send_test_mail', data, null, function (error, data, status) {
if (error) return callback(error);
2018-01-22 13:01:38 -08:00
if (status !== 202) return callback(new ClientError(status, data));
2018-01-22 13:01:38 -08:00
callback(null);
});
2018-01-22 13:01:38 -08:00
};
// Domains
Client.prototype.getDomains = function (callback) {
get('/api/v1/domains', null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
2018-01-22 13:01:38 -08:00
callback(null, data.domains);
});
2018-01-22 13:01:38 -08:00
};
Client.prototype.getDomain = function (domain, callback) {
get('/api/v1/domains/' + domain, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
2018-01-22 13:01:38 -08:00
callback(null, data);
});
2018-01-22 13:01:38 -08:00
};
Client.prototype.checkDNSRecords = function (domain, subdomain, callback) {
2019-09-23 23:47:33 +02:00
get('/api/v1/domains/' + domain + '/dns_check?subdomain=' + subdomain, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
2019-09-23 23:46:55 +02:00
callback(null, data);
});
};
2021-12-24 15:15:07 -08:00
Client.prototype.addDomain = function (domain, zoneName, provider, config, fallbackCertificate, tlsConfig, callback) {
2018-01-22 13:01:38 -08:00
var data = {
domain: domain,
provider: provider,
config: config,
tlsConfig: tlsConfig,
2018-01-22 13:01:38 -08:00
};
if (zoneName) data.zoneName = zoneName;
var that = this;
2018-01-22 13:01:38 -08:00
if (fallbackCertificate) data.fallbackCertificate = fallbackCertificate;
// hack until we fix the domains.js
post('/api/v1/domains', data, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 201) return callback(new ClientError(status, data));
callback();
});
2018-01-22 13:01:38 -08:00
};
Client.prototype.updateDomainConfig = function (domain, zoneName, provider, config, fallbackCertificate, tlsConfig, callback) {
2018-01-22 13:01:38 -08:00
var data = {
provider: provider,
config: config,
tlsConfig: tlsConfig
2018-01-22 13:01:38 -08:00
};
if (zoneName) data.zoneName = zoneName;
var that = this;
2018-01-22 13:01:38 -08:00
if (fallbackCertificate) data.fallbackCertificate = fallbackCertificate;
post('/api/v1/domains/' + domain + '/config', data, null, function (error, data, status) {
if (error) return callback(error);
2018-01-22 13:01:38 -08:00
if (status !== 204) return callback(new ClientError(status, data));
2021-02-24 22:00:05 -08:00
that.setDnsRecords({ domain: domain, type: 'mail' }, callback); // this is done so that an out-of-sync dkim key can be synced
});
2018-01-22 13:01:38 -08:00
};
Client.prototype.updateDomainWellKnown = function (domain, wellKnown, callback) {
var data = {
wellKnown: wellKnown
};
var that = this;
post('/api/v1/domains/' + domain + '/wellknown', data, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 204) return callback(new ClientError(status, data));
callback(null);
});
};
2021-03-13 21:52:37 -08:00
Client.prototype.renewCerts = function (callback) {
post('/api/v1/cloudron/renew_certs', {}, null, function (error, data, status) {
if (error) return callback(error);
2018-10-24 15:24:23 -07:00
if (status !== 202) return callback(new ClientError(status, data));
2018-12-11 10:17:27 -08:00
callback(null, data.taskId);
});
2018-10-24 15:24:23 -07:00
};
Client.prototype.removeDomain = function (domain, callback) {
var config = {
data: {
},
headers: {
'Content-Type': 'application/json'
}
};
del('/api/v1/domains/' + domain, config, function (error, data, status) {
if (error) return callback(error);
if (status !== 204) return callback(new ClientError(status, data));
callback(null);
});
2018-01-22 13:01:38 -08:00
};
2018-12-18 15:05:11 -08:00
Client.prototype.prepareDashboardDomain = function (domain, callback) {
var data = {
domain: domain
};
post('/api/v1/cloudron/prepare_dashboard_domain', data, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 202) return callback(new ClientError(status, data));
callback(null, data.taskId);
});
};
Client.prototype.setDashboardDomain = function (domain, callback) {
var data = {
domain: domain
};
post('/api/v1/cloudron/set_dashboard_domain', data, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 204) return callback(new ClientError(status, data));
callback(null);
});
};
2018-01-23 12:29:57 +01:00
// Email
2020-03-25 20:13:45 -07:00
Client.prototype.getMailEventLogs = function (search, types, page, perPage, callback) {
2020-02-11 22:07:58 -08:00
var config = {
params: {
page: page,
2020-03-25 20:13:45 -07:00
types: types,
2020-02-14 09:09:32 -08:00
per_page: perPage,
search: search
2020-02-11 22:07:58 -08:00
}
};
get('/api/v1/mailserver/eventlog', config, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
callback(null, data.eventlogs);
});
};
2020-02-20 12:08:56 -08:00
Client.prototype.getMailUsage = function (domain, callback) {
var config = {
params: {
domain: domain
}
};
get('/api/v1/mailserver/usage', config, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
2020-08-20 22:07:20 -07:00
callback(null, data.usage);
});
};
2020-08-20 23:06:22 -07:00
Client.prototype.getMailLocation = function (callback) {
var config = {};
get('/api/v1/mailserver/location', config, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
callback(null, data); // { subdomain, domain }
});
};
Client.prototype.setMailLocation = function (subdomain, domain, callback) {
post('/api/v1/mailserver/location', { subdomain: subdomain, domain: domain }, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 202) return callback(new ClientError(status, data));
callback(null, { taskId: data.taskId });
});
};
2020-08-20 22:07:20 -07:00
Client.prototype.getMaxEmailSize = function (callback) {
var config = {};
get('/api/v1/mailserver/max_email_size', config, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
callback(null, data.size);
});
};
Client.prototype.setMaxEmailSize = function (size, callback) {
post('/api/v1/mailserver/max_email_size', { size: size }, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
callback(null);
2020-02-20 12:08:56 -08:00
});
};
Client.prototype.getMailboxSharing = function (callback) {
get('/api/v1/mailserver/mailbox_sharing', {}, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
callback(null, data.enabled);
});
};
Client.prototype.setMailboxSharing = function (enable, callback) {
post('/api/v1/mailserver/mailbox_sharing', { enable: enable }, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
callback(null);
});
};
2021-10-13 14:22:37 -07:00
Client.prototype.getDnsblConfig = function (callback) {
var config = {};
get('/api/v1/mailserver/dnsbl_config', config, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
callback(null, data);
});
};
Client.prototype.setDnsblConfig = function (zones, callback) {
post('/api/v1/mailserver/dnsbl_config', { zones: zones }, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
callback(null);
});
};
2020-11-19 17:45:16 -08:00
Client.prototype.getSolrConfig = function (callback) {
var config = {};
get('/api/v1/mailserver/solr_config', config, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
callback(null, data);
});
};
Client.prototype.setSolrConfig = function (enabled, callback) {
post('/api/v1/mailserver/solr_config', { enabled: enabled }, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
callback(null);
});
};
2020-08-22 13:01:25 -07:00
Client.prototype.getSpamAcl = function (callback) {
var config = {};
get('/api/v1/mailserver/spam_acl', config, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
callback(null, data);
});
};
Client.prototype.setSpamAcl = function (acl, callback) {
post('/api/v1/mailserver/spam_acl', { whitelist: acl.whitelist, blacklist: acl.blacklist }, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
callback(null);
});
};
Client.prototype.getSpamCustomConfig = function (callback) {
var config = {};
get('/api/v1/mailserver/spam_custom_config', config, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
callback(null, data.config);
});
};
Client.prototype.setSpamCustomConfig = function (config, callback) {
post('/api/v1/mailserver/spam_custom_config', { config: config }, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
callback(null);
});
};
2018-01-23 12:29:57 +01:00
Client.prototype.getMailConfigForDomain = function (domain, callback) {
get('/api/v1/mail/' + domain, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
2018-01-23 12:29:57 +01:00
callback(null, data);
});
2018-01-23 12:29:57 +01:00
};
Client.prototype.enableMailForDomain = function (domain, enabled, callback) {
post('/api/v1/mail/' + domain + '/enable', { enabled: enabled }, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 202) return callback(new ClientError(status, data));
callback(null);
});
2018-01-23 12:29:57 +01:00
};
2021-02-24 22:00:05 -08:00
Client.prototype.setDnsRecords = function (options, callback) {
post('/api/v1/cloudron/sync_dns', options, null, function (error, data, status) {
if (error) return callback(error);
2018-07-25 10:51:58 -07:00
if (status !== 201) return callback(new ClientError(status, data));
2021-02-24 22:00:05 -08:00
callback(null, data.taskId);
});
2018-07-25 10:51:58 -07:00
};
2018-01-23 12:29:57 +01:00
Client.prototype.getMailStatusForDomain = function (domain, callback) {
get('/api/v1/mail/' + domain + '/status', null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
2018-01-23 12:29:57 +01:00
callback(null, data);
});
2018-01-23 12:29:57 +01:00
};
Client.prototype.setMailRelay = function (domain, data, callback) {
post('/api/v1/mail/' + domain + '/relay', data, null, function (error, data, status) {
if (error) return callback(error);
2018-01-23 12:29:57 +01:00
if (status !== 202) return callback(new ClientError(status, data));
callback(null);
});
};
Client.prototype.setMailBanner = function (domain, data, callback) {
post('/api/v1/mail/' + domain + '/banner', data, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 202) return callback(new ClientError(status, data));
2018-01-23 12:29:57 +01:00
callback(null);
});
2018-01-23 12:29:57 +01:00
};
Client.prototype.setCatchallAddresses = function (domain, addresses, callback) {
post('/api/v1/mail/' + domain + '/catch_all', { addresses: addresses }, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 202) return callback(new ClientError(status, data));
callback(null);
});
};
Client.prototype.setMailFromValidation = function (domain, enabled, callback) {
post('/api/v1/mail/' + domain + '/mail_from_validation', { enabled: enabled }, null, function (error, data, status) {
if (error) return callback(error);
2018-01-23 12:29:57 +01:00
if (status !== 202) return callback(new ClientError(status, data));
2018-01-23 12:29:57 +01:00
callback(null);
});
2018-01-23 12:29:57 +01:00
};
2018-01-24 16:20:21 +01:00
// Mailboxes
2021-12-03 11:23:25 +01:00
Client.prototype.getAllMailboxes = function (callback) {
var that = this;
this.getDomains(function (error, domains) {
if (error) return callback(error);
var mailboxes = [];
async.eachLimit(domains, 5, function (domain, callback) {
that.listMailboxes(domain.domain, '', 1, 1000, function (error, result) {
if (error) return callback(error);
mailboxes = mailboxes.concat(result);
callback();
});
}, function (error) {
if (error) return callback(error);
callback(null, mailboxes);
});
});
};
2020-07-15 15:35:32 -07:00
Client.prototype.getMailboxCount = function (domain, callback) {
get('/api/v1/mail/' + domain + '/mailbox_count', null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
callback(null, data.count);
});
};
Client.prototype.listMailboxes = function (domain, search, page, perPage, callback) {
var config = {
params: {
2020-07-05 12:18:34 -07:00
search: search,
page: page,
per_page: perPage
}
};
get('/api/v1/mail/' + domain + '/mailboxes', config, function (error, data, status) {
if (error) return callback(error);
2018-01-24 16:20:21 +01:00
if (status !== 200) return callback(new ClientError(status, data));
2018-04-09 15:45:54 +02:00
callback(null, data.mailboxes);
});
2018-01-24 16:20:21 +01:00
};
2018-04-05 14:02:56 +02:00
Client.prototype.getMailbox = function (domain, name, callback) {
get('/api/v1/mail/' + domain + '/mailboxes/' + name, null, function (error, data, status) {
if (error) return callback(error);
2018-01-24 16:20:21 +01:00
if (status !== 200) return callback(new ClientError(status, data));
2018-01-24 16:20:21 +01:00
callback(null, data.mailbox);
});
2018-01-24 16:20:21 +01:00
};
2020-11-12 23:53:02 -08:00
Client.prototype.addMailbox = function (domain, name, ownerId, ownerType, callback) {
2018-04-05 14:02:56 +02:00
var data = {
name: name,
2020-11-12 23:53:02 -08:00
ownerId: ownerId,
ownerType: ownerType,
active: true
2018-04-05 14:02:56 +02:00
};
post('/api/v1/mail/' + domain + '/mailboxes', data, null, function (error, data, status) {
if (error) return callback(error);
2018-01-24 16:20:21 +01:00
if (status !== 201) return callback(new ClientError(status, data));
2018-01-24 16:20:21 +01:00
callback(null);
});
2018-01-24 16:20:21 +01:00
};
2021-10-08 10:20:17 -07:00
Client.prototype.updateMailbox = function (domain, name, data, callback) {
post('/api/v1/mail/' + domain + '/mailboxes/' + name, data, null, function (error, data, status) {
if (error) return callback(error);
2018-04-05 14:02:56 +02:00
if (status !== 204) return callback(new ClientError(status, data));
2018-04-05 14:02:56 +02:00
callback(null);
});
2018-04-05 14:02:56 +02:00
};
Client.prototype.removeMailbox = function (domain, name, deleteMails, callback) {
var config = {
data: {
deleteMails: deleteMails
},
headers: {
'Content-Type': 'application/json'
}
};
del('/api/v1/mail/' + domain + '/mailboxes/' + name, config, function (error, data, status) {
if (error) return callback(error);
2018-01-24 16:20:21 +01:00
if (status !== 201) return callback(new ClientError(status, data));
2018-01-24 16:20:21 +01:00
callback(null);
});
2018-01-24 16:20:21 +01:00
};
2020-04-20 19:09:25 -07:00
Client.prototype.getAliases = function (name, domain, callback) {
var config = {
params: {
page: 1,
per_page: 1000
}
};
2020-04-20 19:09:25 -07:00
get('/api/v1/mail/' + domain + '/mailboxes/' + name + '/aliases', config, function (error, data, status) {
if (error) return callback(error);
2018-01-25 18:16:47 +01:00
if (status !== 200) return callback(new ClientError(status, data));
2018-01-25 18:16:47 +01:00
callback(null, data.aliases);
});
2018-01-25 18:16:47 +01:00
};
2020-04-20 19:09:25 -07:00
Client.prototype.setAliases = function (name, domain, aliases, callback) {
2018-01-25 18:16:47 +01:00
var data = {
aliases: aliases
};
2020-04-20 19:09:25 -07:00
put('/api/v1/mail/' + domain + '/mailboxes/' + name + '/aliases', data, null, function (error, data, status) {
if (error) return callback(error);
2018-01-26 15:39:02 +01:00
if (status !== 202) return callback(new ClientError(status, data));
2018-01-25 18:16:47 +01:00
callback(null);
});
2018-01-25 18:16:47 +01:00
};
2020-07-05 11:55:17 -07:00
Client.prototype.listMailingLists = function (domain, search, page, perPage, callback) {
var config = {
params: {
2020-07-05 11:55:17 -07:00
search: search,
page: page,
per_page: perPage
}
};
get('/api/v1/mail/' + domain + '/lists', config, function (error, data, status) {
if (error) return callback(error);
2018-04-01 21:58:12 +02:00
if (status !== 200) return callback(new ClientError(status, data));
2018-04-01 21:58:12 +02:00
callback(null, data.lists);
});
2018-04-01 21:58:12 +02:00
};
2018-04-05 14:02:56 +02:00
Client.prototype.getMailingList = function (domain, name, callback) {
get('/api/v1/mail/' + domain + '/lists/' + name, null, function (error, data, status) {
if (error) return callback(error);
2018-01-26 11:31:19 +01:00
if (status !== 200) return callback(new ClientError(status, data));
2018-01-26 11:31:19 +01:00
callback(null, data.list);
});
2018-01-26 11:31:19 +01:00
};
2020-04-17 17:37:19 -07:00
Client.prototype.addMailingList = function (domain, name, members, membersOnly, callback) {
2018-01-26 11:31:19 +01:00
var data = {
2018-04-05 14:02:56 +02:00
name: name,
2020-04-17 17:37:19 -07:00
members: members,
membersOnly: membersOnly,
active: true
2018-01-26 11:31:19 +01:00
};
post('/api/v1/mail/' + domain + '/lists', data, null, function (error, data, status) {
if (error) return callback(error);
2018-01-26 11:31:19 +01:00
if (status !== 201) return callback(new ClientError(status, data));
2018-01-26 11:31:19 +01:00
callback(null);
});
2018-01-26 11:31:19 +01:00
};
Client.prototype.updateMailingList = function (domain, name, members, membersOnly, active, callback) {
2018-04-05 14:02:56 +02:00
var data = {
2020-04-17 17:37:19 -07:00
members: members,
membersOnly: membersOnly,
active: active
2018-04-05 14:02:56 +02:00
};
post('/api/v1/mail/' + domain + '/lists/' + name, data, null, function (error, data, status) {
if (error) return callback(error);
2018-04-05 14:02:56 +02:00
if (status !== 204) return callback(new ClientError(status, data));
2018-04-05 14:02:56 +02:00
callback(null);
});
2018-04-05 14:02:56 +02:00
};
Client.prototype.removeMailingList = function (domain, name, callback) {
del('/api/v1/mail/' + domain + '/lists/' + name, null, function (error, data, status) {
if (error) return callback(error);
2018-01-30 13:38:06 +01:00
if (status !== 204) return callback(new ClientError(status, data));
2018-01-26 11:31:19 +01:00
callback(null);
});
2018-01-26 11:31:19 +01:00
};
2020-10-28 16:14:32 -07:00
// Volumes
Client.prototype.getVolumes = function (callback) {
get('/api/v1/volumes', null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
callback(null, data.volumes);
});
};
Client.prototype.getVolume = function (volume, callback) {
get('/api/v1/volumes/' + volume, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
2021-05-13 15:33:07 -07:00
callback(null, data);
});
};
Client.prototype.getVolumeStatus = function (volume, callback) {
get('/api/v1/volumes/' + volume + '/status', null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
2020-10-28 16:14:32 -07:00
callback(null, data);
});
};
Client.prototype.addVolume = function (name, mountType, hostPath, mountOptions, callback) {
2020-10-28 16:14:32 -07:00
var data = {
name: name,
2021-05-12 21:40:30 -07:00
mountType: mountType,
mountOptions: mountOptions
2020-10-28 16:14:32 -07:00
};
if (hostPath) data.hostPath = hostPath;
2020-10-28 16:14:32 -07:00
var that = this;
post('/api/v1/volumes', data, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 201) return callback(new ClientError(status, data));
2021-05-12 21:40:30 -07:00
callback(null, data.id);
});
};
2021-05-13 09:14:34 -07:00
Client.prototype.updateVolume = function (volumeId, mountType, mountOptions, callback) {
var data = {
mountType: mountType,
mountOptions: mountOptions
};
2021-05-12 21:40:30 -07:00
var that = this;
2021-05-13 09:14:34 -07:00
post('/api/v1/volumes/' + volumeId, data, null, function (error, data, status) {
2021-05-12 21:40:30 -07:00
if (error) return callback(error);
2021-05-13 09:14:34 -07:00
if (status !== 200) return callback(new ClientError(status, data));
2020-10-28 16:14:32 -07:00
callback();
});
};
2021-10-11 15:51:26 +02:00
Client.prototype.remountVolume = function (volumeId, callback) {
var that = this;
post('/api/v1/volumes/' + volumeId + '/remount', {}, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 202) return callback(new ClientError(status, data));
callback();
});
};
2020-10-28 16:14:32 -07:00
Client.prototype.removeVolume = function (volume, callback) {
var config = {
data: {
},
headers: {
'Content-Type': 'application/json'
}
};
del('/api/v1/volumes/' + volume, config, function (error, data, status) {
if (error) return callback(error);
if (status !== 204) return callback(new ClientError(status, data));
callback(null);
});
};
Client.prototype.getAppstoreUserToken = function (callback) {
post('/api/v1/appstore/user_token', {}, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 201) return callback(new ClientError(status, data));
callback(null, data.accessToken);
});
};
// This will change the location
Client.prototype.openSubscriptionSetup = function (subscription) {
// we only allow the owner to do so
if (!this._userInfo.isAtLeastOwner) return;
// basically the user has not setup appstore account yet
if (!subscription.plan) return window.location.href = '/#/appstore';
var that = this;
var email = subscription.emailEncoded;
var cloudronId = subscription.cloudronId;
if (!this._userInfo.isAtLeastOwner) return window.location.href = that.getConfig().webServerOrigin + '/console.html#/userprofile?view=subscriptions&email=' + email + '&cloudronId=' + cloudronId;
this.getAppstoreUserToken(function (error, token) {
if (error) console.error('Unable to get appstore user token.', error);
var url = that.getConfig().webServerOrigin + '/console.html#/userprofile?view=subscriptions&email=' + email + '&token=' + token;
// Only open the subscription setup dialog when no subscription exists
if (!subscription.plan || subscription.plan.id === 'free') url += '&cloudronId=' + cloudronId
window.location.href = url;
});
};
2019-05-04 18:15:33 -07:00
Client.prototype.getAppstoreAppByIdAndVersion = function (appId, version, callback) {
var url = '/api/v1/appstore/apps/' + appId;
if (version && version !== 'latest') url += '/versions/' + version;
get(url, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
callback(null, data);
});
};
Client.prototype._onAppstoreApps = function (callback) {
if (!this._fetchingAppstoreApps) {console.log('not fetching'); callback(); }
else this._fetchingAppstoreAppsListener.push(callback);
};
2019-05-04 18:15:33 -07:00
Client.prototype.getAppstoreApps = function (callback) {
var that = this;
get('/api/v1/appstore/apps', null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
angular.copy(data.apps, that._appstoreAppCache);
return callback(null, that._appstoreAppCache);
});
};
Client.prototype.getAppstoreAppsFast = function (callback) {
2019-05-04 18:15:33 -07:00
if (this._appstoreAppCache.length !== 0) return callback(null, this._appstoreAppCache);
2021-09-23 01:14:55 +02:00
this.getAppstoreApps(callback);
2019-05-04 18:15:33 -07:00
};
2019-05-04 19:22:24 -07:00
Client.prototype.getSubscription = function (callback) {
2019-05-05 13:02:23 -07:00
get('/api/v1/appstore/subscription', null, function (error, data, status) {
2019-05-04 19:22:24 -07:00
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
// just some helper property, since angular bindings cannot dot his easily
data.emailEncoded = encodeURIComponent(data.email);
callback(null, data); // { email, plan: { id, name }, cancel_at, status }
});
};
2021-08-10 13:29:06 -07:00
Client.prototype.registerCloudron = function (email, password, totpToken, signup, callback) {
2019-05-04 19:22:24 -07:00
var data = {
email: email,
password: password,
signup: signup,
2019-05-04 19:22:24 -07:00
};
if (totpToken) data.totpToken = totpToken;
2019-05-05 13:02:23 -07:00
post('/api/v1/appstore/register_cloudron', data, null, function (error, data, status) {
2019-05-04 19:22:24 -07:00
if (error) return callback(error);
if (status !== 201) return callback(new ClientError(status, data));
callback(null);
});
};
2020-07-08 17:30:37 +02:00
// FileManager API
// mode can be 'download', 'open', 'link' or 'data'
function getObjpath(id, type) {
if (type === 'mail') return 'mailserver';
if (type === 'app') return 'apps/' + id;
if (type === 'volume') return 'volumes/' + id;
}
Client.prototype.filesGet = function (id, type, path, mode, callback) {
var objpath = getObjpath(id, type);
if (mode === 'download') {
window.open(client.apiOrigin + '/api/v1/' + objpath + '/files/' + path + '?download=true&access_token=' + token);
callback(null);
} else if (mode === 'open') {
window.open(client.apiOrigin + '/api/v1/' + objpath + '/files/' + path + '?download=false&access_token=' + token);
callback(null);
} else if (mode === 'link') {
callback(null, client.apiOrigin + '/api/v1/' + objpath + '/files/' + path + '?download=false&access_token=' + token);
2020-07-13 17:48:53 +02:00
} else {
function responseHandler(data, headers, status) {
if (headers()['content-type'] && headers()['content-type'].indexOf('application/json') !== -1) return JSON.parse(data);
return data;
}
get('/api/v1/' + objpath + '/files/' + path, { transformResponse: responseHandler }, function (error, data, status) {
2020-07-13 17:48:53 +02:00
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
2020-07-08 17:30:37 +02:00
2020-07-13 17:48:53 +02:00
callback(null, data);
});
}
2020-07-08 17:30:37 +02:00
};
Client.prototype.filesRemove = function (id, type, path, callback) {
var objpath = getObjpath(id, type);
del('/api/v1/' + objpath + '/files/' + path, null, function (error, data, status) {
2020-07-09 11:00:11 +02:00
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
callback(null, data);
});
};
Client.prototype.filesExtract = function (id, type, path, callback) {
var objpath = getObjpath(id, type);
put('/api/v1/' + objpath + '/files/' + path, { action: 'extract' }, {}, function (error, data, status) {
2020-10-19 19:18:47 -07:00
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
callback(null, data);
});
};
Client.prototype.filesChown = function (id, type, path, uid, recursive, callback) {
var objpath = getObjpath(id, type);
put('/api/v1/' + objpath + '/files/' + path, { action: 'chown', uid: uid, recursive: recursive }, {}, function (error, data, status) {
2020-07-13 18:30:29 +02:00
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
callback(null, data);
});
};
Client.prototype.filesRename = function (id, type, path, newPath, callback) {
var objpath = getObjpath(id, type);
put('/api/v1/' + objpath + '/files/' + path, { action: 'rename', newFilePath: decodeURIComponent(newPath) }, {}, function (error, data, status) {
2020-07-09 12:05:14 +02:00
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
2021-02-01 16:45:55 +01:00
callback(null, data);
});
};
Client.prototype.filesCopy = function (id, type, path, newPath, callback) {
var that = this;
var objpath = getObjpath(id, type);
2021-02-01 16:45:55 +01:00
put('/api/v1/' + objpath + '/files/' + path, { action: 'copy', newFilePath: decodeURIComponent(newPath) }, {}, function (error, data, status) {
if (error && error.statusCode === 409) return that.filesCopy(id, type, path, newPath + '-copy', callback);
2021-02-01 16:45:55 +01:00
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
2020-07-09 12:05:14 +02:00
callback(null, data);
});
};
Client.prototype.filesCreateDirectory = function (id, type, path, callback) {
var objpath = getObjpath(id, type);
post('/api/v1/' + objpath + '/files/' + path, { directory: decodeURIComponent(path) }, {}, function (error, data, status) {
2020-07-09 12:05:14 +02:00
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
callback(null, data);
});
};
Client.prototype.filesCreateFile = function (id, type, path, callback) {
var objpath = getObjpath(id, type);
post('/api/v1/' + objpath + '/files/' + path, {}, {}, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
2020-07-09 12:05:14 +02:00
callback(null, data);
});
};
Client.prototype.filesUpload = function (id, type, path, file, overwrite, progressHandler, callback) {
var objpath = getObjpath(id, type);
2020-07-09 12:05:14 +02:00
var fd = new FormData();
fd.append('file', file);
2020-10-22 12:45:05 +02:00
if (overwrite) fd.append('overwrite', 'true');
2020-07-10 19:10:29 +02:00
function done(error, data, status) {
2020-07-09 12:05:14 +02:00
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
callback(null, data);
2020-07-10 19:10:29 +02:00
}
$http({
url: client.apiOrigin + '/api/v1/' + objpath + '/files/' + path,
2020-07-10 19:10:29 +02:00
method: 'POST',
data: fd,
transformRequest: angular.identity,
headers: {
'Content-Type': undefined,
Authorization: 'Bearer ' + token
},
uploadEventHandlers: {
progress: function (e) {
progressHandler(e.loaded);
}
}
}).success(defaultSuccessHandler(done)).error(defaultErrorHandler(done));
2020-07-09 12:05:14 +02:00
};
2021-09-14 12:17:17 +02:00
// ----------------------------------------------
// Eventlog helpers
// ----------------------------------------------
2021-10-19 09:49:53 -07:00
Client.prototype.eventLogDetails = function (eventLog, appIdContext) {
2021-09-14 12:17:17 +02:00
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_IMPORT = 'app.import';
var ACTION_APP_UNINSTALL = 'app.uninstall';
var ACTION_APP_UPDATE = 'app.update';
var ACTION_APP_UPDATE_FINISH = 'app.update.finish';
2021-09-30 11:06:27 -07:00
var ACTION_APP_BACKUP = 'app.backup';
var ACTION_APP_BACKUP_FINISH = 'app.backup.finish';
2021-09-14 12:17:17 +02:00
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';
2021-09-24 10:27:14 -07:00
var ACTION_SERVICE_CONFIGURE = 'service.configure';
var ACTION_SERVICE_REBUILD = 'service.rebuild';
var ACTION_SERVICE_RESTART = 'service.restart';
2021-09-14 12:17:17 +02:00
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_LOGOUT = 'user.logout';
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;
2021-10-19 09:49:53 -07:00
function appName(pre, app, defaultValue) {
if (appIdContext) return defaultValue || '';
pre = pre ? (pre + ' ') : '';
2022-01-16 18:29:32 -08:00
return pre + (app.label || app.fqdn || app.subdomain) + ' (' + app.manifest.title + ') ';
2021-09-14 12:17:17 +02:00
}
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 ' + appName('of', app) + ' was changed';
2021-09-23 09:29:29 -07:00
} else if ('operators' in data) {
return 'Operators ' + appName('of', app) + ' was changed';
2021-09-14 12:17:17 +02:00
} else if (data.label) {
return 'Label ' + appName('of', app) + ' was set to ' + q(data.label);
2021-09-14 12:17:17 +02:00
} else if (data.tags) {
return 'Tags ' + appName('of', app) + ' was set to ' + q(data.tags.join(','));
2021-09-14 12:17:17 +02:00
} else if (data.icon) {
return 'Icon ' + appName('of', app) + ' was changed';
2021-09-14 12:17:17 +02:00
} else if (data.memoryLimit) {
return 'Memory limit ' + appName('of', app) + ' was set to ' + data.memoryLimit;
2021-09-14 12:17:17 +02:00
} else if (data.cpuShares) {
return 'CPU shares ' + appName('of', app) + ' was set to ' + Math.round((data.cpuShares * 100)/1024) + '%';
2021-09-14 12:17:17 +02:00
} else if (data.env) {
return 'Env vars ' + appName('of', app) + ' was changed';
2021-09-14 12:17:17 +02:00
} else if ('debugMode' in data) { // since it can be null
if (data.debugMode) {
2021-10-19 09:49:53 -07:00
return appName('', app, 'App') + ' was placed in repair mode';
2021-09-14 12:17:17 +02:00
} else {
2021-10-19 09:49:53 -07:00
return appName('', app, 'App') + ' was taken out of repair mode';
2021-09-14 12:17:17 +02:00
}
} else if ('enableBackup' in data) {
return 'Automatic backups ' + appName('of', app) + ' were ' + (data.enableBackup ? 'enabled' : 'disabled');
2021-09-14 12:17:17 +02:00
} else if ('enableAutomaticUpdate' in data) {
return 'Automatic updates ' + appName('of', app) + ' were ' + (data.enableAutomaticUpdate ? 'enabled' : 'disabled');
2021-09-14 12:17:17 +02:00
} else if ('reverseProxyConfig' in data) {
return 'Reverse proxy configuration ' + appName('of', app) + ' was updated';
2021-09-14 12:17:17 +02:00
} else if ('cert' in data) {
if (data.cert) {
return 'Custom certificate was set ' + appName('for', app);
2021-09-14 12:17:17 +02:00
} else {
return 'Certificate ' + appName('of', app) + ' was reset';
2021-09-14 12:17:17 +02:00
}
2022-01-16 18:29:32 -08:00
} else if (data.subdomain) {
2021-09-14 12:17:17 +02:00
if (data.fqdn !== data.app.fqdn) {
return 'Location ' + appName('of', app) + ' was changed to ' + data.fqdn;
} else if (!angular.equals(data.redirectDomains, data.app.redirectDomains)) {
var altFqdns = data.redirectDomains.map(function (a) { return a.fqdn; });
return 'Alternate domains ' + appName('of', app) + ' was ' + (altFqdns.length ? 'set to ' + altFqdns.join(', ') : 'reset');
2021-09-14 12:17:17 +02:00
} else if (!angular.equals(data.aliasDomains, data.app.aliasDomains)) {
var aliasDomains = data.aliasDomains.map(function (a) { return a.fqdn; });
return 'Alias domains ' + appName('of', app) + ' was ' + (aliasDomains.length ? 'set to ' + aliasDomains.join(', ') : 'reset');
2021-09-14 12:17:17 +02:00
} else if (!angular.equals(data.portBindings, data.app.portBindings)) {
return 'Port bindings ' + appName('of', app) + ' was changed';
2021-09-14 12:17:17 +02:00
}
} else if ('dataDir' in data) {
if (data.dataDir) {
return 'Data directory ' + appName('of', app) + ' was set ' + data.dataDir;
2021-09-14 12:17:17 +02:00
} else {
return 'Data directory ' + appName('of', app) + ' was reset';
2021-09-14 12:17:17 +02:00
}
} else if ('icon' in data) {
if (data.icon) {
return 'Icon ' + appName('of', app) + ' was set';
2021-09-14 12:17:17 +02:00
} else {
return 'Icon ' + appName('of', app) + ' was reset';
2021-09-14 12:17:17 +02:00
}
} else if (('mailboxName' in data) && data.mailboxName !== data.app.mailboxName) {
if (data.mailboxName) {
return 'Mailbox ' + appName('of', app) + ' was set to ' + q(data.mailboxName);
2021-09-14 12:17:17 +02:00
} else {
return 'Mailbox ' + appName('of', app) + ' was reset';
2021-09-14 12:17:17 +02:00
}
}
2021-10-19 09:49:53 -07:00
return appName('', app, 'App') + 'was re-configured';
2021-09-14 12:17:17 +02:00
}
case ACTION_APP_INSTALL:
if (!data.app) return '';
return data.app.manifest.title + ' (package v' + data.app.manifest.version + ') was installed ' + appName('at', data.app);
2021-09-14 12:17:17 +02:00
case ACTION_APP_RESTORE:
if (!data.app) return '';
2021-10-19 09:49:53 -07:00
details = appName('', data.app, 'App') + ' was restored';
2021-09-14 12:17:17 +02:00
// 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_IMPORT:
if (!data.app) return '';
2021-10-19 09:49:53 -07:00
details = appName('', data.app, 'App') + 'was imported';
2021-09-14 12:17:17 +02:00
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 '';
2021-10-19 09:49:53 -07:00
return appName('', data.app, 'App') + ' (package v' + data.app.manifest.version + ') was uninstalled';
2021-09-14 12:17:17 +02:00
case ACTION_APP_UPDATE:
if (!data.app) return '';
return 'Update ' + appName('of', data.app) + ' started from v' + data.fromManifest.version + ' to v' + data.toManifest.version;
2021-09-14 12:17:17 +02:00
case ACTION_APP_UPDATE_FINISH:
if (!data.app) return '';
2021-10-19 09:49:53 -07:00
return appName('', data.app, 'App') + ' was updated to v' + data.app.manifest.version;
2021-09-14 12:17:17 +02:00
2021-09-30 11:06:27 -07:00
case ACTION_APP_BACKUP:
if (!data.app) return '';
return 'Backup ' + appName('of', data.app) + ' started';
2021-09-30 11:06:27 -07:00
case ACTION_APP_BACKUP_FINISH:
if (!data.app) return '';
if (data.errorMessage) {
return 'Backup ' + appName('of', data.app) + ' failed: ' + data.errorMessage;
2021-09-30 11:06:27 -07:00
} else {
return 'Backup ' + appName('of', data.app) + ' succeeded with backup id ' + data.backupId;
2021-09-30 11:06:27 -07:00
}
2021-09-14 12:17:17 +02:00
case ACTION_APP_CLONE:
2021-10-19 09:49:53 -07:00
if (appIdContext === data.oldAppId) {
return 'App was cloned to ' + data.newApp.fqdn + ' using backup ' + data.backupId;
} else if (appIdContext === data.appId) {
return 'App was cloned from ' + data.oldApp.fqdn + ' using backup ' + data.backupId;
} else {
return appName('', data.newApp, 'App') + ' was cloned ' + appName('from', data.oldApp) + ' using backup ' + data.backupId;
}
2021-09-14 12:17:17 +02:00
case ACTION_APP_REPAIR:
2021-10-19 09:49:53 -07:00
return appName('', data.app, 'App') + ' was re-configured'; // re-configure of email apps is more common?
2021-09-14 12:17:17 +02:00
case ACTION_APP_LOGIN: {
app = this.getCachedAppSync(data.appId);
if (!app) return '';
return 'App ' + app.fqdn + ' logged in';
}
case ACTION_APP_OOM:
if (!data.app) return '';
2021-10-19 09:49:53 -07:00
return appName('', data.app, 'App') + ' ran out of memory';
2021-09-14 12:17:17 +02:00
case ACTION_APP_DOWN:
if (!data.app) return '';
2021-10-19 09:49:53 -07:00
return appName('', data.app, 'App') + ' is down';
2021-09-14 12:17:17 +02:00
case ACTION_APP_UP:
if (!data.app) return '';
2021-10-19 09:49:53 -07:00
return appName('', data.app, 'App') + ' is back online';
2021-09-14 12:17:17 +02:00
case ACTION_APP_START:
if (!data.app) return '';
2021-10-19 09:49:53 -07:00
return appName('', data.app, 'App') + ' was started';
2021-09-14 12:17:17 +02:00
case ACTION_APP_STOP:
if (!data.app) return '';
2021-10-19 09:49:53 -07:00
return appName('', data.app, 'App') + ' was stopped';
2021-09-14 12:17:17 +02:00
case ACTION_APP_RESTART:
if (!data.app) return '';
2021-10-19 09:49:53 -07:00
return appName('', data.app, 'App') + ' was restarted';
2021-09-14 12:17:17 +02:00
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;
2021-09-24 10:27:14 -07:00
case ACTION_SERVICE_CONFIGURE:
return 'Service ' + data.id + ' was configured';
case ACTION_SERVICE_REBUILD:
return 'Service ' + data.id + ' was rebuilt';
case ACTION_SERVICE_RESTART:
return 'Service ' + data.id + ' was restarted';
2021-09-14 12:17:17 +02:00
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_USER_LOGOUT:
return (data.user ? data.user.username : data.userId) + ' logged out';
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;
}
}
Client.prototype.eventLogSource = function (eventLog) {
var source = eventLog.source;
var line = '';
line = source.username || source.userId || source.mailboxId || source.authType || 'system';
if (source.appId) {
var app = this.getCachedAppSync(source.appId);
line += ' - ' + (app ? app.fqdn : source.appId);
} else if (source.ip) {
line += ' - ' + source.ip;
}
return line;
}
2018-01-22 13:01:38 -08:00
client = new Client();
return client;
}]);