task(auth): Add third_party_accounts_set_password_complete metric

Becuase:
- When a user sets their password after signing in with a third party, we want to emit a metirc.

This Commit:
- Adds the third_party_accounts_set_password_complete metric.
This commit is contained in:
dschom 2024-06-27 14:41:00 -07:00
Родитель f16bad2cc4
Коммит 6d1deb987c
Не найден ключ, соответствующий данной подписи
7 изменённых файлов: 138 добавлений и 0 удалений

Просмотреть файл

@ -235,6 +235,12 @@ const createEventFn =
linking: metricsData?.reason === 'linking',
});
break;
case 'third_party_auth_set_password_complete':
gleanServerEventLogger.recordThirdPartyAuthSetPasswordComplete(
commonMetrics
);
break;
}
await gleanEventLogger.record({
@ -302,6 +308,9 @@ export function gleanMetrics(config: ConfigType) {
thirdPartyAuth: {
googleLoginComplete: createEventFn('google_login_complete'),
setPasswordComplete: createEventFn(
'third_party_auth_set_password_complete'
),
},
};
}

Просмотреть файл

@ -1911,6 +1911,76 @@ class EventsServerEventLogger {
event,
});
}
/**
* Record and submit a third_party_auth_set_password_complete event:
* Password for third party user was successfully created
* Event is logged using internal mozlog logger.
*
* @param {string} user_agent - The user agent.
* @param {string} ip_address - The IP address. Will be used to decode Geo
* information and scrubbed at ingestion.
* @param {string} account_user_id_sha256 - A hex string of a sha256 hash of the account's uid.
* @param {string} relying_party_oauth_client_id - The client id of the relying party.
* @param {string} relying_party_service - The service name of the relying party.
* @param {string} session_device_type - one of 'mobile', 'tablet', or ''.
* @param {string} session_entrypoint - entrypoint to the service.
* @param {string} session_flow_id - an ID generated by FxA for its flow metrics.
* @param {string} utm_campaign - A marketing campaign. For example, if a user signs into FxA from selecting a Mozilla VPN plan on Mozilla VPN's product site, then the value of this metric could be 'vpn-product-page'. The value has a max length of 128 characters with the alphanumeric characters, _ (underscore), forward slash (/), . (period), % (percentage sign), and - (hyphen) in the allowed set of characters. The special value of 'page+referral+-+not+part+of+a+campaign' is also allowed..
* @param {string} utm_content - The content on which the user acted. For example, if the user clicked on the (previously available) "Get started here" link in "Looking for Firefox Sync? Get started here", then the value for this metric would be 'fx-sync-get-started'. The value has a max length of 128 characters with the alphanumeric characters, _ (underscore), forward slash (/), . (period), % (percentage sign), and - (hyphen) in the allowed set of characters..
* @param {string} utm_medium - The "medium" on which the user acted. For example, if the user clicked on a link in an email, then the value of this metric would be 'email'. The value has a max length of 128 characters with the alphanumeric characters, _ (underscore), forward slash (/), . (period), % (percentage sign), and - (hyphen) in the allowed set of characters..
* @param {string} utm_source - The source from where the user started. For example, if the user clicked on a link on the Mozilla accounts web site, this value could be 'fx-website'. The value has a max length of 128 characters with the alphanumeric characters, _ (underscore), forward slash (/), . (period), % (percentage sign), and - (hyphen) in the allowed set of characters..
* @param {string} utm_term - This metric is similar to the `utm.source`; it is used in the Firefox browser. For example, if the user started from about:welcome, then the value could be 'aboutwelcome-default-screen'. The value has a max length of 128 characters with the alphanumeric characters, _ (underscore), forward slash (/), . (period), % (percentage sign), and - (hyphen) in the allowed set of characters..
*/
recordThirdPartyAuthSetPasswordComplete({
user_agent,
ip_address,
account_user_id_sha256,
relying_party_oauth_client_id,
relying_party_service,
session_device_type,
session_entrypoint,
session_flow_id,
utm_campaign,
utm_content,
utm_medium,
utm_source,
utm_term,
}: {
user_agent: string;
ip_address: string;
account_user_id_sha256: string;
relying_party_oauth_client_id: string;
relying_party_service: string;
session_device_type: string;
session_entrypoint: string;
session_flow_id: string;
utm_campaign: string;
utm_content: string;
utm_medium: string;
utm_source: string;
utm_term: string;
}) {
const event = {
category: 'third_party_auth_set_password',
name: 'complete',
};
this.#record({
user_agent,
ip_address,
account_user_id_sha256,
relying_party_oauth_client_id,
relying_party_service,
session_device_type,
session_entrypoint,
session_flow_id,
utm_campaign,
utm_content,
utm_medium,
utm_source,
utm_term,
event,
});
}
}
/**

Просмотреть файл

@ -1144,6 +1144,20 @@ module.exports = function (
account: { uid },
});
// We need to track when users with third party accounts actually set a passwords. Note that
// this handler will exit early if the user already has a password, and this code would not
// be reached, which ensures this event will only fire when a user is setting their linked
// account password for the first time.
const linkedAccounts = await db.getLinkedAccounts(uid);
if (
linkedAccounts?.length > 0 &&
linkedAccounts.some((x: { enabled: boolean }) => x.enabled)
) {
glean.thirdPartyAuth.setPasswordComplete(request, {
uid,
});
}
return passwordCreated;
},
},

Просмотреть файл

@ -31,6 +31,7 @@ const recordPasswordResetRecoveryKeyCreateSuccessStub = sinon.stub();
const recordAccessTokenCreatedStub = sinon.stub();
const recordAccessTokenCheckedStub = sinon.stub();
const recordThirdPartyAuthGoogleLoginCompleteStub = sinon.stub();
const recordThirdPartyAuthSetPasswordCompleteStub = sinon.stub();
const { gleanMetrics, logErrorWithGlean } = proxyquire.load(
'../../../lib/metrics/glean',
@ -64,6 +65,8 @@ const { gleanMetrics, logErrorWithGlean } = proxyquire.load(
recordAccessTokenChecked: recordAccessTokenCheckedStub,
recordThirdPartyAuthGoogleLoginComplete:
recordThirdPartyAuthGoogleLoginCompleteStub,
recordThirdPartyAuthSetPasswordComplete:
recordThirdPartyAuthSetPasswordCompleteStub,
}),
},
}
@ -536,6 +539,23 @@ describe('Glean server side events', () => {
);
});
});
describe('setPassword', () => {
beforeEach(() => {
recordThirdPartyAuthSetPasswordCompleteStub.reset();
});
it('log string and event metrics with account linking', async () => {
const glean = gleanMetrics(config);
await glean.thirdPartyAuth.setPasswordComplete(request);
sinon.assert.calledOnce(recordStub);
const metrics = recordStub.args[0][0];
assert.equal(
metrics['event_name'],
'third_party_auth_set_password_complete'
);
sinon.assert.calledOnce(recordThirdPartyAuthSetPasswordCompleteStub);
});
});
});
describe('logErrorWithGlean hapi preResponse error logger', () => {

Просмотреть файл

@ -1223,6 +1223,9 @@ describe('/password', () => {
enabled: true,
};
});
mockDB.getLinkedAccounts = sinon.spy(() => {
return Promise.resolve([{ enabled: true }]);
});
passwordRoutes = makeRoutes({
db: mockDB,
mailer: mockMailer,
@ -1235,6 +1238,8 @@ describe('/password', () => {
);
assert.equal(mockDB.account.callCount, 1);
assert.equal(mockDB.createPassword.callCount, 1);
assert.equal(mockDB.getLinkedAccounts.callCount, 1);
assert.equal(glean.thirdPartyAuth.setPasswordComplete.callCount, 1);
assert.deepEqual(res, 1584397692000);
});
});

Просмотреть файл

@ -110,6 +110,7 @@ const DB_METHOD_NAMES = [
'reactivateAccountSubscription',
'fetchAccountSubscriptions',
'getLinkedAccount',
'getLinkedAccounts',
'createLinkedAccount',
'deleteLinkedAccount',
'accountExists',

Просмотреть файл

@ -720,3 +720,22 @@ third_party_auth:
description: |
Indicates the initial linking of the Mozilla account and the third-party account.
type: boolean
third_party_auth_set_password:
complete:
type: event
description: |
Password for third party user was successfully created
send_in_pings:
- events
notification_emails:
- vzare@mozilla.com
- fxa-staff@mozilla.com
bugs:
- https://mozilla-hub.atlassian.net/browse/FXA-9988
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1830504
- https://bugzilla.mozilla.org/show_bug.cgi?id=1844121
expires: never
data_sensitivity:
- interaction