make turn service optional

part of #810
This commit is contained in:
Girish Ramakrishnan
2023-07-13 15:06:07 +05:30
parent a2c53df042
commit 519b258a25
8 changed files with 141 additions and 5 deletions
+33 -5
View File
@@ -42,6 +42,7 @@ exports = module.exports = {
setEnvironment,
setMailbox,
setInbox,
setTurn,
setLocation,
setStorage,
repair,
@@ -106,6 +107,7 @@ exports = module.exports = {
ISTATE_PENDING_CONFIGURE: 'pending_configure', // infra update
ISTATE_PENDING_RECREATE_CONTAINER: 'pending_recreate_container', // env change or addon change
ISTATE_PENDING_LOCATION_CHANGE: 'pending_location_change',
ISTATE_PENDING_SERVICES_CHANGE: 'pending_services_change',
ISTATE_PENDING_DATA_DIR_MIGRATION: 'pending_data_dir_migration',
ISTATE_PENDING_RESIZE: 'pending_resize',
ISTATE_PENDING_DEBUG: 'pending_debug',
@@ -198,7 +200,7 @@ const APPS_FIELDS_PREFIXED = [ 'apps.id', 'apps.appStoreId', 'apps.installationS
'apps.sso', 'apps.debugModeJson', 'apps.enableBackup', 'apps.proxyAuth', 'apps.containerIp', 'apps.crontab',
'apps.creationTime', 'apps.updateTime', 'apps.enableAutomaticUpdate', 'apps.upstreamUri',
'apps.enableMailbox', 'apps.mailboxDisplayName', 'apps.mailboxName', 'apps.mailboxDomain', 'apps.enableInbox', 'apps.inboxName', 'apps.inboxDomain',
'apps.storageVolumeId', 'apps.storageVolumePrefix', 'apps.ts', 'apps.healthTime', '(apps.icon IS NOT NULL) AS hasIcon', '(apps.appStoreIcon IS NOT NULL) AS hasAppStoreIcon' ].join(',');
'apps.enableTurn', 'apps.storageVolumeId', 'apps.storageVolumePrefix', 'apps.ts', 'apps.healthTime', '(apps.icon IS NOT NULL) AS hasIcon', '(apps.appStoreIcon IS NOT NULL) AS hasAppStoreIcon' ].join(',');
// const PORT_BINDINGS_FIELDS = [ 'hostPort', 'type', 'environmentVariable', 'appId' ].join(',');
const LOCATION_FIELDS = [ 'appId', 'subdomain', 'domain', 'type', 'certificateJson' ];
@@ -593,7 +595,7 @@ function removeInternalFields(app) {
'accessRestriction', 'manifest', 'portBindings', 'iconUrl', 'memoryLimit', 'cpuShares', 'operators',
'sso', 'debugMode', 'reverseProxyConfig', 'enableBackup', 'creationTime', 'updateTime', 'ts', 'tags',
'label', 'secondaryDomains', 'redirectDomains', 'aliasDomains', 'env', 'enableAutomaticUpdate',
'storageVolumeId', 'storageVolumePrefix', 'mounts',
'storageVolumeId', 'storageVolumePrefix', 'mounts', 'enableTurn',
'enableMailbox', 'mailboxDisplayName', 'mailboxName', 'mailboxDomain', 'enableInbox', 'inboxName', 'inboxDomain');
removeCertificateKeys(result);
@@ -840,6 +842,7 @@ async function add(id, appStoreId, manifest, subdomain, domain, portBindings, da
servicesConfigJson = data.servicesConfig ? JSON.stringify(data.servicesConfig) : null,
enableMailbox = data.enableMailbox || false,
upstreamUri = data.upstreamUri || '',
enableTurn = 'enableTurn' in data ? data.enableTurn : true,
icon = data.icon || null;
const queries = [];
@@ -847,11 +850,11 @@ async function add(id, appStoreId, manifest, subdomain, domain, portBindings, da
queries.push({
query: 'INSERT INTO apps (id, appStoreId, manifestJson, installationState, runState, accessRestrictionJson, memoryLimit, cpuShares, '
+ 'sso, debugModeJson, mailboxName, mailboxDomain, label, tagsJson, reverseProxyConfigJson, servicesConfigJson, icon, '
+ 'enableMailbox, mailboxDisplayName, upstreamUri) '
+ ' VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)',
+ 'enableMailbox, mailboxDisplayName, upstreamUri, enableTurn) '
+ ' VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)',
args: [ id, appStoreId, manifestJson, installationState, runState, accessRestrictionJson, memoryLimit, cpuShares,
sso, debugModeJson, mailboxName, mailboxDomain, label, tagsJson, reverseProxyConfigJson, servicesConfigJson, icon,
enableMailbox, mailboxDisplayName, upstreamUri ]
enableMailbox, mailboxDisplayName, upstreamUri, enableTurn ]
});
queries.push({
@@ -1324,6 +1327,7 @@ async function install(data, auditSource) {
tags = data.tags || [],
overwriteDns = 'overwriteDns' in data ? data.overwriteDns : false,
skipDnsSetup = 'skipDnsSetup' in data ? data.skipDnsSetup : false,
enableTurn = 'enableTurn' in data ? data.enableTurn : true,
appStoreId = data.appStoreId,
upstreamUri = data.upstreamUri || '',
manifest = data.manifest;
@@ -1411,6 +1415,7 @@ async function install(data, auditSource) {
icon,
enableMailbox,
upstreamUri,
enableTurn,
runState: exports.RSTATE_RUNNING,
installationState: exports.ISTATE_PENDING_INSTALL
};
@@ -1733,6 +1738,29 @@ async function setInbox(app, data, auditSource) {
return { taskId };
}
async function setTurn(app, enableTurn, auditSource) {
assert.strictEqual(typeof app, 'object');
assert.strictEqual(typeof enableTurn, 'boolean');
assert.strictEqual(typeof auditSource, 'object');
const appId = app.id;
let error = checkAppState(app, exports.ISTATE_PENDING_SERVICES_CHANGE);
if (error) throw error;
if (!app.manifest.addons?.turn) throw new BoxError(BoxError.BAD_FIELD, 'App does not use turn addon');
if (!app.manifest.addons.turn.optional) throw new BoxError(BoxError.BAD_FIELD, 'turn service is not optional');
const task = {
args: {},
values: { enableTurn }
};
const taskId = await addTask(appId, exports.ISTATE_PENDING_SERVICES_CHANGE, task, auditSource);
await eventlog.add(eventlog.ACTION_APP_CONFIGURE, auditSource, { appId, app, enableTurn, taskId });
return { taskId };
}
async function setAutomaticBackup(app, enable, auditSource) {
assert.strictEqual(typeof app, 'object');
assert.strictEqual(typeof enable, 'boolean');
+28
View File
@@ -508,6 +508,31 @@ async function changeLocation(app, args, progressCallback) {
await updateApp(app, { installationState: apps.ISTATE_INSTALLED, error: null, health: null });
}
async function changeServices(app, args, progressCallback) {
assert.strictEqual(typeof app, 'object');
assert.strictEqual(typeof args, 'object');
assert.strictEqual(typeof progressCallback, 'function');
await progressCallback({ percent: 10, message: 'Cleaning up old install' });
await deleteContainers(app, { managedOnly: true });
const unusedAddons = {};
if (app.manifest.addons.turn && !args.enableTurn) unusedAddons.turn = app.manifest.addons.turn;
await progressCallback({ percent: 20, message: 'Removing unused addons' });
await services.teardownAddons(app, unusedAddons);
await progressCallback({ percent: 40, message: 'Setting up addons' });
await services.setupAddons(app, app.manifest.addons);
await progressCallback({ percent: 60, message: 'Creating container' });
await createContainer(app);
await startApp(app);
await progressCallback({ percent: 100, message: 'Done' });
await updateApp(app, { installationState: apps.ISTATE_INSTALLED, error: null, health: null });
}
async function migrateDataDir(app, args, progressCallback) {
assert.strictEqual(typeof app, 'object');
assert.strictEqual(typeof args, 'object');
@@ -773,6 +798,9 @@ async function run(appId, args, progressCallback) {
case apps.ISTATE_PENDING_LOCATION_CHANGE:
cmd = changeLocation(app, args, progressCallback);
break;
case apps.ISTATE_PENDING_SERVICES_CHANGE:
cmd = changeServices(app, args, progressCallback);
break;
case apps.ISTATE_PENDING_DATA_DIR_MIGRATION:
cmd = migrateDataDir(app, args, progressCallback);
break;
+15
View File
@@ -24,6 +24,7 @@ exports = module.exports = {
setLabel,
setTags,
setIcon,
setTurn,
setMemoryLimit,
setCpuShares,
setAutomaticBackup,
@@ -176,6 +177,8 @@ async function install(req, res, next) {
if ('skipDnsSetup' in data && typeof data.skipDnsSetup !== 'boolean') return next(new HttpError(400, 'skipDnsSetup must be boolean'));
if ('enableMailbox' in data && typeof data.enableMailbox !== 'boolean') return next(new HttpError(400, 'enableMailbox must be boolean'));
if ('enableTurn' in data && typeof data.enableTurn !== 'boolean') return next(new HttpError(400, 'enableTurn must be boolean'));
let [error, result] = await safe(apps.downloadManifest(data.appStoreId, data.manifest));
if (error) return next(BoxError.toHttpError(error));
@@ -407,6 +410,18 @@ async function setInbox(req, res, next) {
next(new HttpSuccess(202, { taskId: result.taskId }));
}
async function setTurn(req, res, next) {
assert.strictEqual(typeof req.body, 'object');
assert.strictEqual(typeof req.app, 'object');
if (typeof req.body.enable !== 'boolean') return next(new HttpError(400, 'enable must be a boolean'));
const [error, result] = await safe(apps.setTurn(req.app, req.body.enable, AuditSource.fromRequest(req)));
if (error) return next(BoxError.toHttpError(error));
next(new HttpSuccess(202, { taskId: result.taskId }));
}
async function setLocation(req, res, next) {
assert.strictEqual(typeof req.body, 'object');
assert.strictEqual(typeof req.app, 'object');
+1
View File
@@ -231,6 +231,7 @@ async function initializeExpressSync() {
router.post('/api/v1/apps/:id/configure/debug_mode', json, token, routes.apps.load, authorizeOperator, routes.apps.setDebugMode);
router.post('/api/v1/apps/:id/configure/mailbox', json, token, routes.apps.load, authorizeAdmin, routes.apps.setMailbox);
router.post('/api/v1/apps/:id/configure/inbox', json, token, routes.apps.load, authorizeAdmin, routes.apps.setInbox);
router.post('/api/v1/apps/:id/configure/turn', json, token, routes.apps.load, authorizeAdmin, routes.apps.setTurn);
router.post('/api/v1/apps/:id/configure/env', json, token, routes.apps.load, authorizeOperator, routes.apps.setEnvironment);
router.post('/api/v1/apps/:id/configure/storage', json, token, routes.apps.load, authorizeAdmin, routes.apps.setStorage);
router.post('/api/v1/apps/:id/configure/location', json, token, routes.apps.load, authorizeAdmin, routes.apps.setLocation);
+3
View File
@@ -887,6 +887,9 @@ async function setupTurn(app, options) {
assert.strictEqual(typeof app, 'object');
assert.strictEqual(typeof options, 'object');
const disabled = app.manifest.addons.turn.optional && !app.enableTurn;
if (disabled) return await addonConfigs.set(app.id, 'turn', []);
const turnSecret = await blobs.getString(blobs.ADDON_TURN_SECRET);
if (!turnSecret) throw new BoxError(BoxError.ADDONS_ERROR, 'Turn secret is missing');