diff --git a/src/apps.js b/src/apps.js index 62149af5d..96b64ce60 100644 --- a/src/apps.js +++ b/src/apps.js @@ -983,8 +983,7 @@ function setDebugMode(appId, debugMode, auditSource, callback) { function setMailbox(appId, mailboxName, auditSource, callback) { assert.strictEqual(typeof appId, 'string'); - assert(!mailboxName || typeof mailboxName === 'string'); - assert.strictEqual(typeof memoryLimit, 'number'); + assert(mailboxName === null || typeof mailboxName === 'string'); assert.strictEqual(typeof auditSource, 'object'); assert.strictEqual(typeof callback, 'function'); @@ -998,7 +997,7 @@ function setMailbox(appId, mailboxName, auditSource, callback) { mailboxName = mailboxNameForLocation(app.location, app.manifest); } - scheduleTask(appId, {}, { installationState: exports.ISTATE_PENDING_CREATE, mailboxName: mailboxName }, function (error, result) { + scheduleTask(appId, {}, { installationState: exports.ISTATE_PENDING_CREATE_CONTAINER, mailboxName: mailboxName }, function (error, result) { if (error) return callback(error); eventlog.add(eventlog.ACTION_APP_CONFIGURE, auditSource, { appId: appId, app: app, mailboxName: mailboxName, taskId: result.taskId }); @@ -1132,6 +1131,9 @@ function setLocation(appId, data, auditSource, callback) { values.alternateDomains = data.alternateDomains; } + // move the mailbox name to match the new location + if (app.mailboxName.endsWith('.app')) values.mailboxName = mailboxNameForLocation(values.location, app.manifest); + domains.get(values.domain, function (error, domainObject) { if (error && error.reason === DomainsError.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)); diff --git a/src/apptask.js b/src/apptask.js index caca15b94..939faae48 100644 --- a/src/apptask.js +++ b/src/apptask.js @@ -617,6 +617,10 @@ function create(app, progressCallback, callback) { stopApp.bind(null, app, progressCallback), deleteContainers.bind(null, app, { managedOnly: true }), + // FIXME: re-setup addons only because sendmail addon to re-inject env vars on mailboxName change + progressCallback.bind(null, { percent: 30, message: 'Setting up addons' }), + addons.setupAddons.bind(null, app, app.manifest.addons), + progressCallback.bind(null, { percent: 60, message: 'Creating container' }), createContainer.bind(null, app), diff --git a/src/routes/test/apps-test.js b/src/routes/test/apps-test.js index 5b391b235..5720ab27f 100644 --- a/src/routes/test/apps-test.js +++ b/src/routes/test/apps-test.js @@ -478,6 +478,7 @@ describe('App API', function () { expect(res.statusCode).to.equal(200); expect(res.body.id).to.eql(APP_ID); expect(res.body.installationState).to.be.ok(); + expect(res.body.mailboxName).to.be(APP_LOCATION + '.app'); done(); }); }); @@ -1084,10 +1085,12 @@ describe('App API', function () { waitForTask(taskId, done); }); - it('did change env vars', function (done) { + it('did change location', function (done) { apps.get(APP_ID, function (error, app) { if (error) return done(error); + expect(app.mailboxName).to.be(APP_LOCATION_NEW + '.app'); // must follow location change + docker.getContainer(app.containerId).inspect(function (error, data) { expect(error).to.not.be.ok(); expect(data.Config.Env).to.contain('CLOUDRON_APP_ORIGIN=https://' + APP_LOCATION_NEW + '.' + DOMAIN_0.domain); @@ -1275,6 +1278,82 @@ describe('App API', function () { }); }); + describe('configure mailbox', function () { + it('fails with missing mailbox', function (done) { + superagent.post(SERVER_URL + '/api/v1/apps/' + APP_ID + '/configure/mailbox') + .query({ access_token: token }) + .end(function (err, res) { + expect(res.statusCode).to.equal(400); + done(); + }); + }); + + it('fails with bad mailbox', function (done) { + superagent.post(SERVER_URL + '/api/v1/apps/' + APP_ID + '/configure/mailbox') + .query({ access_token: token }) + .send({ mailbox: 'genos@cloudron.io' }) + .end(function (err, res) { + expect(res.statusCode).to.equal(400); + done(); + }); + }); + + it('can set mailbox', function (done) { + superagent.post(SERVER_URL + '/api/v1/apps/' + APP_ID + '/configure/mailbox') + .query({ access_token: token }) + .send({ mailboxName: 'genos' }) + .end(function (err, res) { + expect(res.statusCode).to.equal(202); + taskId = res.body.taskId; + done(); + }); + }); + + it('wait for task', function (done) { + waitForTask(taskId, done); + }); + + it('did set mailbox', function (done) { + apps.get(APP_ID, function (error, app) { + if (error) return done(error); + + docker.getContainer(app.containerId).inspect(function (error, data) { + expect(error).to.not.be.ok(); + + expect(data.Config.Env).to.contain('CLOUDRON_MAIL_FROM=genos@' + app.domain); + done(); + }); + }); + }); + + it('can reset mailbox', function (done) { + superagent.post(SERVER_URL + '/api/v1/apps/' + APP_ID + '/configure/mailbox') + .query({ access_token: token }) + .send({ mailboxName: null }) + .end(function (err, res) { + expect(res.statusCode).to.equal(202); + taskId = res.body.taskId; + done(); + }); + }); + + it('wait for task', function (done) { + waitForTask(taskId, done); + }); + + it('did reset mailbox', function (done) { + apps.get(APP_ID, function (error, app) { + if (error) return done(error); + + docker.getContainer(app.containerId).inspect(function (error, data) { + expect(error).to.not.be.ok(); + expect(data.Config.Env).to.not.contain('CLOUDRON_MAIL_FROM=' + app.location + '@' + app.domain + '.app'); + done(); + }); + }); + }); + }); + describe('start/stop', function () { it('non admin cannot stop app', function (done) { superagent.post(SERVER_URL + '/api/v1/apps/' + APP_ID + '/stop')