diff --git a/.gitignore b/.gitignore index 03cfbea2..59401b15 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ /sandbox /config/public-key.json /config/secret-key.json +/config/vapid-keys.json *.swp server.log* secret* diff --git a/config/index.js b/config/index.js index a7dc098c..a59e575b 100644 --- a/config/index.js +++ b/config/index.js @@ -92,6 +92,12 @@ var conf = convict({ default: [], env: 'TRUSTED_JKUS' }, + vapidKeysFile: { + doc: 'Keys to use for VAPID in push notifications', + format: String, + default: path.resolve(__dirname, '../config/vapid-keys.json'), + env: 'VAPID_KEYS_FILE' + }, db: { backend: { default: 'httpdb', diff --git a/lib/push.js b/lib/push.js index 816fcba5..ab1fef9d 100644 --- a/lib/push.js +++ b/lib/push.js @@ -78,7 +78,17 @@ var reasonToEvents = { } } -module.exports = function (log, db) { +module.exports = function (log, db, config) { + var vapid + if (config.vapidKeysFile) { + var vapidKeys = require(config.vapidKeysFile) + vapid = { + privateKey: vapidKeys.privateKey, + publicKey: vapidKeys.publicKey, + subject: config.publicUrl + } + } + /** * Reports push errors to logs * @@ -311,18 +321,25 @@ module.exports = function (log, db) { if (device.pushCallback) { // send the push notification incrementPushAction(events.send) - var pushParams = { 'TTL': options.TTL || '0' } + var pushSubscription = { endpoint: device.pushCallback } + var pushPayload = null + var pushOptions = { 'TTL': options.TTL || '0' } if (options.data) { if (!device.pushPublicKey || !device.pushAuthKey) { reportPushError(new Error(ERR_DATA_BUT_NO_KEYS), uid, deviceId) incrementPushAction(events.noKeys) return } - pushParams.userPublicKey = device.pushPublicKey - pushParams.userAuth = device.pushAuthKey - pushParams.payload = options.data + pushSubscription.keys = { + p256dh: device.pushPublicKey, + auth: device.pushAuthKey + } + pushPayload = options.data } - return webpush.sendNotification(device.pushCallback, pushParams) + if (vapid) { + pushOptions.vapidDetails = vapid + } + return webpush.sendNotification(pushSubscription, pushPayload, pushOptions) .then( function () { incrementPushAction(events.success) diff --git a/lib/routes/index.js b/lib/routes/index.js index fdc22c2f..efeb02f4 100644 --- a/lib/routes/index.js +++ b/lib/routes/index.js @@ -25,7 +25,7 @@ module.exports = function ( var defaults = require('./defaults')(log, P, db, error) var idp = require('./idp')(log, serverPublicKeys) var checkPassword = require('./utils/password_check')(log, config, Password, customs, db) - var push = require('../push')(log, db) + var push = require('../push')(log, db, config) var devices = require('../devices')(log, db, push) var account = require('./account')( log, diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 01d012a0..aaa4f9d5 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -10149,76 +10149,13 @@ "resolved": "https://registry.npmjs.org/uuid/-/uuid-1.4.1.tgz" }, "web-push": { - "version": "2.1.1", - "from": "web-push@2.1.1", - "resolved": "https://registry.npmjs.org/web-push/-/web-push-2.1.1.tgz", + "version": "3.0.0", + "from": "web-push@latest", + "resolved": "https://registry.npmjs.org/web-push/-/web-push-3.0.0.tgz", "dependencies": { - "array.prototype.find": { - "version": "2.0.0", - "from": "array.prototype.find@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/array.prototype.find/-/array.prototype.find-2.0.0.tgz", - "dependencies": { - "define-properties": { - "version": "1.1.2", - "from": "define-properties@>=1.1.2 <2.0.0", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz", - "dependencies": { - "foreach": { - "version": "2.0.5", - "from": "foreach@>=2.0.5 <3.0.0", - "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz" - }, - "object-keys": { - "version": "1.0.11", - "from": "object-keys@>=1.0.8 <2.0.0", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz" - } - } - }, - "es-abstract": { - "version": "1.6.1", - "from": "es-abstract@>=1.5.0 <2.0.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.6.1.tgz", - "dependencies": { - "function-bind": { - "version": "1.1.0", - "from": "function-bind@>=1.1.0 <2.0.0", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.0.tgz" - }, - "is-callable": { - "version": "1.1.3", - "from": "is-callable@>=1.1.3 <2.0.0", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.3.tgz" - }, - "es-to-primitive": { - "version": "1.1.1", - "from": "es-to-primitive@>=1.1.1 <2.0.0", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.1.1.tgz", - "dependencies": { - "is-date-object": { - "version": "1.0.1", - "from": "is-date-object@>=1.0.1 <2.0.0", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz" - }, - "is-symbol": { - "version": "1.0.1", - "from": "is-symbol@>=1.0.1 <2.0.0", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.1.tgz" - } - } - }, - "is-regex": { - "version": "1.0.3", - "from": "is-regex@>=1.0.3 <2.0.0", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.3.tgz" - } - } - } - } - }, "asn1.js": { "version": "4.8.1", - "from": "asn1.js@>=4.5.2 <5.0.0", + "from": "asn1.js@>=4.8.1 <5.0.0", "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.8.1.tgz", "dependencies": { "bn.js": { @@ -10238,74 +10175,6 @@ } } }, - "bluebird": { - "version": "3.4.6", - "from": "bluebird@>=3.3.5 <4.0.0", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.6.tgz" - }, - "buffer-compare-shim": { - "version": "1.0.0", - "from": "buffer-compare-shim@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/buffer-compare-shim/-/buffer-compare-shim-1.0.0.tgz", - "dependencies": { - "buffer-compare": { - "version": "0.0.1", - "from": "buffer-compare@>=0.0.1 <0.0.2", - "resolved": "https://registry.npmjs.org/buffer-compare/-/buffer-compare-0.0.1.tgz" - } - } - }, - "buffer-equals-polyfill": { - "version": "1.0.0", - "from": "buffer-equals-polyfill@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/buffer-equals-polyfill/-/buffer-equals-polyfill-1.0.0.tgz", - "dependencies": { - "buffer-compare": { - "version": "0.0.1", - "from": "buffer-compare@>=0.0.1 <0.0.2", - "resolved": "https://registry.npmjs.org/buffer-compare/-/buffer-compare-0.0.1.tgz" - } - } - }, - "colors": { - "version": "1.1.2", - "from": "colors@>=1.1.2 <2.0.0", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz" - }, - "create-ecdh": { - "version": "4.0.0", - "from": "create-ecdh@>=4.0.0 <5.0.0", - "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.0.tgz", - "dependencies": { - "bn.js": { - "version": "4.11.6", - "from": "bn.js@>=4.1.0 <5.0.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz" - }, - "elliptic": { - "version": "6.3.2", - "from": "elliptic@>=6.0.0 <7.0.0", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.3.2.tgz", - "dependencies": { - "brorand": { - "version": "1.0.6", - "from": "brorand@>=1.0.1 <2.0.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.0.6.tgz" - }, - "hash.js": { - "version": "1.0.3", - "from": "hash.js@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.0.3.tgz" - }, - "inherits": { - "version": "2.0.3", - "from": "inherits@>=2.0.1 <3.0.0", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" - } - } - } - } - }, "http_ece": { "version": "0.5.1", "from": "http_ece@>=0.5.1 <0.6.0", @@ -10350,16 +10219,62 @@ }, "inherits": { "version": "2.0.3", - "from": "inherits@>=2.0.1 <2.1.0", + "from": "inherits@>=2.0.1 <3.0.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" } } }, + "buffer-compare-shim": { + "version": "1.0.0", + "from": "buffer-compare-shim@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/buffer-compare-shim/-/buffer-compare-shim-1.0.0.tgz", + "dependencies": { + "buffer-compare": { + "version": "0.0.1", + "from": "buffer-compare@0.0.1", + "resolved": "https://registry.npmjs.org/buffer-compare/-/buffer-compare-0.0.1.tgz" + } + } + }, "buffer-io-shim": { "version": "1.0.0", "from": "buffer-io-shim@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/buffer-io-shim/-/buffer-io-shim-1.0.0.tgz" }, + "create-ecdh": { + "version": "4.0.0", + "from": "create-ecdh@>=4.0.0 <4.1.0", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.0.tgz", + "dependencies": { + "bn.js": { + "version": "4.11.6", + "from": "bn.js@>=4.1.0 <5.0.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz" + }, + "elliptic": { + "version": "6.3.2", + "from": "elliptic@>=6.0.0 <7.0.0", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.3.2.tgz", + "dependencies": { + "brorand": { + "version": "1.0.6", + "from": "brorand@>=1.0.1 <2.0.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.0.6.tgz" + }, + "hash.js": { + "version": "1.0.3", + "from": "hash.js@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.0.3.tgz" + }, + "inherits": { + "version": "2.0.3", + "from": "inherits@>=2.0.1 <3.0.0", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" + } + } + } + } + }, "semver": { "version": "5.1.1", "from": "semver@>=5.1.0 <5.2.0", diff --git a/package.json b/package.json index dfd3bd26..b08c8933 100644 --- a/package.json +++ b/package.json @@ -60,7 +60,7 @@ "scrypt-hash": "1.1.14", "through": "2.3.8", "uuid": "1.4.1", - "web-push": "2.1.1" + "web-push": "3.0.0" }, "devDependencies": { "commander": "2.9.0", diff --git a/scripts/gen_vapid_keys.js b/scripts/gen_vapid_keys.js new file mode 100755 index 00000000..ba89a5e8 --- /dev/null +++ b/scripts/gen_vapid_keys.js @@ -0,0 +1,42 @@ +#!/usr/bin/env node + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* scripts/gen_valid_keys.js creates public and private keys suitable for + use with VAPID in push notifications. + + Usage: + ./scripts/gen_valid_keys.js [filename] + + The filename will default to: + + ./config/vapid-keys.json + + If this file already exists, this script will show an error message + and exit. You must remove the file if you want to generate a new + keypair. +*/ + +const fs = require('fs') +const config = require('../config') +const webpush = require('web-push') + +const vapidKeysFile = config.get('vapidKeysFile') + +var fileExists = fs.existsSync(vapidKeysFile) +if (fileExists) { + console.log('keys file already exists') + process.exit() +} + +console.error('Generating key for VAPID') + +var keys = webpush.generateVAPIDKeys() +fs.writeFileSync(vapidKeysFile, JSON.stringify({ + privateKey: keys.privateKey.toString('base64'), + publicKey: keys.publicKey.toString('base64') +})) + +console.error('Done:', vapidKeysFile) diff --git a/scripts/start-local-mysql.sh b/scripts/start-local-mysql.sh index 327bc3d8..49bdd21f 100755 --- a/scripts/start-local-mysql.sh +++ b/scripts/start-local-mysql.sh @@ -3,6 +3,7 @@ set -euo pipefail node ./scripts/gen_keys.js +node ./scripts/gen_vapid_keys.js node ./test/mail_helper.js & MH=$! ls ./node_modules/fxa-auth-db-mysql/node_modules/mysql-patcher || npm i ./node_modules/fxa-auth-db-mysql diff --git a/scripts/start-local.sh b/scripts/start-local.sh index 87ef676d..c11d521c 100755 --- a/scripts/start-local.sh +++ b/scripts/start-local.sh @@ -3,6 +3,7 @@ set -euo pipefail node ./scripts/gen_keys.js +node ./scripts/gen_vapid_keys.js node ./test/mail_helper.js & MH=$! node ./node_modules/fxa-auth-db-mysql/bin/mem.js & diff --git a/scripts/test-local.sh b/scripts/test-local.sh index 71f9673a..8db8d4ca 100755 --- a/scripts/test-local.sh +++ b/scripts/test-local.sh @@ -8,6 +8,7 @@ if [ "$glob" == "" ]; then fi ./scripts/gen_keys.js +./scripts/gen_vapid_keys.js ./scripts/check-i18n.js ./scripts/tap-coverage.js $glob 2>/dev/null grunt eslint copyright diff --git a/test/config/mock-vapid-keys.json b/test/config/mock-vapid-keys.json new file mode 100644 index 00000000..c9a43fd4 --- /dev/null +++ b/test/config/mock-vapid-keys.json @@ -0,0 +1,4 @@ +{ + "privateKey": "private", + "publicKey": "public" +} diff --git a/test/e2e/push_tests.js b/test/e2e/push_tests.js index aca10f23..7215575c 100644 --- a/test/e2e/push_tests.js +++ b/test/e2e/push_tests.js @@ -7,6 +7,7 @@ var proxyquire = require('proxyquire') var test = tap.test var P = require('../../lib/promise') +var config = require('../../config').getProperties() var spyLog = require('../mocks').spyLog var mockUid = new Buffer('foo') @@ -49,7 +50,7 @@ test( } }) - var push = proxyquire('../../lib/push', {})(thisSpyLog, mockDbResult) + var push = proxyquire('../../lib/push', {})(thisSpyLog, mockDbResult, config) var options = { data: new Buffer('foodata') } diff --git a/test/local/account_routes.js b/test/local/account_routes.js index 30276e2f..94241ef1 100644 --- a/test/local/account_routes.js +++ b/test/local/account_routes.js @@ -45,7 +45,7 @@ var makeRoutes = function (options, requireMocks) { check: function () { return P.resolve(true) } } var checkPassword = options.checkPassword || require('../../lib/routes/utils/password_check')(log, config, Password, customs, db) - var push = options.push || require('../../lib/push')(log, db) + var push = options.push || require('../../lib/push')(log, db, {}) var metricsContext = options.metricsContext || log.metricsContext || require('../../lib/metrics/context')(log, config) return proxyquire('../../lib/routes/account', requireMocks || {})( log, diff --git a/test/local/push_tests.js b/test/local/push_tests.js index 3b03b6dd..0e3cf138 100644 --- a/test/local/push_tests.js +++ b/test/local/push_tests.js @@ -13,6 +13,7 @@ var test = tap.test var P = require('../../lib/promise') var mockLog = require('../mocks').mockLog var mockUid = new Buffer('foo') +var mockConfig = {} var PUSH_PAYLOADS_SCHEMA_PATH = '../../docs/pushpayloads.schema.json' var TTL = '42' @@ -55,7 +56,7 @@ var mockDbResult = { test( 'pushToDevices throws on device not found', function (t) { - var push = require('../../lib/push')(mockLog(), mockDbEmpty) + var push = require('../../lib/push')(mockLog(), mockDbEmpty, mockConfig) sinon.spy(push, 'sendPush') push.pushToDevices([mockUid], 'bogusid').then(function () { @@ -79,7 +80,7 @@ test( }) try { - var push = require('../../lib/push')(thisMockLog, mockDbEmpty) + var push = require('../../lib/push')(thisMockLog, mockDbEmpty, mockConfig) push.pushToAllDevices(mockUid).catch(function (err) { t.fail('must not throw') throw err @@ -96,14 +97,14 @@ test( function (t) { var mocks = { 'web-push': { - sendNotification: function (endpoint, params) { + sendNotification: function (sub, payload, options) { t.end() return P.resolve() } } } - var push = proxyquire('../../lib/push', mocks)(mockLog(), mockDbResult) + var push = proxyquire('../../lib/push', mocks)(mockLog(), mockDbResult, mockConfig) var options = { excludedDeviceIds: [mockDevices[0].id] } push.pushToAllDevices(mockUid, 'accountVerify', options) } @@ -113,7 +114,7 @@ test( 'pushToAllDevices calls sendPush', function (t) { try { - var push = require('../../lib/push')(mockLog(), mockDbResult) + var push = require('../../lib/push')(mockLog(), mockDbResult, mockConfig) sinon.stub(push, 'sendPush') var excluded = [mockDevices[0].id] var data = new Buffer('foobar') @@ -141,7 +142,7 @@ test( 'pushToDevices calls sendPush', function (t) { try { - var push = require('../../lib/push')(mockLog(), mockDbResult) + var push = require('../../lib/push')(mockLog(), mockDbResult, mockConfig) sinon.stub(push, 'sendPush') var data = new Buffer('foobar') var options = { data: data, TTL: TTL } @@ -168,7 +169,7 @@ test( 'pushToDevice calls pushToDevices', function (t) { try { - var push = require('../../lib/push')(mockLog(), mockDbResult) + var push = require('../../lib/push')(mockLog(), mockDbResult, mockConfig) sinon.stub(push, 'pushToDevices') var data = new Buffer('foobar') var options = { data: data, TTL: TTL } @@ -207,14 +208,14 @@ test( var mocks = { 'web-push': { - sendNotification: function (endpoint, params) { - t.equal(params.TTL, '0', 'sends the proper ttl header') + sendNotification: function (sub, payload, options) { + t.equal(options.TTL, '0', 'sends the proper ttl header') return P.resolve() } } } - var push = proxyquire('../../lib/push', mocks)(thisMockLog, mockDbResult) + var push = proxyquire('../../lib/push', mocks)(thisMockLog, mockDbResult, mockConfig) push.sendPush(mockUid, mockDevices, 'accountVerify') } ) @@ -239,14 +240,14 @@ test( var mocks = { 'web-push': { - sendNotification: function (endpoint, params) { - t.equal(params.TTL, TTL, 'sends the proper ttl header') + sendNotification: function (sub, payload, options) { + t.equal(options.TTL, TTL, 'sends the proper ttl header') return P.resolve() } } } - var push = proxyquire('../../lib/push', mocks)(thisMockLog, mockDbResult) + var push = proxyquire('../../lib/push', mocks)(thisMockLog, mockDbResult, mockConfig) var options = { TTL: TTL } push.sendPush(mockUid, mockDevices, 'accountVerify', options) } @@ -259,11 +260,11 @@ test( var data = new Buffer('foobar') var mocks = { 'web-push': { - sendNotification: function (endpoint, params) { + sendNotification: function (sub, payload, options) { count++ - t.ok(params.userPublicKey) - t.ok(params.userAuth) - t.deepEqual(params.payload, data) + t.ok(sub.keys.p256dh) + t.ok(sub.keys.auth) + t.deepEqual(payload, data) if (count === 2) { t.end() } @@ -272,7 +273,7 @@ test( } } - var push = proxyquire('../../lib/push', mocks)(mockLog(), mockDbResult) + var push = proxyquire('../../lib/push', mocks)(mockLog(), mockDbResult, mockConfig) var options = { data: data } push.sendPush(mockUid, mockDevices, 'accountVerify', options) } @@ -297,7 +298,7 @@ test( 'pushAuthKey': 'bogus' }] - var push = require('../../lib/push')(thisMockLog, mockDbResult) + var push = require('../../lib/push')(thisMockLog, mockDbResult, mockConfig) var options = { data: new Buffer('foobar') } push.sendPush(mockUid, devices, 'accountVerify', options) } @@ -320,7 +321,7 @@ test( 'name': 'My Phone' }] - var push = require('../../lib/push')(thisMockLog, mockDbResult) + var push = require('../../lib/push')(thisMockLog, mockDbResult, mockConfig) push.sendPush(mockUid, devices, 'accountVerify') } ) @@ -339,13 +340,13 @@ test( var mocks = { 'web-push': { - sendNotification: function (endpoint, params) { + sendNotification: function (sub, payload, options) { return P.reject(new Error('Failed')) } } } - var push = proxyquire('../../lib/push', mocks)(thisMockLog, mockDbResult) + var push = proxyquire('../../lib/push', mocks)(thisMockLog, mockDbResult, mockConfig) push.sendPush(mockUid, [mockDevices[0]], 'accountVerify') } ) @@ -364,13 +365,13 @@ test( var mocks = { 'web-push': { - sendNotification: function (endpoint, params) { - t.equal(params.TTL, '0', 'sends the proper ttl header') + sendNotification: function (sub, payload, options) { + t.equal(options.TTL, '0', 'sends the proper ttl header') return P.resolve() } } } - var push = proxyquire('../../lib/push', mocks)(thisMockLog, mockDbResult) + var push = proxyquire('../../lib/push', mocks)(thisMockLog, mockDbResult, mockConfig) push.sendPush(mockUid, devices, 'accountVerify').then(function () { t.equal(thisMockLog.error.callCount, 0, 'log.error was not called') @@ -410,7 +411,7 @@ test( var mocks = { 'web-push': { - sendNotification: function (endpoint, params) { + sendNotification: function (sub, payload, options) { var err = new Error('Failed') err.statusCode = 410 return P.reject(err) @@ -418,7 +419,7 @@ test( } } - var push = proxyquire('../../lib/push', mocks)(thisMockLog, mockDb) + var push = proxyquire('../../lib/push', mocks)(thisMockLog, mockDb, mockConfig) push.sendPush(mockUid, [mockDevices[0]], 'accountVerify') } ) @@ -427,7 +428,7 @@ test( 'notifyUpdate calls pushToAllDevices', function (t) { try { - var push = require('../../lib/push')(mockLog(), mockDbEmpty) + var push = require('../../lib/push')(mockLog(), mockDbEmpty, mockConfig) sinon.spy(push, 'pushToAllDevices') push.notifyUpdate(mockUid, 'passwordReset').catch(function (err) { t.fail('must not throw') @@ -450,7 +451,7 @@ test( 'notifyUpdate without a 2nd arg calls pushToAllDevices with a accountVerify reason', function (t) { try { - var push = require('../../lib/push')(mockLog(), mockDbEmpty) + var push = require('../../lib/push')(mockLog(), mockDbEmpty, mockConfig) sinon.spy(push, 'pushToAllDevices') push.notifyUpdate(mockUid).catch(function (err) { t.fail('must not throw') @@ -473,7 +474,7 @@ test( 'notifyDeviceConnected calls pushToAllDevices', function (t) { try { - var push = require('../../lib/push')(mockLog(), mockDbEmpty) + var push = require('../../lib/push')(mockLog(), mockDbEmpty, mockConfig) sinon.spy(push, 'pushToAllDevices') var deviceId = 'gjfkd5434jk5h5fd' var deviceName = 'My phone' @@ -512,7 +513,7 @@ test( 'notifyDeviceDisconnected calls pushToDevice', function (t) { try { - var push = require('../../lib/push')(mockLog(), mockDbResult) + var push = require('../../lib/push')(mockLog(), mockDbResult, mockConfig) sinon.spy(push, 'pushToDevice') var idToDisconnect = mockDevices[0].id var expectedData = { @@ -553,12 +554,12 @@ test( try { var mocks = { 'web-push': { - sendNotification: function (endpoint, params) { + sendNotification: function (sub, payload, options) { return P.resolve() } } } - var push = proxyquire('../../lib/push', mocks)(mockLog(), mockDbResult) + var push = proxyquire('../../lib/push', mocks)(mockLog(), mockDbResult, mockConfig) sinon.spy(push, 'sendPush') var expectedData = { version: 1, @@ -594,12 +595,12 @@ test( try { var mocks = { 'web-push': { - sendNotification: function (endpoint, params) { + sendNotification: function (sub, payload, options) { return P.resolve() } } } - var push = proxyquire('../../lib/push', mocks)(mockLog(), mockDbEmpty) + var push = proxyquire('../../lib/push', mocks)(mockLog(), mockDbEmpty, mockConfig) sinon.spy(push, 'sendPush') var expectedData = { version: 1, @@ -628,3 +629,36 @@ test( } } ) + +test( + 'sendPush includes VAPID identification if it is configured', + function (t) { + var thisMockLog = mockLog({ + info: function (log) { + if (log.name === 'push.account_verify.success') { + t.end() + } + } + }) + + var mockConfig = { + publicUrl: 'https://example.com', + vapidKeysFile: path.join(__dirname, '..', 'config', 'mock-vapid-keys.json') + } + + var mocks = { + 'web-push': { + sendNotification: function (sub, payload, options) { + t.ok(options.vapidDetails, 'sends the VAPID params object') + t.equal(options.vapidDetails.subject, mockConfig.publicUrl, 'sends the correct VAPID subject') + t.equal(options.vapidDetails.privateKey, 'private', 'sends the correct VAPID privkey') + t.equal(options.vapidDetails.publicKey, 'public', 'sends the correct VAPID pubkey') + return P.resolve() + } + } + } + + var push = proxyquire('../../lib/push', mocks)(thisMockLog, mockDbResult, mockConfig) + push.sendPush(mockUid, mockDevices, 'accountVerify') + } +) diff --git a/test/remote/push_db_tests.js b/test/remote/push_db_tests.js index 47f88027..8166a2d0 100644 --- a/test/remote/push_db_tests.js +++ b/test/remote/push_db_tests.js @@ -119,7 +119,7 @@ test( }) .then(function () { - var pushWithUnknown400 = proxyquire('../../lib/push', mocksUnknown400)(mockLog, db) + var pushWithUnknown400 = proxyquire('../../lib/push', mocksUnknown400)(mockLog, db, {}) return pushWithUnknown400.pushToAllDevices(ACCOUNT.uid, 'accountVerify') }) .then(function () { @@ -134,7 +134,7 @@ test( }) .then(function () { - var pushWithKnown400 = proxyquire('../../lib/push', mocksKnown400)(mockLog, db) + var pushWithKnown400 = proxyquire('../../lib/push', mocksKnown400)(mockLog, db, {}) return pushWithKnown400.pushToAllDevices(ACCOUNT.uid, 'accountVerify') }) .then(function () {