Permalink
Browse files

fix(metrics): ensure email sent amplitude events include device id

  • Loading branch information...
philbooth committed Nov 29, 2018
1 parent 85c278a commit 03a2f2ee73a396e53d465973715e293d118ff58a
@@ -124,14 +124,14 @@ function logAmplitudeEvent (log, message, eventInfo) {
query: {},
payload: {}
}, {
device_id: message.deviceId || getHeaderValue('X-Device-Id', message),
email_domain: eventInfo.domain,
email_sender: message.emailSender || getHeaderValue('X-Email-Sender', message),
email_service: message.emailService || getHeaderValue('X-Email-Service', message),
service: message.service || getHeaderValue('X-Service-Id', message),
templateVersion: eventInfo.templateVersion,
uid: message.uid || getHeaderValue('X-Uid', message)
}, {
device_id: message.deviceId || getHeaderValue('X-Device-Id', message),
flowBeginTime: message.flowBeginTime || getHeaderValue('X-Flow-Begin-Time', message),
flow_id: eventInfo.flow_id,
time: Date.now()
@@ -76,7 +76,7 @@ module.exports = (log, db, mailer, Password, config, customs, signinUtils, push)

request.validateMetricsContext()

const { flowId, flowBeginTime } = await request.app.metricsContext
const { deviceId, flowId, flowBeginTime } = await request.app.metricsContext

return customs.check(request, email, 'accountCreate')
.then(deleteAccountIfUnverified)
@@ -272,6 +272,7 @@ module.exports = (log, db, mailer, Password, config, customs, signinUtils, push)
redirectTo: form.redirectTo,
resume: form.resume,
acceptLanguage: request.app.acceptLanguage,
deviceId,
flowId,
flowBeginTime,
ip,
@@ -677,14 +678,15 @@ module.exports = (log, db, mailer, Password, config, customs, signinUtils, push)
const geoData = request.app.geo
const service = request.payload.service || request.query.service
const ip = request.app.clientAddress
const { flowId, flowBeginTime } = await request.app.metricsContext
const { deviceId, flowId, flowBeginTime } = await request.app.metricsContext

try {
await mailer.sendNewDeviceLoginNotification(
accountRecord.emails,
accountRecord,
{
acceptLanguage: request.app.acceptLanguage,
deviceId,
flowId,
flowBeginTime,
ip,
@@ -441,7 +441,7 @@ module.exports = function (
}
request.setMetricsFlowCompleteSignal(flowCompleteSignal)

const { flowId, flowBeginTime } = await request.app.metricsContext
const { deviceId, flowId, flowBeginTime } = await request.app.metricsContext

let passwordForgotToken

@@ -483,6 +483,7 @@ module.exports = function (
redirectTo: request.payload.redirectTo,
resume: request.payload.resume,
acceptLanguage: request.app.acceptLanguage,
deviceId,
flowId,
flowBeginTime,
ip,
@@ -538,7 +539,7 @@ module.exports = function (
var service = request.payload.service || request.query.service
const ip = request.app.clientAddress

const { flowId, flowBeginTime } = await request.app.metricsContext
const { deviceId, flowId, flowBeginTime } = await request.app.metricsContext

return P.all([
request.emitMetricsEvent('password.forgot.resend_code.start'),
@@ -564,6 +565,7 @@ module.exports = function (
redirectTo: request.payload.redirectTo,
resume: request.payload.resume,
acceptLanguage: request.app.acceptLanguage,
deviceId,
flowId,
flowBeginTime,
ip,
@@ -621,7 +623,7 @@ module.exports = function (
var code = request.payload.code
const accountResetWithRecoveryKey = request.payload.accountResetWithRecoveryKey

const { flowId, flowBeginTime } = await request.app.metricsContext
const { deviceId, flowId, flowBeginTime } = await request.app.metricsContext

let accountResetToken

@@ -663,6 +665,7 @@ module.exports = function (
{
code,
acceptLanguage: request.app.acceptLanguage,
deviceId,
flowId,
flowBeginTime,
uid: passwordForgotToken.uid
@@ -182,7 +182,7 @@ module.exports = (log, config, customs, db, mailer) => {

let sessions

const { flowId, flowBeginTime } = await request.app.metricsContext
const { deviceId, flowId, flowBeginTime } = await request.app.metricsContext

const mustVerifySession = sessionToken.mustVerify && ! sessionToken.tokenVerified

@@ -278,6 +278,7 @@ module.exports = (log, config, customs, db, mailer) => {
redirectTo,
resume,
acceptLanguage: request.app.acceptLanguage,
deviceId,
flowId,
flowBeginTime,
ip,
@@ -330,6 +331,7 @@ module.exports = (log, config, customs, db, mailer) => {
{
acceptLanguage: request.app.acceptLanguage,
code: sessionToken.tokenVerificationId,
deviceId,
flowId,
flowBeginTime,
ip,
@@ -367,6 +369,7 @@ module.exports = (log, config, customs, db, mailer) => {
{
acceptLanguage: request.app.acceptLanguage,
code: sessionToken.tokenVerificationCode,
deviceId,
flowId,
flowBeginTime,
ip,
@@ -116,14 +116,14 @@ describe('email utils helpers', () => {
payload: {}
})
assert.deepEqual(args[2], {
device_id: 'bbb',
email_domain: 'other',
email_service: 'fxa-email-service',
email_sender: 'ses',
service: 'ddd',
templateVersion: 'eee',
uid: 'fff'
})
assert.equal(args[3].device_id, 'bbb')
assert.equal(args[3].flow_id, 'ccc')
assert.equal(args[3].flowBeginTime, 42)
assert.ok(args[3].time > Date.now() - 1000)
@@ -164,14 +164,14 @@ describe('email utils helpers', () => {
payload: {}
})
assert.deepEqual(args[2], {
device_id: 'b',
email_domain: 'gmail',
email_sender: 'wibble',
email_service: 'fxa-auth-server',
service: 'd',
templateVersion: 42,
uid: 'e'
})
assert.equal(args[3].device_id, 'b')
assert.equal(args[3].flow_id, 'c')
assert.equal(args[3].flowBeginTime, 1)
})
@@ -299,6 +299,7 @@ describe('/account/create', () => {
authPW: hexString(32),
service: 'sync',
metricsContext: {
deviceId: 'wibble',
flowBeginTime: Date.now(),
flowId: 'F1031DF1031DF1031DF1031DF1031DF1031DF1031DF1031DF1031DF1031DF103',
utmCampaign: 'utm campaign',
@@ -505,6 +506,7 @@ describe('/account/create', () => {
assert.equal(args[2].uaOS, 'iOS')
assert.equal(args[2].uaOSVersion, '11')
assert.strictEqual(args[2].uaDeviceType, 'tablet')
assert.equal(args[2].deviceId, mockRequest.payload.metricsContext.deviceId)
assert.equal(args[2].flowId, mockRequest.payload.metricsContext.flowId)
assert.equal(args[2].flowBeginTime, mockRequest.payload.metricsContext.flowBeginTime)
assert.equal(args[2].service, 'sync')
@@ -584,6 +586,7 @@ describe('/account/login', function () {
service: 'sync',
reason: 'signin',
metricsContext: {
deviceId: 'blee',
flowBeginTime: Date.now(),
flowId: 'F1031DF1031DF1031DF1031DF1031DF1031DF1031DF1031DF1031DF1031DF103',
utmCampaign: 'utm campaign',
@@ -611,6 +614,7 @@ describe('/account/login', function () {
service: 'dcdb5ae7add825d2',
reason: 'signin',
metricsContext: {
deviceId: 'blee',
flowBeginTime: Date.now(),
flowId: 'F1031DF1031DF1031DF1031DF1031DF1031DF1031DF1031DF1031DF1031DF103',
service: 'dcdb5ae7add825d2'
@@ -627,6 +631,7 @@ describe('/account/login', function () {
service: 'dcdb5ae7add825d2',
reason: 'signin',
metricsContext: {
deviceId: 'blee',
flowBeginTime: Date.now(),
flowId: 'F1031DF1031DF1031DF1031DF1031DF1031DF1031DF1031DF1031DF1031DF103'
}
@@ -800,6 +805,7 @@ describe('/account/login', function () {
assert.equal(args[2].uaOS, 'Android')
assert.equal(args[2].uaOSVersion, '6')
assert.equal(args[2].uaDeviceType, 'mobile')
assert.equal(args[2].deviceId, mockRequest.payload.metricsContext.deviceId)
assert.equal(args[2].flowId, mockRequest.payload.metricsContext.flowId)
assert.equal(args[2].flowBeginTime, mockRequest.payload.metricsContext.flowBeginTime)
assert.equal(args[2].service, 'sync')
@@ -1058,6 +1064,7 @@ describe('/account/login', function () {
assert.equal(tokenData.tokenVerificationId, null, 'sessionToken was created verified')
assert.equal(mockMailer.sendVerifyCode.callCount, 0, 'mailer.sendVerifyLoginEmail was not called')
assert.equal(mockMailer.sendNewDeviceLoginNotification.callCount, 1, 'mailer.sendNewDeviceLoginNotification was called')
assert.equal(mockMailer.sendNewDeviceLoginNotification.args[0][2].deviceId, mockRequest.payload.metricsContext.deviceId)
assert.equal(mockMailer.sendNewDeviceLoginNotification.args[0][2].flowId, mockRequest.payload.metricsContext.flowId)
assert.equal(mockMailer.sendNewDeviceLoginNotification.args[0][2].flowBeginTime, mockRequest.payload.metricsContext.flowBeginTime)
assert.equal(mockMailer.sendNewDeviceLoginNotification.args[0][2].service, 'sync')
@@ -87,6 +87,7 @@ describe('/password', () => {
payload: {
email: TEST_EMAIL,
metricsContext: {
deviceId: 'wibble',
flowId: 'F1031DF1031DF1031DF1031DF1031DF1031DF1031DF1031DF1031DF1031DF103',
flowBeginTime: Date.now() - 1
}
@@ -127,6 +128,7 @@ describe('/password', () => {
assert.equal(args[2].location.country, 'United States')
assert.equal(args[2].timeZone, 'America/Los_Angeles')
assert.equal(args[2].uid, uid)
assert.equal(args[2].deviceId, 'wibble')
})
})

@@ -172,6 +174,7 @@ describe('/password', () => {
payload: {
email: TEST_EMAIL,
metricsContext: {
deviceId: 'wibble',
flowId: 'F1031DF1031DF1031DF1031DF1031DF1031DF1031DF1031DF1031DF1031DF103',
flowBeginTime: Date.now() - 1
}
@@ -182,6 +185,7 @@ describe('/password', () => {
.then(function(response) {
assert.equal(mockMailer.sendRecoveryCode.callCount, 1, 'mailer.sendRecoveryCode was called once')
assert.equal(mockMailer.sendRecoveryCode.args[0][2].uid, uid)
assert.equal(mockMailer.sendRecoveryCode.args[0][2].deviceId, 'wibble')

assert.equal(mockRequest.validateMetricsContext.callCount, 0)
assert.equal(mockLog.flowEvent.callCount, 2, 'log.flowEvent was called twice')
@@ -242,6 +246,7 @@ describe('/password', () => {
payload: {
code: 'abcdef',
metricsContext: {
deviceId: 'wibble',
flowId: 'F1031DF1031DF1031DF1031DF1031DF1031DF1031DF1031DF1031DF1031DF103',
flowBeginTime: Date.now() - 1
}
@@ -275,6 +280,7 @@ describe('/password', () => {

assert.equal(mockMailer.sendPasswordResetNotification.callCount, 1, 'mailer.sendPasswordResetNotification was called once')
assert.equal(mockMailer.sendPasswordResetNotification.args[0][2].uid, uid, 'mailer.sendPasswordResetNotification was passed uid')
assert.equal(mockMailer.sendPasswordResetNotification.args[0][2].deviceId, 'wibble')
})
}
)
@@ -451,6 +451,7 @@ describe('sendSigninNotifications', () => {
payload: {
service: 'testservice',
metricsContext: {
deviceId: 'wibble',
flowBeginTime: Date.now(),
flowId: 'F1031DF1031DF1031DF1031DF1031DF1031DF1031DF1031DF1031DF1031DF103',
utmCampaign: 'utm campaign',
@@ -543,6 +544,7 @@ describe('sendSigninNotifications', () => {
assert.calledWithExactly(mailer.sendVerifyCode, [], accountRecord, {
acceptLanguage: 'en-US',
code: 'emailVerifyCode',
deviceId: request.payload.metricsContext.deviceId,
flowBeginTime: request.payload.metricsContext.flowBeginTime,
flowId: request.payload.metricsContext.flowId,
ip: CLIENT_ADDRESS,
@@ -590,6 +592,7 @@ describe('sendSigninNotifications', () => {
assert.calledWithExactly(mailer.sendVerifyCode, [], accountRecord, {
acceptLanguage: 'en-US',
code: 'tokenVerifyCode', // the token verification code is used if available
deviceId: request.payload.metricsContext.deviceId,
flowBeginTime: request.payload.metricsContext.flowBeginTime,
flowId: request.payload.metricsContext.flowId,
ip: CLIENT_ADDRESS,
@@ -673,6 +676,7 @@ describe('sendSigninNotifications', () => {
assert.calledWithExactly(mailer.sendVerifyLoginEmail, accountRecord.emails, accountRecord, {
acceptLanguage: 'en-US',
code: 'tokenVerifyCode',
deviceId: request.payload.metricsContext.deviceId,
flowBeginTime: request.payload.metricsContext.flowBeginTime,
flowId: request.payload.metricsContext.flowId,
ip: CLIENT_ADDRESS,
@@ -721,6 +725,7 @@ describe('sendSigninNotifications', () => {
assert.calledWithExactly(mailer.sendVerifyLoginCodeEmail, accountRecord.emails, accountRecord, {
acceptLanguage: 'en-US',
code: 'tokenVerifyShortCode',
deviceId: request.payload.metricsContext.deviceId,
flowBeginTime: request.payload.metricsContext.flowBeginTime,
flowId: request.payload.metricsContext.flowId,
ip: CLIENT_ADDRESS,

0 comments on commit 03a2f2e

Please sign in to comment.