Files
cloudron-box/src/settings.js

845 lines
28 KiB
JavaScript
Raw Normal View History

'use strict';
exports = module.exports = {
getAutoupdatePattern,
setAutoupdatePattern,
2020-08-15 18:19:01 -07:00
getTimeZone,
setTimeZone,
2020-08-15 18:19:01 -07:00
getCloudronName,
setCloudronName,
2020-08-15 18:19:01 -07:00
getCloudronAvatar,
setCloudronAvatar,
2020-08-15 18:19:01 -07:00
getDynamicDnsConfig,
setDynamicDnsConfig,
2017-01-02 13:05:48 +01:00
2020-08-15 18:19:01 -07:00
getUnstableAppsConfig,
setUnstableAppsConfig,
2019-04-27 22:30:32 +02:00
2020-08-15 18:19:01 -07:00
getBackupConfig,
setBackupConfig,
setBackupCredentials,
2015-11-07 18:02:45 -08:00
getServicesConfig,
setServicesConfig,
2020-08-15 18:19:01 -07:00
getExternalLdapConfig,
setExternalLdapConfig,
2020-08-15 18:19:01 -07:00
getRegistryConfig,
setRegistryConfig,
2019-10-22 22:07:44 -07:00
2020-08-15 18:19:01 -07:00
getLicenseKey,
setLicenseKey,
2020-11-17 18:58:43 +01:00
getLanguage,
setLanguage,
2020-08-15 18:19:01 -07:00
getCloudronId,
setCloudronId,
2020-08-15 18:19:01 -07:00
getCloudronToken,
setCloudronToken,
2019-04-30 22:57:43 -07:00
2020-08-15 18:19:01 -07:00
getSysinfoConfig,
setSysinfoConfig,
2019-10-29 15:46:33 -07:00
2020-08-15 18:19:01 -07:00
getFooter,
setFooter,
2020-08-15 18:19:01 -07:00
getDirectoryConfig,
setDirectoryConfig,
2020-08-15 18:19:01 -07:00
getAppstoreListingConfig,
setAppstoreListingConfig,
2020-03-15 17:07:07 -07:00
getFirewallBlocklist,
setFirewallBlocklist,
2020-08-15 18:19:01 -07:00
getSupportConfig,
provider,
list,
2020-08-15 18:19:01 -07:00
initCache,
// these values come from the cache
2020-08-15 18:19:01 -07:00
apiServerOrigin,
webServerOrigin,
2021-05-05 12:29:04 -07:00
dashboardDomain,
setDashboardLocation,
setMailLocation,
mailFqdn,
mailDomain,
2021-05-05 12:29:04 -07:00
dashboardOrigin,
dashboardFqdn,
2020-08-15 18:19:01 -07:00
isDemo,
// booleans. if you add an entry here, be sure to fix getAll
2017-01-02 13:05:48 +01:00
DYNAMIC_DNS_KEY: 'dynamic_dns',
2019-04-27 22:30:32 +02:00
UNSTABLE_APPS_KEY: 'unstable_apps',
2019-07-25 11:16:52 -07:00
DEMO_KEY: 'demo',
// json. if you add an entry here, be sure to fix getAll
2015-11-07 18:02:45 -08:00
BACKUP_CONFIG_KEY: 'backup_config',
SERVICES_CONFIG_KEY: 'services_config',
EXTERNAL_LDAP_KEY: 'external_ldap_config',
2019-10-22 22:07:44 -07:00
REGISTRY_CONFIG_KEY: 'registry_config',
2019-10-29 15:46:33 -07:00
SYSINFO_CONFIG_KEY: 'sysinfo_config',
2020-02-05 11:58:10 -08:00
APPSTORE_LISTING_CONFIG_KEY: 'appstore_listing_config',
2020-02-05 14:30:56 -08:00
SUPPORT_CONFIG_KEY: 'support_config',
DIRECTORY_CONFIG_KEY: 'directory_config',
// strings
AUTOUPDATE_PATTERN_KEY: 'autoupdate_pattern',
TIME_ZONE_KEY: 'time_zone',
CLOUDRON_NAME_KEY: 'cloudron_name',
2019-04-30 22:57:43 -07:00
LICENSE_KEY: 'license_key',
2020-11-17 18:58:43 +01:00
LANGUAGE_KEY: 'language',
2019-04-30 22:57:43 -07:00
CLOUDRON_ID_KEY: 'cloudron_id',
2021-06-03 12:20:44 -07:00
CLOUDRON_TOKEN_KEY: 'cloudron_token', // apstore token
FIREWALL_BLOCKLIST_KEY: 'firewall_blocklist',
2019-07-25 11:16:52 -07:00
API_SERVER_ORIGIN_KEY: 'api_server_origin',
WEB_SERVER_ORIGIN_KEY: 'web_server_origin',
2021-05-05 12:29:04 -07:00
DASHBOARD_DOMAIN_KEY: 'admin_domain',
DASHBOARD_FQDN_KEY: 'admin_fqdn',
MAIL_DOMAIN_KEY: 'mail_domain',
MAIL_FQDN_KEY: 'mail_fqdn',
2019-07-25 11:16:52 -07:00
PROVIDER_KEY: 'provider',
FOOTER_KEY: 'footer',
// blobs
CLOUDRON_AVATAR_KEY: 'cloudron_avatar',
// testing
_setApiServerOrigin: setApiServerOrigin,
_clear: clear
};
const assert = require('assert'),
backups = require('./backups.js'),
2019-10-22 11:03:56 -07:00
BoxError = require('./boxerror.js'),
2016-12-14 14:54:17 +01:00
constants = require('./constants.js'),
cron = require('./cron.js'),
CronJob = require('cron').CronJob,
database = require('./database.js'),
debug = require('debug')('box:settings'),
2019-10-22 22:07:44 -07:00
docker = require('./docker.js'),
2019-10-25 15:58:11 -07:00
externalLdap = require('./externalldap.js'),
2016-06-02 13:36:47 -07:00
moment = require('moment-timezone'),
2021-05-14 15:07:29 -07:00
mounts = require('./mounts.js'),
paths = require('./paths.js'),
safe = require('safetydance'),
settingsdb = require('./settingsdb.js'),
2019-10-29 20:08:45 -07:00
sysinfo = require('./sysinfo.js'),
2020-11-19 23:38:59 +01:00
translation = require('./translation.js'),
_ = require('underscore');
const SETTINGS_FIELDS = [ 'name', 'value' ].join(',');
const SETTINGS_BLOB_FIELDS = [ 'name', 'valueBlob' ].join(',');
let gDefaults = (function () {
var result = { };
result[exports.AUTOUPDATE_PATTERN_KEY] = cron.DEFAULT_AUTOUPDATE_PATTERN;
result[exports.TIME_ZONE_KEY] = 'America/Los_Angeles';
result[exports.CLOUDRON_NAME_KEY] = 'Cloudron';
2017-01-02 13:05:48 +01:00
result[exports.DYNAMIC_DNS_KEY] = false;
2019-11-11 08:42:00 -08:00
result[exports.UNSTABLE_APPS_KEY] = true;
2019-04-30 22:57:43 -07:00
result[exports.LICENSE_KEY] = '';
2020-11-17 18:58:43 +01:00
result[exports.LANGUAGE_KEY] = 'en';
2019-04-30 22:57:43 -07:00
result[exports.CLOUDRON_ID_KEY] = '';
result[exports.CLOUDRON_TOKEN_KEY] = '';
2016-10-21 12:48:48 +02:00
result[exports.BACKUP_CONFIG_KEY] = {
provider: 'filesystem',
backupFolder: '/var/backups',
format: 'tgz',
encryption: null,
retentionPolicy: { keepWithinSecs: 2 * 24 * 60 * 60 }, // 2 days
2020-07-29 09:34:23 -07:00
schedulePattern: '00 00 23 * * *' // every day at 11pm
2016-10-21 12:48:48 +02:00
};
result[exports.SERVICES_CONFIG_KEY] = {};
2019-10-25 15:40:22 -07:00
result[exports.EXTERNAL_LDAP_KEY] = {
provider: 'noop',
autoCreate: false
2019-10-25 15:40:22 -07:00
};
result[exports.REGISTRY_CONFIG_KEY] = {
provider: 'noop'
};
2019-10-29 15:46:33 -07:00
result[exports.SYSINFO_CONFIG_KEY] = {
provider: 'generic'
};
result[exports.DIRECTORY_CONFIG_KEY] = {
2020-07-10 10:00:03 -07:00
lockUserProfiles: false,
mandatory2FA: false
};
2021-05-05 12:29:04 -07:00
result[exports.DASHBOARD_DOMAIN_KEY] = '';
result[exports.DASHBOARD_FQDN_KEY] = '';
result[exports.MAIL_DOMAIN_KEY] = '';
result[exports.MAIL_FQDN_KEY] = '';
result[exports.FIREWALL_BLOCKLIST_KEY] = '';
result[exports.API_SERVER_ORIGIN_KEY] = 'https://api.cloudron.io';
result[exports.WEB_SERVER_ORIGIN_KEY] = 'https://cloudron.io';
result[exports.DEMO_KEY] = false;
2020-02-05 11:58:10 -08:00
result[exports.APPSTORE_LISTING_CONFIG_KEY] = {
blacklist: [],
2020-02-26 09:01:22 -08:00
whitelist: null // null imples nothing is whitelisted. this is an array
2020-02-05 11:58:10 -08:00
};
2020-02-05 14:30:56 -08:00
result[exports.SUPPORT_CONFIG_KEY] = {
email: 'support@cloudron.io',
remoteSupport: true,
ticketFormBody:
'Use this form to open support tickets. You can also write directly to [support@cloudron.io](mailto:support@cloudron.io).\n\n'
2020-09-15 14:46:22 -07:00
+ '* [Knowledge Base & App Docs](https://docs.cloudron.io/apps/?support_view)\n'
+ '* [Custom App Packaging & API](https://docs.cloudron.io/custom-apps/tutorial/?support_view)\n'
2020-02-05 14:30:56 -08:00
+ '* [Forum](https://forum.cloudron.io/)\n\n',
submitTickets: true
};
result[exports.FOOTER_KEY] = '';
return result;
})();
let gCache = {};
function notifyChange(key, value) {
2019-03-04 15:45:04 -08:00
assert.strictEqual(typeof key, 'string');
// value is a variant
cron.handleSettingsChanged(key, value);
}
async function get(key) {
assert.strictEqual(typeof key, 'string');
const result = await database.query(`SELECT ${SETTINGS_FIELDS} FROM settings WHERE name = ?`, [ key ]);
if (result.length === 0) return null; // can't return the default value here because we might need to massage/json parse the result
return result[0].value;
}
async function set(key, value) {
assert.strictEqual(typeof key, 'string');
assert(value === null || typeof value === 'string');
await database.query('INSERT INTO settings (name, value) VALUES (?, ?) ON DUPLICATE KEY UPDATE value=VALUES(value)', [ key, value ]); // don't rely on affectedRows here since it gives 2
}
async function getBlob(key) {
assert.strictEqual(typeof key, 'string');
const result = await database.query(`SELECT ${SETTINGS_BLOB_FIELDS} FROM settings WHERE name = ?`, [ key ]);
if (result.length === 0) return null;
return result[0].valueBlob;
}
async function setBlob(key, value) {
assert.strictEqual(typeof key, 'string');
assert(value === null || Buffer.isBuffer(value));
await database.query('INSERT INTO settings (name, valueBlob) VALUES (?, ?) ON DUPLICATE KEY UPDATE valueBlob=VALUES(valueBlob)', [ key, value ]); // don't rely on affectedRows here since it gives 2
}
async function clear() {
await database.query('DELETE FROM settings');
}
function setAutoupdatePattern(pattern, callback) {
assert.strictEqual(typeof pattern, 'string');
assert.strictEqual(typeof callback, 'function');
if (pattern !== constants.AUTOUPDATE_PATTERN_NEVER) { // check if pattern is valid
var job = safe.safeCall(function () { return new CronJob(pattern); });
2019-10-22 11:03:56 -07:00
if (!job) return callback(new BoxError(BoxError.BAD_FIELD, 'Invalid pattern', { field: 'pattern' }));
}
settingsdb.set(exports.AUTOUPDATE_PATTERN_KEY, pattern, function (error) {
if (error) return callback(error);
notifyChange(exports.AUTOUPDATE_PATTERN_KEY, pattern);
return callback(null);
});
}
function getAutoupdatePattern(callback) {
assert.strictEqual(typeof callback, 'function');
settingsdb.get(exports.AUTOUPDATE_PATTERN_KEY, function (error, pattern) {
if (error && error.reason === BoxError.NOT_FOUND) return callback(null, gDefaults[exports.AUTOUPDATE_PATTERN_KEY]);
if (error) return callback(error);
callback(null, pattern);
});
}
function setTimeZone(tz, callback) {
assert.strictEqual(typeof tz, 'string');
assert.strictEqual(typeof callback, 'function');
2019-10-22 11:03:56 -07:00
if (moment.tz.names().indexOf(tz) === -1) return callback(new BoxError(BoxError.BAD_FIELD, 'Bad timeZone', { field: 'timezone' }));
2016-06-02 13:36:47 -07:00
settingsdb.set(exports.TIME_ZONE_KEY, tz, function (error) {
if (error) return callback(error);
notifyChange(exports.TIME_ZONE_KEY, tz);
return callback(null);
});
}
function getTimeZone(callback) {
assert.strictEqual(typeof callback, 'function');
settingsdb.get(exports.TIME_ZONE_KEY, function (error, tz) {
if (error && error.reason === BoxError.NOT_FOUND) return callback(null, gDefaults[exports.TIME_ZONE_KEY]);
if (error) return callback(error);
callback(null, tz);
});
}
async function getCloudronName() {
const name = await get(exports.CLOUDRON_NAME_KEY);
if (name === null) return gDefaults[exports.CLOUDRON_NAME_KEY];
return name;
}
async function setCloudronName(name) {
assert.strictEqual(typeof name, 'string');
if (!name) throw new BoxError(BoxError.BAD_FIELD, 'name is empty', { field: 'name' });
2016-06-02 12:51:39 -07:00
// some arbitrary restrictions (for sake of ui layout)
2021-01-07 22:49:52 +01:00
// if this is changed, adjust dashboard/branding.html
if (name.length > 64) throw new BoxError(BoxError.BAD_FIELD, 'name cannot exceed 64 characters', { field: 'name' });
await set(exports.CLOUDRON_NAME_KEY, name);
notifyChange(exports.CLOUDRON_NAME_KEY, name);
}
async function getCloudronAvatar() {
let avatar = await getBlob(exports.CLOUDRON_AVATAR_KEY);
if (avatar) return avatar;
// try default fallback
avatar = safe.fs.readFileSync(paths.CLOUDRON_DEFAULT_AVATAR_FILE);
if (avatar) return avatar;
throw new BoxError(BoxError.FS_ERROR, `Could not read avatar: ${safe.error.message}`);
}
async function setCloudronAvatar(avatar) {
2021-04-29 15:37:32 -07:00
assert(Buffer.isBuffer(avatar));
await setBlob(exports.CLOUDRON_AVATAR_KEY, avatar);
}
2017-01-02 13:05:48 +01:00
function getDynamicDnsConfig(callback) {
assert.strictEqual(typeof callback, 'function');
settingsdb.get(exports.DYNAMIC_DNS_KEY, function (error, enabled) {
if (error && error.reason === BoxError.NOT_FOUND) return callback(null, gDefaults[exports.DYNAMIC_DNS_KEY]);
if (error) return callback(error);
2017-01-02 13:05:48 +01:00
callback(null, !!enabled); // settingsdb holds string values only
2017-01-02 13:05:48 +01:00
});
}
function setDynamicDnsConfig(enabled, callback) {
assert.strictEqual(typeof enabled, 'boolean');
assert.strictEqual(typeof callback, 'function');
// settingsdb takes string values only
settingsdb.set(exports.DYNAMIC_DNS_KEY, enabled ? 'enabled' : '', function (error) {
if (error) return callback(error);
2017-01-02 13:05:48 +01:00
notifyChange(exports.DYNAMIC_DNS_KEY, enabled);
2017-01-02 13:05:48 +01:00
return callback(null);
});
}
async function getUnstableAppsConfig() {
const result = await get(exports.UNSTABLE_APPS_KEY);
2021-08-18 15:54:53 -07:00
if (result === null) return gDefaults[exports.UNSTABLE_APPS_KEY];
return !!result; // db holds string values only
2019-04-27 22:30:32 +02:00
}
async function setUnstableAppsConfig(enabled) {
2019-04-27 22:30:32 +02:00
assert.strictEqual(typeof enabled, 'boolean');
await set(exports.UNSTABLE_APPS_KEY, enabled ? 'enabled' : ''); // db holds string values only
notifyChange(exports.UNSTABLE_APPS_KEY, enabled);
2019-04-27 22:30:32 +02:00
}
2015-11-07 18:02:45 -08:00
function getBackupConfig(callback) {
assert.strictEqual(typeof callback, 'function');
2021-05-14 15:07:29 -07:00
settingsdb.get(exports.BACKUP_CONFIG_KEY, async function (error, value) {
if (error && error.reason === BoxError.NOT_FOUND) return callback(null, gDefaults[exports.BACKUP_CONFIG_KEY]);
if (error) return callback(error);
2015-11-07 18:02:45 -08:00
2021-05-14 15:07:29 -07:00
const backupConfig = JSON.parse(value); // provider, token, password, region, prefix, bucket
2021-05-17 15:58:38 -07:00
if (backupConfig.provider === 'sshfs' || backupConfig.provider === 'cifs' || backupConfig.provider === 'nfs' || backupConfig.provider === 'ext4' || backupConfig.provider === 'mountpoint') {
backupConfig.mountStatus = await mounts.getStatus(backupConfig.provider, backupConfig.mountPoint); // { state, message }
2021-05-14 15:07:29 -07:00
}
callback(null, backupConfig);
2015-11-07 18:02:45 -08:00
});
}
function mountOptionsChanged(currentConfig, backupConfig) {
return currentConfig.provider !== backupConfig.provider
|| currentConfig.mountPoint !== backupConfig.mountPoint
|| !_.isEqual(currentConfig.mountOptions, backupConfig.mountOptions);
}
function mountObject(backupConfig) {
return {
name: 'backup',
hostPath: backupConfig.mountPoint,
mountType: backupConfig.provider,
mountOptions: backupConfig.mountOptions
};
}
2015-11-07 18:02:45 -08:00
function setBackupConfig(backupConfig, callback) {
assert.strictEqual(typeof backupConfig, 'object');
assert.strictEqual(typeof callback, 'function');
getBackupConfig(async function (error, oldConfig) {
if (error) return callback(error);
backups.injectPrivateFields(backupConfig, oldConfig);
2021-07-14 11:07:19 -07:00
if (mounts.isMountProvider(backupConfig.provider) && (!mounts.isMountProvider(oldConfig.provider) || mountOptionsChanged(oldConfig, backupConfig))) {
error = mounts.validateMountOptions(backupConfig.provider, backupConfig.mountOptions);
if (error) return callback(error);
[error] = await safe(mounts.tryAddMount(mountObject(backupConfig), { timeout: 10 })); // 10 seconds
2021-06-21 22:37:32 -07:00
if (error) {
2021-07-14 11:07:19 -07:00
if (mounts.isMountProvider(oldConfig.provider)) { // put back the old mount configuration
2021-06-21 22:37:32 -07:00
debug('setBackupConfig: rolling back to previous mount configuration');
await safe(mounts.tryAddMount(mountObject(oldConfig), { timeout: 10 }));
2021-06-21 22:37:32 -07:00
}
return callback(error);
}
}
2021-05-14 15:07:29 -07:00
backups.testConfig(backupConfig, async function (error) {
2019-10-22 20:36:20 -07:00
if (error) return callback(error);
2016-10-11 15:56:07 +02:00
2020-05-14 11:18:41 -07:00
if ('password' in backupConfig) { // user set password
backupConfig.encryption = backups.generateEncryptionKeysSync(backupConfig.password);
delete backupConfig.password;
}
// if any of these changes, we have to clear the cache
if ([ 'format', 'provider', 'prefix', 'bucket', 'region', 'endpoint', 'backupFolder', 'mountPoint', 'encryption' ].some(p => backupConfig[p] !== oldConfig[p])) {
debug('setBackupConfig: clearing backup cache');
backups.cleanupCacheFilesSync();
}
settingsdb.set(exports.BACKUP_CONFIG_KEY, JSON.stringify(backupConfig), async function (error) {
2021-05-14 15:07:29 -07:00
if (error) return callback(error);
2021-07-14 11:07:19 -07:00
if (mounts.isMountProvider(oldConfig.provider) && !mounts.isMountProvider(backupConfig.provider)) {
debug('setBackupConfig: removing old backup mount point');
await safe(mounts.removeMount(mountObject(oldConfig)));
}
notifyChange(exports.BACKUP_CONFIG_KEY, backupConfig);
2016-10-11 15:56:07 +02:00
2020-01-31 13:37:07 -08:00
backups.configureCollectd(backupConfig, callback);
});
});
2015-11-07 18:02:45 -08:00
});
}
function setBackupCredentials(credentials, callback) {
assert.strictEqual(typeof credentials, 'object');
assert.strictEqual(typeof callback, 'function');
getBackupConfig(function (error, currentConfig) {
if (error) return callback(error);
// preserve these fields
2020-08-19 14:38:59 -07:00
const extra = _.pick(currentConfig, 'retentionPolicy', 'schedulePattern', 'copyConcurrency', 'syncConcurrency', 'memoryLimit', 'downloadConcurrency', 'deleteConcurrency', 'uploadPartSize');
const backupConfig = _.extend({}, credentials, extra);
backups.cleanupCacheFilesSync();
settingsdb.set(exports.BACKUP_CONFIG_KEY, JSON.stringify(backupConfig), function (error) {
if (error) return callback(error);
notifyChange(exports.BACKUP_CONFIG_KEY, backupConfig);
backups.configureCollectd(backupConfig, callback);
});
});
}
function getServicesConfig(callback) {
assert.strictEqual(typeof callback, 'function');
settingsdb.get(exports.SERVICES_CONFIG_KEY, function (error, value) {
if (error && error.reason === BoxError.NOT_FOUND) return callback(null, gDefaults[exports.SERVICES_CONFIG_KEY]);
if (error) return callback(error);
callback(null, JSON.parse(value));
});
}
function setServicesConfig(platformConfig, callback) {
assert.strictEqual(typeof callback, 'function');
settingsdb.set(exports.SERVICES_CONFIG_KEY, JSON.stringify(platformConfig), function (error) {
if (error) return callback(error);
notifyChange(exports.SERVICES_CONFIG_KEY, platformConfig);
2020-09-22 21:42:47 -07:00
callback(null);
});
}
function getExternalLdapConfig(callback) {
assert.strictEqual(typeof callback, 'function');
settingsdb.get(exports.EXTERNAL_LDAP_KEY, function (error, value) {
if (error && error.reason === BoxError.NOT_FOUND) return callback(null, gDefaults[exports.EXTERNAL_LDAP_KEY]);
if (error) return callback(error);
let config = JSON.parse(value);
// ensure new keys
if (!config.autoCreate) config.autoCreate = false;
callback(null, config);
});
}
function setExternalLdapConfig(externalLdapConfig, callback) {
assert.strictEqual(typeof externalLdapConfig, 'object');
assert.strictEqual(typeof callback, 'function');
2020-07-22 17:53:04 -07:00
if (isDemo()) return callback(new BoxError(BoxError.BAD_FIELD, 'Not allowed in demo mode'));
getExternalLdapConfig(function (error, currentConfig) {
2019-10-24 13:41:41 -07:00
if (error) return callback(error);
externalLdap.injectPrivateFields(externalLdapConfig, currentConfig);
2019-10-25 15:58:11 -07:00
externalLdap.testConfig(externalLdapConfig, function (error) {
if (error) return callback(error);
2019-10-25 15:58:11 -07:00
settingsdb.set(exports.EXTERNAL_LDAP_KEY, JSON.stringify(externalLdapConfig), function (error) {
if (error) return callback(error);
notifyChange(exports.EXTERNAL_LDAP_KEY, externalLdapConfig);
2019-10-25 15:58:11 -07:00
callback(null);
});
});
});
}
2019-10-22 22:07:44 -07:00
function getRegistryConfig(callback) {
assert.strictEqual(typeof callback, 'function');
settingsdb.get(exports.REGISTRY_CONFIG_KEY, function (error, value) {
if (error && error.reason === BoxError.NOT_FOUND) return callback(null, gDefaults[exports.REGISTRY_CONFIG_KEY]);
if (error) return callback(error);
2019-10-22 22:07:44 -07:00
callback(null, JSON.parse(value));
});
}
function setRegistryConfig(registryConfig, callback) {
assert.strictEqual(typeof registryConfig, 'object');
assert.strictEqual(typeof callback, 'function');
getRegistryConfig(function (error, curentConfig) {
if (error) return callback(error);
docker.injectPrivateFields(registryConfig, curentConfig);
docker.testRegistryConfig(registryConfig, function (error) {
if (error) return callback(error);
settingsdb.set(exports.REGISTRY_CONFIG_KEY, JSON.stringify(registryConfig), function (error) {
if (error) return callback(error);
2019-10-22 22:07:44 -07:00
notifyChange(exports.REGISTRY_CONFIG_KEY, registryConfig);
callback(null);
});
});
});
}
2019-10-29 15:46:33 -07:00
function getSysinfoConfig(callback) {
assert.strictEqual(typeof callback, 'function');
settingsdb.get(exports.SYSINFO_CONFIG_KEY, function (error, value) {
if (error && error.reason === BoxError.NOT_FOUND) return callback(null, gDefaults[exports.SYSINFO_CONFIG_KEY]);
if (error) return callback(error);
callback(null, JSON.parse(value));
});
}
function setSysinfoConfig(sysinfoConfig, callback) {
assert.strictEqual(typeof sysinfoConfig, 'object');
assert.strictEqual(typeof callback, 'function');
if (isDemo()) return callback(new BoxError(BoxError.BAD_FIELD, 'Not allowed in demo mode'));
2019-10-29 20:08:45 -07:00
sysinfo.testConfig(sysinfoConfig, function (error) {
2019-10-29 15:46:33 -07:00
if (error) return callback(error);
2019-10-29 20:08:45 -07:00
settingsdb.set(exports.SYSINFO_CONFIG_KEY, JSON.stringify(sysinfoConfig), function (error) {
if (error) return callback(error);
notifyChange(exports.SYSINFO_CONFIG_KEY, sysinfoConfig);
2019-10-29 15:46:33 -07:00
2019-10-29 20:08:45 -07:00
callback(null);
});
2019-10-29 15:46:33 -07:00
});
}
async function getDirectoryConfig() {
const value = await get(exports.DIRECTORY_CONFIG_KEY);
if (value === null) return gDefaults[exports.DIRECTORY_CONFIG_KEY];
return JSON.parse(value);
}
async function setDirectoryConfig(directoryConfig) {
assert.strictEqual(typeof directoryConfig, 'object');
if (isDemo()) throw new BoxError(BoxError.BAD_FIELD, 'Not allowed in demo mode');
await set(exports.DIRECTORY_CONFIG_KEY, JSON.stringify(directoryConfig));
notifyChange(exports.DIRECTORY_CONFIG_KEY, directoryConfig);
}
2021-08-18 15:54:53 -07:00
async function getAppstoreListingConfig() {
const value = await get(exports.APPSTORE_LISTING_CONFIG_KEY);
if (value === null) return gDefaults[exports.APPSTORE_LISTING_CONFIG_KEY];
2020-02-05 11:58:10 -08:00
2021-08-18 15:54:53 -07:00
return JSON.parse(value);
2020-02-05 11:58:10 -08:00
}
2021-08-18 15:54:53 -07:00
async function setAppstoreListingConfig(listingConfig) {
2020-03-15 17:07:07 -07:00
assert.strictEqual(typeof listingConfig, 'object');
2021-08-18 15:54:53 -07:00
await set(exports.APPSTORE_LISTING_CONFIG_KEY, JSON.stringify(listingConfig));
notifyChange(exports.APPSTORE_LISTING_CONFIG_KEY, listingConfig);
2020-03-15 17:07:07 -07:00
}
async function getFirewallBlocklist() {
const value = await getBlob(exports.FIREWALL_BLOCKLIST_KEY);
if (value === null) return gDefaults[exports.FIREWALL_BLOCKLIST_KEY];
return value.toString('utf8');
}
async function setFirewallBlocklist(blocklist) {
assert.strictEqual(typeof blocklist, 'string');
// store in blob since the value field is TEXT and has 16kb size limit
await setBlob(exports.FIREWALL_BLOCKLIST_KEY, Buffer.from(blocklist));
}
2020-03-15 17:07:07 -07:00
2021-08-18 15:54:53 -07:00
async function getSupportConfig() {
const value = await get(exports.SUPPORT_CONFIG_KEY);
if (value === null) return gDefaults[exports.SUPPORT_CONFIG_KEY];
2020-02-05 14:30:56 -08:00
2021-08-18 15:54:53 -07:00
return JSON.parse(value);
2020-02-05 14:30:56 -08:00
}
2021-08-18 15:54:53 -07:00
async function getLicenseKey() {
const value = get(exports.LICENSE_KEY);
if (value === null) return gDefaults[exports.LICENSE_KEY];
return value;
2019-04-30 22:57:43 -07:00
}
2021-08-18 15:54:53 -07:00
async function setLicenseKey(licenseKey) {
assert.strictEqual(typeof licenseKey, 'string');
2021-08-18 15:54:53 -07:00
await set(exports.LICENSE_KEY, licenseKey);
notifyChange(exports.LICENSE_KEY, licenseKey);
}
2021-08-19 11:00:35 -07:00
async function getLanguage() {
const value = await get(exports.LANGUAGE_KEY);
if (value === null) return gDefaults[exports.LANGUAGE_KEY];
return value;
2020-11-17 18:58:43 +01:00
}
2021-08-19 11:00:35 -07:00
async function setLanguage(language) {
2020-11-17 18:58:43 +01:00
assert.strictEqual(typeof language, 'string');
2021-08-19 11:00:35 -07:00
const languages = await translation.getLanguages();
2020-11-18 00:10:06 +01:00
2021-08-19 11:00:35 -07:00
if (languages.indexOf(language) === -1) throw new BoxError(BoxError.NOT_FOUND, 'Language not found');
2020-11-18 00:10:06 +01:00
2021-08-19 11:00:35 -07:00
await set(exports.LANGUAGE_KEY, language);
notifyChange(exports.LANGUAGE_KEY, language);
2020-11-17 18:58:43 +01:00
}
2021-08-18 15:54:53 -07:00
async function getCloudronId() {
const value = await get(exports.CLOUDRON_ID_KEY);
if (value === null) return gDefaults[exports.CLOUDRON_ID_KEY];
return value;
2019-04-30 22:57:43 -07:00
}
2021-08-18 15:54:53 -07:00
async function setCloudronId(cid) {
assert.strictEqual(typeof cid, 'string');
2021-08-18 15:54:53 -07:00
await set(exports.CLOUDRON_ID_KEY, cid);
notifyChange(exports.CLOUDRON_ID_KEY, cid);
}
2021-08-18 15:54:53 -07:00
async function getCloudronToken() {
const value = await get(exports.CLOUDRON_TOKEN_KEY);
if (value === null) return gDefaults[exports.CLOUDRON_TOKEN_KEY];
return value;
2019-04-30 22:57:43 -07:00
}
2021-08-18 15:54:53 -07:00
async function setCloudronToken(token) {
assert.strictEqual(typeof token, 'string');
2018-11-05 17:12:04 -08:00
2021-08-18 15:54:53 -07:00
await set(exports.CLOUDRON_TOKEN_KEY, token);
notifyChange(exports.CLOUDRON_TOKEN_KEY, token);
2016-07-26 14:31:07 +02:00
}
async function list() {
const settings = await database.query(`SELECT ${SETTINGS_FIELDS} FROM settings WHERE value IS NOT NULL ORDER BY name`);
const result = _.extend({ }, gDefaults);
settings.forEach(function (setting) { result[setting.name] = setting.value; });
// convert booleans
result[exports.DYNAMIC_DNS_KEY] = !!result[exports.DYNAMIC_DNS_KEY];
result[exports.UNSTABLE_APPS_KEY] = !!result[exports.UNSTABLE_APPS_KEY];
result[exports.DEMO_KEY] = !!result[exports.DEMO_KEY];
// convert JSON objects
[exports.BACKUP_CONFIG_KEY, exports.DIRECTORY_CONFIG_KEY, exports.SERVICES_CONFIG_KEY, exports.EXTERNAL_LDAP_KEY, exports.REGISTRY_CONFIG_KEY, exports.SYSINFO_CONFIG_KEY ].forEach(function (key) {
result[key] = typeof result[key] === 'object' ? result[key] : safe.JSON.parse(result[key]);
});
return result;
}
async function initCache() {
debug('initCache: pre-load settings');
const allSettings = await list();
const provider = safe.fs.readFileSync(paths.PROVIDER_FILE, 'utf8');
gCache = {
apiServerOrigin: allSettings[exports.API_SERVER_ORIGIN_KEY],
webServerOrigin: allSettings[exports.WEB_SERVER_ORIGIN_KEY],
dashboardDomain: allSettings[exports.DASHBOARD_DOMAIN_KEY],
dashboardFqdn: allSettings[exports.DASHBOARD_FQDN_KEY],
mailDomain: allSettings[exports.MAIL_DOMAIN_KEY],
mailFqdn: allSettings[exports.MAIL_FQDN_KEY],
isDemo: allSettings[exports.DEMO_KEY],
provider: provider ? provider.trim() : 'generic'
};
}
// this is together so we can do this in a transaction later
2021-05-05 12:29:04 -07:00
function setDashboardLocation(dashboardDomain, dashboardFqdn, callback) {
assert.strictEqual(typeof dashboardDomain, 'string');
2021-05-05 12:29:04 -07:00
assert.strictEqual(typeof dashboardFqdn, 'string');
assert.strictEqual(typeof callback, 'function');
2021-05-05 12:29:04 -07:00
settingsdb.set(exports.DASHBOARD_DOMAIN_KEY, dashboardDomain, function (error) {
if (error) return callback(error);
settingsdb.set(exports.DASHBOARD_FQDN_KEY, dashboardFqdn, function (error) {
if (error) return callback(error);
2021-05-05 12:29:04 -07:00
gCache.dashboardDomain = dashboardDomain;
gCache.dashboardFqdn = dashboardFqdn;
callback(null);
});
});
}
function setMailLocation(mailDomain, mailFqdn, callback) {
assert.strictEqual(typeof mailDomain, 'string');
assert.strictEqual(typeof mailFqdn, 'string');
assert.strictEqual(typeof callback, 'function');
settingsdb.set(exports.MAIL_DOMAIN_KEY, mailDomain, function (error) {
if (error) return callback(error);
settingsdb.set(exports.MAIL_FQDN_KEY, mailFqdn, function (error) {
if (error) return callback(error);
gCache.mailDomain = mailDomain;
gCache.mailFqdn = mailFqdn;
callback(null);
});
});
}
function setApiServerOrigin(origin, callback) {
assert.strictEqual(typeof origin, 'string');
assert.strictEqual(typeof callback, 'function');
settingsdb.set(exports.API_SERVER_ORIGIN_KEY, origin, function (error) {
if (error) return callback(error);
gCache.apiServerOrigin = origin;
notifyChange(exports.API_SERVER_ORIGIN_KEY, origin);
callback(null);
});
}
async function getFooter() {
const value = await get(exports.FOOTER_KEY);
if (value === null) return gDefaults[exports.FOOTER_KEY];
return value;
}
async function setFooter(footer) {
assert.strictEqual(typeof footer, 'string');
await set(exports.FOOTER_KEY, footer);
notifyChange(exports.FOOTER_KEY, footer);
}
2019-10-29 15:46:33 -07:00
function provider() { return gCache.provider; }
function apiServerOrigin() { return gCache.apiServerOrigin; }
function webServerOrigin() { return gCache.webServerOrigin; }
2021-05-05 12:29:04 -07:00
function dashboardDomain() { return gCache.dashboardDomain; }
function dashboardFqdn() { return gCache.dashboardFqdn; }
function isDemo() { return gCache.isDemo; }
function mailDomain() { return gCache.mailDomain; }
function mailFqdn() { return gCache.mailFqdn; }
2021-05-05 12:29:04 -07:00
function dashboardOrigin() { return 'https://' + dashboardFqdn(); }