feat(server): lazily get devices array on the request object (#2107) r=vladikoff,vbudhram
Fixes #2106. Prevents us from accidentally calling db.devices more than once per request. I saw one definite case of this in /recovery_email/verify_code and it's possible there were others. I'll also be making use of this property heavily for the amplitude events, so it will get further usage imminently. Making the change necessitated pulling calls to db.devices out of lib/push, which triggered some refactoring that almost got away from me. I'll add inline commentary to call out why things have changed the way they have, but most push methods now take an extra devices argument and a few other methods became redundant so I deleted them. I don't think I've broken anything.
This commit is contained in:
Родитель
dae0e58340
Коммит
f084830bcf
|
@ -28,6 +28,6 @@ var profileUpdatesQueue = new SQSReceiver(config.profileServerMessaging.region,
|
|||
DB.connect(config[config.db.backend])
|
||||
.then(
|
||||
function (db) {
|
||||
profileUpdates(profileUpdatesQueue, push(log, db, config))
|
||||
profileUpdates(profileUpdatesQueue, push(log, db, config), db)
|
||||
}
|
||||
)
|
||||
|
|
|
@ -57,7 +57,9 @@ module.exports = (log, db, push) => {
|
|||
deviceName = synthesizeName(deviceInfo)
|
||||
}
|
||||
if (sessionToken.tokenVerified) {
|
||||
push.notifyDeviceConnected(sessionToken.uid, deviceName, result.id)
|
||||
request.app.devices.then(devices =>
|
||||
push.notifyDeviceConnected(sessionToken.uid, devices, deviceName, result.id)
|
||||
)
|
||||
}
|
||||
if (isPlaceholderDevice) {
|
||||
log.info({
|
||||
|
|
|
@ -2,27 +2,25 @@
|
|||
* 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/. */
|
||||
|
||||
const P = require('./../promise')
|
||||
'use strict'
|
||||
|
||||
module.exports = function (log) {
|
||||
|
||||
return function start(messageQueue, push) {
|
||||
return function start(messageQueue, push, db) {
|
||||
|
||||
function handleProfileUpdated(message) {
|
||||
const uid = message && message.uid
|
||||
|
||||
return new P(resolve => {
|
||||
log.info({ op: 'handleProfileUpdated', uid: uid, action: 'notify' })
|
||||
resolve(push.notifyProfileUpdated(message.uid))
|
||||
})
|
||||
.catch(function(err) {
|
||||
log.error({ op: 'handleProfileUpdated', uid: uid, action: 'error', err: err, stack: err && err.stack })
|
||||
})
|
||||
.then(function () {
|
||||
log.info({ op: 'handleProfileUpdated', uid: uid, action: 'delete' })
|
||||
// We always delete the message, we are not really mission critical
|
||||
message.del()
|
||||
})
|
||||
log.info({ op: 'handleProfileUpdated', uid, action: 'notify' })
|
||||
|
||||
return db.devices(uid)
|
||||
.then(devices => push.notifyProfileUpdated(uid, devices))
|
||||
.catch(err => log.error({ op: 'handleProfileUpdated', uid, action: 'error', err, stack: err && err.stack }))
|
||||
.then(() => {
|
||||
log.info({ op: 'handleProfileUpdated', uid, action: 'delete' })
|
||||
// We always delete the message, we are not really mission critical
|
||||
message.del()
|
||||
})
|
||||
}
|
||||
|
||||
messageQueue.on('data', handleProfileUpdated)
|
||||
|
|
267
lib/push.js
267
lib/push.js
|
@ -11,7 +11,7 @@ var ERR_NO_PUSH_CALLBACK = 'No Push Callback'
|
|||
var ERR_DATA_BUT_NO_KEYS = 'Data payload present but missing key(s)'
|
||||
var ERR_TOO_MANY_DEVICES = 'Too many devices connected to account'
|
||||
|
||||
var LOG_OP_PUSH_TO_DEVICES = 'push.pushToDevices'
|
||||
var LOG_OP_PUSH_TO_DEVICES = 'push.sendPush'
|
||||
|
||||
var PUSH_PAYLOAD_SCHEMA_VERSION = 1
|
||||
var PUSH_COMMANDS = {
|
||||
|
@ -253,190 +253,148 @@ module.exports = function (log, db, config) {
|
|||
|
||||
return {
|
||||
|
||||
isValidPublicKey: isValidPublicKey,
|
||||
isValidPublicKey,
|
||||
|
||||
/**
|
||||
* Notifies all devices that there was an update to the account
|
||||
* Notify devices that there was an update to the account
|
||||
*
|
||||
* @param {String} uid
|
||||
* @param {Device[]} devices
|
||||
* @param {String} reason
|
||||
* @param {Object} [options]
|
||||
* @param {String[]} [options.includedDeviceIds]
|
||||
* @param {String[]} [options.excludedDeviceIds]
|
||||
* @param {String} [options.data]
|
||||
* @param {String} [options.TTL] (in seconds)
|
||||
* @promise
|
||||
*/
|
||||
notifyUpdate: function notifyUpdate(uid, reason) {
|
||||
reason = reason || 'accountVerify'
|
||||
return this.pushToAllDevices(uid, reason)
|
||||
notifyUpdate (uid, devices, reason, options = {}) {
|
||||
if (options.includedDeviceIds) {
|
||||
const include = new Set(options.includedDeviceIds)
|
||||
devices = devices.filter(device => include.has(device.id))
|
||||
|
||||
if (devices.length === 0) {
|
||||
return P.reject('devices empty')
|
||||
}
|
||||
} else if (options.excludedDeviceIds) {
|
||||
const exclude = new Set(options.excludedDeviceIds)
|
||||
devices = devices.filter(device => ! exclude.has(device.id))
|
||||
}
|
||||
|
||||
return this.sendPush(uid, devices, reason, filterOptions(options))
|
||||
},
|
||||
|
||||
/**
|
||||
* Notifies all devices (except the one who joined) that a new device joined the account
|
||||
* Notify devices (except currentDeviceId) that a new device was connected
|
||||
*
|
||||
* @param {String} uid
|
||||
* @param {Device[]} devices
|
||||
* @param {String} deviceName
|
||||
* @param {String} currentDeviceId
|
||||
* @promise
|
||||
*/
|
||||
notifyDeviceConnected: function notifyDeviceConnected(uid, deviceName, currentDeviceId) {
|
||||
var data = Buffer.from(JSON.stringify({
|
||||
version: PUSH_PAYLOAD_SCHEMA_VERSION,
|
||||
command: PUSH_COMMANDS.DEVICE_CONNECTED,
|
||||
data: {
|
||||
deviceName: deviceName
|
||||
}
|
||||
}))
|
||||
var options = { data: data, excludedDeviceIds: [currentDeviceId] }
|
||||
return this.pushToAllDevices(uid, 'deviceConnected', options)
|
||||
notifyDeviceConnected (uid, devices, deviceName, currentDeviceId) {
|
||||
return this.notifyUpdate(uid, devices, 'deviceConnected', {
|
||||
data: encodePayload({
|
||||
version: PUSH_PAYLOAD_SCHEMA_VERSION,
|
||||
command: PUSH_COMMANDS.DEVICE_CONNECTED,
|
||||
data: {
|
||||
deviceName
|
||||
}
|
||||
}),
|
||||
excludedDeviceIds: [ currentDeviceId ]
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Notifies a device that it is now disconnected from the account
|
||||
* Notify devices that a device was disconnected from the account
|
||||
*
|
||||
* @param {String} uid
|
||||
* @param {Device[]} devices
|
||||
* @param {String} idToDisconnect
|
||||
* @promise
|
||||
*/
|
||||
notifyDeviceDisconnected: function notifyDeviceDisconnected(uid, idToDisconnect) {
|
||||
var data = Buffer.from(JSON.stringify({
|
||||
version: PUSH_PAYLOAD_SCHEMA_VERSION,
|
||||
command: PUSH_COMMANDS.DEVICE_DISCONNECTED,
|
||||
data: {
|
||||
id: idToDisconnect
|
||||
}
|
||||
}))
|
||||
var options = { data: data, TTL: TTL_DEVICE_DISCONNECTED }
|
||||
return this.pushToAllDevices(uid, 'deviceDisconnected', options)
|
||||
},
|
||||
|
||||
/**
|
||||
* Notifies all devices that a the profile attached to the account was updated
|
||||
*
|
||||
* @param {String} uid
|
||||
* @promise
|
||||
*/
|
||||
notifyProfileUpdated: function notifyProfileUpdated(uid) {
|
||||
var data = Buffer.from(JSON.stringify({
|
||||
version: PUSH_PAYLOAD_SCHEMA_VERSION,
|
||||
command: PUSH_COMMANDS.PROFILE_UPDATED
|
||||
}))
|
||||
var options = { data: data }
|
||||
return this.pushToAllDevices(uid, 'profileUpdated', options)
|
||||
},
|
||||
|
||||
/**
|
||||
* Notifies a set of devices that the password was changed
|
||||
*
|
||||
* @param {String} uid
|
||||
* @param {Device[]} devices
|
||||
* @promise
|
||||
*/
|
||||
notifyPasswordChanged: function notifyPasswordChanged(uid, devices) {
|
||||
var data = Buffer.from(JSON.stringify({
|
||||
version: PUSH_PAYLOAD_SCHEMA_VERSION,
|
||||
command: PUSH_COMMANDS.PASSWORD_CHANGED
|
||||
}))
|
||||
var options = { data: data, TTL: TTL_PASSWORD_CHANGED }
|
||||
return this.sendPush(uid, devices, 'passwordChange', options)
|
||||
},
|
||||
|
||||
/**
|
||||
* Notifies a set of devices that the password was reset
|
||||
*
|
||||
* @param {String} uid
|
||||
* @param {Device[]} devices
|
||||
* @promise
|
||||
*/
|
||||
notifyPasswordReset: function notifyPasswordReset(uid, devices) {
|
||||
var data = Buffer.from(JSON.stringify({
|
||||
version: PUSH_PAYLOAD_SCHEMA_VERSION,
|
||||
command: PUSH_COMMANDS.PASSWORD_RESET
|
||||
}))
|
||||
var options = { data: data, TTL: TTL_PASSWORD_RESET }
|
||||
return this.sendPush(uid, devices, 'passwordReset', options)
|
||||
},
|
||||
|
||||
/**
|
||||
* Notifies a set of devices that the account no longer exists
|
||||
*
|
||||
* @param {String} uid
|
||||
* @param {Device[]} devices
|
||||
* @promise
|
||||
*/
|
||||
notifyAccountDestroyed: function notifyAccountDestroyed(uid, devices) {
|
||||
var data = Buffer.from(JSON.stringify({
|
||||
version: PUSH_PAYLOAD_SCHEMA_VERSION,
|
||||
command: PUSH_COMMANDS.ACCOUNT_DESTROYED,
|
||||
data: {
|
||||
uid: uid
|
||||
}
|
||||
}))
|
||||
var options = { data: data, TTL: TTL_ACCOUNT_DESTROYED }
|
||||
return this.sendPush(uid, devices, 'accountDestroyed', options)
|
||||
},
|
||||
|
||||
/**
|
||||
* Send a push notification with or without data to all the devices in the account (except the ones in the excludedDeviceIds)
|
||||
*
|
||||
* @param {String} uid
|
||||
* @param {String} reason
|
||||
* @param {Object} options
|
||||
* @param {String} options.excludedDeviceIds
|
||||
* @param {String} options.data
|
||||
* @param {String} options.TTL (in seconds)
|
||||
* @promise
|
||||
*/
|
||||
pushToAllDevices: function pushToAllDevices(uid, reason, options) {
|
||||
options = options || {}
|
||||
var self = this
|
||||
return db.devices(uid).then(
|
||||
function (devices) {
|
||||
if (options.excludedDeviceIds) {
|
||||
devices = devices.filter(function(device) {
|
||||
return options.excludedDeviceIds.indexOf(device.id) === -1
|
||||
})
|
||||
notifyDeviceDisconnected (uid, devices, idToDisconnect) {
|
||||
return this.sendPush(uid, devices, 'deviceDisconnected', {
|
||||
data: encodePayload({
|
||||
version: PUSH_PAYLOAD_SCHEMA_VERSION,
|
||||
command: PUSH_COMMANDS.DEVICE_DISCONNECTED,
|
||||
data: {
|
||||
id: idToDisconnect
|
||||
}
|
||||
var pushOptions = filterOptions(options)
|
||||
return self.sendPush(uid, devices, reason, pushOptions)
|
||||
})
|
||||
}),
|
||||
TTL: TTL_DEVICE_DISCONNECTED
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Send a push notification with or without data to a set of devices in the account
|
||||
* Notify devices that the profile attached to the account was updated
|
||||
*
|
||||
* @param {String} uid
|
||||
* @param {String[]} ids
|
||||
* @param {String} reason
|
||||
* @param {Object} options
|
||||
* @param {String} options.data
|
||||
* @param {String} options.TTL (in seconds)
|
||||
* @param {Device[]} devices
|
||||
* @promise
|
||||
*/
|
||||
pushToDevices: function pushToDevices(uid, ids, reason, options) {
|
||||
var self = this
|
||||
return db.devices(uid).then(
|
||||
function (devices) {
|
||||
devices = devices.filter(function(device) {
|
||||
return ids.indexOf(device.id) !== -1
|
||||
})
|
||||
if (devices.length === 0) {
|
||||
return P.reject('Devices ids not found in devices')
|
||||
notifyProfileUpdated (uid, devices) {
|
||||
return this.sendPush(uid, devices, 'profileUpdated', {
|
||||
data: encodePayload({
|
||||
version: PUSH_PAYLOAD_SCHEMA_VERSION,
|
||||
command: PUSH_COMMANDS.PROFILE_UPDATED
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Notify devices that the password was changed
|
||||
*
|
||||
* @param {String} uid
|
||||
* @param {Device[]} devices
|
||||
* @promise
|
||||
*/
|
||||
notifyPasswordChanged (uid, devices) {
|
||||
return this.sendPush(uid, devices, 'passwordChange', {
|
||||
data: encodePayload({
|
||||
version: PUSH_PAYLOAD_SCHEMA_VERSION,
|
||||
command: PUSH_COMMANDS.PASSWORD_CHANGED
|
||||
}),
|
||||
TTL: TTL_PASSWORD_CHANGED
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Notify devices that the password was reset
|
||||
*
|
||||
* @param {String} uid
|
||||
* @param {Device[]} devices
|
||||
* @promise
|
||||
*/
|
||||
notifyPasswordReset (uid, devices) {
|
||||
return this.sendPush(uid, devices, 'passwordReset', {
|
||||
data: encodePayload({
|
||||
version: PUSH_PAYLOAD_SCHEMA_VERSION,
|
||||
command: PUSH_COMMANDS.PASSWORD_RESET
|
||||
}),
|
||||
TTL: TTL_PASSWORD_RESET
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Notify devices that the account no longer exists
|
||||
*
|
||||
* @param {String} uid
|
||||
* @param {Device[]} devices
|
||||
* @promise
|
||||
*/
|
||||
notifyAccountDestroyed (uid, devices) {
|
||||
return this.sendPush(uid, devices, 'accountDestroyed', {
|
||||
data: encodePayload({
|
||||
version: PUSH_PAYLOAD_SCHEMA_VERSION,
|
||||
command: PUSH_COMMANDS.ACCOUNT_DESTROYED,
|
||||
data: {
|
||||
uid
|
||||
}
|
||||
var pushOptions = filterOptions(options || {})
|
||||
return self.sendPush(uid, devices, reason, pushOptions)
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Send a push notification with or without data to one device in the account
|
||||
*
|
||||
* @param {String} uid
|
||||
* @param {String} id
|
||||
* @param {String} reason
|
||||
* @param {Object} options
|
||||
* @param {String} options.data
|
||||
* @param {String} options.TTL (in seconds)
|
||||
* @promise
|
||||
*/
|
||||
pushToDevice: function pushToDevice(uid, id, reason, options) {
|
||||
return this.pushToDevices(uid, [id], reason, options)
|
||||
}),
|
||||
TTL: TTL_ACCOUNT_DESTROYED
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -541,3 +499,8 @@ module.exports = function (log, db, config) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
function encodePayload (data) {
|
||||
return Buffer.from(JSON.stringify(data))
|
||||
}
|
||||
|
||||
|
|
|
@ -1343,10 +1343,10 @@ module.exports = (log, db, mailer, Password, config, customs, checkPassword, pus
|
|||
},
|
||||
handler: function accountReset(request, reply) {
|
||||
log.begin('Account.reset', request)
|
||||
var accountResetToken = request.auth.credentials
|
||||
var authPW = request.payload.authPW
|
||||
var account, sessionToken, keyFetchToken, verifyHash, wrapKb, devicesToNotify
|
||||
var hasSessionToken = request.payload.sessionToken
|
||||
const accountResetToken = request.auth.credentials
|
||||
const authPW = request.payload.authPW
|
||||
const hasSessionToken = request.payload.sessionToken
|
||||
let account, sessionToken, keyFetchToken, verifyHash, wrapKb
|
||||
|
||||
request.validateMetricsContext()
|
||||
|
||||
|
@ -1358,25 +1358,13 @@ module.exports = (log, db, mailer, Password, config, customs, checkPassword, pus
|
|||
}
|
||||
request.setMetricsFlowCompleteSignal(flowCompleteSignal)
|
||||
|
||||
return fetchDevicesToNotify()
|
||||
.then(resetAccountData)
|
||||
return resetAccountData()
|
||||
.then(createSessionToken)
|
||||
.then(createKeyFetchToken)
|
||||
.then(recordSecurityEvent)
|
||||
.then(createResponse)
|
||||
.then(reply, reply)
|
||||
|
||||
function fetchDevicesToNotify() {
|
||||
// We fetch the devices to notify before resetAccountData() because
|
||||
// db.resetAccount() deletes all the devices saved in the account.
|
||||
return db.devices(accountResetToken.uid)
|
||||
.then(
|
||||
function(devices) {
|
||||
devicesToNotify = devices
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
function resetAccountData () {
|
||||
let authSalt, password, wrapWrapKb
|
||||
return random.hex(32, 32)
|
||||
|
@ -1411,7 +1399,9 @@ module.exports = (log, db, mailer, Password, config, customs, checkPassword, pus
|
|||
.then(
|
||||
function () {
|
||||
// Notify the devices that the account has changed.
|
||||
push.notifyPasswordReset(accountResetToken.uid, devicesToNotify)
|
||||
request.app.devices.then(devices =>
|
||||
push.notifyPasswordReset(accountResetToken.uid, devices)
|
||||
)
|
||||
|
||||
return db.account(accountResetToken.uid)
|
||||
.then((accountData) => {
|
||||
|
@ -1578,7 +1568,8 @@ module.exports = (log, db, mailer, Password, config, customs, checkPassword, pus
|
|||
)
|
||||
.then(
|
||||
function () {
|
||||
push.notifyAccountDestroyed(uid, devicesToNotify).catch(function () {})
|
||||
push.notifyAccountDestroyed(uid, devicesToNotify)
|
||||
.catch(() => {})
|
||||
return P.all([
|
||||
log.notifyAttachedServices('delete', request, {
|
||||
uid: uid,
|
||||
|
|
|
@ -189,6 +189,10 @@ module.exports = (log, db, config, customs, push, devices) => {
|
|||
data: Buffer.from(JSON.stringify(payload))
|
||||
}
|
||||
|
||||
if (body.to !== 'all') {
|
||||
pushOptions.includedDeviceIds = body.to
|
||||
}
|
||||
|
||||
if (body.excluded) {
|
||||
pushOptions.excludedDeviceIds = body.excluded
|
||||
}
|
||||
|
@ -200,15 +204,11 @@ module.exports = (log, db, config, customs, push, devices) => {
|
|||
const endpointAction = 'devicesNotify'
|
||||
|
||||
return customs.checkAuthenticated(endpointAction, ip, uid)
|
||||
.then(() => {
|
||||
if (body.to === 'all') {
|
||||
push.pushToAllDevices(uid, endpointAction, pushOptions)
|
||||
.catch(catchPushError)
|
||||
} else {
|
||||
push.pushToDevices(uid, body.to, endpointAction, pushOptions)
|
||||
.catch(catchPushError)
|
||||
}
|
||||
})
|
||||
.then(() => request.app.devices)
|
||||
.then(devices =>
|
||||
push.notifyUpdate(uid, devices, endpointAction, pushOptions)
|
||||
.catch(catchPushError)
|
||||
)
|
||||
.then(() => {
|
||||
// Emit a metrics event for when a user sends tabs between devices.
|
||||
// In the future we will aim to get this event directly from sync telemetry,
|
||||
|
@ -420,8 +420,10 @@ module.exports = (log, db, config, customs, push, devices) => {
|
|||
.then(res => {
|
||||
result = res
|
||||
})
|
||||
.then(() => push.notifyDeviceDisconnected(uid, id)
|
||||
.catch(() => {})
|
||||
.then(() => request.app.devices)
|
||||
.then(devices =>
|
||||
push.notifyDeviceDisconnected(uid, devices, id)
|
||||
.catch(() => {})
|
||||
)
|
||||
.then(() => {
|
||||
return P.all([
|
||||
|
|
|
@ -413,7 +413,9 @@ module.exports = (log, db, mailer, config, customs, push) => {
|
|||
request.emitMetricsEvent('account.confirmed', {
|
||||
uid: uid
|
||||
})
|
||||
push.notifyUpdate(uid, 'accountConfirm')
|
||||
request.app.devices.then(devices =>
|
||||
push.notifyUpdate(uid, devices, 'accountConfirm')
|
||||
)
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
|
@ -432,7 +434,9 @@ module.exports = (log, db, mailer, config, customs, push) => {
|
|||
})
|
||||
.then(() => {
|
||||
if (device) {
|
||||
push.notifyDeviceConnected(uid, device.name, device.id)
|
||||
request.app.devices.then(devices =>
|
||||
push.notifyDeviceConnected(uid, devices, device.name, device.id)
|
||||
)
|
||||
}
|
||||
})
|
||||
.then(() => {
|
||||
|
@ -471,7 +475,9 @@ module.exports = (log, db, mailer, config, customs, push) => {
|
|||
})
|
||||
.then(() => {
|
||||
// send a push notification to all devices that the account changed
|
||||
push.notifyUpdate(uid, 'accountVerify')
|
||||
request.app.devices.then(devices =>
|
||||
push.notifyUpdate(uid, devices, 'accountVerify')
|
||||
)
|
||||
|
||||
// remove verification reminders
|
||||
verificationReminder.delete({
|
||||
|
@ -791,7 +797,7 @@ module.exports = (log, db, mailer, config, customs, push) => {
|
|||
return db.setPrimaryEmail(uid, email.normalizedEmail)
|
||||
})
|
||||
.then(() => {
|
||||
push.notifyProfileUpdated(uid)
|
||||
request.app.devices.then(devices => push.notifyProfileUpdated(uid, devices))
|
||||
log.notifyAttachedServices('primaryEmailChanged', request, {
|
||||
uid: account.uid,
|
||||
email: email
|
||||
|
|
|
@ -184,18 +184,15 @@ module.exports = function (
|
|||
function fetchDevicesToNotify() {
|
||||
// We fetch the devices to notify before changePassword() because
|
||||
// db.resetAccount() deletes all the devices saved in the account.
|
||||
return db.devices(passwordChangeToken.uid)
|
||||
.then(
|
||||
function(devices) {
|
||||
devicesToNotify = devices
|
||||
// If the originating sessionToken belongs to a device,
|
||||
// do not send the notification to that device. It will
|
||||
// get informed about the change via WebChannel message.
|
||||
if (originatingDeviceId) {
|
||||
devicesToNotify = devicesToNotify.filter(d => (d.id !== originatingDeviceId))
|
||||
}
|
||||
}
|
||||
)
|
||||
return request.app.devices.then(devices => {
|
||||
devicesToNotify = devices
|
||||
// If the originating sessionToken belongs to a device,
|
||||
// do not send the notification to that device. It will
|
||||
// get informed about the change via WebChannel message.
|
||||
if (originatingDeviceId) {
|
||||
devicesToNotify = devicesToNotify.filter(d => (d.id !== originatingDeviceId))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function changePassword() {
|
||||
|
|
|
@ -3,12 +3,12 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
const fs = require('fs')
|
||||
const Hapi = require('hapi')
|
||||
const path = require('path')
|
||||
const url = require('url')
|
||||
const Hapi = require('hapi')
|
||||
const userAgent = require('./userAgent')
|
||||
|
||||
const HEX_STRING = require('./routes/validators').HEX_STRING
|
||||
const { HEX_STRING } = require('./routes/validators')
|
||||
|
||||
function trimLocale(header) {
|
||||
if (! header) {
|
||||
|
@ -275,6 +275,17 @@ function create(log, error, config, routes, db, translator) {
|
|||
|
||||
defineLazyGetter(request.app, 'ua', () => userAgent(request.headers['user-agent']))
|
||||
defineLazyGetter(request.app, 'geo', () => getGeoData(request.app.clientAddress))
|
||||
defineLazyGetter(request.app, 'devices', () => {
|
||||
let uid
|
||||
|
||||
if (request.auth && request.auth.credentials) {
|
||||
uid = request.auth.credentials.uid
|
||||
} else if (request.payload && request.payload.uid) {
|
||||
uid = request.payload.uid
|
||||
}
|
||||
|
||||
return db.devices(uid)
|
||||
})
|
||||
|
||||
if (request.headers.authorization) {
|
||||
// Log some helpful details for debugging authentication problems.
|
||||
|
|
|
@ -5,18 +5,16 @@
|
|||
'use strict'
|
||||
|
||||
const assert = require('insist')
|
||||
var proxyquire = require('proxyquire')
|
||||
const config = require('../../config').getProperties()
|
||||
const proxyquire = require('proxyquire')
|
||||
const { mockDB, spyLog } = require('../mocks')
|
||||
const { PushManager } = require('../push_helper')
|
||||
|
||||
var P = require('../../lib/promise')
|
||||
var config = require('../../config').getProperties()
|
||||
var spyLog = require('../mocks').spyLog
|
||||
var mockUid = Buffer.from('foo')
|
||||
|
||||
var PushManager = require('../push_helper').PushManager
|
||||
const mockUid = 'foo'
|
||||
|
||||
describe('e2e/push', () => {
|
||||
|
||||
let pushManager
|
||||
|
||||
before(() => {
|
||||
pushManager = new PushManager({
|
||||
server: 'wss://push.services.mozilla.com/',
|
||||
|
@ -24,31 +22,9 @@ describe('e2e/push', () => {
|
|||
})
|
||||
})
|
||||
|
||||
it(
|
||||
'pushToAllDevices sends notifications using a real push server',
|
||||
() => {
|
||||
return pushManager.getSubscription().then(function (subscription) { // eslint-disable-line no-unreachable
|
||||
var mockDbResult = {
|
||||
devices: function (/* uid */) {
|
||||
return P.resolve([
|
||||
{
|
||||
'id': '0f7aa00356e5416e82b3bef7bc409eef',
|
||||
'isCurrentDevice': true,
|
||||
'lastAccessTime': 1449235471335,
|
||||
'name': 'My Phone',
|
||||
'type': 'mobile',
|
||||
'pushCallback': subscription.endpoint,
|
||||
'pushPublicKey': 'BBXOKjUb84pzws1wionFpfCBjDuCh4-s_1b52WA46K5wYL2gCWEOmFKWn_NkS5nmJwTBuO8qxxdjAIDtNeklvQc',
|
||||
'pushAuthKey': 'GSsIiaD2Mr83iPqwFNK4rw',
|
||||
'pushEndpointExpired': false
|
||||
}
|
||||
])
|
||||
},
|
||||
updateDevice: function () {
|
||||
return P.resolve()
|
||||
}
|
||||
}
|
||||
|
||||
it('notifyUpdate sends notifications using a real push server', () => {
|
||||
return pushManager.getSubscription()
|
||||
.then(subscription => {
|
||||
let count = 0
|
||||
var thisSpyLog = spyLog({
|
||||
info: function (log) {
|
||||
|
@ -58,15 +34,27 @@ describe('e2e/push', () => {
|
|||
}
|
||||
})
|
||||
|
||||
var push = proxyquire('../../lib/push', {})(thisSpyLog, mockDbResult, config)
|
||||
var push = proxyquire('../../lib/push', {})(thisSpyLog, mockDB(), config)
|
||||
var options = {
|
||||
data: Buffer.from('foodata')
|
||||
}
|
||||
return push.pushToAllDevices(mockUid, 'accountVerify', options).then(function() {
|
||||
assert.equal(thisSpyLog.error.callCount, 0, 'No errors should have been logged')
|
||||
assert.equal(count, 1)
|
||||
})
|
||||
return push.notifyUpdate(mockUid, [
|
||||
{
|
||||
id: '0f7aa00356e5416e82b3bef7bc409eef',
|
||||
isCurrentDevice: true,
|
||||
lastAccessTime: 1449235471335,
|
||||
name: 'My Phone',
|
||||
type: 'mobile',
|
||||
pushCallback: subscription.endpoint,
|
||||
pushPublicKey: 'BBXOKjUb84pzws1wionFpfCBjDuCh4-s_1b52WA46K5wYL2gCWEOmFKWn_NkS5nmJwTBuO8qxxdjAIDtNeklvQc',
|
||||
pushAuthKey: 'GSsIiaD2Mr83iPqwFNK4rw',
|
||||
pushEndpointExpired: false
|
||||
}
|
||||
], 'accountVerify', options)
|
||||
.then(() => {
|
||||
assert.equal(thisSpyLog.error.callCount, 0, 'No errors should have been logged')
|
||||
assert.equal(count, 1, 'log.info::push.account_verify.success was called once')
|
||||
})
|
||||
})
|
||||
}
|
||||
)
|
||||
})
|
||||
})
|
||||
|
|
|
@ -116,10 +116,11 @@ describe('devices', () => {
|
|||
|
||||
assert.equal(push.notifyDeviceConnected.callCount, 1, 'push.notifyDeviceConnected was called once')
|
||||
args = push.notifyDeviceConnected.args[0]
|
||||
assert.equal(args.length, 3, 'push.notifyDeviceConnected was passed three arguments')
|
||||
assert.equal(args.length, 4, 'push.notifyDeviceConnected was passed four arguments')
|
||||
assert.equal(args[0], sessionToken.uid, 'first argument was uid')
|
||||
assert.equal(args[1], device.name, 'second arguent was device name')
|
||||
assert.equal(args[2], deviceId, 'third argument was device id')
|
||||
assert.ok(Array.isArray(args[1]), 'second argument was devices array')
|
||||
assert.equal(args[2], device.name, 'third arguent was device name')
|
||||
assert.equal(args[3], deviceId, 'fourth argument was device id')
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -156,7 +157,7 @@ describe('devices', () => {
|
|||
|
||||
assert.equal(push.notifyDeviceConnected.callCount, 1, 'push.notifyDeviceConnected was called once')
|
||||
assert.equal(push.notifyDeviceConnected.args[0][0], sessionToken.uid, 'uid was correct')
|
||||
assert.equal(push.notifyDeviceConnected.args[0][1], 'Firefox', 'device name was included')
|
||||
assert.equal(push.notifyDeviceConnected.args[0][2], 'Firefox', 'device name was included')
|
||||
|
||||
})
|
||||
})
|
||||
|
|
|
@ -6,7 +6,7 @@ const assert = require('insist')
|
|||
|
||||
const EventEmitter = require('events').EventEmitter
|
||||
const sinon = require('sinon')
|
||||
const spyLog = require('../../mocks').spyLog
|
||||
const { mockDB, spyLog } = require('../../mocks')
|
||||
const profileUpdates = require('../../../lib/profile/updates')
|
||||
const P = require('../../../lib/promise')
|
||||
|
||||
|
@ -30,7 +30,7 @@ const mockPush = {
|
|||
}
|
||||
|
||||
function mockProfileUpdates(log) {
|
||||
return profileUpdates(log)(mockDeliveryQueue, mockPush)
|
||||
return profileUpdates(log)(mockDeliveryQueue, mockPush, mockDB())
|
||||
}
|
||||
|
||||
describe('profile updates', () => {
|
||||
|
|
|
@ -7,128 +7,124 @@
|
|||
const ROOT_DIR = '../..'
|
||||
|
||||
const assert = require('insist')
|
||||
var proxyquire = require('proxyquire')
|
||||
var sinon = require('sinon')
|
||||
var ajv = require('ajv')()
|
||||
var fs = require('fs')
|
||||
var path = require('path')
|
||||
const proxyquire = require('proxyquire')
|
||||
const sinon = require('sinon')
|
||||
const ajv = require('ajv')()
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
|
||||
const P = require(`${ROOT_DIR}/lib/promise`)
|
||||
const mocks = require('../mocks')
|
||||
const mockLog = mocks.mockLog
|
||||
var mockUid = 'deadbeef'
|
||||
var mockConfig = {}
|
||||
const mockUid = 'deadbeef'
|
||||
const mockConfig = {}
|
||||
|
||||
const PUSH_PAYLOADS_SCHEMA_PATH = `${ROOT_DIR}/docs/pushpayloads.schema.json`
|
||||
var TTL = '42'
|
||||
const TTL = '42'
|
||||
const pushModulePath = `${ROOT_DIR}/lib/push`
|
||||
|
||||
var mockDbEmpty = {
|
||||
devices: function () {
|
||||
return P.resolve([])
|
||||
}
|
||||
}
|
||||
|
||||
var mockDevices = [
|
||||
{
|
||||
'id': '0f7aa00356e5416e82b3bef7bc409eef',
|
||||
'isCurrentDevice': true,
|
||||
'lastAccessTime': 1449235471335,
|
||||
'name': 'My Phone',
|
||||
'type': 'mobile',
|
||||
'pushCallback': 'https://updates.push.services.mozilla.com/update/abcdef01234567890abcdefabcdef01234567890abcdef',
|
||||
'pushPublicKey': mocks.MOCK_PUSH_KEY,
|
||||
'pushAuthKey': 'w3b14Zjc-Afj2SDOLOyong==',
|
||||
'pushEndpointExpired': false
|
||||
},
|
||||
{
|
||||
'id': '3a45e6d0dae543qqdKyqjuvAiEupsnOd',
|
||||
'isCurrentDevice': false,
|
||||
'lastAccessTime': 1417699471335,
|
||||
'name': 'My Desktop',
|
||||
'type': null,
|
||||
'pushCallback': 'https://updates.push.services.mozilla.com/update/d4c5b1e3f5791ef83896c27519979b93a45e6d0da34c75',
|
||||
'pushPublicKey': mocks.MOCK_PUSH_KEY,
|
||||
'pushAuthKey': 'w3b14Zjc-Afj2SDOLOyong==',
|
||||
'pushEndpointExpired': false
|
||||
},
|
||||
{
|
||||
'id': '50973923bc3e4507a0aa4e285513194a',
|
||||
'isCurrentDevice': false,
|
||||
'lastAccessTime': 1402149471335,
|
||||
'name': 'My Ipad',
|
||||
'type': null,
|
||||
'uaOS': 'iOS',
|
||||
'pushCallback': 'https://updates.push.services.mozilla.com/update/50973923bc3e4507a0aa4e285513194a',
|
||||
'pushPublicKey': mocks.MOCK_PUSH_KEY,
|
||||
'pushAuthKey': 'w3b14Zjc-Afj2SDOLOyong==',
|
||||
'pushEndpointExpired': false
|
||||
}
|
||||
]
|
||||
|
||||
var mockDbResult = {
|
||||
devices: function (/* uid */) {
|
||||
return P.resolve(mockDevices)
|
||||
}
|
||||
}
|
||||
|
||||
describe('push', () => {
|
||||
let mockDb, mockDevices
|
||||
|
||||
beforeEach(() => {
|
||||
mockDb = mocks.mockDB()
|
||||
mockDevices = [
|
||||
{
|
||||
'id': '0f7aa00356e5416e82b3bef7bc409eef',
|
||||
'isCurrentDevice': true,
|
||||
'lastAccessTime': 1449235471335,
|
||||
'name': 'My Phone',
|
||||
'type': 'mobile',
|
||||
'pushCallback': 'https://updates.push.services.mozilla.com/update/abcdef01234567890abcdefabcdef01234567890abcdef',
|
||||
'pushPublicKey': mocks.MOCK_PUSH_KEY,
|
||||
'pushAuthKey': 'w3b14Zjc-Afj2SDOLOyong==',
|
||||
'pushEndpointExpired': false
|
||||
},
|
||||
{
|
||||
'id': '3a45e6d0dae543qqdKyqjuvAiEupsnOd',
|
||||
'isCurrentDevice': false,
|
||||
'lastAccessTime': 1417699471335,
|
||||
'name': 'My Desktop',
|
||||
'type': null,
|
||||
'pushCallback': 'https://updates.push.services.mozilla.com/update/d4c5b1e3f5791ef83896c27519979b93a45e6d0da34c75',
|
||||
'pushPublicKey': mocks.MOCK_PUSH_KEY,
|
||||
'pushAuthKey': 'w3b14Zjc-Afj2SDOLOyong==',
|
||||
'pushEndpointExpired': false
|
||||
},
|
||||
{
|
||||
'id': '50973923bc3e4507a0aa4e285513194a',
|
||||
'isCurrentDevice': false,
|
||||
'lastAccessTime': 1402149471335,
|
||||
'name': 'My Ipad',
|
||||
'type': null,
|
||||
'uaOS': 'iOS',
|
||||
'pushCallback': 'https://updates.push.services.mozilla.com/update/50973923bc3e4507a0aa4e285513194a',
|
||||
'pushPublicKey': mocks.MOCK_PUSH_KEY,
|
||||
'pushAuthKey': 'w3b14Zjc-Afj2SDOLOyong==',
|
||||
'pushEndpointExpired': false
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
it(
|
||||
'pushToDevices throws on device not found',
|
||||
'notifyUpdate rejects on device not found',
|
||||
() => {
|
||||
var push = require(pushModulePath)(mockLog(), mockDbEmpty, mockConfig)
|
||||
const push = require(pushModulePath)(mockLog(), mockDb, mockConfig)
|
||||
sinon.spy(push, 'sendPush')
|
||||
|
||||
return push.pushToDevices([mockUid], 'bogusid').then(function () {
|
||||
assert(false, 'must throw')
|
||||
}, function(err) {
|
||||
assert(! push.sendPush.called)
|
||||
})
|
||||
return push.notifyUpdate(mockUid, mockDevices, 'wibble', {
|
||||
includedDeviceIds: [ 'bogusid' ]
|
||||
}).then(
|
||||
() => assert(false, 'must throw'),
|
||||
err => assert(! push.sendPush.called)
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
it(
|
||||
'pushToAllDevices does not throw on empty device result',
|
||||
'notifyUpdate does not reject on empty device array',
|
||||
() => {
|
||||
var thisMockLog = mockLog({
|
||||
const thisMockLog = mockLog({
|
||||
info: function (log) {
|
||||
if (log.name === 'push.account_verify.success') {
|
||||
assert.fail('must not call push.success')
|
||||
}
|
||||
}
|
||||
})
|
||||
const push = require(pushModulePath)(thisMockLog, mockDb, mockConfig)
|
||||
|
||||
var push = require(pushModulePath)(thisMockLog, mockDbEmpty, mockConfig)
|
||||
return push.pushToAllDevices(mockUid, 'accountVerify')
|
||||
return push.notifyUpdate(mockUid, [], 'accountVerify')
|
||||
}
|
||||
)
|
||||
|
||||
it(
|
||||
'pushToAllDevices does not send notification to an excluded device',
|
||||
'notifyUpdate does not send notification to an excluded device',
|
||||
() => {
|
||||
var mocks = {
|
||||
const mocks = {
|
||||
'web-push': {
|
||||
sendNotification: function (sub, payload, options) {
|
||||
return P.resolve()
|
||||
}
|
||||
}
|
||||
}
|
||||
const push = proxyquire(pushModulePath, mocks)(mockLog(), mockDb, mockConfig)
|
||||
const options = { excludedDeviceIds: [ mockDevices[0].id ] }
|
||||
|
||||
var push = proxyquire(pushModulePath, mocks)(mockLog(), mockDbResult, mockConfig)
|
||||
var options = { excludedDeviceIds: [mockDevices[0].id] }
|
||||
return push.pushToAllDevices(mockUid, 'accountVerify', options)
|
||||
return push.notifyUpdate(mockUid, mockDevices, 'accountVerify', options)
|
||||
}
|
||||
)
|
||||
|
||||
it(
|
||||
'pushToAllDevices calls sendPush',
|
||||
'notifyUpdate calls sendPush',
|
||||
() => {
|
||||
var push = require(pushModulePath)(mockLog(), mockDbResult, mockConfig)
|
||||
sinon.stub(push, 'sendPush')
|
||||
var excluded = [mockDevices[0].id, mockDevices[2].id]
|
||||
var data = Buffer.from('foobar')
|
||||
var options = { data: data, excludedDeviceIds: excluded, TTL: TTL }
|
||||
return push.pushToAllDevices(mockUid, 'deviceConnected', options)
|
||||
const push = require(pushModulePath)(mockLog(), mockDb, mockConfig)
|
||||
sinon.stub(push, 'sendPush', () => P.resolve())
|
||||
const excluded = [ mockDevices[0].id, mockDevices[2].id ]
|
||||
const data = Buffer.from('foobar')
|
||||
const options = { data: data, excludedDeviceIds: excluded, TTL: TTL }
|
||||
|
||||
return push.notifyUpdate(mockUid, mockDevices, 'deviceConnected', options)
|
||||
.then(function() {
|
||||
assert.ok(push.sendPush.calledOnce, 'push was called')
|
||||
assert.equal(push.sendPush.getCall(0).args[0], mockUid)
|
||||
|
@ -140,43 +136,6 @@ describe('push', () => {
|
|||
}
|
||||
)
|
||||
|
||||
it(
|
||||
'pushToDevices calls sendPush',
|
||||
() => {
|
||||
var push = require(pushModulePath)(mockLog(), mockDbResult, mockConfig)
|
||||
sinon.stub(push, 'sendPush')
|
||||
var data = Buffer.from('foobar')
|
||||
var options = { data: data, TTL: TTL }
|
||||
return push.pushToDevices(mockUid, [mockDevices[0].id], 'deviceConnected', options)
|
||||
.then(function() {
|
||||
assert.ok(push.sendPush.calledOnce, 'push was called')
|
||||
assert.equal(push.sendPush.getCall(0).args[0], mockUid)
|
||||
assert.deepEqual(push.sendPush.getCall(0).args[1], [mockDevices[0]])
|
||||
assert.equal(push.sendPush.getCall(0).args[2], 'deviceConnected')
|
||||
assert.deepEqual(push.sendPush.getCall(0).args[3], { data: data, TTL: TTL })
|
||||
push.sendPush.restore()
|
||||
})
|
||||
}
|
||||
)
|
||||
|
||||
it(
|
||||
'pushToDevice calls pushToDevices',
|
||||
() => {
|
||||
var push = require(pushModulePath)(mockLog(), mockDbResult, mockConfig)
|
||||
sinon.stub(push, 'pushToDevices')
|
||||
var data = Buffer.from('foobar')
|
||||
var options = { data: data, TTL: TTL }
|
||||
push.pushToDevice(mockUid, mockDevices[0].id, 'deviceConnected', options)
|
||||
|
||||
assert.ok(push.pushToDevices.calledOnce, 'pushToDevices was called')
|
||||
assert.equal(push.pushToDevices.getCall(0).args[0], mockUid)
|
||||
assert.deepEqual(push.pushToDevices.getCall(0).args[1], [mockDevices[0].id])
|
||||
assert.equal(push.pushToDevices.getCall(0).args[2], 'deviceConnected')
|
||||
assert.deepEqual(push.pushToDevices.getCall(0).args[3], { data: data, TTL: TTL })
|
||||
push.pushToDevices.restore()
|
||||
}
|
||||
)
|
||||
|
||||
it(
|
||||
'sendPush sends notifications with a TTL of 0',
|
||||
() => {
|
||||
|
@ -199,7 +158,7 @@ describe('push', () => {
|
|||
}
|
||||
}
|
||||
|
||||
var push = proxyquire(pushModulePath, mocks)(thisMockLog, mockDbResult, mockConfig)
|
||||
const push = proxyquire(pushModulePath, mocks)(thisMockLog, mockDb, mockConfig)
|
||||
return push.sendPush(mockUid, mockDevices, 'accountVerify')
|
||||
.then(() => {
|
||||
assert.equal(successCalled, 2)
|
||||
|
@ -229,7 +188,7 @@ describe('push', () => {
|
|||
}
|
||||
}
|
||||
|
||||
var push = proxyquire(pushModulePath, mocks)(thisMockLog, mockDbResult, mockConfig)
|
||||
const push = proxyquire(pushModulePath, mocks)(thisMockLog, mockDb, mockConfig)
|
||||
var options = { TTL: TTL }
|
||||
return push.sendPush(mockUid, mockDevices, 'accountVerify', options)
|
||||
.then(() => {
|
||||
|
@ -255,7 +214,7 @@ describe('push', () => {
|
|||
}
|
||||
}
|
||||
|
||||
var push = proxyquire(pushModulePath, mocks)(mockLog(), mockDbResult, mockConfig)
|
||||
const push = proxyquire(pushModulePath, mocks)(mockLog(), mockDb, mockConfig)
|
||||
var options = { data: data }
|
||||
return push.sendPush(mockUid, mockDevices, 'accountVerify', options)
|
||||
.then(() => {
|
||||
|
@ -278,7 +237,7 @@ describe('push', () => {
|
|||
}
|
||||
}
|
||||
|
||||
const push = proxyquire(pushModulePath, mocks)(mockLog(), mockDbResult, mockConfig)
|
||||
const push = proxyquire(pushModulePath, mocks)(mockLog(), mockDb, mockConfig)
|
||||
const options = { data: data }
|
||||
return push.sendPush(mockUid, mockDevices, 'devicesNotify', options)
|
||||
.then(() => {
|
||||
|
@ -303,7 +262,7 @@ describe('push', () => {
|
|||
}
|
||||
}
|
||||
|
||||
const push = proxyquire(pushModulePath, mocks)(mockLog(), mockDbResult, mockConfig)
|
||||
const push = proxyquire(pushModulePath, mocks)(mockLog(), mockDb, mockConfig)
|
||||
const options = { data: data }
|
||||
return push.sendPush(mockUid, mockDevices, 'devicesNotify', options)
|
||||
.then(() => {
|
||||
|
@ -329,7 +288,7 @@ describe('push', () => {
|
|||
}
|
||||
}
|
||||
|
||||
const push = proxyquire(pushModulePath, mocks)(mockLog(), mockDbResult, mockConfig)
|
||||
const push = proxyquire(pushModulePath, mocks)(mockLog(), mockDb, mockConfig)
|
||||
const options = { data: data }
|
||||
return push.sendPush(mockUid, mockDevices, 'devicesNotify', options)
|
||||
.then(() => {
|
||||
|
@ -400,7 +359,7 @@ describe('push', () => {
|
|||
'pushEndpointExpired': false
|
||||
}]
|
||||
|
||||
var push = require(pushModulePath)(thisMockLog, mockDbResult, mockConfig)
|
||||
const push = require(pushModulePath)(thisMockLog, mockDb, mockConfig)
|
||||
var options = { data: Buffer.from('foobar') }
|
||||
return push.sendPush(mockUid, devices, 'accountVerify', options)
|
||||
.then(() => {
|
||||
|
@ -427,7 +386,7 @@ describe('push', () => {
|
|||
'name': 'My Phone'
|
||||
}]
|
||||
|
||||
var push = require(pushModulePath)(thisMockLog, mockDbResult, mockConfig)
|
||||
const push = require(pushModulePath)(thisMockLog, mockDb, mockConfig)
|
||||
return push.sendPush(mockUid, devices, 'accountVerify')
|
||||
.then(() => {
|
||||
assert.equal(count, 1)
|
||||
|
@ -456,7 +415,7 @@ describe('push', () => {
|
|||
}
|
||||
}
|
||||
|
||||
var push = proxyquire(pushModulePath, mocks)(thisMockLog, mockDbResult, mockConfig)
|
||||
const push = proxyquire(pushModulePath, mocks)(thisMockLog, mockDb, mockConfig)
|
||||
return push.sendPush(mockUid, [mockDevices[0]], 'accountVerify')
|
||||
.then(() => {
|
||||
assert.equal(count, 1)
|
||||
|
@ -484,7 +443,7 @@ describe('push', () => {
|
|||
}
|
||||
}
|
||||
}
|
||||
var push = proxyquire(pushModulePath, mocks)(thisMockLog, mockDbResult, mockConfig)
|
||||
const push = proxyquire(pushModulePath, mocks)(thisMockLog, mockDb, mockConfig)
|
||||
|
||||
return push.sendPush(mockUid, devices, 'accountVerify').then(function () {
|
||||
assert.equal(thisMockLog.error.callCount, 0, 'log.error was not called')
|
||||
|
@ -493,7 +452,7 @@ describe('push', () => {
|
|||
}).then(function () {
|
||||
assert.equal(thisMockLog.error.callCount, 1, 'log.error was called')
|
||||
var arg = thisMockLog.error.getCall(0).args[0]
|
||||
assert.equal(arg.op, 'push.pushToDevices')
|
||||
assert.equal(arg.op, 'push.sendPush')
|
||||
assert.equal(arg.err.message, 'Too many devices connected to account')
|
||||
})
|
||||
}
|
||||
|
@ -502,12 +461,6 @@ describe('push', () => {
|
|||
it(
|
||||
'push resets device push data when push server responds with a 400 level error',
|
||||
() => {
|
||||
var mockDb = {
|
||||
updateDevice: sinon.spy(function () {
|
||||
return P.resolve()
|
||||
})
|
||||
}
|
||||
|
||||
let count = 0
|
||||
var thisMockLog = mockLog({
|
||||
info: function (log) {
|
||||
|
@ -532,7 +485,7 @@ describe('push', () => {
|
|||
}
|
||||
}
|
||||
|
||||
var push = proxyquire(pushModulePath, mocks)(thisMockLog, mockDb, mockConfig)
|
||||
const push = proxyquire(pushModulePath, mocks)(thisMockLog, mockDb, mockConfig)
|
||||
// Careful, the argument gets modified in-place.
|
||||
var device = JSON.parse(JSON.stringify(mockDevices[0]))
|
||||
return push.sendPush(mockUid, [device], 'accountVerify')
|
||||
|
@ -545,12 +498,6 @@ describe('push', () => {
|
|||
it(
|
||||
'push resets device push data when a failure is caused by bad encryption keys',
|
||||
() => {
|
||||
var mockDb = {
|
||||
updateDevice: sinon.spy(function () {
|
||||
return P.resolve()
|
||||
})
|
||||
}
|
||||
|
||||
let count = 0
|
||||
var thisMockLog = mockLog({
|
||||
info: function (log) {
|
||||
|
@ -574,7 +521,7 @@ describe('push', () => {
|
|||
}
|
||||
}
|
||||
|
||||
var push = proxyquire(pushModulePath, mocks)(thisMockLog, mockDb, mockConfig)
|
||||
const push = proxyquire(pushModulePath, mocks)(thisMockLog, mockDb, mockConfig)
|
||||
// Careful, the argument gets modified in-place.
|
||||
var device = JSON.parse(JSON.stringify(mockDevices[0]))
|
||||
device.pushPublicKey = 'E' + device.pushPublicKey.substring(1) // make the key invalid
|
||||
|
@ -588,12 +535,6 @@ describe('push', () => {
|
|||
it(
|
||||
'push does not reset device push data after an unexpected failure',
|
||||
() => {
|
||||
var mockDb = {
|
||||
updateDevice: sinon.spy(function () {
|
||||
return P.resolve()
|
||||
})
|
||||
}
|
||||
|
||||
let count = 0
|
||||
var thisMockLog = mockLog({
|
||||
info: function (log) {
|
||||
|
@ -614,7 +555,7 @@ describe('push', () => {
|
|||
}
|
||||
}
|
||||
|
||||
var push = proxyquire(pushModulePath, mocks)(thisMockLog, mockDb, mockConfig)
|
||||
const push = proxyquire(pushModulePath, mocks)(thisMockLog, mockDb, mockConfig)
|
||||
return push.sendPush(mockUid, [mockDevices[0]], 'accountVerify')
|
||||
.then(() => {
|
||||
assert.equal(count, 1)
|
||||
|
@ -623,40 +564,10 @@ describe('push', () => {
|
|||
)
|
||||
|
||||
it(
|
||||
'notifyUpdate calls pushToAllDevices',
|
||||
'notifyDeviceConnected calls notifyUpdate',
|
||||
() => {
|
||||
var push = require(pushModulePath)(mockLog(), mockDbEmpty, mockConfig)
|
||||
sinon.spy(push, 'pushToAllDevices')
|
||||
return push.notifyUpdate(mockUid, 'passwordReset')
|
||||
.then(function() {
|
||||
assert.ok(push.pushToAllDevices.calledOnce, 'pushToAllDevices was called')
|
||||
assert.equal(push.pushToAllDevices.getCall(0).args[0], mockUid)
|
||||
assert.equal(push.pushToAllDevices.getCall(0).args[1], 'passwordReset')
|
||||
push.pushToAllDevices.restore()
|
||||
})
|
||||
}
|
||||
)
|
||||
|
||||
it(
|
||||
'notifyUpdate without a 2nd arg calls pushToAllDevices with a accountVerify reason',
|
||||
() => {
|
||||
var push = require(pushModulePath)(mockLog(), mockDbEmpty, mockConfig)
|
||||
sinon.spy(push, 'pushToAllDevices')
|
||||
return push.notifyUpdate(mockUid)
|
||||
.then(function() {
|
||||
assert.ok(push.pushToAllDevices.calledOnce, 'pushToAllDevices was called')
|
||||
assert.equal(push.pushToAllDevices.getCall(0).args[0], mockUid)
|
||||
assert.equal(push.pushToAllDevices.getCall(0).args[1], 'accountVerify')
|
||||
push.pushToAllDevices.restore()
|
||||
})
|
||||
}
|
||||
)
|
||||
|
||||
it(
|
||||
'notifyDeviceConnected calls pushToAllDevices',
|
||||
() => {
|
||||
var push = require(pushModulePath)(mockLog(), mockDbEmpty, mockConfig)
|
||||
sinon.spy(push, 'pushToAllDevices')
|
||||
const push = require(pushModulePath)(mockLog(), mockDb, mockConfig)
|
||||
sinon.spy(push, 'notifyUpdate')
|
||||
var deviceId = 'gjfkd5434jk5h5fd'
|
||||
var deviceName = 'My phone'
|
||||
var expectedData = {
|
||||
|
@ -666,63 +577,67 @@ describe('push', () => {
|
|||
deviceName: deviceName
|
||||
}
|
||||
}
|
||||
return push.notifyDeviceConnected(mockUid, deviceName, deviceId).catch(function (err) {
|
||||
assert.fail('must not throw')
|
||||
throw err
|
||||
})
|
||||
.then(function() {
|
||||
assert.ok(push.pushToAllDevices.calledOnce, 'pushToAllDevices was called')
|
||||
assert.equal(push.pushToAllDevices.getCall(0).args[0], mockUid)
|
||||
assert.equal(push.pushToAllDevices.getCall(0).args[1], 'deviceConnected')
|
||||
var options = push.pushToAllDevices.getCall(0).args[2]
|
||||
var payload = JSON.parse(options.data.toString('utf8'))
|
||||
assert.deepEqual(payload, expectedData)
|
||||
var schemaPath = path.resolve(__dirname, PUSH_PAYLOADS_SCHEMA_PATH)
|
||||
var schema = JSON.parse(fs.readFileSync(schemaPath))
|
||||
assert.ok(ajv.validate(schema, payload))
|
||||
assert.deepEqual(options.excludedDeviceIds, [deviceId])
|
||||
push.pushToAllDevices.restore()
|
||||
})
|
||||
return push.notifyDeviceConnected(mockUid, mockDevices, deviceName, deviceId)
|
||||
.catch(err => {
|
||||
assert.fail('must not throw')
|
||||
throw err
|
||||
})
|
||||
.then(() => {
|
||||
assert.ok(push.notifyUpdate.calledOnce, 'notifyUpdate was called')
|
||||
assert.equal(push.notifyUpdate.getCall(0).args[0], mockUid)
|
||||
assert.equal(push.notifyUpdate.getCall(0).args[1], mockDevices)
|
||||
assert.equal(push.notifyUpdate.getCall(0).args[2], 'deviceConnected')
|
||||
const options = push.notifyUpdate.getCall(0).args[3]
|
||||
const payload = JSON.parse(options.data.toString('utf8'))
|
||||
assert.deepEqual(payload, expectedData)
|
||||
const schemaPath = path.resolve(__dirname, PUSH_PAYLOADS_SCHEMA_PATH)
|
||||
const schema = JSON.parse(fs.readFileSync(schemaPath))
|
||||
assert.ok(ajv.validate(schema, payload))
|
||||
assert.deepEqual(options.excludedDeviceIds, [deviceId])
|
||||
push.notifyUpdate.restore()
|
||||
})
|
||||
}
|
||||
)
|
||||
|
||||
it(
|
||||
'notifyDeviceDisconnected calls pushToAllDevices',
|
||||
'notifyDeviceDisconnected calls sendPush',
|
||||
() => {
|
||||
var mocks = {
|
||||
const mocks = {
|
||||
'web-push': {
|
||||
sendNotification: function (sub, payload, options) {
|
||||
return P.resolve()
|
||||
}
|
||||
}
|
||||
}
|
||||
var push = proxyquire(pushModulePath, mocks)(mockLog(), mockDbResult, mockConfig)
|
||||
sinon.spy(push, 'pushToAllDevices')
|
||||
var idToDisconnect = mockDevices[0].id
|
||||
var expectedData = {
|
||||
const push = proxyquire(pushModulePath, mocks)(mockLog(), mockDb, mockConfig)
|
||||
sinon.spy(push, 'sendPush')
|
||||
const idToDisconnect = mockDevices[0].id
|
||||
const expectedData = {
|
||||
version: 1,
|
||||
command: 'fxaccounts:device_disconnected',
|
||||
data: {
|
||||
id: idToDisconnect
|
||||
}
|
||||
}
|
||||
return push.notifyDeviceDisconnected(mockUid, idToDisconnect).catch(function (err) {
|
||||
assert.fail('must not throw')
|
||||
throw err
|
||||
})
|
||||
.then(function() {
|
||||
assert.ok(push.pushToAllDevices.calledOnce, 'pushToAllDevices was called')
|
||||
assert.equal(push.pushToAllDevices.getCall(0).args[0], mockUid)
|
||||
assert.equal(push.pushToAllDevices.getCall(0).args[1], 'deviceDisconnected')
|
||||
var options = push.pushToAllDevices.getCall(0).args[2]
|
||||
var payload = JSON.parse(options.data.toString('utf8'))
|
||||
assert.deepEqual(payload, expectedData)
|
||||
var schemaPath = path.resolve(__dirname, PUSH_PAYLOADS_SCHEMA_PATH)
|
||||
var schema = JSON.parse(fs.readFileSync(schemaPath))
|
||||
assert.ok(ajv.validate(schema, payload))
|
||||
assert.ok(options.TTL, 'TTL should be set')
|
||||
push.pushToAllDevices.restore()
|
||||
})
|
||||
return push.notifyDeviceDisconnected(mockUid, mockDevices, idToDisconnect)
|
||||
.catch(err => {
|
||||
assert.fail('must not throw')
|
||||
throw err
|
||||
})
|
||||
.then(() => {
|
||||
assert.ok(push.sendPush.calledOnce, 'sendPush was called')
|
||||
assert.equal(push.sendPush.getCall(0).args[0], mockUid)
|
||||
assert.equal(push.sendPush.getCall(0).args[1], mockDevices)
|
||||
assert.equal(push.sendPush.getCall(0).args[2], 'deviceDisconnected')
|
||||
const options = push.sendPush.getCall(0).args[3]
|
||||
const payload = JSON.parse(options.data.toString('utf8'))
|
||||
assert.deepEqual(payload, expectedData)
|
||||
const schemaPath = path.resolve(__dirname, PUSH_PAYLOADS_SCHEMA_PATH)
|
||||
const schema = JSON.parse(fs.readFileSync(schemaPath))
|
||||
assert.ok(ajv.validate(schema, payload))
|
||||
assert.ok(options.TTL, 'TTL should be set')
|
||||
push.sendPush.restore()
|
||||
})
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -736,7 +651,7 @@ describe('push', () => {
|
|||
}
|
||||
}
|
||||
}
|
||||
var push = proxyquire(pushModulePath, mocks)(mockLog(), mockDbResult, mockConfig)
|
||||
const push = proxyquire(pushModulePath, mocks)(mockLog(), mockDb, mockConfig)
|
||||
sinon.spy(push, 'sendPush')
|
||||
var expectedData = {
|
||||
version: 1,
|
||||
|
@ -772,7 +687,7 @@ describe('push', () => {
|
|||
}
|
||||
}
|
||||
}
|
||||
var push = proxyquire(pushModulePath, mocks)(mockLog(), mockDbEmpty, mockConfig)
|
||||
const push = proxyquire(pushModulePath, mocks)(mockLog(), mockDb, mockConfig)
|
||||
sinon.spy(push, 'sendPush')
|
||||
var expectedData = {
|
||||
version: 1,
|
||||
|
@ -808,7 +723,7 @@ describe('push', () => {
|
|||
}
|
||||
}
|
||||
}
|
||||
var push = proxyquire(pushModulePath, mocks)(mockLog(), mockDbEmpty, mockConfig)
|
||||
const push = proxyquire(pushModulePath, mocks)(mockLog(), mockDb, mockConfig)
|
||||
sinon.spy(push, 'sendPush')
|
||||
var expectedData = {
|
||||
version: 1,
|
||||
|
@ -866,7 +781,7 @@ describe('push', () => {
|
|||
}
|
||||
}
|
||||
|
||||
var push = proxyquire(pushModulePath, mocks)(thisMockLog, mockDbResult, mockConfig)
|
||||
const push = proxyquire(pushModulePath, mocks)(thisMockLog, mockDb, mockConfig)
|
||||
return push.sendPush(mockUid, mockDevices, 'accountVerify')
|
||||
.then(() => {
|
||||
assert.equal(count, 2)
|
||||
|
@ -888,7 +803,7 @@ describe('push', () => {
|
|||
}
|
||||
}
|
||||
|
||||
var push = proxyquire(pushModulePath, mocks)(thisMockLog, mockDbResult, mockConfig)
|
||||
const push = proxyquire(pushModulePath, mocks)(thisMockLog, mockDb, mockConfig)
|
||||
return push.sendPush(mockUid, mockDevices, 'anUnknownReasonString').then(
|
||||
function () {
|
||||
assert(false, 'calling sendPush should have failed')
|
||||
|
|
|
@ -244,7 +244,7 @@ describe('/account/devices/notify', function () {
|
|||
assert(false, 'should have thrown')
|
||||
})
|
||||
.then(() => assert(false), function (err) {
|
||||
assert.equal(mockPush.pushToDevices.callCount, 0, 'mockPush.pushToDevices was not called')
|
||||
assert.equal(mockPush.notifyUpdate.callCount, 0, 'mockPush.notifyUpdate was not called')
|
||||
assert.equal(err.errno, 107, 'Correct errno for invalid push payload')
|
||||
})
|
||||
})
|
||||
|
@ -256,22 +256,23 @@ describe('/account/devices/notify', function () {
|
|||
TTL: 60,
|
||||
payload: pushPayload
|
||||
}
|
||||
// We don't wait on pushToAllDevices in the request handler, that's why
|
||||
// We don't wait on notifyUpdate in the request handler, that's why
|
||||
// we have to wait on it manually by spying.
|
||||
var pushToAllDevicesPromise = P.defer()
|
||||
mockPush.pushToAllDevices = sinon.spy(function () {
|
||||
pushToAllDevicesPromise.resolve()
|
||||
var notifyUpdatePromise = P.defer()
|
||||
mockPush.notifyUpdate = sinon.spy(function () {
|
||||
notifyUpdatePromise.resolve()
|
||||
return P.resolve()
|
||||
})
|
||||
return runTest(route, mockRequest, function (response) {
|
||||
return pushToAllDevicesPromise.promise.then(function () {
|
||||
return notifyUpdatePromise.promise.then(function () {
|
||||
assert.equal(mockCustoms.checkAuthenticated.callCount, 1, 'mockCustoms.checkAuthenticated was called once')
|
||||
assert.equal(mockPush.pushToAllDevices.callCount, 1, 'mockPush.pushToAllDevices was called once')
|
||||
var args = mockPush.pushToAllDevices.args[0]
|
||||
assert.equal(args.length, 3, 'mockPush.pushToAllDevices was passed three arguments')
|
||||
assert.equal(mockPush.notifyUpdate.callCount, 1, 'mockPush.notifyUpdate was called once')
|
||||
var args = mockPush.notifyUpdate.args[0]
|
||||
assert.equal(args.length, 4, 'mockPush.notifyUpdate was passed four arguments')
|
||||
assert.equal(args[0], uid, 'first argument was the device uid')
|
||||
assert.equal(args[1], 'devicesNotify', 'second argument was the devicesNotify reason')
|
||||
assert.deepEqual(args[2], {
|
||||
assert.ok(Array.isArray(args[1]), 'second argument was devices array')
|
||||
assert.equal(args[2], 'devicesNotify', 'second argument was the devicesNotify reason')
|
||||
assert.deepEqual(args[3], {
|
||||
data: Buffer.from(JSON.stringify(pushPayload)),
|
||||
excludedDeviceIds: ['bogusid'],
|
||||
TTL: 60
|
||||
|
@ -290,11 +291,11 @@ describe('/account/devices/notify', function () {
|
|||
TTL: 60,
|
||||
payload: extraPropsPayload
|
||||
}
|
||||
// We don't wait on pushToAllDevices in the request handler, that's why
|
||||
// We don't wait on notifyUpdate in the request handler, that's why
|
||||
// we have to wait on it manually by spying.
|
||||
var pushToAllDevicesPromise = P.defer()
|
||||
mockPush.pushToAllDevices = sinon.spy(function () {
|
||||
pushToAllDevicesPromise.resolve()
|
||||
var notifyUpdatePromise = P.defer()
|
||||
mockPush.notifyUpdate = sinon.spy(function () {
|
||||
notifyUpdatePromise.resolve()
|
||||
return Promise.resolve()
|
||||
})
|
||||
return runTest(route, mockRequest, function () {
|
||||
|
@ -315,25 +316,26 @@ describe('/account/devices/notify', function () {
|
|||
TTL: 60,
|
||||
payload: pushPayload
|
||||
}
|
||||
// We don't wait on pushToDevices in the request handler, that's why
|
||||
// We don't wait on notifyUpdate in the request handler, that's why
|
||||
// we have to wait on it manually by spying.
|
||||
var pushToDevicesPromise = P.defer()
|
||||
mockPush.pushToDevices = sinon.spy(function () {
|
||||
pushToDevicesPromise.resolve()
|
||||
var notifyUpdatePromise = P.defer()
|
||||
mockPush.notifyUpdate = sinon.spy(function () {
|
||||
notifyUpdatePromise.resolve()
|
||||
return P.resolve()
|
||||
})
|
||||
return runTest(route, mockRequest, function (response) {
|
||||
return pushToDevicesPromise.promise.then(function () {
|
||||
return notifyUpdatePromise.promise.then(function () {
|
||||
assert.equal(mockCustoms.checkAuthenticated.callCount, 1, 'mockCustoms.checkAuthenticated was called once')
|
||||
assert.equal(mockPush.pushToDevices.callCount, 1, 'mockPush.pushToDevices was called once')
|
||||
var args = mockPush.pushToDevices.args[0]
|
||||
assert.equal(args.length, 4, 'mockPush.pushToDevices was passed four arguments')
|
||||
assert.equal(mockPush.notifyUpdate.callCount, 1, 'mockPush.notifyUpdate was called once')
|
||||
var args = mockPush.notifyUpdate.args[0]
|
||||
assert.equal(args.length, 4, 'mockPush.notifyUpdate was passed four arguments')
|
||||
assert.equal(args[0], uid, 'first argument was the device uid')
|
||||
assert.deepEqual(args[1], ['bogusid1', 'bogusid2'], 'second argument was the list of device ids')
|
||||
assert.ok(Array.isArray(args[1]), 'second argument was devices array')
|
||||
assert.equal(args[2], 'devicesNotify', 'third argument was the devicesNotify reason')
|
||||
assert.deepEqual(args[3], {
|
||||
data: Buffer.from(JSON.stringify(pushPayload)),
|
||||
TTL: 60
|
||||
TTL: 60,
|
||||
includedDeviceIds: [ 'bogusid1', 'bogusid2' ]
|
||||
}, 'fourth argument was the push options')
|
||||
assert.equal(mockLog.activityEvent.callCount, 1, 'log.activityEvent was called once')
|
||||
args = mockLog.activityEvent.args[0]
|
||||
|
@ -351,7 +353,7 @@ describe('/account/devices/notify', function () {
|
|||
})
|
||||
|
||||
it('does not log activity event for non-send-tab-related messages', function () {
|
||||
mockPush.pushToDevices.reset()
|
||||
mockPush.notifyUpdate.reset()
|
||||
mockLog.activityEvent.reset()
|
||||
mockLog.error.reset()
|
||||
mockRequest.payload = {
|
||||
|
@ -363,7 +365,7 @@ describe('/account/devices/notify', function () {
|
|||
}
|
||||
}
|
||||
return runTest(route, mockRequest, function (response) {
|
||||
assert.equal(mockPush.pushToDevices.callCount, 1, 'mockPush.pushToDevices was called once')
|
||||
assert.equal(mockPush.notifyUpdate.callCount, 1, 'mockPush.notifyUpdate was called once')
|
||||
assert.equal(mockLog.activityEvent.callCount, 0, 'log.activityEvent was not called')
|
||||
assert.equal(mockLog.error.callCount, 0, 'log.error was not called')
|
||||
})
|
||||
|
@ -419,7 +421,7 @@ describe('/account/devices/notify', function () {
|
|||
|
||||
var mockLog = mocks.spyLog()
|
||||
var mockPush = mocks.mockPush({
|
||||
pushToDevices: () => P.reject('Devices ids not found in devices')
|
||||
notifyUpdate: () => P.reject('devices empty')
|
||||
})
|
||||
var mockCustoms = {
|
||||
checkAuthenticated: () => P.resolve()
|
||||
|
@ -465,7 +467,7 @@ describe('/account/device/destroy', function () {
|
|||
assert.ok(mockDB.deleteDevice.calledBefore(mockPush.notifyDeviceDisconnected))
|
||||
assert.equal(mockPush.notifyDeviceDisconnected.callCount, 1)
|
||||
assert.equal(mockPush.notifyDeviceDisconnected.firstCall.args[0], mockRequest.auth.credentials.uid)
|
||||
assert.equal(mockPush.notifyDeviceDisconnected.firstCall.args[1], deviceId)
|
||||
assert.equal(mockPush.notifyDeviceDisconnected.firstCall.args[2], deviceId)
|
||||
|
||||
assert.equal(mockLog.activityEvent.callCount, 1, 'log.activityEvent was called once')
|
||||
var args = mockLog.activityEvent.args[0]
|
||||
|
|
|
@ -509,9 +509,10 @@ describe('/recovery_email/verify_code', function () {
|
|||
|
||||
assert.equal(mockPush.notifyUpdate.callCount, 1, 'mockPush.notifyUpdate should have been called once')
|
||||
args = mockPush.notifyUpdate.args[0]
|
||||
assert.equal(args.length, 2, 'mockPush.notifyUpdate should have been passed two arguments')
|
||||
assert.equal(args.length, 3, 'mockPush.notifyUpdate should have been passed three arguments')
|
||||
assert.equal(args[0].toString('hex'), uid, 'first argument should have been uid')
|
||||
assert.equal(args[1], 'accountVerify', 'second argument should have been reason')
|
||||
assert.ok(Array.isArray(args[1]), 'second argument should have been devices array')
|
||||
assert.equal(args[2], 'accountVerify', 'third argument should have been reason')
|
||||
|
||||
assert.equal(JSON.stringify(response), '{}')
|
||||
})
|
||||
|
@ -639,9 +640,10 @@ describe('/recovery_email/verify_code', function () {
|
|||
|
||||
assert.equal(mockPush.notifyUpdate.callCount, 1, 'mockPush.notifyUpdate should have been called once')
|
||||
args = mockPush.notifyUpdate.args[0]
|
||||
assert.equal(args.length, 2, 'mockPush.notifyUpdate should have been passed two arguments')
|
||||
assert.equal(args.length, 3, 'mockPush.notifyUpdate should have been passed three arguments')
|
||||
assert.equal(args[0].toString('hex'), uid, 'first argument should have been uid')
|
||||
assert.equal(args[1], 'accountConfirm', 'second argument should have been reason')
|
||||
assert.ok(Array.isArray(args[1]), 'second argument should have been devices array')
|
||||
assert.equal(args[2], 'accountConfirm', 'third argument should have been reason')
|
||||
})
|
||||
.then(function () {
|
||||
mockDB.verifyTokens.reset()
|
||||
|
|
|
@ -276,8 +276,8 @@ describe('/password', () => {
|
|||
]
|
||||
var mockDB = mocks.mockDB({
|
||||
email: TEST_EMAIL,
|
||||
uid: uid,
|
||||
devices: devices
|
||||
uid,
|
||||
devices
|
||||
})
|
||||
var mockPush = mocks.mockPush()
|
||||
var mockMailer = mocks.mockMailer()
|
||||
|
@ -286,6 +286,7 @@ describe('/password', () => {
|
|||
credentials: {
|
||||
uid: uid
|
||||
},
|
||||
devices,
|
||||
payload: {
|
||||
authPW: crypto.randomBytes(32).toString('hex'),
|
||||
wrapKb: crypto.randomBytes(32).toString('hex'),
|
||||
|
|
|
@ -69,7 +69,9 @@ describe('lib/server', () => {
|
|||
log = mocks.spyLog()
|
||||
config = getConfig()
|
||||
routes = getRoutes()
|
||||
db = mocks.mockDB()
|
||||
db = mocks.mockDB({
|
||||
devices: [ { id: 'fake device id' } ]
|
||||
})
|
||||
translator = {
|
||||
getTranslator: sinon.spy(() => ({ en: { format: () => {}, language: 'en' } })),
|
||||
getLocale: sinon.spy(() => 'en')
|
||||
|
@ -93,12 +95,15 @@ describe('lib/server', () => {
|
|||
assert.equal(log.summary.callCount, 0)
|
||||
})
|
||||
|
||||
describe('successful request, acceptable locale, signinCodes feature enabled:', () => {
|
||||
describe('successful request, authenticated, acceptable locale, signinCodes feature enabled:', () => {
|
||||
let request
|
||||
|
||||
beforeEach(() => {
|
||||
response = 'ok'
|
||||
return instance.inject({
|
||||
credentials: {
|
||||
uid: 'fake uid'
|
||||
},
|
||||
headers: {
|
||||
'accept-language': 'fr-CH, fr;q=0.9, en-GB, en;q=0.5',
|
||||
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:57.0) Gecko/20100101 Firefox/57.0',
|
||||
|
@ -170,7 +175,18 @@ describe('lib/server', () => {
|
|||
})
|
||||
})
|
||||
|
||||
describe('another request:', () => {
|
||||
it('fetched devices correctly', () => {
|
||||
assert.ok(request.app.devices)
|
||||
assert.equal(typeof request.app.devices.then, 'function')
|
||||
assert.equal(db.devices.callCount, 1)
|
||||
assert.equal(db.devices.args[0].length, 1)
|
||||
assert.equal(db.devices.args[0][0], 'fake uid')
|
||||
return request.app.devices.then(devices => {
|
||||
assert.deepEqual(devices, [ { id: 'fake device id' } ])
|
||||
})
|
||||
})
|
||||
|
||||
describe('successful request, unauthenticated, uid in payload:', () => {
|
||||
let secondRequest
|
||||
|
||||
beforeEach(() => {
|
||||
|
@ -184,7 +200,8 @@ describe('lib/server', () => {
|
|||
method: 'POST',
|
||||
url: '/account/create',
|
||||
payload: {
|
||||
features: [ 'signinCodes' ]
|
||||
features: [ 'signinCodes' ],
|
||||
uid: 'another fake uid'
|
||||
},
|
||||
remoteAddress: '194.12.187.0'
|
||||
}).then(response => secondRequest = response.request)
|
||||
|
@ -202,7 +219,6 @@ describe('lib/server', () => {
|
|||
})
|
||||
|
||||
it('second request has its own location info', () => {
|
||||
assert.notEqual(request, secondRequest)
|
||||
assert.notEqual(request.app.geo, secondRequest.app.geo)
|
||||
return secondRequest.app.geo.then(geo => {
|
||||
assert.equal(geo.location.city, 'Geneva')
|
||||
|
@ -213,6 +229,16 @@ describe('lib/server', () => {
|
|||
assert.equal(geo.timeZone, 'Europe/Zurich')
|
||||
})
|
||||
})
|
||||
|
||||
it('second request fetched devices correctly', () => {
|
||||
assert.notEqual(request.app.devices, secondRequest.app.devices)
|
||||
assert.equal(db.devices.callCount, 2)
|
||||
assert.equal(db.devices.args[1].length, 1)
|
||||
assert.equal(db.devices.args[1][0], 'another fake uid')
|
||||
return request.app.devices.then(devices => {
|
||||
assert.deepEqual(devices, [ { id: 'fake device id' } ])
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
|
|
|
@ -112,9 +112,7 @@ const PUSH_METHOD_NAMES = [
|
|||
'notifyPasswordReset',
|
||||
'notifyAccountDestroyed',
|
||||
'notifyProfileUpdated',
|
||||
'notifyUpdate',
|
||||
'pushToAllDevices',
|
||||
'pushToDevices'
|
||||
'notifyUpdate'
|
||||
]
|
||||
|
||||
module.exports = {
|
||||
|
@ -487,6 +485,7 @@ function mockRequest (data, errors) {
|
|||
app: {
|
||||
acceptLanguage: 'en-US',
|
||||
clientAddress: data.clientAddress || '63.245.221.32',
|
||||
devices: P.resolve(data.devices || []),
|
||||
features: new Set(data.features),
|
||||
geo,
|
||||
locale: data.locale || 'en-US',
|
||||
|
|
|
@ -119,10 +119,9 @@ describe('remote push db', function() {
|
|||
.then(function () {
|
||||
return db.devices(ACCOUNT.uid)
|
||||
})
|
||||
|
||||
.then(function () {
|
||||
var pushWithUnknown400 = proxyquire('../../lib/push', mocksUnknown400)(mockLog, db, {})
|
||||
return pushWithUnknown400.pushToAllDevices(ACCOUNT.uid, 'accountVerify')
|
||||
.then(devices => {
|
||||
const pushWithUnknown400 = proxyquire('../../lib/push', mocksUnknown400)(mockLog, db, {})
|
||||
return pushWithUnknown400.notifyUpdate(ACCOUNT.uid, devices, 'accountVerify')
|
||||
})
|
||||
.then(function () {
|
||||
return db.devices(ACCOUNT.uid)
|
||||
|
@ -134,11 +133,9 @@ describe('remote push db', function() {
|
|||
assert.equal(device.pushPublicKey, deviceInfo.pushPublicKey, 'device.pushPublicKey is correct')
|
||||
assert.equal(device.pushAuthKey, deviceInfo.pushAuthKey, 'device.pushAuthKey is correct')
|
||||
assert.equal(device.pushEndpointExpired, deviceInfo.pushEndpointExpired, 'device.pushEndpointExpired is correct')
|
||||
})
|
||||
|
||||
.then(function () {
|
||||
var pushWithKnown400 = proxyquire('../../lib/push', mocksKnown400)(mockLog, db, {})
|
||||
return pushWithKnown400.pushToAllDevices(ACCOUNT.uid, 'accountVerify')
|
||||
const pushWithKnown400 = proxyquire('../../lib/push', mocksKnown400)(mockLog, db, {})
|
||||
return pushWithKnown400.notifyUpdate(ACCOUNT.uid, devices, 'accountVerify')
|
||||
})
|
||||
.then(function () {
|
||||
return db.devices(ACCOUNT.uid)
|
||||
|
|
Загрузка…
Ссылка в новой задаче