diff --git a/src/appstore.js b/src/appstore.js index 4183c52c4..41aef69cc 100644 --- a/src/appstore.js +++ b/src/appstore.js @@ -24,31 +24,23 @@ exports = module.exports = { getAppUpdate, getBoxUpdate, - createTicket, - // exported for tests _setApiServerOrigin: setApiServerOrigin, _unregister: unregister }; -const apps = require('./apps.js'), - assert = require('assert'), +const assert = require('assert'), BoxError = require('./boxerror.js'), constants = require('./constants.js'), dashboard = require('./dashboard.js'), debug = require('debug')('box:appstore'), - eventlog = require('./eventlog.js'), manifestFormat = require('cloudron-manifestformat'), - network = require('./network.js'), - path = require('path'), paths = require('./paths.js'), promiseRetry = require('./promise-retry.js'), safe = require('safetydance'), semver = require('semver'), settings = require('./settings.js'), - shell = require('./shell.js')('appstore'), - superagent = require('./superagent.js'), - support = require('./support.js'); + superagent = require('./superagent.js'); // These are the default options and will be adjusted once a subscription state is obtained // Keep in sync with appstore/routes/cloudrons.js @@ -344,54 +336,6 @@ async function unregister() { await settings.set(settings.APPSTORE_API_TOKEN_KEY, ''); } -async function createTicket(info, auditSource) { - assert.strictEqual(typeof info, 'object'); - assert.strictEqual(typeof info.email, 'string'); - assert.strictEqual(typeof info.displayName, 'string'); - assert.strictEqual(typeof info.type, 'string'); - assert.strictEqual(typeof info.subject, 'string'); - assert.strictEqual(typeof info.description, 'string'); - assert.strictEqual(typeof auditSource, 'object'); - - const token = await settings.get(settings.APPSTORE_API_TOKEN_KEY); - if (!token) throw new BoxError(BoxError.LICENSE_ERROR, 'Missing token'); - - if (info.enableSshSupport) { - await safe(support.enableRemoteSupport(true, auditSource)); - info.ipv4 = await network.getIPv4(); - } - - info.app = info.appId ? await apps.get(info.appId) : null; - info.supportEmail = constants.SUPPORT_EMAIL; // destination address for tickets - - const request = superagent.post(`${await getApiServerOrigin()}/api/v1/ticket`) - .query({ accessToken: token }) - .timeout(60 * 1000) - .ok(() => true); - - // either send as JSON through body or as multipart, depending on attachments - if (info.app) { - request.field('infoJSON', JSON.stringify(info)); - - const logPaths = await apps.getLogPaths(info.app); - for (const logPath of logPaths) { - const [error, logs] = await safe(shell.spawn('tail', ['--lines=1000', logPath], { encoding: 'utf8' })); - if (!error && logs) request.attach(path.basename(logPath), logs, path.basename(logPath)); - } - } else { - request.send(info); - } - - const [error, response] = await safe(request); - if (error) throw new BoxError(BoxError.NETWORK_ERROR, error); - if (response.status === 401) throw new BoxError(BoxError.INVALID_CREDENTIALS, 'Invalid appstore token'); - if (response.status !== 201) throw new BoxError(BoxError.EXTERNAL_ERROR, `Bad response: ${response.status} ${response.text}`); - - await eventlog.add(eventlog.ACTION_SUPPORT_TICKET, auditSource, info); - - return { message: `An email was sent to ${constants.SUPPORT_EMAIL}. We will get back shortly!` }; -} - async function downloadManifest(appStoreId, manifest) { if (!appStoreId && !manifest) throw new BoxError(BoxError.BAD_FIELD, 'Neither manifest nor appStoreId provided'); diff --git a/src/routes/support.js b/src/routes/support.js index 54924558e..ddb7f6a71 100644 --- a/src/routes/support.js +++ b/src/routes/support.js @@ -1,40 +1,17 @@ 'use strict'; exports = module.exports = { - createTicket, - getRemoteSupport, enableRemoteSupport, }; -const appstore = require('../appstore.js'), - assert = require('assert'), +const assert = require('assert'), AuditSource = require('../auditsource.js'), - constants = require('../constants.js'), HttpError = require('connect-lastmile').HttpError, HttpSuccess = require('connect-lastmile').HttpSuccess, safe = require('safetydance'), support = require('../support.js'); -async function createTicket(req, res, next) { - assert.strictEqual(typeof req.user, 'object'); - - const VALID_TYPES = [ 'feedback', 'ticket', 'app_missing', 'app_error', 'upgrade_request', 'email_error', 'billing' ]; - - if (typeof req.body.type !== 'string' || !req.body.type) return next(new HttpError(400, 'type must be string')); - if (VALID_TYPES.indexOf(req.body.type) === -1) return next(new HttpError(400, 'unknown type')); - if (typeof req.body.subject !== 'string' || !req.body.subject) return next(new HttpError(400, 'subject must be string')); - if (typeof req.body.description !== 'string' || !req.body.description) return next(new HttpError(400, 'description must be string')); - if (req.body.appId && typeof req.body.appId !== 'string') return next(new HttpError(400, 'appId must be string')); - if (req.body.altEmail && typeof req.body.altEmail !== 'string') return next(new HttpError(400, 'altEmail must be string')); - if (req.body.enableSshSupport && typeof req.body.enableSshSupport !== 'boolean') return next(new HttpError(400, 'enableSshSupport must be a boolean')); - - const [ticketError, result] = await safe(appstore.createTicket(Object.assign({ }, req.body, { email: req.user.email, displayName: req.user.displayName }), AuditSource.fromRequest(req))); - if (ticketError) return next(new HttpError(503, `Error contacting cloudron.io: ${ticketError.message}. Please email ${constants.SUPPORT_EMAIL}`)); - - next(new HttpSuccess(201, result)); -} - async function enableRemoteSupport(req, res, next) { assert.strictEqual(typeof req.body, 'object'); diff --git a/src/server.js b/src/server.js index 310a03725..8a08a58b4 100644 --- a/src/server.js +++ b/src/server.js @@ -395,7 +395,6 @@ async function initializeExpressSync() { router.del ('/api/v1/mail/:domain/lists/:name', token, authorizeMailManager, routes.mail.delList); // support routes - router.post('/api/v1/support/ticket', json, token, authorizeOwner, routes.support.createTicket); router.get ('/api/v1/support/remote_support', token, authorizeOwner, routes.support.getRemoteSupport); router.post('/api/v1/support/remote_support', json, token, authorizeOwner, routes.support.enableRemoteSupport);