4195 lines
157 KiB
JavaScript
4195 lines
157 KiB
JavaScript
'use strict';
|
|
|
|
/* global $, angular, async */
|
|
|
|
// keep in sync with box/src/notfications.js
|
|
const NOTIFICATION_TYPES = {
|
|
CLOUDRON_INSTALLED: 'cloudronInstalled',
|
|
CLOUDRON_UPDATED: 'cloudronUpdated',
|
|
CLOUDRON_UPDATE_FAILED: 'cloudronUpdateFailed',
|
|
CERTIFICATE_RENEWAL_FAILED: 'certificateRenewalFailed',
|
|
BACKUP_CONFIG: 'backupConfig',
|
|
DISK_SPACE: 'diskSpace',
|
|
MAIL_STATUS: 'mailStatus',
|
|
REBOOT: 'reboot',
|
|
BOX_UPDATE: 'boxUpdate',
|
|
UPDATE_UBUNTU: 'ubuntuUpdate',
|
|
MANUAL_APP_UPDATE: 'manualAppUpdate',
|
|
APP_OOM: 'appOutOfMemory',
|
|
APP_UPDATED: 'appUpdated',
|
|
BACKUP_FAILED: 'backupFailed',
|
|
};
|
|
|
|
// 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',
|
|
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_SERVICES_CHANGE: 'pending_services_change',
|
|
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,
|
|
};
|
|
|
|
var ROLES = {
|
|
OWNER: 'owner',
|
|
ADMIN: 'admin',
|
|
MAIL_MANAGER: 'mailmanager',
|
|
USER_MANAGER: 'usermanager',
|
|
USER: 'user'
|
|
};
|
|
|
|
// sync up with tokens.js
|
|
const TOKEN_TYPES = {
|
|
ID_WEBADMIN: 'cid-webadmin', // dashboard
|
|
ID_DEVELOPMENT: 'cid-development', // dashboard development
|
|
ID_CLI: 'cid-cli', // cloudron cli
|
|
ID_SDK: 'cid-sdk', // created by user via dashboard
|
|
};
|
|
|
|
// sync up with tasks.js
|
|
var TASK_TYPES = {
|
|
TASK_APP: 'app',
|
|
TASK_BACKUP: 'backup',
|
|
TASK_UPDATE: 'update',
|
|
TASK_CHECK_CERTS: 'checkCerts',
|
|
TASK_PREPARE_DASHBOARD_LOCATION: 'prepareDashboardLocation',
|
|
TASK_CLEAN_BACKUPS: 'cleanBackups',
|
|
TASK_SYNC_EXTERNAL_LDAP: 'syncExternalLdap',
|
|
TASK_CHANGE_MAIL_LOCATION: 'changeMailLocation',
|
|
TASK_SYNC_DNS_RECORDS: 'syncDnsRecords',
|
|
TASK_UPDATE_DISK_USAGE: 'updateDiskUsage',
|
|
TASK_SYNC_DYNDNS: 'syncDyndns',
|
|
};
|
|
|
|
const APP_TYPES = {
|
|
APP: 'app', //default
|
|
LINK: 'link',
|
|
PROXIED: 'proxied'
|
|
};
|
|
|
|
var SECRET_PLACEHOLDER = String.fromCharCode(0x25CF).repeat(8);
|
|
|
|
// List is from http://docs.aws.amazon.com/general/latest/gr/rande.html#s3_region
|
|
const REGIONS_S3 = [
|
|
{ name: 'Africa (Cape Town)', value: 'af-south-1' },
|
|
{ name: 'Asia Pacific (Hong Kong)', value: 'ap-east-1' },
|
|
{ name: 'Asia Pacific (Hyderabad)', value: 'ap-south-2' },
|
|
{ name: 'Asia Pacific (Jakarta)', value: 'ap-southeast-3' },
|
|
{ name: 'Asia Pacific (Melbourne)', value: 'ap-southeast-4' },
|
|
{ name: 'Asia Pacific (Mumbai)', value: 'ap-south-1' },
|
|
{ name: 'Asia Pacific (Osaka)', value: 'ap-northeast-3' },
|
|
{ name: 'Asia Pacific (Seoul)', value: 'ap-northeast-2' },
|
|
{ name: 'Asia Pacific (Singapore)', value: 'ap-southeast-1' },
|
|
{ name: 'Asia Pacific (Sydney)', value: 'ap-southeast-2' },
|
|
{ name: 'Asia Pacific (Tokyo)', value: 'ap-northeast-1' },
|
|
{ name: 'Canada (Central)', value: 'ca-central-1' },
|
|
{ name: 'China (Beijing)', value: 'cn-north-1' },
|
|
{ name: 'China (Ningxia)', value: 'cn-northwest-1' },
|
|
{ name: 'Middle East (Bahrain)', value: 'me-south-1' },
|
|
{ name: 'Middle East (UAE)', value: 'me-central-1' },
|
|
{ name: 'EU (Frankfurt)', value: 'eu-central-1' },
|
|
{ name: 'EU (Ireland)', value: 'eu-west-1' },
|
|
{ name: 'EU (London)', value: 'eu-west-2' },
|
|
{ name: 'EU (Milan)', value: 'eu-south-1' },
|
|
{ name: 'EU (Paris)', value: 'eu-west-3' },
|
|
{ name: 'EU (Spain)', value: 'eu-south-2' },
|
|
{ name: 'EU (Stockholm)', value: 'eu-north-1' },
|
|
{ name: 'EU (Zurich)', value: 'eu-central-2' },
|
|
{ name: 'South America (São Paulo)', value: 'sa-east-1' },
|
|
{ name: 'US East (N. Virginia)', value: 'us-east-1' },
|
|
{ name: 'US East (Ohio)', value: 'us-east-2' },
|
|
{ name: 'US West (N. California)', value: 'us-west-1' },
|
|
{ name: 'US West (Oregon)', value: 'us-west-2' },
|
|
];
|
|
|
|
// https://wasabi.com/locations/
|
|
const REGIONS_WASABI = [
|
|
{ name: 'Amsterdam (EU Central 1)', value: 'https://s3.eu-central-1.wasabisys.com' },
|
|
{ name: 'Frankfurt (EU Central 2)', value: 'https://s3.eu-central-2.wasabisys.com' },
|
|
{ name: 'London (EU West 1)', value: 'https://s3.eu-west-1.wasabisys.com' },
|
|
{ name: 'Oregon (US West 1)', value: 'https://s3.us-west-1.wasabisys.com' },
|
|
{ name: 'Osaka (AP Northeast 2)', value: 'https://s3.ap-northeast-2.wasabisys.com' },
|
|
{ name: 'Paris (EU West 2)', value: 'https://s3.eu-west-2.wasabisys.com' },
|
|
{ name: 'Plano (US Central 1)', value: 'https://s3.us-central-1.wasabisys.com' },
|
|
{ name: 'Singapore (AP Southeast 1)', value: 'https://s3.ap-southeast-1.wasabisys.com' },
|
|
{ name: 'Sydney (AP Southeast 2)', value: 'https://s3.ap-southeast-2.wasabisys.com' },
|
|
{ name: 'Tokyo (AP Northeast 1)', value: 'https://s3.ap-northeast-1.wasabisys.com' },
|
|
{ name: 'Toronto (CA Central 1)', value: 'https://s3.ca-central-1.wasabisys.com' },
|
|
{ name: 'Virginia (US East 1)', value: 'https://s3.us-east-1.wasabisys.com' },
|
|
{ name: 'Virginia (US East 2)', value: 'https://s3.us-east-2.wasabisys.com' }
|
|
];
|
|
|
|
const REGIONS_HETZNER = [
|
|
{ name: 'Falkenstein (FSN1)', value: 'https://fsn1.your-objectstorage.com' },
|
|
{ name: 'Helsinki (HEL1)', value: 'https://hel1.your-objectstorage.com' },
|
|
{ name: 'Nuremberg (NBG1)', value: 'https://nbg1.your-objectstorage.com' }
|
|
];
|
|
|
|
// https://docs.digitalocean.com/products/platform/availability-matrix/
|
|
const REGIONS_DIGITALOCEAN = [
|
|
{ name: 'AMS3', value: 'https://ams3.digitaloceanspaces.com' },
|
|
{ name: 'FRA1', value: 'https://fra1.digitaloceanspaces.com' },
|
|
{ name: 'LON1', value: 'https://lon1.digitaloceanspaces.com' },
|
|
{ name: 'NYC3', value: 'https://nyc3.digitaloceanspaces.com' },
|
|
{ name: 'SFO2', value: 'https://sfo2.digitaloceanspaces.com' },
|
|
{ name: 'SFO3', value: 'https://sfo3.digitaloceanspaces.com' },
|
|
{ name: 'SGP1', value: 'https://sgp1.digitaloceanspaces.com' },
|
|
{ name: 'SYD1', value: 'https://syd1.digitaloceanspaces.com' }
|
|
];
|
|
|
|
// https://www.exoscale.com/datacenters/
|
|
const REGIONS_EXOSCALE = [
|
|
{ name: 'Vienna (AT-VIE-1)', value: 'https://sos-at-vie-1.exo.io' },
|
|
{ name: 'Vienna (AT-VIE-2)', value: 'https://sos-at-vie-2.exo.io' },
|
|
{ name: 'Sofia (BG-SOF-1)', value: 'https://sos-bg-sof-1.exo.io' },
|
|
{ name: 'Zurich (CH-DK-2)', value: 'https://sos-ch-dk-2.exo.io' },
|
|
{ name: 'Geneva (CH-GVA-2)', value: 'https://sos-ch-gva-2.exo.io' },
|
|
{ name: 'Frankfurt (DE-FRA-1)', value: 'https://sos-de-fra-1.exo.io' },
|
|
{ name: 'Munich (DE-MUC-1)', value: 'https://sos-de-muc-1.exo.io' },
|
|
];
|
|
|
|
// https://www.scaleway.com/docs/object-storage-feature/
|
|
const REGIONS_SCALEWAY = [
|
|
{ name: 'Paris (FR-PAR)', value: 'https://s3.fr-par.scw.cloud', region: 'fr-par' }, // default
|
|
{ name: 'Amsterdam (NL-AMS)', value: 'https://s3.nl-ams.scw.cloud', region: 'nl-ams' },
|
|
{ name: 'Warsaw (PL-WAW)', value: 'https://s3.pl-waw.scw.cloud', region: 'nl-ams' }
|
|
];
|
|
|
|
// https://www.linode.com/docs/products/storage/object-storage/guides/urls/
|
|
const REGIONS_LINODE = [
|
|
{ name: 'Amsterdam', value: 'https://nl-ams-1.linodeobjects.com', region: 'nl-ams-1' },
|
|
{ name: 'Atlanta', value: 'https://us-southeast-1.linodeobjects.com', region: 'us-southeast-1' },
|
|
{ name: 'Chennai', value: 'https://in-maa-1.linodeobjects.com', region: 'in-maa-1' },
|
|
{ name: 'Chicago', value: 'https://us-ord-1.linodeobjects.com', region: 'us-ord-1' },
|
|
{ name: 'Frankfurt', value: 'https://eu-central-1.linodeobjects.com', region: 'eu-central-1' },
|
|
{ name: 'Jakarta', value: 'https://id-cgk-1.linodeobjects.com', region: 'id-cgk-1' },
|
|
{ name: 'Los Angeles, CA (USA)', value: 'https://us-lax-1.linodeobjects.com', region: 'us-lax-1' },
|
|
{ name: 'Miami', value: 'https://us-mia-1.linodeobjects.com', region: 'us-mia-1' },
|
|
{ name: 'Milan', value: 'https://it-mil-1.linodeobjects.com', region: 'it-mil-1' },
|
|
{ name: 'Newark', value: 'https://us-east-1.linodeobjects.com', region: 'us-east-1' }, // default
|
|
{ name: 'Osaka', value: 'https://jp-osa-1.linodeobjects.com', region: 'jp-osa-1' },
|
|
{ name: 'Paris', value: 'https://fr-par-1.linodeobjects.com', region: 'fr-par-1' },
|
|
{ name: 'Sao Paulo', value: 'https://br-gru-1.linodeobjects.com', region: 'br-gru-1' },
|
|
{ name: 'Seattle', value: 'https://us-sea-1.linodeobjects.com', region: 'us-sea-1' },
|
|
{ name: 'Singapore', value: 'https://ap-south-1.linodeobjects.com', region: 'ap-south-1' },
|
|
{ name: 'Stockholm', value: 'https://se-sto-1.linodeobjects.com', region: 'se-sto-1' },
|
|
{ name: 'Washington', value: 'https://us-iad-1.linodeobjects.com', region: 'us-iad-1' },
|
|
];
|
|
|
|
// note: ovh also has a storage endpoint but that only supports path style access (https://docs.ovh.com/au/en/storage/object-storage/s3/location/)
|
|
const REGIONS_OVH = [
|
|
{ name: 'Beauharnois (BHS)', value: 'https://s3.bhs.io.cloud.ovh.net', region: 'bhs' }, // default
|
|
{ name: 'Frankfurt (DE)', value: 'https://s3.de.io.cloud.ovh.net', region: 'de' },
|
|
{ name: 'Gravelines (GRA)', value: 'https://s3.gra.io.cloud.ovh.net', region: 'gra' },
|
|
{ name: 'Roubaix (RBX)', value: 'https://s3.rbx.io.cloud.ovh.net', region: 'rbx' },
|
|
{ name: 'Strasbourg (SBG)', value: 'https://s3.sbg.io.cloud.ovh.net', region: 'sbg' },
|
|
{ name: 'London (UK)', value: 'https://s3.uk.io.cloud.ovh.net', region: 'uk' },
|
|
{ name: 'Sydney (SYD)', value: 'https://s3.syd.io.cloud.ovh.net', region: 'syd' },
|
|
{ name: 'Warsaw (WAW)', value: 'https://s3.waw.io.cloud.ovh.net', region: 'waw' },
|
|
];
|
|
|
|
const ENDPOINTS_OVH = [
|
|
{ name: 'OVH Europe', value: 'ovh-eu' },
|
|
{ name: 'OVH US', value: 'ovh-us' },
|
|
{ name: 'OVH North-America', value: 'ovh-ca' },
|
|
{ name: 'SoYouStart Europe', value: 'soyoustart-eu' },
|
|
{ name: 'SoYouStart North-America', value: 'soyoustart-ca' },
|
|
{ name: 'Kimsufi Europe', value: 'kimsufi-eu' },
|
|
{ name: 'Kimsufi North-America', value: 'kimsufi-ca' },
|
|
];
|
|
|
|
// https://docs.ionos.com/cloud/managed-services/s3-object-storage/endpoints
|
|
const REGIONS_IONOS = [
|
|
{ name: 'Berlin (eu-central-3)', value: 'https://s3.eu-central-3.ionoscloud.com', region: 'de' }, // default. contract-owned
|
|
{ name: 'Frankfurt (DE)', value: 'https://s3.eu-central-1.ionoscloud.com', region: 'de' },
|
|
{ name: 'Berlin (eu-central-2)', value: 'https://s3-eu-central-2.ionoscloud.com', region: 'eu-central-2' },
|
|
{ name: 'Logrono (eu-south-2)', value: 'https://s3-eu-south-2.ionoscloud.com', region: 'eu-south-2' },
|
|
];
|
|
|
|
// this is not used anywhere because upcloud needs endpoint URL. we detect region from the URL (https://upcloud.com/data-centres)
|
|
const REGIONS_UPCLOUD = [
|
|
{ name: 'AU-SYD1 (Australia)', value: 'https://au-syd1.upcloudobjects.com', region: 'au-syd1' }, // default
|
|
{ name: 'DE-FRA1 (Germany)', value: 'https://de-fra1.upcloudobjects.com', region: 'de-fra1' },
|
|
{ name: 'ES-MAD1 (Spain)', value: 'https://es-mad1.upcloudobjects.com', region: 'es-mad1' },
|
|
{ name: 'FI-HEL2 (Finland)', value: 'https://fi-hel2.upcloudobjects.com', region: 'fi-hel2' },
|
|
{ name: 'NL-AMS1 (Netherlands)', value: 'https://nl-ams1.upcloudobjects.com', region: 'nl-ams1' },
|
|
{ name: 'PL-WAW1 (Poland)', value: 'https://pl-waw1.upcloudobjects.com', region: 'pl-waw1' },
|
|
{ name: 'SG-SIN1 (Singapore)', value: 'https://sg-sin1.upcloudobjects.com', region: 'sg-sin1' },
|
|
{ name: 'UK-LON1 (United Kingdom)', value: 'https://uk-lon1.upcloudobjects.com', region: 'uk-lon1' },
|
|
{ name: 'US-CHI1 (USA)', value: 'https://us-chi1.upcloudobjects.com', region: 'us-chi1' },
|
|
{ name: 'US-NYC1 (USA)', value: 'https://us-nyc1.upcloudobjects.com', region: 'us-nyc1' },
|
|
{ name: 'US-SJO1 (USA)', value: 'https://us-sjo1.upcloudobjects.com', region: 'us-sjo1' },
|
|
];
|
|
|
|
// region is ignored in vultr (https://www.vultr.com/docs/vultr-object-storage/)
|
|
const REGIONS_VULTR = [
|
|
{ name: 'Amsterdam', value: 'https://ams1.vultrobjects.com', region: 'eu-central-1' },
|
|
{ name: 'Bangalore', value: 'https://blr1.vultrobjects.com', region: 'ap-south-1' },
|
|
{ name: 'New Jersey', value: 'https://ewr1.vultrobjects.com', region: 'us-east-1' },
|
|
{ name: 'Silicon Valley', value: 'https://sjc1.vultrobjects.com', region: 'us-west-1' },
|
|
{ name: 'Singapore', value: 'https://sgp1.vultrobjects.com', region: 'ap-southeast-1' },
|
|
];
|
|
|
|
// https://docs.contabo.com/docs/products/Object-Storage/s3-connection-settings
|
|
const REGIONS_CONTABO = [
|
|
{ name: 'European Union (Germany)', value: 'https://eu2.contabostorage.com' , region: 'us-east-1' },
|
|
{ name: 'Singapore', value: 'https://sin1.contabostorage.com' , region: 'us-east-1' },
|
|
{ name: 'United States', value: 'https://usc1.contabostorage.com' , region: 'us-east-1' }
|
|
];
|
|
|
|
const STORAGE_PROVIDERS = [
|
|
{ name: 'Amazon S3', value: 's3' },
|
|
{ name: 'Backblaze B2 (S3 API)', value: 'backblaze-b2' },
|
|
{ name: 'CIFS Mount', value: 'cifs' },
|
|
{ name: 'Cloudflare R2', value: 'cloudflare-r2' },
|
|
{ name: 'Contabo Object Storage', value: 'contabo-objectstorage' },
|
|
{ name: 'DigitalOcean Spaces', value: 'digitalocean-spaces' },
|
|
{ name: 'External/Local Disk (EXT4 or XFS)', value: 'disk' },
|
|
{ name: 'EXT4 Disk', value: 'ext4' },
|
|
{ name: 'Exoscale SOS', value: 'exoscale-sos' },
|
|
{ name: 'Filesystem', value: 'filesystem' },
|
|
{ name: 'Filesystem (Mountpoint)', value: 'mountpoint' }, // legacy
|
|
{ name: 'Google Cloud Storage', value: 'gcs' },
|
|
{ name: 'Hetzner Object Storage', value: 'hetzner-objectstorage' },
|
|
{ name: 'IDrive e2', value: 'idrive-e2' },
|
|
{ name: 'IONOS (Profitbricks)', value: 'ionos-objectstorage' },
|
|
{ name: 'Linode Object Storage', value: 'linode-objectstorage' },
|
|
{ name: 'Minio', value: 'minio' },
|
|
{ name: 'NFS Mount', value: 'nfs' },
|
|
{ name: 'OVH Object Storage', value: 'ovh-objectstorage' },
|
|
{ name: 'S3 API Compatible (v4)', value: 's3-v4-compat' },
|
|
{ name: 'Scaleway Object Storage', value: 'scaleway-objectstorage' },
|
|
{ name: 'SSHFS Mount', value: 'sshfs' },
|
|
{ name: 'UpCloud Object Storage', value: 'upcloud-objectstorage' },
|
|
{ name: 'Vultr Object Storage', value: 'vultr-objectstorage' },
|
|
{ name: 'Wasabi', value: 'wasabi' },
|
|
{ name: 'XFS Disk', value: 'xfs' },
|
|
];
|
|
|
|
const BACKUP_FORMATS = [
|
|
{ name: 'Tarball (zipped)', value: 'tgz' },
|
|
{ name: 'rsync', value: 'rsync' }
|
|
];
|
|
|
|
// ----------------------------------------------
|
|
// Helper to ensure loading a fallback app icon on first load failure
|
|
// ----------------------------------------------
|
|
function imageErrorHandler(elem) {
|
|
elem.src = elem.getAttribute('fallback-icon');
|
|
}
|
|
|
|
// ----------------------------------------------
|
|
// Shared Angular Filters
|
|
// ----------------------------------------------
|
|
|
|
// https://en.wikipedia.org/wiki/Binary_prefix
|
|
// binary units (IEC) 1024 based
|
|
function prettyBinarySize(size, fallback) {
|
|
if (!size) return fallback || 0;
|
|
if (size === -1) return 'Unlimited';
|
|
|
|
// we can also use KB here (JEDEC)
|
|
var i = Math.floor(Math.log(size) / Math.log(1024));
|
|
return (size / Math.pow(1024, i)).toFixed(3) * 1 + ' ' + ['B', 'KiB', 'MiB', 'GiB', 'TiB'][i];
|
|
}
|
|
|
|
// decimal units (SI) 1000 based
|
|
function prettyDecimalSize(size, fallback) {
|
|
if (!size) return fallback || 0;
|
|
|
|
var i = Math.floor(Math.log(size) / Math.log(1000));
|
|
return (size / Math.pow(1000, i)).toFixed(2) * 1 + ' ' + ['B', 'kB', 'MB', 'GB', 'TB'][i];
|
|
}
|
|
|
|
angular.module('Application').filter('prettyDecimalSize', function () {
|
|
return function (size, fallback) { return prettyDecimalSize(size, fallback) || '0 kb'; };
|
|
});
|
|
|
|
angular.module('Application').filter('prettyBinarySize', function () {
|
|
return function (size, fallback) { return prettyBinarySize(size, fallback) || '0 KiB'; };
|
|
});
|
|
|
|
angular.module('Application').filter('prettyDiskSize', function () {
|
|
return function (size, fallback) { return prettyDecimalSize(size, fallback) || 'Not available yet'; };
|
|
});
|
|
|
|
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 '';
|
|
};
|
|
});
|
|
|
|
angular.module('Application').filter('prettyDate', function ($translate) {
|
|
// http://ejohn.org/files/pretty.js
|
|
return function prettyDate(utc) {
|
|
if (utc === null) return $translate.instant('main.prettyDate.never', {});
|
|
|
|
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);
|
|
|
|
if (isNaN(day_diff) || day_diff < 0) return $translate.instant('main.prettyDate.justNow', {});
|
|
|
|
return day_diff === 0 && (diff < 60 && $translate.instant('main.prettyDate.justNow', {}) ||
|
|
moment(utc).locale(navigator.language).format('LT')) ||
|
|
day_diff === 1 && $translate.instant('main.prettyDate.yeserday', {}) ||
|
|
moment(utc).locale(navigator.language).format('L');
|
|
};
|
|
});
|
|
|
|
angular.module('Application').filter('prettyFutureDate', function () {
|
|
return function prettyFutureDate(utc) {
|
|
return moment(utc).fromNow(); // this converts utc into browser timezone and not cloudron timezone!
|
|
};
|
|
});
|
|
|
|
angular.module('Application').filter('prettyLongDate', function () {
|
|
return function prettyLongDate(utc) {
|
|
return moment(utc).locale(navigator.language).format('LLL'); // this converts utc into browser timezone and not cloudron timezone!
|
|
};
|
|
});
|
|
|
|
angular.module('Application').filter('prettyShortDate', function () {
|
|
return function prettyShortDate(utc) {
|
|
return moment(utc).locale(navigator.language).format('L'); // 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'
|
|
});
|
|
$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);
|
|
|
|
// checks provision status and redirects to correct view
|
|
// {
|
|
// setup: { active, message, errorMessage }
|
|
// restore { active, message, errorMessage }
|
|
// activated
|
|
// adminFqn
|
|
// }
|
|
// returns true if redirected . currentView is one of dashboard/restore/setup/activation
|
|
function redirectIfNeeded(status, currentView) {
|
|
var search = decodeURIComponent(window.location.search).slice(1).split('&').map(function (item) { return item.split('='); }).reduce(function (o, k) { o[k[0]] = k[1]; return o; }, {});
|
|
|
|
if ('develop' in search || localStorage.getItem('develop')) {
|
|
console.warn('Cloudron develop mode on. To disable run localStorage.removeItem(\'develop\')');
|
|
localStorage.setItem('develop', true);
|
|
return false;
|
|
}
|
|
|
|
if (status.activated) {
|
|
console.log('Already activated');
|
|
if (currentView === 'dashboard') {
|
|
// support local development with localhost check
|
|
if (window.location.hostname !== status.adminFqdn && window.location.hostname !== 'localhost' && !window.location.hostname.startsWith('192.')) {
|
|
// user is accessing by IP or by the old admin location (pre-migration)
|
|
window.location.href = '/setup.html' + window.location.search;
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
window.location.href = 'https://' + status.adminFqdn + '/';
|
|
return true;
|
|
}
|
|
|
|
if (status.setup.active) {
|
|
console.log('Setup is active');
|
|
if (currentView === 'setup') return false;
|
|
window.location.href = '/setup.html' + window.location.search;
|
|
return true;
|
|
}
|
|
|
|
if (status.restore.active) {
|
|
console.log('Restore is active');
|
|
if (currentView === 'restore') return;
|
|
window.location.href = '/restore.html' + window.location.search;
|
|
return true;
|
|
}
|
|
|
|
if (status.adminFqdn) {
|
|
console.log('adminFqdn is set');
|
|
// if we are here from https://ip/activation.html ,go to https://admin/activation.html
|
|
if (status.adminFqdn !== window.location.hostname) {
|
|
window.location.href = 'https://' + status.adminFqdn + '/activation.html' + (window.location.search);
|
|
return true;
|
|
}
|
|
if (currentView === 'activation') return false;
|
|
window.location.href = 'https://' + status.adminFqdn + '/activation.html' + (window.location.search);
|
|
return true;
|
|
}
|
|
|
|
if (currentView === 'dashboard') {
|
|
window.location.href = '/setup.html' + window.location.search;
|
|
return true;
|
|
}
|
|
|
|
// if we are here, proceed with current view
|
|
return false;
|
|
}
|
|
|
|
// ----------------------------------------------
|
|
// Cloudron REST API wrapper
|
|
// ----------------------------------------------
|
|
|
|
angular.module('Application').service('Client', ['$http', '$interval', '$timeout', 'md5', 'Notification', '$translate', function ($http, $interval, $timeout, md5, Notification, $translate) {
|
|
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
|
|
}
|
|
}
|
|
|
|
function defaultErrorHandler(callback) {
|
|
function handleServerOffline() {
|
|
if (client.offline) return;
|
|
|
|
(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) {
|
|
client.offline = true;
|
|
$timeout(onlineCheck, 5000);
|
|
});
|
|
})();
|
|
}
|
|
|
|
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();
|
|
return callback(new ClientError(status, data));
|
|
}
|
|
|
|
var obj = data;
|
|
try {
|
|
obj = JSON.parse(data);
|
|
} catch (e) {}
|
|
|
|
callback(new ClientError(status, obj));
|
|
};
|
|
}
|
|
|
|
function defaultSuccessHandler(callback) {
|
|
return function (data, status) {
|
|
return callback(null, data, status);
|
|
};
|
|
}
|
|
|
|
// 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');
|
|
}
|
|
|
|
config = config || {};
|
|
config.headers = config.headers || {};
|
|
config.headers.Authorization = 'Bearer ' + token;
|
|
|
|
return $http.get(client.apiOrigin + url, config)
|
|
.success(defaultSuccessHandler(callback))
|
|
.error(defaultErrorHandler(callback));
|
|
}
|
|
|
|
function post(url, data, config, callback) {
|
|
if (arguments.length !== 4) {
|
|
console.error('POST', arguments);
|
|
throw('Wrong number of arguments');
|
|
}
|
|
|
|
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));
|
|
}
|
|
|
|
function put(url, data, config, callback) {
|
|
if (arguments.length !== 4) {
|
|
console.error('PUT', arguments);
|
|
throw('Wrong number of arguments');
|
|
}
|
|
|
|
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));
|
|
}
|
|
|
|
function del(url, config, callback) {
|
|
if (arguments.length !== 3) {
|
|
console.error('DEL', arguments);
|
|
throw('Wrong number of arguments');
|
|
}
|
|
|
|
config = config || {};
|
|
config.headers = config.headers || {};
|
|
config.headers.Authorization = 'Bearer ' + token;
|
|
|
|
return $http.delete(client.apiOrigin + url, config)
|
|
.success(defaultSuccessHandler(callback))
|
|
.error(defaultErrorHandler(callback));
|
|
}
|
|
|
|
function Client() {
|
|
this.offline = false;
|
|
this._ready = false;
|
|
this._configListener = [];
|
|
this._readyListener = [];
|
|
this._reconnectListener = [];
|
|
this._userInfo = {
|
|
id: null,
|
|
username: null,
|
|
email: null,
|
|
twoFactorAuthenticationEnabled: false,
|
|
source: null,
|
|
avatarUrl: null,
|
|
avatarType: null,
|
|
hasBackgroundImage: false,
|
|
notificationConfig: []
|
|
};
|
|
this._config = {
|
|
consoleServerOrigin: null,
|
|
fqdn: null,
|
|
ip: null,
|
|
revision: null,
|
|
update: { box: null, apps: null },
|
|
progress: {},
|
|
region: null,
|
|
size: null
|
|
};
|
|
this._installedApps = [];
|
|
this._installedAppsById = {};
|
|
this._appTags = [];
|
|
// window.location fallback for websocket connections which do not have relative uris
|
|
this.apiOrigin = window.cloudronApiOrigin || window.location.origin;
|
|
this.avatar = '';
|
|
this.background = '';
|
|
this._availableLanguages = ['en'];
|
|
this._appstoreAppCache = [];
|
|
|
|
this.resetAvatar();
|
|
|
|
this.setToken(localStorage.token);
|
|
}
|
|
|
|
Client.prototype.error = function (error, action) {
|
|
var message = '';
|
|
|
|
console.error(error);
|
|
|
|
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') {
|
|
message = 'Got empty response. Click to check the server logs.';
|
|
action = action || '/logs.html?id=box';
|
|
}
|
|
|
|
this.notify('Cloudron Error', message, true, 'error', action);
|
|
};
|
|
|
|
// 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();
|
|
};
|
|
|
|
/*
|
|
|
|
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
|
|
|
|
*/
|
|
Client.prototype.notify = function (title, message, persistent, type, action) {
|
|
var options = { title: title, message: message};
|
|
|
|
if (persistent) options.delay = 'never'; // any non Number means never timeout
|
|
|
|
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);
|
|
};
|
|
}
|
|
|
|
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) callback(this._config);
|
|
};
|
|
|
|
Client.prototype.onReconnect = function (callback) {
|
|
if (this._ready) callback();
|
|
else this._reconnectListener.push(callback);
|
|
};
|
|
|
|
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;
|
|
this._userInfo.twoFactorAuthenticationEnabled = userInfo.twoFactorAuthenticationEnabled;
|
|
this._userInfo.role = userInfo.role;
|
|
this._userInfo.source = userInfo.source;
|
|
this._userInfo.avatarUrl = userInfo.avatarUrl + '?ts=' + Date.now(); // we add the timestamp to avoid caching
|
|
this._userInfo.avatarType = userInfo.avatarType;
|
|
this._userInfo.hasBackgroundImage = userInfo.hasBackgroundImage;
|
|
this._userInfo.notificationConfig = userInfo.notificationConfig;
|
|
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;
|
|
};
|
|
|
|
Client.prototype.setConfig = function (config) {
|
|
var that = this;
|
|
|
|
angular.copy(config, this._config);
|
|
|
|
// <% if (appstore.consoleOrigin) { -%>
|
|
// this._config.consoleServerOrigin = '<%= appstore.consoleOrigin %>';
|
|
// <% } -%>
|
|
|
|
this._configListener.forEach(function (callback) {
|
|
callback(that._config);
|
|
});
|
|
};
|
|
|
|
Client.prototype.getInstalledApps = function () {
|
|
return this._installedApps;
|
|
};
|
|
|
|
Client.prototype.getInstalledAppsByAppId = function () {
|
|
return this._installedAppsById;
|
|
};
|
|
|
|
Client.prototype.getAppTags = function () {
|
|
return this._appTags;
|
|
};
|
|
|
|
Client.prototype.getUserInfo = function () {
|
|
return this._userInfo;
|
|
};
|
|
|
|
Client.prototype.getConfig = function () {
|
|
return this._config;
|
|
};
|
|
|
|
Client.prototype.getAvailableLanguages = function () {
|
|
return this._availableLanguages;
|
|
};
|
|
|
|
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;
|
|
};
|
|
|
|
/*
|
|
* Rest API wrappers
|
|
*/
|
|
Client.prototype.config = function (callback) {
|
|
get('/api/v1/dashboard/config', null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 200 || typeof data !== 'object') return callback(new ClientError(status, data));
|
|
callback(null, data);
|
|
});
|
|
};
|
|
|
|
Client.prototype.getProfile = function (callback) {
|
|
get('/api/v1/profile', null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 200 || typeof data !== 'object') return callback(new ClientError(status, data));
|
|
callback(null, data);
|
|
});
|
|
};
|
|
|
|
Client.prototype.hasCloudronBackground = function (callback) {
|
|
get('/api/v1/branding/cloudron_background', null, function (error, data, status) {
|
|
if (error && error.statusCode !== 404) callback(error);
|
|
else if (error) callback(null, false);
|
|
else callback(null, status === 200);
|
|
});
|
|
};
|
|
|
|
Client.prototype.changeCloudronBackground = function (background, callback) {
|
|
var fd = new FormData();
|
|
if (background) fd.append('background', background);
|
|
|
|
var config = {
|
|
headers: { 'Content-Type': undefined },
|
|
transformRequest: angular.identity
|
|
};
|
|
|
|
post('/api/v1/branding/cloudron_background', fd, config, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 202) return callback(new ClientError(status, data));
|
|
|
|
callback(null);
|
|
});
|
|
};
|
|
|
|
Client.prototype.changeCloudronAvatar = function (avatarFile, callback) {
|
|
var fd = new FormData();
|
|
fd.append('avatar', avatarFile);
|
|
|
|
var config = {
|
|
headers: { 'Content-Type': undefined },
|
|
transformRequest: angular.identity
|
|
};
|
|
|
|
post('/api/v1/branding/cloudron_avatar', fd, config, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 200) return callback(new ClientError(status, data));
|
|
callback(null);
|
|
});
|
|
};
|
|
|
|
Client.prototype.changeCloudronName = function (name, callback) {
|
|
var data = {
|
|
name: name
|
|
};
|
|
|
|
post('/api/v1/branding/cloudron_name', data, null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 200) return callback(new ClientError(status, data));
|
|
callback(null);
|
|
});
|
|
};
|
|
|
|
Client.prototype.installApp = function (id, manifest, config, callback) {
|
|
var data = {
|
|
appStoreId: id + '@' + manifest.version,
|
|
subdomain: config.subdomain,
|
|
domain: config.domain,
|
|
secondaryDomains: config.secondaryDomains,
|
|
ports: config.ports,
|
|
accessRestriction: config.accessRestriction,
|
|
cert: config.cert,
|
|
key: config.key,
|
|
sso: config.sso,
|
|
overwriteDns: config.overwriteDns,
|
|
upstreamUri: config.upstreamUri,
|
|
backupId: config.backupId // when restoring from archive
|
|
};
|
|
|
|
post('/api/v1/apps', data, null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 202) return callback(new ClientError(status, data));
|
|
|
|
callback(null, data.id);
|
|
});
|
|
};
|
|
|
|
Client.prototype.cloneApp = function (appId, config, callback) {
|
|
var data = {
|
|
subdomain: config.subdomain,
|
|
domain: config.domain,
|
|
secondaryDomains: config.secondaryDomains,
|
|
ports: config.ports,
|
|
backupId: config.backupId,
|
|
overwriteDns: !!config.overwriteDns
|
|
};
|
|
|
|
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));
|
|
|
|
callback(null, data);
|
|
});
|
|
};
|
|
|
|
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);
|
|
if (status !== 202) return callback(new ClientError(status, data));
|
|
|
|
callback(null);
|
|
});
|
|
};
|
|
|
|
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.archiveApp = function (appId, backupId, callback) {
|
|
var data = { backupId: backupId };
|
|
|
|
post('/api/v1/apps/' + appId + '/archive', 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);
|
|
if (status !== 202) return callback(new ClientError(status, data));
|
|
|
|
callback(null);
|
|
});
|
|
};
|
|
|
|
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) {
|
|
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);
|
|
});
|
|
};
|
|
|
|
Client.prototype.editAppBackup = function (id, backupId, label, preserveSecs, callback) {
|
|
post('/api/v1/apps/' + id + '/backups/' + backupId, { label: label, preserveSecs: preserveSecs }, null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 200) return callback(new ClientError(status, data));
|
|
|
|
callback(null);
|
|
});
|
|
};
|
|
|
|
Client.prototype.ackAppChecklistItem = function (appId, key, acknowledged, callback) {
|
|
put('/api/v1/apps/' + appId + '/checklist/' + key, { done: acknowledged }, null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 202) return callback(new ClientError(status, data));
|
|
|
|
callback(null);
|
|
});
|
|
};
|
|
|
|
Client.prototype.updateApp = function (id, manifest, options, callback) {
|
|
var data = {
|
|
appStoreId: manifest.id + '@' + manifest.version,
|
|
skipBackup: !!options.skipBackup
|
|
};
|
|
|
|
post('/api/v1/apps/' + id + '/update', data, null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 202) return callback(new ClientError(status, data));
|
|
|
|
callback(null, data);
|
|
});
|
|
};
|
|
|
|
Client.prototype.startApp = function (id, callback) {
|
|
post('/api/v1/apps/' + id + '/start', {}, null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 202) return callback(new ClientError(status, data));
|
|
|
|
callback(null, data);
|
|
});
|
|
};
|
|
|
|
Client.prototype.stopApp = function (id, callback) {
|
|
post('/api/v1/apps/' + id + '/stop', {}, null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 202) return callback(new ClientError(status, data));
|
|
|
|
callback(null, data);
|
|
});
|
|
};
|
|
|
|
Client.prototype.restartApp = function (id, callback) {
|
|
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);
|
|
});
|
|
};
|
|
|
|
Client.prototype.debugApp = function (id, state, callback) {
|
|
var data = {
|
|
debugMode: state ? {
|
|
readonlyRootfs: false,
|
|
cmd: [ '/bin/bash', '-c', 'echo "Repair mode. Use the webterminal or cloudron exec to repair. Sleeping" && sleep infinity' ]
|
|
} : null
|
|
};
|
|
|
|
post('/api/v1/apps/' + id + '/configure/debug_mode', data, null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 202) return callback(new ClientError(status, data));
|
|
|
|
callback(null);
|
|
});
|
|
};
|
|
|
|
Client.prototype.getProvisionStatus = function (callback) {
|
|
get('/api/v1/provision/status', null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 200 || typeof data !== 'object') return callback(new ClientError(status, data));
|
|
callback(null, data);
|
|
});
|
|
};
|
|
|
|
Client.prototype.getStatus = function (callback) {
|
|
get('/api/v1/cloudron/status', null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 200 || typeof data !== 'object') return callback(new ClientError(status, data));
|
|
callback(null, data);
|
|
});
|
|
};
|
|
|
|
Client.prototype.getPlatformStatus = function (callback) {
|
|
get('/api/v1/services/platform_status', null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 200 || typeof data !== 'object') return callback(new ClientError(status, data));
|
|
callback(null, data);
|
|
});
|
|
};
|
|
|
|
Client.prototype.setBackupConfig = function (backupConfig, callback) {
|
|
const storageConfig = Object.assign({}, backupConfig);
|
|
delete storageConfig.limits;
|
|
|
|
post('/api/v1/backups/config/storage', storageConfig, null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 200) return callback(new ClientError(status, data));
|
|
|
|
post('/api/v1/backups/config/limits', backupConfig.limits, null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 200) return callback(new ClientError(status, data));
|
|
|
|
callback(null);
|
|
});
|
|
});
|
|
};
|
|
|
|
Client.prototype.getBackupConfig = function (callback) {
|
|
get('/api/v1/backups/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.setBackupPolicy = function (backupPolicy, callback) {
|
|
post('/api/v1/backups/policy', backupPolicy, null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 200) return callback(new ClientError(status, data));
|
|
|
|
callback(null);
|
|
});
|
|
};
|
|
|
|
Client.prototype.getBackupPolicy = function (callback) {
|
|
get('/api/v1/backups/policy', null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 200) return callback(new ClientError(status, data));
|
|
|
|
callback(null, data.policy);
|
|
});
|
|
};
|
|
|
|
Client.prototype.getBackupMountStatus = function (callback) {
|
|
get('/api/v1/backups/mount_status', 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);
|
|
});
|
|
};
|
|
|
|
Client.prototype.setExternalLdapConfig = function (config, callback) {
|
|
post('/api/v1/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/external_ldap/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.setProfileConfig = function (config, callback) {
|
|
post('/api/v1/user_directory/profile_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.getProfileConfig = function (callback) {
|
|
get('/api/v1/user_directory/profile_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.setUserDirectoryConfig = function (config, callback) {
|
|
post('/api/v1/directory_server/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/directory_server/config', null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 200) return callback(new ClientError(status, data));
|
|
|
|
callback(null, data);
|
|
});
|
|
};
|
|
|
|
// network
|
|
Client.prototype.setIPv4Config = function (config, callback) {
|
|
post('/api/v1/network/ipv4_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.getIPv4Config = function (callback) {
|
|
get('/api/v1/network/ipv4_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.getServerIpv4 = function (callback) {
|
|
get('/api/v1/network/ipv4', null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 200) return callback(new ClientError(status, data));
|
|
|
|
callback(null, data);
|
|
});
|
|
};
|
|
|
|
Client.prototype.getServerIpv6 = function (callback) {
|
|
get('/api/v1/network/ipv6', null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 200) return callback(new ClientError(status, data));
|
|
|
|
callback(null, data);
|
|
});
|
|
};
|
|
|
|
Client.prototype.getBlocklist = function (callback) {
|
|
get('/api/v1/network/blocklist', null, 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);
|
|
});
|
|
};
|
|
|
|
Client.prototype.getTrustedIps = function (callback) {
|
|
get('/api/v1/reverseproxy/trusted_ips', null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 200) return callback(new ClientError(status, data));
|
|
callback(null, data.trustedIps);
|
|
});
|
|
};
|
|
|
|
Client.prototype.setTrustedIps = function (trustedIps, callback) {
|
|
post('/api/v1/reverseproxy/trusted_ips', { trustedIps: trustedIps }, null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 200) return callback(new ClientError(status, data));
|
|
|
|
callback(null);
|
|
});
|
|
};
|
|
|
|
Client.prototype.setDynamicDnsConfig = function (enabled, callback) {
|
|
post('/api/v1/network/dynamic_dns', { 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.getDynamicDnsConfig = function (callback) {
|
|
get('/api/v1/network/dynamic_dns', null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 200) return callback(new ClientError(status, data));
|
|
|
|
callback(null, data.enabled);
|
|
});
|
|
};
|
|
|
|
Client.prototype.setIPv6Config = function (config, callback) {
|
|
post('/api/v1/network/ipv6_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.getIPv6Config = function (callback) {
|
|
get('/api/v1/network/ipv6_config', null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 200) return callback(new ClientError(status, data));
|
|
|
|
callback(null, data);
|
|
});
|
|
};
|
|
|
|
// branding
|
|
Client.prototype.setFooter = function (footer, callback) {
|
|
post('/api/v1/branding/footer', { footer: footer }, null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 200) return callback(new ClientError(status, data));
|
|
|
|
callback(null);
|
|
});
|
|
};
|
|
|
|
Client.prototype.getFooter = function (callback) {
|
|
get('/api/v1/branding/footer', null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 200) return callback(new ClientError(status, data));
|
|
|
|
callback(null, data.footer);
|
|
});
|
|
};
|
|
|
|
Client.prototype.setRegistryConfig = function (rc, callback) {
|
|
post('/api/v1/docker/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/docker/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) {
|
|
get('/api/v1/updater/updates', null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 200) return callback(new ClientError(status, data));
|
|
|
|
callback(null, data);
|
|
});
|
|
};
|
|
|
|
Client.prototype.checkForUpdates = function (callback) {
|
|
post('/api/v1/updater/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.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/updater/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/updater/autoupdate_pattern', null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 200) return callback(new ClientError(status, data));
|
|
|
|
callback(null, data);
|
|
});
|
|
};
|
|
|
|
Client.prototype.setTimeZone = function (timeZone, callback) {
|
|
post('/api/v1/cloudron/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/cloudron/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);
|
|
});
|
|
};
|
|
|
|
Client.prototype.setLanguage = function (language, callback) {
|
|
post('/api/v1/cloudron/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/cloudron/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);
|
|
});
|
|
};
|
|
|
|
Client.prototype.enableRemoteSupport = function (enable, callback) {
|
|
post('/api/v1/support/remote_support', { enable: enable }, null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 202) return callback(new ClientError(status, data));
|
|
|
|
callback(null);
|
|
});
|
|
};
|
|
|
|
Client.prototype.listArchives = function (callback) {
|
|
var config = {
|
|
params: {
|
|
page: 1,
|
|
per_page: 100
|
|
}
|
|
};
|
|
|
|
get('/api/v1/archives', config, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 200) return callback(new ClientError(status, data));
|
|
|
|
callback(null, data.archives);
|
|
});
|
|
};
|
|
|
|
Client.prototype.deleteArchive = function (id, callback) {
|
|
del('/api/v1/archives/' + id, null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 204) return callback(new ClientError(status, data));
|
|
|
|
callback(null);
|
|
});
|
|
};
|
|
|
|
Client.prototype.unarchiveApp = function (archiveId, data, callback) {
|
|
post('/api/v1/archives/' + archiveId + '/unarchive', data, null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 202) return callback(new ClientError(status, data));
|
|
|
|
callback(null, data);
|
|
});
|
|
};
|
|
|
|
|
|
Client.prototype.getBackups = function (callback) {
|
|
var page = 1;
|
|
var perPage = 100;
|
|
var backups = [];
|
|
|
|
function fetchMore() {
|
|
var config = {
|
|
params: {
|
|
page: page,
|
|
per_page: perPage
|
|
}
|
|
};
|
|
|
|
get('/api/v1/backups', config, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 200) return callback(new ClientError(status, data));
|
|
|
|
backups = backups.concat(data.backups);
|
|
|
|
if (data.backups.length < perPage) return callback(null, backups);
|
|
|
|
page++;
|
|
|
|
fetchMore();
|
|
});
|
|
}
|
|
|
|
fetchMore();
|
|
};
|
|
|
|
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));
|
|
|
|
callback(null, data.tasks.length ? data.tasks[0] : null);
|
|
});
|
|
};
|
|
|
|
Client.prototype.getTasksByType = function (type, callback) {
|
|
get('/api/v1/tasks?type=' + type, null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 200) return callback(new ClientError(status, data));
|
|
|
|
callback(null, data.tasks);
|
|
});
|
|
};
|
|
|
|
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));
|
|
|
|
callback(null, data);
|
|
});
|
|
};
|
|
|
|
Client.prototype.editBackup = function (backupId, label, preserveSecs, callback) {
|
|
post('/api/v1/backups/' + backupId, { label: label, preserveSecs: preserveSecs }, null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 200) return callback(new ClientError(status, data));
|
|
|
|
callback(null);
|
|
});
|
|
};
|
|
|
|
Client.prototype.startBackup = function (callback) {
|
|
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));
|
|
|
|
callback(null, data.taskId);
|
|
});
|
|
};
|
|
|
|
Client.prototype.stopTask = function (taskId, callback) {
|
|
post('/api/v1/tasks/' + taskId + '/stop', {}, null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 204) return callback(new ClientError(status, data));
|
|
|
|
callback(null, data);
|
|
});
|
|
};
|
|
|
|
Client.prototype.restore = function (data, callback) {
|
|
post('/api/v1/provision/restore', data, null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 200) return callback(new ClientError(status));
|
|
|
|
callback(null);
|
|
});
|
|
};
|
|
|
|
Client.prototype.importBackup = function (appId, remotePath, backupFormat, backupConfig, callback) {
|
|
var data = {
|
|
remotePath: remotePath,
|
|
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) {
|
|
if (error) return callback(error);
|
|
if (status !== 204) return callback(new ClientError(status));
|
|
|
|
callback(null);
|
|
});
|
|
};
|
|
|
|
Client.prototype.getEvent = function (eventId, callback) {
|
|
get('/api/v1/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) {
|
|
var config = {
|
|
params: {
|
|
actions: actions,
|
|
search: search,
|
|
page: page,
|
|
per_page: perPage
|
|
}
|
|
};
|
|
|
|
get('/api/v1/eventlog', config, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 200) return callback(new ClientError(status, data));
|
|
|
|
callback(null, data.eventlogs);
|
|
});
|
|
};
|
|
|
|
Client.prototype.getApps = function (callback) {
|
|
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));
|
|
|
|
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);
|
|
});
|
|
};
|
|
|
|
Client.prototype.getAppBackups = function (appId, callback) {
|
|
var page = 1;
|
|
var perPage = 100;
|
|
var backups = [];
|
|
|
|
function fetchMore() {
|
|
var config = {
|
|
params: {
|
|
page: page,
|
|
per_page: perPage
|
|
}
|
|
};
|
|
|
|
get('/api/v1/apps/' + appId + '/backups', config, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 200) return callback(new ClientError(status, data));
|
|
|
|
backups = backups.concat(data.backups);
|
|
|
|
if (data.backups.length < perPage) return callback(null, backups);
|
|
|
|
page++;
|
|
|
|
fetchMore();
|
|
});
|
|
}
|
|
|
|
fetchMore();
|
|
};
|
|
|
|
Client.prototype.getAppBackupDownloadLink = function (appId, backupId) {
|
|
return client.apiOrigin + '/api/v1/apps/' + appId + '/backups/' + backupId + '/download?access_token=' + token;
|
|
};
|
|
|
|
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));
|
|
|
|
callback(null, data.services);
|
|
});
|
|
};
|
|
|
|
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));
|
|
|
|
callback(null, data.service);
|
|
});
|
|
};
|
|
|
|
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);
|
|
});
|
|
};
|
|
|
|
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);
|
|
});
|
|
};
|
|
|
|
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.getAllUsers = function (callback) {
|
|
var page = 1;
|
|
var perPage = 5000;
|
|
var users = [];
|
|
|
|
function fetchMore() {
|
|
var config = {
|
|
params: {
|
|
page: page,
|
|
per_page: perPage
|
|
}
|
|
};
|
|
|
|
get('/api/v1/users', config, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 200) return callback(new ClientError(status, data));
|
|
|
|
users = users.concat(data.users);
|
|
|
|
if (data.users.length < perPage) return callback(null, users);
|
|
|
|
page++;
|
|
|
|
fetchMore();
|
|
});
|
|
}
|
|
|
|
fetchMore();
|
|
};
|
|
|
|
Client.prototype.getUsers = function (search, active, page, perPage, callback) {
|
|
var config = {
|
|
params: {
|
|
page: page,
|
|
per_page: perPage
|
|
}
|
|
};
|
|
|
|
if (search) config.params.search = search;
|
|
if (active !== null) config.params.active = active ? 'true' : 'false';
|
|
|
|
get('/api/v1/users', config, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 200) return callback(new ClientError(status, data));
|
|
|
|
callback(null, data.users);
|
|
});
|
|
};
|
|
|
|
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);
|
|
});
|
|
};
|
|
|
|
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));
|
|
|
|
callback(null, data.groups);
|
|
});
|
|
};
|
|
|
|
Client.prototype.setLocalGroups = function (userId, localGroupIds, callback) {
|
|
put('/api/v1/users/' + userId + '/groups', { groupIds: localGroupIds }, null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 204) return callback(new ClientError(status, data));
|
|
|
|
callback(null);
|
|
});
|
|
};
|
|
|
|
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));
|
|
|
|
callback(null, data);
|
|
});
|
|
};
|
|
|
|
Client.prototype.createGroup = function (name, callback) {
|
|
var data = {
|
|
name: name
|
|
};
|
|
|
|
post('/api/v1/groups', 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.setGroupName = function (id, name, callback) {
|
|
var data = {
|
|
name: name
|
|
};
|
|
|
|
put('/api/v1/groups/' + id + '/name', 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) {
|
|
var config = {
|
|
data: {},
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
}
|
|
};
|
|
|
|
del('/api/v1/groups/' + groupId, config, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 204) return callback(new ClientError(status, data));
|
|
|
|
callback(null, data);
|
|
});
|
|
};
|
|
|
|
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);
|
|
|
|
callback(null, data);
|
|
});
|
|
};
|
|
|
|
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.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;
|
|
};
|
|
|
|
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.detectIp = function (callback) {
|
|
post('/api/v1/provision/detect_ip', {}, 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/provision/setup', data, null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 200) return callback(new ClientError(status, data));
|
|
|
|
callback(null);
|
|
});
|
|
};
|
|
|
|
Client.prototype.getProvisionBlockDevices = function (callback) {
|
|
get('/api/v1/provision/block_devices', null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 200) return callback(new ClientError(status, data));
|
|
|
|
callback(null, data.devices);
|
|
});
|
|
};
|
|
|
|
Client.prototype.createAdmin = function (data, callback) {
|
|
var that = this;
|
|
|
|
post('/api/v1/provision/activate', data, null, function (error, result, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 201) return callback(new ClientError(status, result));
|
|
|
|
callback(null, result.token);
|
|
});
|
|
};
|
|
|
|
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, scope, callback) {
|
|
var data = {
|
|
name: name,
|
|
scope: scope
|
|
};
|
|
|
|
post('/api/v1/tokens', data, null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 201) return callback(new ClientError(status, data));
|
|
|
|
callback(null, data);
|
|
});
|
|
};
|
|
|
|
// 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);
|
|
});
|
|
};
|
|
|
|
Client.prototype.getOidcClients = function (callback) {
|
|
get('/api/v1/oidc/clients', null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 200) return callback(new ClientError(status, data));
|
|
|
|
callback(null, data.clients);
|
|
});
|
|
};
|
|
|
|
Client.prototype.addOidcClient = function (name, loginRedirectUri, tokenSignatureAlgorithm, callback) {
|
|
var data = {
|
|
name: name,
|
|
loginRedirectUri: loginRedirectUri,
|
|
tokenSignatureAlgorithm: tokenSignatureAlgorithm
|
|
};
|
|
|
|
post('/api/v1/oidc/clients', data, null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 201) return callback(new ClientError(status, data));
|
|
|
|
callback(null);
|
|
});
|
|
};
|
|
|
|
Client.prototype.updateOidcClient = function (id, name, loginRedirectUri, tokenSignatureAlgorithm, callback) {
|
|
var data = {
|
|
name: name,
|
|
loginRedirectUri: loginRedirectUri,
|
|
tokenSignatureAlgorithm, tokenSignatureAlgorithm
|
|
};
|
|
|
|
post('/api/v1/oidc/clients/' + id, data, null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 201) return callback(new ClientError(status, data));
|
|
|
|
callback(null);
|
|
});
|
|
};
|
|
|
|
Client.prototype.delOidcClient = function (id, callback) {
|
|
del('/api/v1/oidc/clients/' + id, null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 204) return callback(new ClientError(status, data));
|
|
|
|
callback(null);
|
|
});
|
|
};
|
|
|
|
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);
|
|
});
|
|
};
|
|
|
|
Client.prototype.update = function (options, callback) {
|
|
var data = {
|
|
skipBackup: !!options.skipBackup
|
|
};
|
|
|
|
post('/api/v1/updater/update', 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.isRebootRequired = function (callback) {
|
|
get('/api/v1/system/info', null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 200) return callback(new ClientError(status, data));
|
|
|
|
callback(null, data.rebootRequired);
|
|
});
|
|
};
|
|
|
|
Client.prototype.reboot = function (callback) {
|
|
post('/api/v1/system/reboot', {}, null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 202) return callback(new ClientError(status, data));
|
|
|
|
callback(null, data);
|
|
});
|
|
};
|
|
|
|
Client.prototype.getBlockDevices = function (callback) {
|
|
get('/api/v1/system/block_devices', null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 200) return callback(new ClientError(status, data));
|
|
|
|
callback(null, data.devices);
|
|
});
|
|
};
|
|
|
|
Client.prototype.diskUsage = function (callback) {
|
|
get('/api/v1/system/disk_usage', null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 200) return callback(new ClientError(status, data));
|
|
|
|
callback(null, data);
|
|
});
|
|
};
|
|
|
|
Client.prototype.refreshDiskUsage = function (callback) {
|
|
post('/api/v1/system/disk_usage', {}, null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 201) return callback(new ClientError(status, data));
|
|
|
|
callback(null, data.taskId);
|
|
});
|
|
};
|
|
|
|
Client.prototype.systemInfo = function (callback) {
|
|
get('/api/v1/system/info', null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 200) return callback(new ClientError(status, data));
|
|
|
|
callback(null, data.info);
|
|
});
|
|
};
|
|
|
|
Client.prototype.cpus = function (callback) {
|
|
get('/api/v1/system/cpus', null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 200) return callback(new ClientError(status, data));
|
|
|
|
callback(null, data.cpus);
|
|
});
|
|
};
|
|
|
|
Client.prototype.memory = function (callback) {
|
|
get('/api/v1/system/memory', null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 200) return callback(new ClientError(status, data));
|
|
|
|
callback(null, data);
|
|
});
|
|
};
|
|
|
|
Client.prototype.getAppGraphs = function (appId, fromMinutes, callback) {
|
|
get('/api/v1/apps/' + appId + '/graphs', { params: { fromMinutes: fromMinutes } }, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 200) return callback(new ClientError(status, data));
|
|
|
|
callback(null, data);
|
|
});
|
|
};
|
|
|
|
Client.prototype.getSystemGraphs = function (fromMinutes, callback) {
|
|
get('/api/v1/system/graphs', { params: { fromMinutes: fromMinutes } }, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 200) return callback(new ClientError(status, data));
|
|
|
|
callback(null, data);
|
|
});
|
|
};
|
|
|
|
Client.prototype.systemGraphs = 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));
|
|
}
|
|
|
|
var result = [];
|
|
async.eachSeries(chunks, function (chunk, iteratorCallback) {
|
|
var config = {
|
|
params: {
|
|
target: chunk,
|
|
format: 'json',
|
|
from: from,
|
|
until: 'now'
|
|
}
|
|
};
|
|
|
|
if (options.noNullPoints) config.params.noNullPoints = true;
|
|
|
|
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);
|
|
});
|
|
};
|
|
|
|
Client.prototype.createTicket = function (ticket, callback) {
|
|
// just to be eplicit here
|
|
var data = {
|
|
enableSshSupport: !!ticket.enableSshSupport,
|
|
type: ticket.type,
|
|
subject: ticket.subject,
|
|
description: ticket.description,
|
|
appId: ticket.appId || undefined,
|
|
altEmail: ticket.altEmail || undefined
|
|
};
|
|
|
|
post('/api/v1/support/ticket', 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.getApplinks = function (callback) {
|
|
var that = this;
|
|
|
|
get('/api/v1/applinks', null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 200) return callback(new ClientError(status, data));
|
|
|
|
// amend properties to mimick full app
|
|
data.applinks.forEach(function (applink) {
|
|
applink.type = APP_TYPES.LINK;
|
|
applink.fqdn = applink.upstreamUri;
|
|
applink.manifest = { addons: {}};
|
|
applink.installationState = ISTATES.INSTALLED;
|
|
applink.runState = RSTATES.RUNNING;
|
|
applink.health = HSTATES.HEALTHY;
|
|
applink.iconUrl = that.apiOrigin + '/api/v1/applinks/' + applink.id + '/icon?access_token=' + token + '&ts=' + applink.ts;
|
|
applink.accessLevel = that._userInfo.isAtLeastAdmin ? 'admin' : 'user';
|
|
});
|
|
|
|
callback(null, data.applinks);
|
|
});
|
|
};
|
|
|
|
Client.prototype.addApplink = function (applink, callback) {
|
|
post('/api/v1/applinks', applink, null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 201) return callback(new ClientError(status, data));
|
|
|
|
callback(null);
|
|
});
|
|
};
|
|
|
|
Client.prototype.updateApplink = function (id, data, callback) {
|
|
post('/api/v1/applinks/' + id, data, null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 200) return callback(new ClientError(status, data));
|
|
|
|
callback(null);
|
|
});
|
|
};
|
|
|
|
Client.prototype.removeApplink = function (id, callback) {
|
|
del('/api/v1/applinks/' + id, null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 204) return callback(new ClientError(status, data));
|
|
|
|
callback(null);
|
|
});
|
|
};
|
|
|
|
Client.prototype.addUser = function (user, callback) {
|
|
var data = {
|
|
email: user.email,
|
|
fallbackEmail: user.fallbackEmail,
|
|
displayName: user.displayName,
|
|
role: user.role
|
|
};
|
|
|
|
if (user.username) data.username = user.username;
|
|
if (user.password) data.password = user.password;
|
|
|
|
post('/api/v1/users', data, null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 201) return callback(new ClientError(status, data));
|
|
|
|
callback(null, data.id);
|
|
});
|
|
};
|
|
|
|
Client.prototype.updateUserProfile = function (userId, data, callback) {
|
|
post('/api/v1/users/' + userId + '/profile', data, null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 204) return callback(new ClientError(status, data));
|
|
|
|
callback(null);
|
|
});
|
|
};
|
|
|
|
Client.prototype.setRole = function (userId, role, callback) {
|
|
put('/api/v1/users/' + userId + '/role', { role: role }, null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 204) return callback(new ClientError(status, data));
|
|
|
|
callback(null);
|
|
});
|
|
};
|
|
|
|
Client.prototype.setActive = function (userId, active, callback) {
|
|
put('/api/v1/users/' + userId + '/active', { active: active }, 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) {
|
|
var config = {
|
|
data: {},
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
}
|
|
};
|
|
|
|
del('/api/v1/users/' + userId, config, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 204) return callback(new ClientError(status, data));
|
|
|
|
callback(null);
|
|
});
|
|
};
|
|
|
|
Client.prototype.setProfileDisplayName = function (displayName, callback) {
|
|
post('/api/v1/profile/display_name', { displayName: displayName }, null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 204) return callback(new ClientError(status, data));
|
|
|
|
callback(null, data);
|
|
});
|
|
};
|
|
|
|
Client.prototype.setProfileLanguage = function (language, callback) {
|
|
post('/api/v1/profile/language', { language: language }, null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 204) return callback(new ClientError(status, data));
|
|
|
|
callback(null, data);
|
|
});
|
|
};
|
|
|
|
Client.prototype.setNotificationConfig = function (notificationConfig, callback) {
|
|
post('/api/v1/profile/notification_config', { notificationConfig }, null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 204) return callback(new ClientError(status, data));
|
|
|
|
callback(null, data);
|
|
});
|
|
};
|
|
|
|
Client.prototype.setProfileEmail = function (email, password, callback) {
|
|
post('/api/v1/profile/email', { email: email, password: password }, null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 204) return callback(new ClientError(status, data));
|
|
|
|
callback(null, data);
|
|
});
|
|
};
|
|
|
|
Client.prototype.setProfileFallbackEmail = function (fallbackEmail, password, callback) {
|
|
post('/api/v1/profile/fallback_email', { fallbackEmail: fallbackEmail, password: password }, null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 204) return callback(new ClientError(status, data));
|
|
|
|
callback(null, data);
|
|
});
|
|
};
|
|
|
|
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);
|
|
});
|
|
}
|
|
};
|
|
|
|
Client.prototype.getBackgroundImageUrl = function () {
|
|
return client.apiOrigin + '/api/v1/profile/background_image?access_token=' + token + '&bustcache=' + Date.now();
|
|
};
|
|
|
|
Client.prototype.setBackgroundImage = function (backgroundImage, callback) {
|
|
// Blob type if object
|
|
var fd = new FormData();
|
|
if (backgroundImage) fd.append('backgroundImage', backgroundImage);
|
|
|
|
var config = {
|
|
headers: { 'Content-Type': undefined },
|
|
transformRequest: angular.identity
|
|
};
|
|
|
|
post('/api/v1/profile/background_image', fd, config, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 202) return callback(new ClientError(status, data));
|
|
callback(null);
|
|
});
|
|
};
|
|
|
|
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);
|
|
if (status !== 204) return callback(new ClientError(status, data));
|
|
|
|
callback(null, data);
|
|
});
|
|
};
|
|
|
|
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));
|
|
|
|
callback(null, data);
|
|
});
|
|
};
|
|
|
|
Client.prototype.sendSelfPasswordReset = function (identifier, callback) {
|
|
post('/api/v1/auth/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);
|
|
});
|
|
};
|
|
|
|
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);
|
|
});
|
|
};
|
|
|
|
Client.prototype.setTwoFactorAuthenticationSecret = function (callback) {
|
|
var data = {};
|
|
|
|
post('/api/v1/profile/twofactorauthentication_secret', 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.enableTwoFactorAuthentication = function (totpToken, callback) {
|
|
var data = {
|
|
totpToken: totpToken
|
|
};
|
|
|
|
post('/api/v1/profile/twofactorauthentication_enable', data, null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 204) return callback(new ClientError(status, data));
|
|
|
|
callback(null);
|
|
});
|
|
};
|
|
|
|
Client.prototype.disableTwoFactorAuthentication = function (password, callback) {
|
|
var data = {
|
|
password: password
|
|
};
|
|
|
|
post('/api/v1/profile/twofactorauthentication_disable', data, null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 204) return callback(new ClientError(status, data));
|
|
|
|
callback(null);
|
|
});
|
|
};
|
|
|
|
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/external_ldap/sync', {}, 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.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);
|
|
});
|
|
};
|
|
|
|
Client.prototype.refreshProfile = function (callback) {
|
|
var that = this;
|
|
|
|
callback = typeof callback === 'function' ? callback : function () {};
|
|
|
|
this.getProfile(function (error, result) {
|
|
if (error) return callback(error);
|
|
|
|
if (result.language !== '' && $translate.use() !== result.language) {
|
|
console.log('Changing users language from ' + $translate.use() + ' to ', result.language);
|
|
$translate.use(result.language);
|
|
}
|
|
|
|
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) {
|
|
if (error) return callback(error);
|
|
|
|
result.update = info.update;
|
|
that.setConfig(result);
|
|
callback(null);
|
|
});
|
|
});
|
|
};
|
|
|
|
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;
|
|
|
|
// 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
|
|
text = text.replace(/\$CLOUDRON-APP-LOCATION/g, app.subdomain);
|
|
text = text.replace(/\$CLOUDRON-APP-DOMAIN/g, app.domain);
|
|
text = text.replace(/\$CLOUDRON-APP-FQDN/g, app.fqdn);
|
|
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;
|
|
}
|
|
|
|
app.type = app.manifest.id === 'io.cloudron.builtin.appproxy' ? APP_TYPES.PROXIED : APP_TYPES.APP;
|
|
|
|
return app;
|
|
};
|
|
|
|
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;
|
|
}
|
|
|
|
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]);
|
|
} else {
|
|
this._installedApps.push(tmp);
|
|
foundIndex = this._installedApps.length-1;
|
|
}
|
|
|
|
// add reference to object map with appId keys
|
|
this._installedAppsById[app.id] = this._installedApps[foundIndex];
|
|
|
|
// 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
|
|
.filter(function (v, i, self) { return self.indexOf(v) === i; }) // filter duplicates
|
|
.sort(function (a, b) { return a.localeCompare(b); }); // sort
|
|
|
|
// keep tag array references
|
|
angular.copy(tmp, this._appTags);
|
|
};
|
|
|
|
Client.prototype.refreshInstalledApps = function (callback) {
|
|
callback = callback || function (error) { if (error) console.error(error); };
|
|
var that = this;
|
|
|
|
this.getApps(function (error, apps) {
|
|
if (error) return callback(error);
|
|
|
|
that.getApplinks(function (error, applinks) {
|
|
if (error) return callback(error);
|
|
|
|
apps = apps.concat(applinks);
|
|
|
|
async.eachLimit(apps, 20, function (app, iteratorCallback) {
|
|
app.ssoAuth = app.sso && (app.manifest.addons['ldap'] || app.manifest.addons['oidc'] || app.manifest.addons['proxyAuth']); // checking app.sso first ensures app.manifest.addons is not null
|
|
|
|
if (app.accessLevel !== 'operator' && app.accessLevel !== 'admin') { // only fetch if we have permissions
|
|
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;
|
|
}
|
|
|
|
that._updateAppCache(app);
|
|
|
|
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);
|
|
});
|
|
});
|
|
});
|
|
};
|
|
|
|
Client.prototype.login = function () {
|
|
this.setToken(null);
|
|
|
|
localStorage.setItem('redirectToHash', window.location.hash);
|
|
|
|
// start oidc flow
|
|
window.location.href = this.apiOrigin + '/openid/auth?client_id=' + (window.cloudronApiOrigin ? TOKEN_TYPES.ID_DEVELOPMENT : TOKEN_TYPES.ID_WEBADMIN) + '&scope=openid email profile&response_type=code token&redirect_uri=' + window.location.origin + '/authcallback.html';
|
|
};
|
|
|
|
Client.prototype.logout = function () {
|
|
var that = this;
|
|
|
|
// destroy oidc session in the spirit of true SSO
|
|
del('/api/v1/oidc/sessions', null, function (error, data, status) {
|
|
if (error) console.error('Failed to logout from oidc session');
|
|
|
|
that.setToken(null);
|
|
|
|
window.location.href = '/';
|
|
});
|
|
};
|
|
|
|
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);
|
|
});
|
|
};
|
|
|
|
Client.prototype.sendTestMail = function (domain, to, callback) {
|
|
var data = {
|
|
to: to
|
|
};
|
|
|
|
post('/api/v1/mail/' + domain + '/send_test_mail', data, null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 202) return callback(new ClientError(status, data));
|
|
|
|
callback(null);
|
|
});
|
|
};
|
|
|
|
// 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));
|
|
|
|
callback(null, data.domains);
|
|
});
|
|
};
|
|
|
|
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));
|
|
|
|
callback(null, data);
|
|
});
|
|
};
|
|
|
|
Client.prototype.checkDNSRecords = function (domain, subdomain, callback) {
|
|
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));
|
|
|
|
callback(null, data);
|
|
});
|
|
};
|
|
|
|
Client.prototype.addDomain = function (domain, zoneName, provider, config, fallbackCertificate, tlsConfig, callback) {
|
|
var data = {
|
|
domain: domain,
|
|
provider: provider,
|
|
config: config,
|
|
tlsConfig: tlsConfig,
|
|
};
|
|
if (zoneName) data.zoneName = zoneName;
|
|
var that = this;
|
|
|
|
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();
|
|
});
|
|
};
|
|
|
|
Client.prototype.updateDomainConfig = function (domain, zoneName, provider, config, fallbackCertificate, tlsConfig, callback) {
|
|
var data = {
|
|
provider: provider,
|
|
config: config,
|
|
tlsConfig: tlsConfig
|
|
};
|
|
if (zoneName) data.zoneName = zoneName;
|
|
var that = this;
|
|
|
|
if (fallbackCertificate) data.fallbackCertificate = fallbackCertificate;
|
|
|
|
post('/api/v1/domains/' + domain + '/config', data, null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 204) return callback(new ClientError(status, data));
|
|
|
|
that.setDnsRecords({ domain: domain, type: 'mail' }, callback); // this is done so that an out-of-sync dkim key can be synced
|
|
});
|
|
};
|
|
|
|
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);
|
|
});
|
|
};
|
|
|
|
Client.prototype.renewCerts = function (options, callback) {
|
|
post('/api/v1/reverseproxy/renew_certs', options, 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.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);
|
|
});
|
|
};
|
|
|
|
Client.prototype.prepareDashboardDomain = function (domain, callback) {
|
|
var data = {
|
|
domain: domain
|
|
};
|
|
|
|
post('/api/v1/dashboard/prepare_location', 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/dashboard/location', data, null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 204) return callback(new ClientError(status, data));
|
|
|
|
callback(null);
|
|
});
|
|
};
|
|
|
|
// Email
|
|
Client.prototype.getMailEventLogs = function (search, types, page, perPage, callback) {
|
|
var config = {
|
|
params: {
|
|
page: page,
|
|
types: types,
|
|
per_page: perPage,
|
|
search: search
|
|
}
|
|
};
|
|
|
|
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);
|
|
});
|
|
};
|
|
|
|
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));
|
|
callback(null, data.usage); // { quotaValue (IEC/1024), quotaLimit (IEC/1024), quotaPercent }
|
|
});
|
|
};
|
|
|
|
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 });
|
|
});
|
|
};
|
|
|
|
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);
|
|
});
|
|
};
|
|
|
|
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);
|
|
});
|
|
};
|
|
|
|
Client.prototype.getVirtualAllMail = function (callback) {
|
|
get('/api/v1/mailserver/virtual_all_mail', {}, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 200) return callback(new ClientError(status, data));
|
|
callback(null, data.enabled);
|
|
});
|
|
};
|
|
|
|
Client.prototype.setVirtualAllMail = function (enable, callback) {
|
|
post('/api/v1/mailserver/virtual_all_mail', { enable: enable }, null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 200) return callback(new ClientError(status, data));
|
|
|
|
callback(null);
|
|
});
|
|
};
|
|
|
|
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);
|
|
});
|
|
};
|
|
|
|
Client.prototype.getFtsConfig = function (callback) {
|
|
var config = {};
|
|
|
|
get('/api/v1/mailserver/fts_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.setFtsConfig = function (state, callback) {
|
|
post('/api/v1/mailserver/fts_config', { enable: state }, null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 200) return callback(new ClientError(status, data));
|
|
|
|
callback(null);
|
|
});
|
|
};
|
|
|
|
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', { allowlist: acl.allowlist, blocklist: acl.blocklist }, 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);
|
|
});
|
|
};
|
|
|
|
Client.prototype.listMailQueue = function (search, page, perPage, callback) {
|
|
var config = {
|
|
params: {
|
|
search: search,
|
|
page: page,
|
|
per_page: perPage
|
|
}
|
|
};
|
|
|
|
get('/api/v1/mailserver/queue', config, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 200) return callback(new ClientError(status, data));
|
|
callback(null, data.queue);
|
|
});
|
|
};
|
|
|
|
Client.prototype.delMailQueueItem = function (file, callback) {
|
|
del('/api/v1/mailserver/queue/' + file, null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 200) return callback(new ClientError(status, data));
|
|
callback(null, data.usage);
|
|
});
|
|
};
|
|
|
|
Client.prototype.resendMailQueueItem = function (file, callback) {
|
|
post('/api/v1/mailserver/queue/' + file + '/resend', {}, null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 201) return callback(new ClientError(status, data));
|
|
callback(null, data.usage);
|
|
});
|
|
};
|
|
|
|
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));
|
|
|
|
callback(null, data);
|
|
});
|
|
};
|
|
|
|
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);
|
|
});
|
|
};
|
|
|
|
Client.prototype.setDnsRecords = function (options, callback) {
|
|
post('/api/v1/domains/sync_dns', options, null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 201) return callback(new ClientError(status, data));
|
|
|
|
callback(null, data.taskId);
|
|
});
|
|
};
|
|
|
|
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));
|
|
|
|
callback(null, data);
|
|
});
|
|
};
|
|
|
|
Client.prototype.setMailRelay = function (domain, data, callback) {
|
|
post('/api/v1/mail/' + domain + '/relay', data, null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
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));
|
|
|
|
callback(null);
|
|
});
|
|
};
|
|
|
|
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);
|
|
if (status !== 202) return callback(new ClientError(status, data));
|
|
|
|
callback(null);
|
|
});
|
|
};
|
|
|
|
// Mailboxes
|
|
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);
|
|
});
|
|
});
|
|
};
|
|
|
|
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: {
|
|
search: search,
|
|
page: page,
|
|
per_page: perPage
|
|
}
|
|
};
|
|
|
|
get('/api/v1/mail/' + domain + '/mailboxes', config, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 200) return callback(new ClientError(status, data));
|
|
|
|
callback(null, data.mailboxes);
|
|
});
|
|
};
|
|
|
|
Client.prototype.getMailbox = function (domain, name, callback) {
|
|
get('/api/v1/mail/' + domain + '/mailboxes/' + name, null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 200) return callback(new ClientError(status, data));
|
|
|
|
callback(null, data.mailbox);
|
|
});
|
|
};
|
|
|
|
Client.prototype.addMailbox = function (domain, name, ownerId, ownerType, callback) {
|
|
var data = {
|
|
name: name,
|
|
ownerId: ownerId,
|
|
ownerType: ownerType,
|
|
active: true,
|
|
storageQuota: 0,
|
|
messagesQuota: 0
|
|
};
|
|
|
|
post('/api/v1/mail/' + domain + '/mailboxes', data, null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 201) return callback(new ClientError(status, data));
|
|
|
|
callback(null);
|
|
});
|
|
};
|
|
|
|
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);
|
|
if (status !== 204) return callback(new ClientError(status, data));
|
|
|
|
callback(null);
|
|
});
|
|
};
|
|
|
|
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);
|
|
if (status !== 201) return callback(new ClientError(status, data));
|
|
|
|
callback(null);
|
|
});
|
|
};
|
|
|
|
Client.prototype.getAliases = function (name, domain, callback) {
|
|
var config = {
|
|
params: {
|
|
page: 1,
|
|
per_page: 1000
|
|
}
|
|
};
|
|
|
|
get('/api/v1/mail/' + domain + '/mailboxes/' + name + '/aliases', config, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 200) return callback(new ClientError(status, data));
|
|
|
|
callback(null, data.aliases);
|
|
});
|
|
};
|
|
|
|
Client.prototype.setAliases = function (name, domain, aliases, callback) {
|
|
var data = {
|
|
aliases: aliases
|
|
};
|
|
|
|
put('/api/v1/mail/' + domain + '/mailboxes/' + name + '/aliases', data, null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 202) return callback(new ClientError(status, data));
|
|
|
|
callback(null);
|
|
});
|
|
};
|
|
|
|
Client.prototype.listMailingLists = function (domain, search, page, perPage, callback) {
|
|
var config = {
|
|
params: {
|
|
search: search,
|
|
page: page,
|
|
per_page: perPage
|
|
}
|
|
};
|
|
|
|
get('/api/v1/mail/' + domain + '/lists', config, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 200) return callback(new ClientError(status, data));
|
|
|
|
callback(null, data.lists);
|
|
});
|
|
};
|
|
|
|
Client.prototype.getMailingList = function (domain, name, callback) {
|
|
get('/api/v1/mail/' + domain + '/lists/' + name, null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 200) return callback(new ClientError(status, data));
|
|
|
|
callback(null, data.list);
|
|
});
|
|
};
|
|
|
|
Client.prototype.addMailingList = function (domain, name, members, membersOnly, callback) {
|
|
var data = {
|
|
name: name,
|
|
members: members,
|
|
membersOnly: membersOnly,
|
|
active: true
|
|
};
|
|
|
|
post('/api/v1/mail/' + domain + '/lists', data, null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 201) return callback(new ClientError(status, data));
|
|
|
|
callback(null);
|
|
});
|
|
};
|
|
|
|
Client.prototype.updateMailingList = function (domain, name, members, membersOnly, active, callback) {
|
|
var data = {
|
|
members: members,
|
|
membersOnly: membersOnly,
|
|
active: active
|
|
};
|
|
|
|
post('/api/v1/mail/' + domain + '/lists/' + name, data, null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 204) return callback(new ClientError(status, data));
|
|
|
|
callback(null);
|
|
});
|
|
};
|
|
|
|
Client.prototype.removeMailingList = function (domain, name, callback) {
|
|
del('/api/v1/mail/' + domain + '/lists/' + name, null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 204) return callback(new ClientError(status, data));
|
|
|
|
callback(null);
|
|
});
|
|
};
|
|
|
|
// 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));
|
|
|
|
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));
|
|
|
|
callback(null, data);
|
|
});
|
|
};
|
|
|
|
Client.prototype.addVolume = function (name, mountType, mountOptions, callback) {
|
|
var data = {
|
|
name: name,
|
|
mountType: mountType,
|
|
mountOptions: mountOptions
|
|
};
|
|
|
|
post('/api/v1/volumes', data, null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 201) return callback(new ClientError(status, data));
|
|
|
|
callback(null, data.id);
|
|
});
|
|
};
|
|
|
|
Client.prototype.updateVolume = function (volumeId, mountOptions, callback) {
|
|
var data = {
|
|
mountOptions: mountOptions
|
|
};
|
|
|
|
post('/api/v1/volumes/' + volumeId, data, null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 204) return callback(new ClientError(status, data));
|
|
|
|
callback();
|
|
});
|
|
};
|
|
|
|
Client.prototype.remountVolume = function (volumeId, callback) {
|
|
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();
|
|
});
|
|
};
|
|
|
|
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);
|
|
});
|
|
};
|
|
|
|
// 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';
|
|
|
|
window.open(this.getConfig().consoleServerOrigin + '/#/cloudron/' + subscription.cloudronId + '?email=' + subscription.emailEncoded, '_blank');
|
|
};
|
|
|
|
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) { callback(); }
|
|
else this._fetchingAppstoreAppsListener.push(callback);
|
|
};
|
|
|
|
Client.prototype.getAppstoreApps = function (callback) {
|
|
var that = this;
|
|
|
|
callback = callback || function () {};
|
|
|
|
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) {
|
|
if (this._appstoreAppCache.length !== 0) return callback(null, this._appstoreAppCache);
|
|
|
|
this.getAppstoreApps(callback);
|
|
};
|
|
|
|
Client.prototype.getSubscription = function (callback) {
|
|
get('/api/v1/appstore/subscription', null, function (error, data, status) {
|
|
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 }
|
|
});
|
|
};
|
|
|
|
Client.prototype.registerCloudronWithSetupToken = function (setupToken, callback) {
|
|
var data = {
|
|
setupToken: setupToken
|
|
};
|
|
|
|
post('/api/v1/appstore/register_cloudron_with_setup_token', data, null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 201) return callback(new ClientError(status, data));
|
|
|
|
callback(null);
|
|
});
|
|
};
|
|
|
|
Client.prototype.registerCloudron = function (email, password, totpToken, signup, callback) {
|
|
var data = {
|
|
email: email,
|
|
password: password,
|
|
signup: signup
|
|
};
|
|
|
|
if (totpToken) data.totpToken = totpToken;
|
|
|
|
post('/api/v1/appstore/register_cloudron', data, null, function (error, data, status) {
|
|
if (error) return callback(error);
|
|
if (status !== 201) return callback(new ClientError(status, data));
|
|
|
|
callback(null);
|
|
});
|
|
};
|
|
|
|
// ----------------------------------------------
|
|
// Eventlog helpers
|
|
// ----------------------------------------------
|
|
Client.prototype.eventLogDetails = function (eventLog, appIdContext) {
|
|
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';
|
|
var ACTION_APP_BACKUP = 'app.backup';
|
|
var ACTION_APP_BACKUP_FINISH = 'app.backup.finish';
|
|
var ACTION_APP_LOGIN = 'app.login';
|
|
var ACTION_APP_OOM = 'app.oom';
|
|
var ACTION_APP_UP = 'app.up';
|
|
var ACTION_APP_DOWN = 'app.down';
|
|
var ACTION_APP_START = 'app.start';
|
|
var ACTION_APP_STOP = 'app.stop';
|
|
var ACTION_APP_RESTART = 'app.restart';
|
|
|
|
var ACTION_ARCHIVES_ADD = 'archives.add';
|
|
var ACTION_ARCHIVES_DEL = 'archives.del';
|
|
|
|
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_BRANDING_AVATAR = 'branding.avatar';
|
|
var ACTION_BRANDING_NAME = 'branding.name';
|
|
var ACTION_BRANDING_FOOTER = 'branding.footer';
|
|
|
|
var ACTION_CERTIFICATE_NEW = 'certificate.new';
|
|
var ACTION_CERTIFICATE_RENEWAL = 'certificate.renew';
|
|
var ACTION_CERTIFICATE_CLEANUP = 'certificate.cleanup';
|
|
|
|
var ACTION_DASHBOARD_DOMAIN_UPDATE = 'dashboard.domain.update';
|
|
|
|
var ACTION_DIRECTORY_SERVER_CONFIGURE = 'directoryserver.configure';
|
|
|
|
var ACTION_DOMAIN_ADD = 'domain.add';
|
|
var ACTION_DOMAIN_UPDATE = 'domain.update';
|
|
var ACTION_DOMAIN_REMOVE = 'domain.remove';
|
|
|
|
var ACTION_EXTERNAL_LDAP_CONFIGURE = 'externalldap.configure';
|
|
|
|
var ACTION_GROUP_ADD = 'group.add';
|
|
var ACTION_GROUP_UPDATE = 'group.update';
|
|
var ACTION_GROUP_REMOVE = 'group.remove';
|
|
var ACTION_GROUP_MEMBERSHIP = 'group.membership';
|
|
|
|
var ACTION_INSTALL_FINISH = 'cloudron.install.finish';
|
|
|
|
var ACTION_START = 'cloudron.start';
|
|
var ACTION_SERVICE_CONFIGURE = 'service.configure';
|
|
var ACTION_SERVICE_REBUILD = 'service.rebuild';
|
|
var ACTION_SERVICE_RESTART = 'service.restart';
|
|
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_LOGIN_GHOST = 'user.login.ghost';
|
|
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_USER_DIRECTORY_PROFILE_CONFIG_UPDATE = 'userdirectory.profileconfig.update';
|
|
|
|
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 data = eventLog.data;
|
|
var errorMessage = data.errorMessage;
|
|
var details, app;
|
|
|
|
function appName(pre, app, defaultValue) {
|
|
if (appIdContext) return defaultValue || '';
|
|
|
|
pre = pre ? (pre + ' ') : '';
|
|
|
|
return pre + (app.label || app.fqdn || app.subdomain) + ' (' + app.manifest.title + ') ';
|
|
}
|
|
|
|
function eventBy() {
|
|
if (eventLog.source && eventLog.source.username) return ' by ' + eventLog.source.username;
|
|
return '';
|
|
}
|
|
|
|
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 at ' + data.remotePath;
|
|
|
|
case ACTION_APP_CONFIGURE: {
|
|
if (!data.app) return '';
|
|
app = data.app;
|
|
|
|
if ('accessRestriction' in data) { // since it can be null
|
|
return 'Access restriction ' + appName('of', app) + ' was changed';
|
|
} else if ('operators' in data) {
|
|
return 'Operators ' + appName('of', app) + ' was changed';
|
|
} else if (data.label) {
|
|
return `Label ${appName('of', app)} was set to ${data.label}`;
|
|
} else if (data.tags) {
|
|
return `Tags ${appName('of', app)} was set to ${data.tags.join(', ')}`;
|
|
} else if (data.icon) {
|
|
return 'Icon ' + appName('of', app) + ' was changed';
|
|
} else if (data.memoryLimit) {
|
|
return 'Memory limit ' + appName('of', app) + ' was set to ' + prettyBinarySize(data.memoryLimit);
|
|
} else if (data.cpuShares) { // replaced by cpuQuota in 8.0
|
|
return 'CPU shares ' + appName('of', app) + ' was set to ' + Math.round((data.cpuShares * 100)/1024) + '%';
|
|
} else if (data.cpuQuota) {
|
|
return 'CPU quota ' + appName('of', app) + ' was set to ' + data.cpuQuota + '%';
|
|
} else if (data.env) {
|
|
return 'Env vars ' + appName('of', app) + ' was changed';
|
|
} else if ('debugMode' in data) { // since it can be null
|
|
if (data.debugMode) {
|
|
return appName('', app, 'App') + ' was placed in repair mode';
|
|
} else {
|
|
return appName('', app, 'App') + ' was taken out of repair mode';
|
|
}
|
|
} else if ('enableBackup' in data) {
|
|
return 'Automatic backups ' + appName('of', app) + ' was ' + (data.enableBackup ? 'enabled' : 'disabled');
|
|
} else if ('enableAutomaticUpdate' in data) {
|
|
return 'Automatic updates ' + appName('of', app) + ' was ' + (data.enableAutomaticUpdate ? 'enabled' : 'disabled');
|
|
} else if ('reverseProxyConfig' in data) {
|
|
return 'Reverse proxy configuration ' + appName('of', app) + ' was updated';
|
|
} else if ('upstreamUri' in data) {
|
|
return 'Upstream URI ' + appName('of', app) + ' was updated';
|
|
} else if ('cert' in data) {
|
|
if (data.cert) {
|
|
return 'Custom certificate was set ' + appName('for', app);
|
|
} else {
|
|
return 'Certificate ' + appName('of', app) + ' was reset';
|
|
}
|
|
} else if (data.subdomain) {
|
|
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');
|
|
} 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');
|
|
} else if (!angular.equals(data.portBindings, data.app.portBindings)) {
|
|
return 'Port bindings ' + appName('of', app) + ' was changed';
|
|
}
|
|
} else if ('dataDir' in data) {
|
|
if (data.dataDir) {
|
|
return 'Data directory ' + appName('of', app) + ' was set ' + data.dataDir;
|
|
} else {
|
|
return 'Data directory ' + appName('of', app) + ' was reset';
|
|
}
|
|
} else if ('icon' in data) {
|
|
if (data.icon) {
|
|
return 'Icon ' + appName('of', app) + ' was set';
|
|
} else {
|
|
return 'Icon ' + appName('of', app) + ' was reset';
|
|
}
|
|
} else if ('mailboxName' in data) {
|
|
if (data.mailboxName) {
|
|
return `Mailbox ${appName('of', app)} was set to ${data.mailboxDisplayName || '' } ${data.mailboxName}@${data.mailboxDomain}`;
|
|
} else {
|
|
return 'Mailbox ' + appName('of', app) + ' was disabled';
|
|
}
|
|
}
|
|
|
|
return appName('', app, 'App ') + 'was re-configured';
|
|
}
|
|
|
|
case ACTION_APP_INSTALL:
|
|
if (!data.app) return '';
|
|
return data.app.manifest.title + ' (package v' + data.app.manifest.version + ') was installed ' + appName('at', data.app) + eventBy();
|
|
|
|
case ACTION_APP_RESTORE:
|
|
if (!data.app) return '';
|
|
details = appName('', data.app, 'App') + ' was restored';
|
|
// 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.remotePath) details += ' using backup at ' + data.remotePath;
|
|
return details;
|
|
|
|
case ACTION_APP_IMPORT:
|
|
if (!data.app) return '';
|
|
details = appName('', data.app, 'App') + ' was imported';
|
|
if (data.toManifest) details += ' to version ' + data.toManifest.version;
|
|
if (data.remotePath) details += ' using backup at ' + data.remotePath;
|
|
return details;
|
|
|
|
case ACTION_APP_UNINSTALL:
|
|
if (!data.app) return '';
|
|
return appName('', data.app, 'App') + ' (package v' + data.app.manifest.version + ') was uninstalled';
|
|
|
|
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;
|
|
|
|
case ACTION_APP_UPDATE_FINISH:
|
|
if (!data.app) return '';
|
|
return appName('', data.app, 'App') + ' was updated to v' + data.app.manifest.version;
|
|
|
|
case ACTION_APP_BACKUP:
|
|
if (!data.app) return '';
|
|
return 'Backup ' + appName('of', data.app) + ' started';
|
|
|
|
case ACTION_APP_BACKUP_FINISH:
|
|
if (!data.app) return '';
|
|
if (data.errorMessage) {
|
|
return 'Backup ' + appName('of', data.app) + ' failed: ' + data.errorMessage;
|
|
} else {
|
|
return 'Backup ' + appName('of', data.app) + ' succeeded with backup id ' + data.backupId + ' at ' + data.remotePath;
|
|
}
|
|
|
|
case ACTION_APP_CLONE:
|
|
if (appIdContext === data.oldAppId) {
|
|
return 'App was cloned to ' + data.newApp.fqdn + ' using backup at ' + data.remotePath;
|
|
} else if (appIdContext === data.appId) {
|
|
return 'App was cloned from ' + data.oldApp.fqdn + ' using backup at ' + data.remotePath;
|
|
} else {
|
|
return appName('', data.newApp, 'App') + ' was cloned ' + appName('from', data.oldApp) + ' using backup at ' + data.remotePath;
|
|
}
|
|
|
|
case ACTION_APP_REPAIR:
|
|
return appName('', data.app, 'App') + ' was re-configured'; // re-configure of email apps is more common?
|
|
|
|
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 '';
|
|
return appName('', data.app, 'App') + ' ran out of memory';
|
|
|
|
case ACTION_APP_DOWN:
|
|
if (!data.app) return '';
|
|
return appName('', data.app, 'App') + ' is down';
|
|
|
|
case ACTION_APP_UP:
|
|
if (!data.app) return '';
|
|
return appName('', data.app, 'App') + ' is back online';
|
|
|
|
case ACTION_APP_START:
|
|
if (!data.app) return '';
|
|
return appName('', data.app, 'App') + ' was started';
|
|
|
|
case ACTION_APP_STOP:
|
|
if (!data.app) return '';
|
|
return appName('', data.app, 'App') + ' was stopped';
|
|
|
|
case ACTION_APP_RESTART:
|
|
if (!data.app) return '';
|
|
return appName('', data.app, 'App') + ' was restarted';
|
|
|
|
case ACTION_ARCHIVES_ADD:
|
|
return 'Backup ' + data.backupId + ' added to archive';
|
|
|
|
case ACTION_ARCHIVES_DEL:
|
|
return 'Backup ' + data.backupId + ' deleted from archive';
|
|
|
|
case ACTION_BACKUP_START:
|
|
return 'Backup started';
|
|
|
|
case ACTION_BACKUP_FINISH:
|
|
if (!errorMessage) {
|
|
return 'Cloudron backup created at ' + data.remotePath;
|
|
} 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.removedBoxBackupPaths ? data.removedBoxBackupPaths.length : '0') + ' backups';
|
|
|
|
case ACTION_BRANDING_AVATAR:
|
|
return 'Cloudron Avatar Changed';
|
|
|
|
case ACTION_BRANDING_NAME:
|
|
return 'Cloudron Name set to ' + data.name;
|
|
|
|
case ACTION_BRANDING_FOOTER:
|
|
return 'Cloudron Footer set to ' + data.footer;
|
|
|
|
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_CERTIFICATE_CLEANUP:
|
|
return 'Certificate(s) of ' + data.domains.join(',') + ' was cleaned up since they expired 6 months ago';
|
|
|
|
case ACTION_DASHBOARD_DOMAIN_UPDATE:
|
|
return 'Dashboard domain set to ' + data.fqdn || (data.subdomain + '.' + data.domain);
|
|
|
|
case ACTION_DIRECTORY_SERVER_CONFIGURE:
|
|
if (data.fromEnabled !== data.toEnabled) {
|
|
return 'Directory server was ' + (data.toEnabled ? 'enabled' : 'disabled');
|
|
} else {
|
|
return 'Directory server configuration was changed';
|
|
}
|
|
|
|
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_EXTERNAL_LDAP_CONFIGURE:
|
|
if (data.config.provider === 'noop') {
|
|
return 'External Directory disabled';
|
|
} else {
|
|
return 'External Directory set to ' + data.config.url + ' (' + data.config.provider + ')';
|
|
}
|
|
|
|
case ACTION_GROUP_ADD:
|
|
return 'Group ' + data.name + ' was added';
|
|
|
|
case ACTION_GROUP_UPDATE:
|
|
return 'Group name changed from ' + data.oldName + ' to ' + data.group.name;
|
|
|
|
case ACTION_GROUP_REMOVE:
|
|
return 'Group ' + data.group.name + ' was removed';
|
|
|
|
case ACTION_GROUP_MEMBERSHIP:
|
|
return 'Group membership of ' + data.group.name + ' changed. Now was ' + data.userIds.length + ' member(s).';
|
|
|
|
case ACTION_INSTALL_FINISH:
|
|
return 'Cloudron version ' + data.version + ' installed';
|
|
|
|
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 ' + data.name + '@' + data.domain + ' was added';
|
|
|
|
case ACTION_MAIL_MAILBOX_UPDATE:
|
|
if (data.aliases) {
|
|
return 'Mailbox aliases of ' + data.name + '@' + data.domain + ' was updated';
|
|
} else {
|
|
return 'Mailbox ' + data.name + '@' + data.domain + ' was updated';
|
|
}
|
|
|
|
case ACTION_MAIL_MAILBOX_REMOVE:
|
|
return 'Mailbox ' + data.name + '@' + data.domain + ' was removed';
|
|
|
|
case ACTION_MAIL_LIST_ADD:
|
|
return 'Mail list ' + data.name + '@' + data.domain + 'was added';
|
|
|
|
case ACTION_MAIL_LIST_UPDATE:
|
|
return 'Mail list ' + data.name + '@' + data.domain + ' was updated';
|
|
|
|
case ACTION_MAIL_LIST_REMOVE:
|
|
return 'Mail list ' + data.name + '@' + data.domain + ' was removed';
|
|
|
|
case ACTION_START:
|
|
return 'Cloudron started with version ' + data.version;
|
|
|
|
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';
|
|
|
|
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 'User ' + data.email + (data.user.username ? ' (' + data.user.username + ')' : '') + ' was added';
|
|
|
|
case ACTION_USER_UPDATE:
|
|
return 'User ' + (data.user ? (data.user.email + (data.user.username ? ' (' + data.user.username + ')' : '')) : data.userId) + ' was updated';
|
|
|
|
case ACTION_USER_REMOVE:
|
|
return 'User ' + (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:
|
|
if (data.mailboxId) {
|
|
return 'User ' + (data.user ? data.user.username : data.userId) + ' logged in to mailbox ' + data.mailboxId;
|
|
} else if (data.appId) {
|
|
app = this.getCachedAppSync(data.appId);
|
|
return 'User ' + (data.user ? data.user.username : data.userId) + ' logged in to ' + (app ? app.fqdn : data.appId);
|
|
} else { // can happen with directoryserver
|
|
return 'User ' + (data.user ? data.user.username : data.userId) + ' authenticated';
|
|
}
|
|
|
|
case ACTION_USER_LOGIN_GHOST:
|
|
return 'User ' + (data.user ? data.user.username : data.userId) + ' was impersonated';
|
|
|
|
case ACTION_USER_LOGOUT:
|
|
return 'User ' + (data.user ? data.user.username : data.userId) + ' logged out';
|
|
|
|
case ACTION_USER_DIRECTORY_PROFILE_CONFIG_UPDATE:
|
|
return 'User directory profile config updated. Mandatory 2FA: ' + (data.config.mandatory2FA) + ' Lock profiles: ' + (data.config.lockUserProfiles);
|
|
|
|
case ACTION_DYNDNS_UPDATE: {
|
|
details = data.errorMessage ? 'Error updating DNS. ' : 'Updated DNS. ';
|
|
if (data.fromIpv4 !== data.toIpv4) details += 'From IPv4 ' + data.fromIpv4 + ' to ' + data.toIpv4 + '. ';
|
|
if (data.fromIpv6 !== data.toIpv6) details += 'From IPv6 ' + data.fromIpv6 + ' to ' + data.toIpv6 + '.';
|
|
if (data.errorMessage) details += ' ' + data.errorMessage;
|
|
return details;
|
|
}
|
|
|
|
case ACTION_SUPPORT_SSH:
|
|
return 'Remote Support was ' + (data.enable ? 'enabled' : 'disabled');
|
|
|
|
case ACTION_SUPPORT_TICKET:
|
|
return 'Support ticket was created';
|
|
|
|
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);
|
|
}
|
|
|
|
return line;
|
|
};
|
|
|
|
|
|
client = new Client();
|
|
return client;
|
|
}]);
|