diff --git a/src/appstore.js b/src/appstore.js index 1b205c7c7..fb4f80d76 100644 --- a/src/appstore.js +++ b/src/appstore.js @@ -11,6 +11,8 @@ exports = module.exports = { getAppUpdate: getAppUpdate, getBoxUpdate: getBoxUpdate, + getAccount: getAccount, + AppstoreError: AppstoreError }; @@ -245,3 +247,21 @@ function getAppUpdate(app, callback) { }); }); } + +function getAccount(callback) { + assert.strictEqual(typeof callback, 'function'); + + getAppstoreConfig(function (error, appstoreConfig) { + if (error) return callback(error); + + var url = config.apiServerOrigin() + '/api/v1/users/' + appstoreConfig.userId; + + superagent.get(url).query({ accessToken: appstoreConfig.token }).timeout(10 * 1000).end(function (error, result) { + if (error && !error.response) return callback(new AppstoreError(AppstoreError.EXTERNAL_ERROR, error)); + if (result.statusCode !== 200) return callback(new AppstoreError(AppstoreError.EXTERNAL_ERROR, util.format('Bad response: %s %s', result.statusCode, result.text))); + + // { profile: { id, email, groupId, billing, firstName, lastName, company, street, city, zip, state, country } } + callback(null, result.body.profile); + }); + }); +} diff --git a/src/mailer.js b/src/mailer.js index 8f9f45b3d..da6fd232d 100644 --- a/src/mailer.js +++ b/src/mailer.js @@ -36,7 +36,9 @@ exports = module.exports = { _clearMailQueue: _clearMailQueue }; -var assert = require('assert'), +var appstore = require('./appstore.js'), + AppstoreError = appstore.AppstoreError, + assert = require('assert'), async = require('async'), config = require('./config.js'), debug = require('debug')('box:mailer'), @@ -426,29 +428,34 @@ function sendDigest(info) { cloudronName = 'Cloudron'; } - var templateData = { - fqdn: config.fqdn(), - webadminUrl: config.adminOrigin(), - cloudronName: cloudronName, - cloudronAvatarUrl: config.adminOrigin() + '/api/v1/cloudron/avatar', - info: info - }; + appstore.getAccount(function (error, appstoreProfile) { + if (error && error.reason !== AppstoreError.BILLING_REQUIRED) console.error(error); + if (appstoreProfile) adminEmails.push(appstoreProfile.email); - var templateDataText = JSON.parse(JSON.stringify(templateData)); - templateDataText.format = 'text'; + var templateData = { + fqdn: config.fqdn(), + webadminUrl: config.adminOrigin(), + cloudronName: cloudronName, + cloudronAvatarUrl: config.adminOrigin() + '/api/v1/cloudron/avatar', + info: info + }; - var templateDataHTML = JSON.parse(JSON.stringify(templateData)); - templateDataHTML.format = 'html'; + var templateDataText = JSON.parse(JSON.stringify(templateData)); + templateDataText.format = 'text'; - var mailOptions = { - from: mailConfig().from, - to: adminEmails.join(', '), - subject: util.format('[%s] Cloudron - Weekly activity digest', config.fqdn()), - text: render('digest.ejs', templateDataText), - html: render('digest.ejs', templateDataHTML) - }; + var templateDataHTML = JSON.parse(JSON.stringify(templateData)); + templateDataHTML.format = 'html'; - enqueue(mailOptions); + var mailOptions = { + from: mailConfig().from, + to: adminEmails.join(', '), + subject: util.format('[%s] Cloudron - Weekly activity digest', config.fqdn()), + text: render('digest.ejs', templateDataText), + html: render('digest.ejs', templateDataHTML) + }; + + enqueue(mailOptions); + }); }); }); } diff --git a/src/test/digest-test.js b/src/test/digest-test.js index a2ab3bcfb..2eef10180 100644 --- a/src/test/digest-test.js +++ b/src/test/digest-test.js @@ -12,6 +12,7 @@ var async = require('async'), eventlog = require('../eventlog.js'), expect = require('expect.js'), mailer = require('../mailer.js'), + nock = require('nock'), paths = require('../paths.js'), safe = require('safetydance'), settings = require('../settings.js'), @@ -30,10 +31,15 @@ var AUDIT_SOURCE = { ip: '1.2.3.4' }; -function checkMails(number, done) { +function checkMails(number, email, done) { // mails are enqueued async setTimeout(function () { expect(mailer._getMailQueue().length).to.equal(number); + + if (number && email) { + expect(mailer._getMailQueue()[0].to.indexOf(email)).to.not.equal(-1); + } + mailer._clearMailQueue(); done(); }, 500); @@ -78,7 +84,7 @@ describe('digest', function () { it('does not send mail with digest disabled', function (done) { digest.maybeSend(function (error) { if (error) return done(error); - checkMails(0, done); + checkMails(0, '', done); }); }); @@ -93,7 +99,7 @@ describe('digest', function () { digest.maybeSend(function (error) { if (error) return done(error); - checkMails(1, done); + checkMails(1, '', done); }); }); @@ -103,7 +109,40 @@ describe('digest', function () { digest.maybeSend(function (error) { if (error) return done(error); - checkMails(1, done); + checkMails(1, '', done); + }); + }); + + it('sends mail for pending update to appstore account email (caas)', function (done) { + var subscription = { + id: 'caas', + created: 0, + canceled_at: 0, + status: 'active', + plan: { id: 'caas' } + }; + + updatechecker._setUpdateInfo({ box: null, apps: { 'appid': { manifest: { version: '1.2.5', changelog: 'noop\nreally' } } } }); + var fake1 = nock(config.apiServerOrigin()).post(function (uri) { return uri.indexOf('/api/v1/users/test-user/cloudrons') >= 0; }).reply(201, { cloudron: { id: 'test-cloudron' }}); + var fake2 = nock(config.apiServerOrigin()).get(function (uri) { return uri.indexOf('/api/v1/users/test-user/cloudrons/test-cloudron/subscription') >= 0; }).reply(200, { subscription: subscription }); + var fake3 = nock(config.apiServerOrigin()).get('/api/v1/users/test-user?accessToken=test-token').reply(200, { profile: { id: 'test-user', email: 'test@email.com' } }); + + settings.setAppstoreConfig({ userId: 'test-user', token: 'test-token', cloudronId: 'test-cloudron' }, function (error) { + if (error) return done(error); + + digest.maybeSend(function (error) { + if (error) return done(error); + + checkMails(1, 'test@email.com', function (error) { + if (error) return done(error); + + expect(fake1.isDone()).to.be.ok(); + expect(fake2.isDone()).to.be.ok(); + expect(fake3.isDone()).to.be.ok(); + + done(); + }); + }); }); }); });