Move AppsError to BoxError
This commit is contained in:
+133
-165
@@ -1,8 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
exports = module.exports = {
|
||||
AppsError: AppsError,
|
||||
|
||||
hasAccessTo: hasAccessTo,
|
||||
removeInternalFields: removeInternalFields,
|
||||
removeRestrictedFields: removeRestrictedFields,
|
||||
@@ -138,38 +136,6 @@ var appdb = require('./appdb.js'),
|
||||
validator = require('validator'),
|
||||
_ = require('underscore');
|
||||
|
||||
// http://dustinsenos.com/articles/customErrorsInNode
|
||||
// http://code.google.com/p/v8/wiki/JavaScriptStackTraceApi
|
||||
function AppsError(reason, errorOrMessage, details) {
|
||||
assert.strictEqual(typeof reason, 'string');
|
||||
assert(errorOrMessage instanceof Error || typeof errorOrMessage === 'string' || typeof errorOrMessage === 'undefined');
|
||||
assert(typeof details === 'object' || typeof details === 'undefined');
|
||||
|
||||
Error.call(this);
|
||||
Error.captureStackTrace(this, this.constructor);
|
||||
|
||||
this.name = this.constructor.name;
|
||||
this.reason = reason;
|
||||
if (typeof errorOrMessage === 'undefined') {
|
||||
this.message = reason;
|
||||
} else if (typeof errorOrMessage === 'string') {
|
||||
this.message = errorOrMessage;
|
||||
} else {
|
||||
this.message = 'Internal error';
|
||||
this.nestedError = errorOrMessage;
|
||||
}
|
||||
|
||||
this.details = details || {};
|
||||
}
|
||||
util.inherits(AppsError, Error);
|
||||
AppsError.INTERNAL_ERROR = 'Internal Error';
|
||||
AppsError.EXTERNAL_ERROR = 'External Error';
|
||||
AppsError.ALREADY_EXISTS = 'Already Exists';
|
||||
AppsError.NOT_FOUND = 'Not Found';
|
||||
AppsError.BAD_FIELD = 'Bad Field';
|
||||
AppsError.BAD_STATE = 'Bad State';
|
||||
AppsError.PLAN_LIMIT = 'Plan Limit';
|
||||
|
||||
const NOOP_CALLBACK = function (error) { if (error) debug(error); };
|
||||
|
||||
// validate the port bindings
|
||||
@@ -209,12 +175,12 @@ function validatePortBindings(portBindings, manifest) {
|
||||
if (!portBindings) return null;
|
||||
|
||||
for (let portName in portBindings) {
|
||||
if (!/^[a-zA-Z0-9_]+$/.test(portName)) return new AppsError(AppsError.BAD_FIELD, `${portName} is not a valid environment variable`, { field: 'portBindings', portName: portName });
|
||||
if (!/^[a-zA-Z0-9_]+$/.test(portName)) return new BoxError(BoxError.BAD_FIELD, `${portName} is not a valid environment variable`, { field: 'portBindings', portName: portName });
|
||||
|
||||
const hostPort = portBindings[portName];
|
||||
if (!Number.isInteger(hostPort)) return new AppsError(AppsError.BAD_FIELD, `${hostPort} is not an integer`, { field: 'portBindings', portName: portName });
|
||||
if (RESERVED_PORTS.indexOf(hostPort) !== -1) return new AppsError(AppsError.BAD_FIELD, `Port ${hostPort} is reserved.`, { field: 'portBindings', portName: portName });
|
||||
if (hostPort <= 1023 || hostPort > 65535) return new AppsError(AppsError.BAD_FIELD, `${hostPort} is not in permitted range`, { field: 'portBindings', portName: portName });
|
||||
if (!Number.isInteger(hostPort)) return new BoxError(BoxError.BAD_FIELD, `${hostPort} is not an integer`, { field: 'portBindings', portName: portName });
|
||||
if (RESERVED_PORTS.indexOf(hostPort) !== -1) return new BoxError(BoxError.BAD_FIELD, `Port ${hostPort} is reserved.`, { field: 'portBindings', portName: portName });
|
||||
if (hostPort <= 1023 || hostPort > 65535) return new BoxError(BoxError.BAD_FIELD, `${hostPort} is not in permitted range`, { field: 'portBindings', portName: portName });
|
||||
}
|
||||
|
||||
// it is OK if there is no 1-1 mapping between values in manifest.tcpPorts and portBindings. missing values implies
|
||||
@@ -222,7 +188,7 @@ function validatePortBindings(portBindings, manifest) {
|
||||
const tcpPorts = manifest.tcpPorts || { };
|
||||
const udpPorts = manifest.udpPorts || { };
|
||||
for (let portName in portBindings) {
|
||||
if (!(portName in tcpPorts) && !(portName in udpPorts)) return new AppsError(AppsError.BAD_FIELD, `Invalid portBindings ${portName}`, { field: 'portBindings', portName: portName });
|
||||
if (!(portName in tcpPorts) && !(portName in udpPorts)) return new BoxError(BoxError.BAD_FIELD, `Invalid portBindings ${portName}`, { field: 'portBindings', portName: portName });
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -250,13 +216,13 @@ function validateAccessRestriction(accessRestriction) {
|
||||
if (accessRestriction === null) return null;
|
||||
|
||||
if (accessRestriction.users) {
|
||||
if (!Array.isArray(accessRestriction.users)) return new AppsError(AppsError.BAD_FIELD, 'users array property required');
|
||||
if (!accessRestriction.users.every(function (e) { return typeof e === 'string'; })) return new AppsError(AppsError.BAD_FIELD, 'All users have to be strings');
|
||||
if (!Array.isArray(accessRestriction.users)) return new BoxError(BoxError.BAD_FIELD, 'users array property required');
|
||||
if (!accessRestriction.users.every(function (e) { return typeof e === 'string'; })) return new BoxError(BoxError.BAD_FIELD, 'All users have to be strings');
|
||||
}
|
||||
|
||||
if (accessRestriction.groups) {
|
||||
if (!Array.isArray(accessRestriction.groups)) return new AppsError(AppsError.BAD_FIELD, 'groups array property required');
|
||||
if (!accessRestriction.groups.every(function (e) { return typeof e === 'string'; })) return new AppsError(AppsError.BAD_FIELD, 'All groups have to be strings');
|
||||
if (!Array.isArray(accessRestriction.groups)) return new BoxError(BoxError.BAD_FIELD, 'groups array property required');
|
||||
if (!accessRestriction.groups.every(function (e) { return typeof e === 'string'; })) return new BoxError(BoxError.BAD_FIELD, 'All groups have to be strings');
|
||||
}
|
||||
|
||||
// TODO: maybe validate if the users and groups actually exist
|
||||
@@ -277,8 +243,8 @@ function validateMemoryLimit(manifest, memoryLimit) {
|
||||
// a special value that indicates unlimited memory
|
||||
if (memoryLimit === -1) return null;
|
||||
|
||||
if (memoryLimit < min) return new AppsError(AppsError.BAD_FIELD, 'memoryLimit too small');
|
||||
if (memoryLimit > max) return new AppsError(AppsError.BAD_FIELD, 'memoryLimit too large');
|
||||
if (memoryLimit < min) return new BoxError(BoxError.BAD_FIELD, 'memoryLimit too small');
|
||||
if (memoryLimit > max) return new BoxError(BoxError.BAD_FIELD, 'memoryLimit too large');
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -287,8 +253,8 @@ function validateDebugMode(debugMode) {
|
||||
assert.strictEqual(typeof debugMode, 'object');
|
||||
|
||||
if (debugMode === null) return null;
|
||||
if ('cmd' in debugMode && debugMode.cmd !== null && !Array.isArray(debugMode.cmd)) return new AppsError(AppsError.BAD_FIELD, 'debugMode.cmd must be an array or null' );
|
||||
if ('readonlyRootfs' in debugMode && typeof debugMode.readonlyRootfs !== 'boolean') return new AppsError(AppsError.BAD_FIELD, 'debugMode.readonlyRootfs must be a boolean' );
|
||||
if ('cmd' in debugMode && debugMode.cmd !== null && !Array.isArray(debugMode.cmd)) return new BoxError(BoxError.BAD_FIELD, 'debugMode.cmd must be an array or null' );
|
||||
if ('readonlyRootfs' in debugMode && typeof debugMode.readonlyRootfs !== 'boolean') return new BoxError(BoxError.BAD_FIELD, 'debugMode.readonlyRootfs must be a boolean' );
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -297,7 +263,7 @@ function validateRobotsTxt(robotsTxt) {
|
||||
if (robotsTxt === null) return null;
|
||||
|
||||
// this is the nginx limit on inline strings. if we really hit this, we have to generate a file
|
||||
if (robotsTxt.length > 4096) return new AppsError(AppsError.BAD_FIELD, 'robotsTxt must be less than 4096', { field: 'robotsTxt' });
|
||||
if (robotsTxt.length > 4096) return new BoxError(BoxError.BAD_FIELD, 'robotsTxt must be less than 4096', { field: 'robotsTxt' });
|
||||
|
||||
// TODO: validate the robots file? we escape the string when templating the nginx config right now
|
||||
|
||||
@@ -307,9 +273,9 @@ function validateRobotsTxt(robotsTxt) {
|
||||
function validateCsp(csp) {
|
||||
if (csp === null) return null;
|
||||
|
||||
if (csp.length > 4096) return new AppsError(AppsError.BAD_FIELD, 'CSP must be less than 4096', { field: 'csp' });
|
||||
if (csp.length > 4096) return new BoxError(BoxError.BAD_FIELD, 'CSP must be less than 4096', { field: 'csp' });
|
||||
|
||||
if (csp.includes('"')) return new AppsError(AppsError.BAD_FIELD, 'CSP cannot contains double quotes', { field: 'csp' });
|
||||
if (csp.includes('"')) return new BoxError(BoxError.BAD_FIELD, 'CSP cannot contains double quotes', { field: 'csp' });
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -319,31 +285,31 @@ function validateBackupFormat(format) {
|
||||
|
||||
if (format === 'tgz' || format == 'rsync') return null;
|
||||
|
||||
return new AppsError(AppsError.BAD_FIELD, 'Invalid backup format');
|
||||
return new BoxError(BoxError.BAD_FIELD, 'Invalid backup format');
|
||||
}
|
||||
|
||||
function validateLabel(label) {
|
||||
if (label === null) return null;
|
||||
|
||||
if (label.length > 128) return new AppsError(AppsError.BAD_FIELD, 'label must be less than 128', { field: 'label' });
|
||||
if (label.length > 128) return new BoxError(BoxError.BAD_FIELD, 'label must be less than 128', { field: 'label' });
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function validateTags(tags) {
|
||||
if (tags.length > 64) return new AppsError(AppsError.BAD_FIELD, 'Can only set up to 64 tags', { field: 'tags' });
|
||||
if (tags.length > 64) return new BoxError(BoxError.BAD_FIELD, 'Can only set up to 64 tags', { field: 'tags' });
|
||||
|
||||
if (tags.some(tag => tag.length == 0)) return new AppsError(AppsError.BAD_FIELD, 'tag cannot be empty', { field: 'tags' });
|
||||
if (tags.some(tag => tag.length > 128)) return new AppsError(AppsError.BAD_FIELD, 'tag must be less than 128', { field: 'tags' });
|
||||
if (tags.some(tag => tag.length == 0)) return new BoxError(BoxError.BAD_FIELD, 'tag cannot be empty', { field: 'tags' });
|
||||
if (tags.some(tag => tag.length > 128)) return new BoxError(BoxError.BAD_FIELD, 'tag must be less than 128', { field: 'tags' });
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function validateEnv(env) {
|
||||
for (let key in env) {
|
||||
if (key.length > 512) return new AppsError(AppsError.BAD_FIELD, 'Max env var key length is 512', { field: 'env', env: env });
|
||||
if (key.length > 512) return new BoxError(BoxError.BAD_FIELD, 'Max env var key length is 512', { field: 'env', env: env });
|
||||
// http://pubs.opengroup.org/onlinepubs/000095399/basedefs/xbd_chap08.html
|
||||
if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(key)) return new AppsError(AppsError.BAD_FIELD, `"${key}" is not a valid environment variable`, { field: 'env', env: env });
|
||||
if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(key)) return new BoxError(BoxError.BAD_FIELD, `"${key}" is not a valid environment variable`, { field: 'env', env: env });
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -352,23 +318,23 @@ function validateEnv(env) {
|
||||
function validateDataDir(dataDir) {
|
||||
if (dataDir === null) return null;
|
||||
|
||||
if (path.resolve(dataDir) !== dataDir) return new AppsError(AppsError.BAD_FIELD, 'dataDir must be an absolute path', { field: 'dataDir' });
|
||||
if (path.resolve(dataDir) !== dataDir) return new BoxError(BoxError.BAD_FIELD, 'dataDir must be an absolute path', { field: 'dataDir' });
|
||||
|
||||
// nfs shares will have the directory mounted already
|
||||
let stat = safe.fs.lstatSync(dataDir);
|
||||
if (stat) {
|
||||
if (!stat.isDirectory()) return new AppsError(AppsError.BAD_FIELD, `dataDir ${dataDir} is not a directory`, { field: 'dataDir' });
|
||||
if (!stat.isDirectory()) return new BoxError(BoxError.BAD_FIELD, `dataDir ${dataDir} is not a directory`, { field: 'dataDir' });
|
||||
let entries = safe.fs.readdirSync(dataDir);
|
||||
if (!entries) return new AppsError(AppsError.BAD_FIELD, `dataDir ${dataDir} could not be listed`, { field: 'dataDir' });
|
||||
if (entries.length !== 0) return new AppsError(AppsError.BAD_FIELD, `dataDir ${dataDir} is not empty`, { field: 'dataDir' });
|
||||
if (!entries) return new BoxError(BoxError.BAD_FIELD, `dataDir ${dataDir} could not be listed`, { field: 'dataDir' });
|
||||
if (entries.length !== 0) return new BoxError(BoxError.BAD_FIELD, `dataDir ${dataDir} is not empty`, { field: 'dataDir' });
|
||||
}
|
||||
|
||||
// backup logic relies on paths not overlapping (because it recurses)
|
||||
if (dataDir.startsWith(paths.APPS_DATA_DIR)) return new AppsError(AppsError.BAD_FIELD, `dataDir ${dataDir} cannot be inside apps data`, { field: 'dataDir' });
|
||||
if (dataDir.startsWith(paths.APPS_DATA_DIR)) return new BoxError(BoxError.BAD_FIELD, `dataDir ${dataDir} cannot be inside apps data`, { field: 'dataDir' });
|
||||
|
||||
// if we made it this far, it cannot start with any of these realistically
|
||||
const fhs = [ '/bin', '/boot', '/etc', '/lib', '/lib32', '/lib64', '/proc', '/run', '/sbin', '/tmp', '/usr' ];
|
||||
if (fhs.some((p) => dataDir.startsWith(p))) return new AppsError(AppsError.BAD_FIELD, `dataDir ${dataDir} cannot be placed inside this location`, { field: 'dataDir' });
|
||||
if (fhs.some((p) => dataDir.startsWith(p))) return new BoxError(BoxError.BAD_FIELD, `dataDir ${dataDir} cannot be placed inside this location`, { field: 'dataDir' });
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -382,7 +348,7 @@ function getDuplicateErrorDetails(errorMessage, locations, domainObjectMap, port
|
||||
var match = errorMessage.match(/ER_DUP_ENTRY: Duplicate entry '(.*)' for key '(.*)'/);
|
||||
if (!match) {
|
||||
debug('Unexpected SQL error message.', errorMessage);
|
||||
return new AppsError(AppsError.INTERNAL_ERROR, new Error(errorMessage));
|
||||
return new BoxError(BoxError.INTERNAL_ERROR, new Error(errorMessage));
|
||||
}
|
||||
|
||||
// check if a location conflicts
|
||||
@@ -391,20 +357,20 @@ function getDuplicateErrorDetails(errorMessage, locations, domainObjectMap, port
|
||||
const { subdomain, domain } = locations[i];
|
||||
if (match[1] !== `${subdomain}-${domain}`) continue;
|
||||
|
||||
return new AppsError(AppsError.ALREADY_EXISTS, `Domain '${domains.fqdn(subdomain, domainObjectMap[domain])}' is in use`, { subdomain, domain });
|
||||
return new BoxError(BoxError.ALREADY_EXISTS, `Domain '${domains.fqdn(subdomain, domainObjectMap[domain])}' is in use`, { subdomain, domain });
|
||||
}
|
||||
}
|
||||
|
||||
// check if any of the port bindings conflict
|
||||
for (let portName in portBindings) {
|
||||
if (portBindings[portName] === parseInt(match[1])) return new AppsError(AppsError.ALREADY_EXISTS, `Port ${match[1]} is reserved`, { portName });
|
||||
if (portBindings[portName] === parseInt(match[1])) return new BoxError(BoxError.ALREADY_EXISTS, `Port ${match[1]} is reserved`, { portName });
|
||||
}
|
||||
|
||||
if (match[2] === 'dataDir') {
|
||||
return new AppsError(AppsError.BAD_FIELD, `Data directory ${match[1]} is in use`, { field: 'dataDir' });
|
||||
return new BoxError(BoxError.BAD_FIELD, `Data directory ${match[1]} is in use`, { field: 'dataDir' });
|
||||
}
|
||||
|
||||
return new AppsError(AppsError.ALREADY_EXISTS, `${match[2]} '${match[1]}' is in use`);
|
||||
return new BoxError(BoxError.ALREADY_EXISTS, `${match[2]} '${match[1]}' is in use`);
|
||||
}
|
||||
|
||||
function getDataDir(app, dataDir) {
|
||||
@@ -454,7 +420,7 @@ function getIconPath(appId, options, callback) {
|
||||
const appstoreIconPath = `${paths.APP_ICONS_DIR}/${appId}.png`;
|
||||
if (safe.fs.existsSync(appstoreIconPath)) return callback(null, appstoreIconPath);
|
||||
|
||||
callback(new AppsError(AppsError.NOT_FOUND, 'No icon'));
|
||||
callback(new BoxError(BoxError.NOT_FOUND, 'No icon'));
|
||||
}
|
||||
|
||||
function postProcess(app, domainObjectMap) {
|
||||
@@ -492,7 +458,7 @@ function getDomainObjectMap(callback) {
|
||||
assert.strictEqual(typeof callback, 'function');
|
||||
|
||||
domaindb.getAll(function (error, domainObjects) {
|
||||
if (error) return callback(new AppsError(AppsError.INTERNAL_ERROR, error));
|
||||
if (error) return callback(error);
|
||||
|
||||
let domainObjectMap = {};
|
||||
for (let d of domainObjects) { domainObjectMap[d.domain] = d; }
|
||||
@@ -509,8 +475,8 @@ function get(appId, callback) {
|
||||
if (error) return callback(error);
|
||||
|
||||
appdb.get(appId, function (error, app) {
|
||||
if (error && error.reason === DatabaseError.NOT_FOUND) return callback(new AppsError(AppsError.NOT_FOUND, 'No such app'));
|
||||
if (error) return callback(new AppsError(AppsError.INTERNAL_ERROR, error));
|
||||
if (error && error.reason === DatabaseError.NOT_FOUND) return callback(new BoxError(BoxError.NOT_FOUND, 'No such app'));
|
||||
if (error) return callback(new BoxError(BoxError.DATABASE_ERROR, error));
|
||||
|
||||
postProcess(app, domainObjectMap);
|
||||
|
||||
@@ -527,8 +493,8 @@ function getByContainerId(containerId, callback) {
|
||||
if (error) return callback(error);
|
||||
|
||||
appdb.getByContainerId(containerId, function (error, app) {
|
||||
if (error && error.reason === DatabaseError.NOT_FOUND) return callback(new AppsError(AppsError.NOT_FOUND, 'No such app'));
|
||||
if (error) return callback(new AppsError(AppsError.INTERNAL_ERROR, error));
|
||||
if (error && error.reason === DatabaseError.NOT_FOUND) return callback(new BoxError(BoxError.NOT_FOUND, 'No such app'));
|
||||
if (error) return callback(new BoxError(BoxError.DATABASE_ERROR, error));
|
||||
|
||||
postProcess(app, domainObjectMap);
|
||||
|
||||
@@ -546,13 +512,13 @@ function getByIpAddress(ip, callback) {
|
||||
if (constants.TEST && exports._MOCK_GET_BY_IP_APP_ID) return get(exports._MOCK_GET_BY_IP_APP_ID, callback);
|
||||
|
||||
docker.getContainerIdByIp(ip, function (error, containerId) {
|
||||
if (error) return callback(new AppsError(AppsError.INTERNAL_ERROR, error));
|
||||
if (error) return callback(error);
|
||||
|
||||
docker.inspect(containerId, function (error, result) {
|
||||
if (error) return callback(new AppsError(AppsError.INTERNAL_ERROR, error));
|
||||
if (error) return callback(error);
|
||||
|
||||
const appId = safe.query(result, 'Config.Labels.appId', null);
|
||||
if (!appId) return callback(new AppsError(AppsError.NOT_FOUND, 'No such app'));
|
||||
if (!appId) return callback(new BoxError(BoxError.NOT_FOUND, 'No such app'));
|
||||
|
||||
get(appId, callback);
|
||||
});
|
||||
@@ -567,7 +533,7 @@ function getByFqdn(fqdn, callback) {
|
||||
if (error) return callback(error);
|
||||
|
||||
var app = result.find(function (a) { return a.fqdn === fqdn; });
|
||||
if (!app) return callback(new AppsError(AppsError.NOT_FOUND, 'No such app'));
|
||||
if (!app) return callback(new BoxError(BoxError.NOT_FOUND, 'No such app'));
|
||||
|
||||
callback(null, app);
|
||||
});
|
||||
@@ -580,7 +546,7 @@ function getAll(callback) {
|
||||
if (error) return callback(error);
|
||||
|
||||
appdb.getAll(function (error, apps) {
|
||||
if (error) return callback(new AppsError(AppsError.INTERNAL_ERROR, error));
|
||||
if (error) return callback(new BoxError(BoxError.DATABASE_ERROR, error));
|
||||
|
||||
apps.forEach((app) => postProcess(app, domainObjectMap));
|
||||
|
||||
@@ -603,7 +569,7 @@ function getAllByUser(user, callback) {
|
||||
}
|
||||
|
||||
function downloadManifest(appStoreId, manifest, callback) {
|
||||
if (!appStoreId && !manifest) return callback(new AppsError(AppsError.BAD_FIELD, 'Neither manifest nor appStoreId provided'));
|
||||
if (!appStoreId && !manifest) return callback(new BoxError(BoxError.BAD_FIELD, 'Neither manifest nor appStoreId provided'));
|
||||
|
||||
if (!appStoreId) return callback(null, '', manifest);
|
||||
|
||||
@@ -614,9 +580,9 @@ function downloadManifest(appStoreId, manifest, callback) {
|
||||
debug('downloading manifest from %s', url);
|
||||
|
||||
superagent.get(url).timeout(30 * 1000).end(function (error, result) {
|
||||
if (error && !error.response) return callback(new AppsError(AppsError.EXTERNAL_ERROR, 'Network error downloading manifest:' + error.message));
|
||||
if (error && !error.response) return callback(new BoxError(BoxError.EXTERNAL_ERROR, 'Network error downloading manifest:' + error.message));
|
||||
|
||||
if (result.statusCode !== 200) return callback(new AppsError(AppsError.NOT_FOUND, util.format('Failed to get app info from store.', result.statusCode, result.text)));
|
||||
if (result.statusCode !== 200) return callback(new BoxError(BoxError.NOT_FOUND, util.format('Failed to get app info from store.', result.statusCode, result.text)));
|
||||
|
||||
callback(null, parts[0], result.body.manifest);
|
||||
});
|
||||
@@ -662,12 +628,12 @@ function addTask(appId, installationState, task, callback) {
|
||||
const requireNullTaskId = 'requireNullTaskId' in task ? task.requireNullTaskId : true;
|
||||
|
||||
tasks.add(tasks.TASK_APP, [ appId, args ], function (error, taskId) {
|
||||
if (error) return callback(new AppsError(AppsError.INTERNAL_ERROR, error));
|
||||
if (error) return callback(error);
|
||||
|
||||
appdb.setTask(appId, _.extend({ installationState, taskId, error: null }, values), { requiredState, requireNullTaskId }, function (error) {
|
||||
if (error && error.reason === DatabaseError.ALREADY_EXISTS) return callback(new AppsError(AppsError.ALREADY_EXISTS, error.message));
|
||||
if (error && error.reason === DatabaseError.NOT_FOUND) return callback(new AppsError(AppsError.BAD_STATE, 'Another task is scheduled for this app')); // could be because app went away OR a taskId exists
|
||||
if (error) return callback(new AppsError(AppsError.INTERNAL_ERROR, error));
|
||||
if (error && error.reason === DatabaseError.ALREADY_EXISTS) return callback(new BoxError(BoxError.ALREADY_EXISTS, error.message));
|
||||
if (error && error.reason === DatabaseError.NOT_FOUND) return callback(new BoxError(BoxError.BAD_STATE, 'Another task is scheduled for this app')); // could be because app went away OR a taskId exists
|
||||
if (error) return callback(new BoxError(BoxError.DATABASE_ERROR, error));
|
||||
|
||||
if (scheduleNow) scheduleTask(appId, installationState, taskId, NOOP_CALLBACK);
|
||||
|
||||
@@ -680,10 +646,10 @@ function checkAppState(app, state) {
|
||||
assert.strictEqual(typeof app, 'object');
|
||||
assert.strictEqual(typeof state, 'string');
|
||||
|
||||
if (app.taskId) return new AppsError(AppsError.BAD_STATE, `Not allowed in this app state : ${app.installationState} / ${app.runState}`);
|
||||
if (app.taskId) return new BoxError(BoxError.BAD_STATE, `Not allowed in this app state : ${app.installationState} / ${app.runState}`);
|
||||
|
||||
if (app.installationState === exports.ISTATE_ERROR) {
|
||||
if (state !== exports.ISTATE_PENDING_UNINSTALL) return new AppsError(AppsError.BAD_STATE, 'Not allowed in error state');
|
||||
if (state !== exports.ISTATE_PENDING_UNINSTALL) return new BoxError(BoxError.BAD_STATE, 'Not allowed in error state');
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -697,10 +663,10 @@ function validateLocations(locations, callback) {
|
||||
if (error) return callback(error);
|
||||
|
||||
for (let location of locations) {
|
||||
if (!(location.domain in domainObjectMap)) return callback(new AppsError(AppsError.BAD_FIELD, 'No such domain', { field: 'location', domain: location.domain, subdomain: location.subdomain }));
|
||||
if (!(location.domain in domainObjectMap)) return callback(new BoxError(BoxError.BAD_FIELD, 'No such domain', { field: 'location', domain: location.domain, subdomain: location.subdomain }));
|
||||
|
||||
error = domains.validateHostname(location.subdomain, domainObjectMap[location.domain]);
|
||||
if (error) return callback(new AppsError(AppsError.BAD_FIELD, 'Bad location: ' + error.message, { field: 'location', domain: location.domain, subdomain: location.subdomain }));
|
||||
if (error) return callback(new BoxError(BoxError.BAD_FIELD, 'Bad location: ' + error.message, { field: 'location', domain: location.domain, subdomain: location.subdomain }));
|
||||
}
|
||||
|
||||
callback(null, domainObjectMap);
|
||||
@@ -738,7 +704,7 @@ function install(data, user, auditSource, callback) {
|
||||
if (error) return callback(error);
|
||||
|
||||
error = manifestFormat.parse(manifest);
|
||||
if (error) return callback(new AppsError(AppsError.BAD_FIELD, 'Manifest error: ' + error.message));
|
||||
if (error) return callback(new BoxError(BoxError.BAD_FIELD, 'Manifest error: ' + error.message));
|
||||
|
||||
error = checkManifestConstraints(manifest);
|
||||
if (error) return callback(error);
|
||||
@@ -761,7 +727,7 @@ function install(data, user, auditSource, callback) {
|
||||
error = validateTags(tags);
|
||||
if (error) return callback(error);
|
||||
|
||||
if ('sso' in data && !('optionalSso' in manifest)) return callback(new AppsError(AppsError.BAD_FIELD, 'sso can only be specified for apps with optionalSso'));
|
||||
if ('sso' in data && !('optionalSso' in manifest)) return callback(new BoxError(BoxError.BAD_FIELD, 'sso can only be specified for apps with optionalSso'));
|
||||
// if sso was unspecified, enable it by default if possible
|
||||
if (sso === null) sso = !!manifest.addons['ldap'] || !!manifest.addons['oauth'];
|
||||
|
||||
@@ -770,7 +736,7 @@ function install(data, user, auditSource, callback) {
|
||||
|
||||
if (mailboxName) {
|
||||
error = mail.validateName(mailboxName);
|
||||
if (error) return callback(new AppsError(AppsError.BAD_FIELD, error.message, { field: 'mailboxName' }));
|
||||
if (error) return callback(new BoxError(BoxError.BAD_FIELD, error.message, { field: 'mailboxName' }));
|
||||
} else {
|
||||
mailboxName = mailboxNameForLocation(location, manifest);
|
||||
}
|
||||
@@ -778,10 +744,10 @@ function install(data, user, auditSource, callback) {
|
||||
var appId = uuid.v4();
|
||||
|
||||
if (icon) {
|
||||
if (!validator.isBase64(icon)) return callback(new AppsError(AppsError.BAD_FIELD, 'icon is not base64', { field: 'icon' }));
|
||||
if (!validator.isBase64(icon)) return callback(new BoxError(BoxError.BAD_FIELD, 'icon is not base64', { field: 'icon' }));
|
||||
|
||||
if (!safe.fs.writeFileSync(path.join(paths.APP_ICONS_DIR, appId + '.png'), Buffer.from(icon, 'base64'))) {
|
||||
return callback(new AppsError(AppsError.INTERNAL_ERROR, 'Error saving icon:' + safe.error.message));
|
||||
return callback(new BoxError(BoxError.FS_ERROR, 'Error saving icon:' + safe.error.message));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -791,7 +757,7 @@ function install(data, user, auditSource, callback) {
|
||||
|
||||
if (cert && key) {
|
||||
error = reverseProxy.validateCertificate(location, domainObjectMap[domain], { cert, key });
|
||||
if (error) return callback(new AppsError(AppsError.BAD_FIELD, error.message, { field: 'cert' }));
|
||||
if (error) return callback(new BoxError(BoxError.BAD_FIELD, error.message, { field: 'cert' }));
|
||||
}
|
||||
|
||||
debug('Will install app with id : ' + appId);
|
||||
@@ -814,8 +780,8 @@ function install(data, user, auditSource, callback) {
|
||||
|
||||
appdb.add(appId, appStoreId, manifest, location, domain, translatePortBindings(portBindings, manifest), data, function (error) {
|
||||
if (error && error.reason === DatabaseError.ALREADY_EXISTS) return callback(getDuplicateErrorDetails(error.message, locations, domainObjectMap, portBindings));
|
||||
if (error && error.reason === DatabaseError.NOT_FOUND) return callback(new AppsError(AppsError.NOT_FOUND, error.message));
|
||||
if (error) return callback(new AppsError(AppsError.INTERNAL_ERROR, error));
|
||||
if (error && error.reason === DatabaseError.NOT_FOUND) return callback(new BoxError(BoxError.NOT_FOUND, error.message));
|
||||
if (error) return callback(new BoxError(BoxError.DATABASE_ERROR, error));
|
||||
|
||||
purchaseApp({ appId: appId, appstoreId: appStoreId, manifestId: manifest.id }, function (error) {
|
||||
if (error) return callback(error);
|
||||
@@ -823,7 +789,7 @@ function install(data, user, auditSource, callback) {
|
||||
// save cert to boxdata/certs
|
||||
if (cert && key) {
|
||||
let error = reverseProxy.setAppCertificateSync(location, domainObjectMap[domain], { cert, key });
|
||||
if (error) return callback(new AppsError(AppsError.INTERNAL_ERROR, 'Error setting cert: ' + error.message));
|
||||
if (error) return callback(error);
|
||||
}
|
||||
|
||||
const task = {
|
||||
@@ -862,8 +828,8 @@ function setAccessRestriction(appId, accessRestriction, auditSource, callback) {
|
||||
if (error) return callback(error);
|
||||
|
||||
appdb.update(appId, { accessRestriction: accessRestriction }, function (error) {
|
||||
if (error && error.reason === DatabaseError.NOT_FOUND) return callback(new AppsError(AppsError.NOT_FOUND, 'No such app'));
|
||||
if (error) return callback(new AppsError(AppsError.INTERNAL_ERROR, error));
|
||||
if (error && error.reason === DatabaseError.NOT_FOUND) return callback(new BoxError(BoxError.NOT_FOUND, 'No such app'));
|
||||
if (error) return callback(new BoxError(BoxError.DATABASE_ERROR, error));
|
||||
|
||||
eventlog.add(eventlog.ACTION_APP_CONFIGURE, auditSource, { appId: appId, app: app, accessRestriction: accessRestriction });
|
||||
|
||||
@@ -885,8 +851,8 @@ function setLabel(appId, label, auditSource, callback) {
|
||||
if (error) return callback(error);
|
||||
|
||||
appdb.update(appId, { label: label }, function (error) {
|
||||
if (error && error.reason === DatabaseError.NOT_FOUND) return callback(new AppsError(AppsError.NOT_FOUND, 'No such app'));
|
||||
if (error) return callback(new AppsError(AppsError.INTERNAL_ERROR, error));
|
||||
if (error && error.reason === DatabaseError.NOT_FOUND) return callback(new BoxError(BoxError.NOT_FOUND, 'No such app'));
|
||||
if (error) return callback(new BoxError(BoxError.DATABASE_ERROR, error));
|
||||
|
||||
eventlog.add(eventlog.ACTION_APP_CONFIGURE, auditSource, { appId: appId, app: app, label: label });
|
||||
|
||||
@@ -908,8 +874,8 @@ function setTags(appId, tags, auditSource, callback) {
|
||||
if (error) return callback(error);
|
||||
|
||||
appdb.update(appId, { tags: tags }, function (error) {
|
||||
if (error && error.reason === DatabaseError.NOT_FOUND) return callback(new AppsError(AppsError.NOT_FOUND, 'No such app'));
|
||||
if (error) return callback(new AppsError(AppsError.INTERNAL_ERROR, error));
|
||||
if (error && error.reason === DatabaseError.NOT_FOUND) return callback(new BoxError(BoxError.NOT_FOUND, 'No such app'));
|
||||
if (error) return callback(new BoxError(BoxError.DATABASE_ERROR, error));
|
||||
|
||||
eventlog.add(eventlog.ACTION_APP_CONFIGURE, auditSource, { appId: appId, app: app, tags: tags });
|
||||
|
||||
@@ -928,10 +894,10 @@ function setIcon(appId, icon, auditSource, callback) {
|
||||
if (error) return callback(error);
|
||||
|
||||
if (icon) {
|
||||
if (!validator.isBase64(icon)) return callback(new AppsError(AppsError.BAD_FIELD, 'icon is not base64', { field: 'icon' }));
|
||||
if (!validator.isBase64(icon)) return callback(new BoxError(BoxError.BAD_FIELD, 'icon is not base64', { field: 'icon' }));
|
||||
|
||||
if (!safe.fs.writeFileSync(path.join(paths.APP_ICONS_DIR, appId + '.user.png'), Buffer.from(icon, 'base64'))) {
|
||||
return callback(new AppsError(AppsError.INTERNAL_ERROR, 'Error saving icon:' + safe.error.message));
|
||||
return callback(new BoxError(BoxError.FS_ERROR, 'Error saving icon:' + safe.error.message));
|
||||
}
|
||||
} else {
|
||||
safe.fs.unlinkSync(path.join(paths.APP_ICONS_DIR, appId + '.user.png'));
|
||||
@@ -1044,7 +1010,7 @@ function setMailbox(appId, mailboxName, auditSource, callback) {
|
||||
|
||||
if (mailboxName) {
|
||||
error = mail.validateName(mailboxName);
|
||||
if (error) return callback(new AppsError(AppsError.BAD_FIELD, error.message, { field: 'mailboxName' }));
|
||||
if (error) return callback(new BoxError(BoxError.BAD_FIELD, error.message, { field: 'mailboxName' }));
|
||||
} else {
|
||||
mailboxName = mailboxNameForLocation(app.location, app.manifest);
|
||||
}
|
||||
@@ -1073,8 +1039,8 @@ function setAutomaticBackup(appId, enable, auditSource, callback) {
|
||||
if (error) return callback(error);
|
||||
|
||||
appdb.update(appId, { enableBackup: enable }, function (error) {
|
||||
if (error && error.reason === DatabaseError.NOT_FOUND) return callback(new AppsError(AppsError.NOT_FOUND, 'No such app'));
|
||||
if (error) return callback(new AppsError(AppsError.INTERNAL_ERROR, error));
|
||||
if (error && error.reason === DatabaseError.NOT_FOUND) return callback(new BoxError(BoxError.NOT_FOUND, 'No such app'));
|
||||
if (error) return callback(new BoxError(BoxError.DATABASE_ERROR, error));
|
||||
|
||||
eventlog.add(eventlog.ACTION_APP_CONFIGURE, auditSource, { appId: appId, app: app, enableBackup: enable });
|
||||
|
||||
@@ -1093,8 +1059,8 @@ function setAutomaticUpdate(appId, enable, auditSource, callback) {
|
||||
if (error) return callback(error);
|
||||
|
||||
appdb.update(appId, { enableAutomaticUpdate: enable }, function (error) {
|
||||
if (error && error.reason === DatabaseError.NOT_FOUND) return callback(new AppsError(AppsError.NOT_FOUND, 'No such app'));
|
||||
if (error) return callback(new AppsError(AppsError.INTERNAL_ERROR, error));
|
||||
if (error && error.reason === DatabaseError.NOT_FOUND) return callback(new BoxError(BoxError.NOT_FOUND, 'No such app'));
|
||||
if (error) return callback(new BoxError(BoxError.DATABASE_ERROR, error));
|
||||
|
||||
eventlog.add(eventlog.ACTION_APP_CONFIGURE, auditSource, { appId: appId, app: app, enableAutomaticUpdate: enable });
|
||||
|
||||
@@ -1121,11 +1087,11 @@ function setReverseProxyConfig(appId, reverseProxyConfig, auditSource, callback)
|
||||
if (error) return callback(error);
|
||||
|
||||
reverseProxy.writeAppConfig(_.extend({}, app, { reverseProxyConfig }), function (error) {
|
||||
if (error) return callback(new AppsError(AppsError.EXTERNAL_ERROR, 'Error writing nginx config'));
|
||||
if (error) return callback(error);
|
||||
|
||||
appdb.update(appId, { reverseProxyConfig }, function (error) {
|
||||
if (error && error.reason === DatabaseError.NOT_FOUND) return callback(new AppsError(AppsError.NOT_FOUND, 'No such app'));
|
||||
if (error) return callback(new AppsError(AppsError.INTERNAL_ERROR, error));
|
||||
if (error && error.reason === DatabaseError.NOT_FOUND) return callback(new BoxError(BoxError.NOT_FOUND, 'No such app'));
|
||||
if (error) return callback(new BoxError(BoxError.DATABASE_ERROR, error));
|
||||
|
||||
eventlog.add(eventlog.ACTION_APP_CONFIGURE, auditSource, { appId, app, reverseProxyConfig });
|
||||
|
||||
@@ -1145,16 +1111,16 @@ function setCertificate(appId, bundle, auditSource, callback) {
|
||||
if (error) return callback(error);
|
||||
|
||||
domains.get(app.domain, function (error, domainObject) {
|
||||
if (error && error.reason === BoxError.NOT_FOUND) return callback(new AppsError(AppsError.NOT_FOUND, 'No such domain'));
|
||||
if (error) return callback(new AppsError(AppsError.INTERNAL_ERROR, 'Could not get domain info:' + error.message));
|
||||
if (error && error.reason === BoxError.NOT_FOUND) return callback(new BoxError(BoxError.NOT_FOUND, 'No such domain'));
|
||||
if (error) return callback(new BoxError(BoxError.DATABASE_ERROR, 'Could not get domain info:' + error.message));
|
||||
|
||||
if (bundle.cert && bundle.key) {
|
||||
error = reverseProxy.validateCertificate(app.location, domainObject, { cert: bundle.cert, key: bundle.key });
|
||||
if (error) return callback(new AppsError(AppsError.BAD_FIELD, error.message, { field: 'cert' }));
|
||||
if (error) return callback(new BoxError(BoxError.BAD_FIELD, error.message, { field: 'cert' }));
|
||||
}
|
||||
|
||||
error = reverseProxy.setAppCertificateSync(app.location, domainObject, { cert: bundle.cert, key: bundle.key });
|
||||
if (error) return callback(new AppsError(AppsError.INTERNAL_ERROR, 'Error setting cert: ' + error.message));
|
||||
if (error) return callback(error);
|
||||
|
||||
eventlog.add(eventlog.ACTION_APP_CONFIGURE, auditSource, { appId: appId, app: app, cert: bundle.cert, key: bundle.key });
|
||||
|
||||
@@ -1210,7 +1176,7 @@ function setLocation(appId, data, auditSource, callback) {
|
||||
values
|
||||
};
|
||||
addTask(appId, exports.ISTATE_PENDING_LOCATION_CHANGE, task, function (error, result) {
|
||||
if (error && error.reason === AppsError.ALREADY_EXISTS) error = getDuplicateErrorDetails(error.message, locations, domainObjectMap, data.portBindings);
|
||||
if (error && error.reason === BoxError.ALREADY_EXISTS) error = getDuplicateErrorDetails(error.message, locations, domainObjectMap, data.portBindings);
|
||||
if (error) return callback(error);
|
||||
|
||||
values.fqdn = domains.fqdn(values.location, domainObjectMap[values.domain]);
|
||||
@@ -1273,7 +1239,7 @@ function update(appId, data, auditSource, callback) {
|
||||
if (error) return callback(error);
|
||||
|
||||
error = manifestFormat.parse(manifest);
|
||||
if (error) return callback(new AppsError(AppsError.BAD_FIELD, 'Manifest error:' + error.message));
|
||||
if (error) return callback(new BoxError(BoxError.BAD_FIELD, 'Manifest error:' + error.message));
|
||||
|
||||
error = checkManifestConstraints(manifest);
|
||||
if (error) return callback(error);
|
||||
@@ -1283,7 +1249,7 @@ function update(appId, data, auditSource, callback) {
|
||||
// prevent user from installing a app with different manifest id over an existing app
|
||||
// this allows cloudron install -f --app <appid> for an app installed from the appStore
|
||||
if (app.manifest.id !== updateConfig.manifest.id) {
|
||||
if (!data.force) return callback(new AppsError(AppsError.BAD_FIELD, 'manifest id does not match. force to override'));
|
||||
if (!data.force) return callback(new BoxError(BoxError.BAD_FIELD, 'manifest id does not match. force to override'));
|
||||
// clear appStoreId so that this app does not get updates anymore
|
||||
updateConfig.appStoreId = '';
|
||||
}
|
||||
@@ -1292,15 +1258,15 @@ function update(appId, data, auditSource, callback) {
|
||||
const currentVersion = semver.prerelease(app.manifest.version) ? app.manifest.version : `${app.manifest.version}-0`;
|
||||
const updateVersion = semver.prerelease(updateConfig.manifest.version) ? updateConfig.manifest.version : `${updateConfig.manifest.version}-0`;
|
||||
if (app.appStoreId !== '' && semver.lte(updateVersion, currentVersion)) {
|
||||
if (!data.force) return callback(new AppsError(AppsError.BAD_FIELD, 'Downgrades are not permitted for apps installed from AppStore. force to override'));
|
||||
if (!data.force) return callback(new BoxError(BoxError.BAD_FIELD, 'Downgrades are not permitted for apps installed from AppStore. force to override'));
|
||||
}
|
||||
|
||||
if ('icon' in data) {
|
||||
if (data.icon) {
|
||||
if (!validator.isBase64(data.icon)) return callback(new AppsError(AppsError.BAD_FIELD, 'icon is not base64', { field: 'icon' }));
|
||||
if (!validator.isBase64(data.icon)) return callback(new BoxError(BoxError.BAD_FIELD, 'icon is not base64', { field: 'icon' }));
|
||||
|
||||
if (!safe.fs.writeFileSync(path.join(paths.APP_ICONS_DIR, appId + '.user.png'), Buffer.from(data.icon, 'base64'))) {
|
||||
return callback(new AppsError(AppsError.INTERNAL_ERROR, 'Error saving icon:' + safe.error.message));
|
||||
return callback(new BoxError(BoxError.FS_ERROR, 'Error saving icon:' + safe.error.message));
|
||||
}
|
||||
} else {
|
||||
safe.fs.unlinkSync(path.join(paths.APP_ICONS_DIR, appId + '.user.png'));
|
||||
@@ -1308,7 +1274,7 @@ function update(appId, data, auditSource, callback) {
|
||||
}
|
||||
|
||||
// do not update apps in debug mode
|
||||
if (app.debugMode && !data.force) return callback(new AppsError(AppsError.BAD_STATE, 'debug mode enabled. force to override'));
|
||||
if (app.debugMode && !data.force) return callback(new BoxError(BoxError.BAD_STATE, 'debug mode enabled. force to override'));
|
||||
|
||||
// Ensure we update the memory limit in case the new app requires more memory as a minimum
|
||||
// 0 and -1 are special updateConfig for memory limit indicating unset and unlimited
|
||||
@@ -1420,7 +1386,7 @@ function repair(appId, data, auditSource, callback) {
|
||||
|
||||
// create a new task instead of updating the old one, since it helps tracking
|
||||
addTask(appId, newState, { args, values, requiredState: null }, function (error, result) {
|
||||
if (error && error.reason === AppsError.ALREADY_EXISTS) error = getDuplicateErrorDetails(error.message, locations, domainObjectMap, { /* portBindings */});
|
||||
if (error && error.reason === BoxError.ALREADY_EXISTS) error = getDuplicateErrorDetails(error.message, locations, domainObjectMap, { /* portBindings */});
|
||||
if (error) return callback(error);
|
||||
|
||||
eventlog.add(eventlog.ACTION_APP_REPAIR, auditSource, { taskId: result.taskId, app, newState });
|
||||
@@ -1450,11 +1416,11 @@ function restore(appId, data, auditSource, callback) {
|
||||
var func = data.backupId ? backups.get.bind(null, data.backupId) : function (next) { return next(null, { manifest: app.manifest }); };
|
||||
|
||||
func(function (error, backupInfo) {
|
||||
if (error && error.reason === BoxError.NOT_FOUND) return callback(new AppsError(AppsError.EXTERNAL_ERROR, error.message));
|
||||
if (error && error.reason === BoxError.EXTERNAL_ERROR) return callback(new AppsError(AppsError.EXTERNAL_ERROR, error.message));
|
||||
if (error) return callback(new AppsError(AppsError.INTERNAL_ERROR, error));
|
||||
if (error && error.reason === BoxError.NOT_FOUND) return callback(new BoxError(BoxError.EXTERNAL_ERROR, error.message));
|
||||
if (error && error.reason === BoxError.EXTERNAL_ERROR) return callback(new BoxError(BoxError.EXTERNAL_ERROR, error.message));
|
||||
if (error) return callback(new BoxError(BoxError.DATABASE_ERROR, error));
|
||||
|
||||
if (!backupInfo.manifest) callback(new AppsError(AppsError.EXTERNAL_ERROR, 'Could not get restore manifest'));
|
||||
if (!backupInfo.manifest) callback(new BoxError(BoxError.EXTERNAL_ERROR, 'Could not get restore manifest'));
|
||||
|
||||
// re-validate because this new box version may not accept old configs
|
||||
error = checkManifestConstraints(backupInfo.manifest);
|
||||
@@ -1530,14 +1496,14 @@ function purchaseApp(data, callback) {
|
||||
appdb.del(data.appId, function (delError) {
|
||||
if (delError) debug('install: Failed to rollback app installation.', delError);
|
||||
|
||||
if (error.reason === AppstoreError.NOT_FOUND) return callback(new AppsError(AppsError.NOT_FOUND, error.message));
|
||||
if (error && error.reason === AppstoreError.PLAN_LIMIT) return callback(new AppsError(AppsError.PLAN_LIMIT, error.message));
|
||||
if (error && error.reason === AppstoreError.INVALID_TOKEN) return callback(new AppsError(AppsError.EXTERNAL_ERROR, error.message));
|
||||
if (error && error.reason === AppstoreError.LICENSE_ERROR) return callback(new AppsError(AppsError.EXTERNAL_ERROR, error.message));
|
||||
if (error && error.reason === AppstoreError.NOT_REGISTERED) return callback(new AppsError(AppsError.EXTERNAL_ERROR, error.message));
|
||||
if (error && error.reason === AppstoreError.EXTERNAL_ERROR) return callback(new AppsError(AppsError.EXTERNAL_ERROR, error.message));
|
||||
if (error.reason === AppstoreError.NOT_FOUND) return callback(new BoxError(BoxError.NOT_FOUND, error.message));
|
||||
if (error && error.reason === AppstoreError.PLAN_LIMIT) return callback(new BoxError(BoxError.PLAN_LIMIT, error.message));
|
||||
if (error && error.reason === AppstoreError.INVALID_TOKEN) return callback(new BoxError(BoxError.EXTERNAL_ERROR, error.message));
|
||||
if (error && error.reason === AppstoreError.LICENSE_ERROR) return callback(new BoxError(BoxError.EXTERNAL_ERROR, error.message));
|
||||
if (error && error.reason === AppstoreError.NOT_REGISTERED) return callback(new BoxError(BoxError.EXTERNAL_ERROR, error.message));
|
||||
if (error && error.reason === AppstoreError.EXTERNAL_ERROR) return callback(new BoxError(BoxError.EXTERNAL_ERROR, error.message));
|
||||
|
||||
callback(new AppsError(AppsError.INTERNAL_ERROR, error));
|
||||
callback(new BoxError(BoxError.DATABASE_ERROR, error));
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -1567,11 +1533,11 @@ function clone(appId, data, user, auditSource, callback) {
|
||||
if (error) return callback(error);
|
||||
|
||||
backups.get(backupId, function (error, backupInfo) {
|
||||
if (error && error.reason === BoxError.EXTERNAL_ERROR) return callback(new AppsError(AppsError.EXTERNAL_ERROR, error.message));
|
||||
if (error && error.reason === BoxError.NOT_FOUND) return callback(new AppsError(AppsError.EXTERNAL_ERROR, 'Backup not found'));
|
||||
if (error) return callback(new AppsError(AppsError.INTERNAL_ERROR, error));
|
||||
if (error && error.reason === BoxError.EXTERNAL_ERROR) return callback(new BoxError(BoxError.EXTERNAL_ERROR, error.message));
|
||||
if (error && error.reason === BoxError.NOT_FOUND) return callback(new BoxError(BoxError.EXTERNAL_ERROR, 'Backup not found'));
|
||||
if (error) return callback(new BoxError(BoxError.DATABASE_ERROR, error));
|
||||
|
||||
if (!backupInfo.manifest) callback(new AppsError(AppsError.EXTERNAL_ERROR, 'Could not get restore config'));
|
||||
if (!backupInfo.manifest) callback(new BoxError(BoxError.EXTERNAL_ERROR, 'Could not get restore config'));
|
||||
|
||||
const manifest = backupInfo.manifest, appStoreId = app.appStoreId;
|
||||
|
||||
@@ -1584,7 +1550,7 @@ function clone(appId, data, user, auditSource, callback) {
|
||||
|
||||
if (mailboxName) {
|
||||
error = mail.validateName(mailboxName);
|
||||
if (error) return callback(new AppsError(AppsError.BAD_FIELD, error.message, { field: 'mailboxName' }));
|
||||
if (error) return callback(new BoxError(BoxError.BAD_FIELD, error.message, { field: 'mailboxName' }));
|
||||
} else {
|
||||
mailboxName = mailboxNameForLocation(location, manifest);
|
||||
}
|
||||
@@ -1610,7 +1576,7 @@ function clone(appId, data, user, auditSource, callback) {
|
||||
|
||||
appdb.add(newAppId, appStoreId, manifest, location, domain, translatePortBindings(portBindings, manifest), data, function (error) {
|
||||
if (error && error.reason === DatabaseError.ALREADY_EXISTS) return callback(getDuplicateErrorDetails(error.message, locations, domainObjectMap, portBindings));
|
||||
if (error) return callback(new AppsError(AppsError.INTERNAL_ERROR, error));
|
||||
if (error) return callback(new BoxError(BoxError.DATABASE_ERROR, error));
|
||||
|
||||
purchaseApp({ appId: newAppId, appstoreId: app.appStoreId, manifestId: manifest.id }, function (error) {
|
||||
if (error) return callback(error);
|
||||
@@ -1652,11 +1618,11 @@ function uninstall(appId, auditSource, callback) {
|
||||
if (error) return callback(error);
|
||||
|
||||
appstore.unpurchaseApp(appId, { appstoreId: app.appStoreId, manifestId: app.manifest.id }, function (error) {
|
||||
if (error && error.reason === AppstoreError.NOT_FOUND) return callback(new AppsError(AppsError.NOT_FOUND));
|
||||
if (error && error.reason === AppstoreError.INVALID_TOKEN) return callback(new AppsError(AppsError.EXTERNAL_ERROR, error.message));
|
||||
if (error && error.reason === AppstoreError.LICENSE_ERROR) return callback(new AppsError(AppsError.EXTERNAL_ERROR, error.message));
|
||||
if (error && error.reason === AppstoreError.EXTERNAL_ERROR) return callback(new AppsError(AppsError.EXTERNAL_ERROR, error.message));
|
||||
if (error) return callback(new AppsError(AppsError.INTERNAL_ERROR, error));
|
||||
if (error && error.reason === AppstoreError.NOT_FOUND) return callback(new BoxError(BoxError.NOT_FOUND));
|
||||
if (error && error.reason === AppstoreError.INVALID_TOKEN) return callback(new BoxError(BoxError.EXTERNAL_ERROR, error.message));
|
||||
if (error && error.reason === AppstoreError.LICENSE_ERROR) return callback(new BoxError(BoxError.EXTERNAL_ERROR, error.message));
|
||||
if (error && error.reason === AppstoreError.EXTERNAL_ERROR) return callback(new BoxError(BoxError.EXTERNAL_ERROR, error.message));
|
||||
if (error) return callback(new BoxError(BoxError.DATABASE_ERROR, error));
|
||||
|
||||
const task = {
|
||||
args: {},
|
||||
@@ -1725,16 +1691,16 @@ function stop(appId, callback) {
|
||||
function checkManifestConstraints(manifest) {
|
||||
assert(manifest && typeof manifest === 'object');
|
||||
|
||||
if (manifest.manifestVersion > 2) return new AppsError(AppsError.BAD_FIELD, 'Manifest version must be <= 2');
|
||||
if (manifest.manifestVersion > 2) return new BoxError(BoxError.BAD_FIELD, 'Manifest version must be <= 2');
|
||||
|
||||
if (!manifest.dockerImage) return new AppsError(AppsError.BAD_FIELD, 'Missing dockerImage'); // dockerImage is optional in manifest
|
||||
if (!manifest.dockerImage) return new BoxError(BoxError.BAD_FIELD, 'Missing dockerImage'); // dockerImage is optional in manifest
|
||||
|
||||
if (semver.valid(manifest.maxBoxVersion) && semver.gt(constants.VERSION, manifest.maxBoxVersion)) {
|
||||
return new AppsError(AppsError.BAD_FIELD, 'Box version exceeds Apps maxBoxVersion');
|
||||
return new BoxError(BoxError.BAD_FIELD, 'Box version exceeds Apps maxBoxVersion');
|
||||
}
|
||||
|
||||
if (semver.valid(manifest.minBoxVersion) && semver.gt(manifest.minBoxVersion, constants.VERSION)) {
|
||||
return new AppsError(AppsError.BAD_FIELD, 'App version requires a new platform version');
|
||||
return new BoxError(BoxError.BAD_FIELD, 'App version requires a new platform version');
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -1752,7 +1718,7 @@ function exec(appId, options, callback) {
|
||||
if (error) return callback(error);
|
||||
|
||||
if (app.installationState !== exports.ISTATE_INSTALLED || app.runState !== exports.RSTATE_RUNNING) {
|
||||
return callback(new AppsError(AppsError.BAD_STATE, 'App not installed or running'));
|
||||
return callback(new BoxError(BoxError.BAD_STATE, 'App not installed or running'));
|
||||
}
|
||||
|
||||
var container = docker.connection.getContainer(app.containerId);
|
||||
@@ -1770,9 +1736,9 @@ function exec(appId, options, callback) {
|
||||
};
|
||||
|
||||
container.exec(execOptions, function (error, exec) {
|
||||
if (error && error.statusCode === 409) return callback(new AppsError(AppsError.BAD_STATE, error.message)); // container restarting/not running
|
||||
if (error && error.statusCode === 409) return callback(new BoxError(BoxError.BAD_STATE, error.message)); // container restarting/not running
|
||||
if (error) return callback(error);
|
||||
|
||||
if (error) return callback(new AppsError(AppsError.INTERNAL_ERROR, error));
|
||||
var startOptions = {
|
||||
Detach: false,
|
||||
Tty: options.tty,
|
||||
@@ -1788,7 +1754,7 @@ function exec(appId, options, callback) {
|
||||
stderr: true
|
||||
};
|
||||
exec.start(startOptions, function(error, stream /* in hijacked mode, this is a net.socket */) {
|
||||
if (error) return callback(new AppsError(AppsError.INTERNAL_ERROR, error));
|
||||
if (error) return callback(error);
|
||||
|
||||
if (options.rows && options.columns) {
|
||||
// there is a race where resizing too early results in a 404 "no such exec"
|
||||
@@ -1884,11 +1850,11 @@ function listBackups(page, perPage, appId, callback) {
|
||||
assert.strictEqual(typeof callback, 'function');
|
||||
|
||||
appdb.exists(appId, function (error, exists) {
|
||||
if (error) return callback(new AppsError(AppsError.INTERNAL_ERROR, error));
|
||||
if (!exists) return callback(new AppsError(AppsError.NOT_FOUND));
|
||||
if (error) return callback(new BoxError(BoxError.DATABASE_ERROR, error));
|
||||
if (!exists) return callback(new BoxError(BoxError.NOT_FOUND));
|
||||
|
||||
backups.getByAppIdPaged(page, perPage, appId, function (error, results) {
|
||||
if (error) return callback(new AppsError(AppsError.INTERNAL_ERROR, error));
|
||||
if (error) return callback(error);
|
||||
|
||||
callback(null, results);
|
||||
});
|
||||
@@ -1899,7 +1865,8 @@ function restoreInstalledApps(callback) {
|
||||
assert.strictEqual(typeof callback, 'function');
|
||||
|
||||
getAll(function (error, apps) {
|
||||
if (error) return callback(new AppsError(AppsError.INTERNAL_ERROR, error));
|
||||
if (error) return callback(error);
|
||||
|
||||
apps = apps.filter(app => app.installationState !== exports.ISTATE_ERROR); // remove errored apps. let them be 'repaired' by hand
|
||||
apps = apps.filter(app => app.installationState !== exports.ISTATE_PENDING_RESTORE); // safeguard against tasks being created non-stop if we crash on startup
|
||||
|
||||
@@ -1938,7 +1905,8 @@ function configureInstalledApps(callback) {
|
||||
assert.strictEqual(typeof callback, 'function');
|
||||
|
||||
getAll(function (error, apps) {
|
||||
if (error) return callback(new AppsError(AppsError.INTERNAL_ERROR, error));
|
||||
if (error) return callback(error);
|
||||
|
||||
apps = apps.filter(app => app.installationState !== exports.ISTATE_ERROR); // remove errored apps. let them be 'repaired' by hand
|
||||
apps = apps.filter(app => app.installationState !== exports.ISTATE_PENDING_CONFIGURE); // safeguard against tasks being created non-stop if we crash on startup
|
||||
|
||||
@@ -1998,7 +1966,7 @@ function downloadFile(appId, filePath, callback) {
|
||||
stream.on('data', function (d) { data += d; });
|
||||
stream.on('end', function () {
|
||||
var parts = data.split('-');
|
||||
if (parts.length !== 2) return callback(new AppsError(AppsError.NOT_FOUND, 'file does not exist'));
|
||||
if (parts.length !== 2) return callback(new BoxError(BoxError.NOT_FOUND, 'file does not exist'));
|
||||
|
||||
var type = parts[0], filename, cmd, size;
|
||||
|
||||
@@ -2006,13 +1974,13 @@ function downloadFile(appId, filePath, callback) {
|
||||
cmd = [ 'cat', filePath ];
|
||||
size = parseInt(parts[1], 10);
|
||||
filename = path.basename(filePath);
|
||||
if (isNaN(size)) return callback(new AppsError(AppsError.NOT_FOUND, 'file does not exist'));
|
||||
if (isNaN(size)) return callback(new BoxError(BoxError.NOT_FOUND, 'file does not exist'));
|
||||
} else if (type === 'directory') {
|
||||
cmd = ['tar', 'zcf', '-', '-C', filePath, '.'];
|
||||
filename = path.basename(filePath) + '.tar.gz';
|
||||
size = 0; // unknown
|
||||
} else {
|
||||
return callback(new AppsError(AppsError.NOT_FOUND, 'only files or dirs can be downloaded'));
|
||||
return callback(new BoxError(BoxError.NOT_FOUND, 'only files or dirs can be downloaded'));
|
||||
}
|
||||
|
||||
exec(appId, { cmd: cmd , tty: false }, function (error, stream) {
|
||||
|
||||
Reference in New Issue
Block a user