Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 25 additions & 7 deletions app/controllers/analytics_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,39 @@ class AnalyticsController < ApplicationController
before_action :confirm_two_factor_authenticated

def create
unless analytics_saved?
session[:platform_authenticator] = true
analytics.track_event(Analytics::PLATFORM_AUTHENTICATOR, results.to_h)
results.each do |event, result|
next if result.nil?

analytics.track_event(event, result.to_h)
end
head :ok
end

private

def results
FormResponse.new(success: true, errors: {},
extra: { platform_authenticator: params[:available] })
{
Analytics::FRONTEND_BROWSER_CAPABILITIES => platform_authenticator_result,
}
end

def platform_authenticator_result
return if platform_authenticator_results_saved? || !platform_authenticator_params_valid?

session[:platform_authenticator_analytics_saved] = true
platform_authenticator_available = params[:available] ||
params.dig(:platform_authenticator, :available)
extra = { platform_authenticator: (platform_authenticator_available == 'true') }
FormResponse.new(success: true, errors: {}, extra: extra)
end

def platform_authenticator_params_valid?
result = params[:available] || params.dig(:platform_authenticator, :available)
%w[true false].include?(result)
end

def analytics_saved?
session[:platform_authenticator]
def platform_authenticator_results_saved?
session[:platform_authenticator_analytics_saved] == true ||
session[:platform_authenticator] == true
end
end
2 changes: 1 addition & 1 deletion app/javascript/app/platform-authenticator.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ function platformAuthenticator() {
const xhr = new XMLHttpRequest();
xhr.open('POST', '/analytics', true);
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhr.send(`available=${userIntent}`);
xhr.send(`platform_authenticator[available]=${userIntent}`);
});
}
}
Expand Down
2 changes: 1 addition & 1 deletion app/services/analytics.rb
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ def browser
DOC_AUTH = 'Doc Auth'.freeze # visited or submitted is appended
EMAIL_AND_PASSWORD_AUTH = 'Email and Password Authentication'.freeze
EMAIL_CHANGE_REQUEST = 'Email Change Request'.freeze
FRONTEND_BROWSER_CAPABILITIES = 'Frontend: Browser capabilities'.freeze
IDV_BASIC_INFO_VISIT = 'IdV: basic info visited'.freeze
IDV_BASIC_INFO_SUBMITTED_FORM = 'IdV: basic info form submitted'.freeze
IDV_BASIC_INFO_SUBMITTED_VENDOR = 'IdV: basic info vendor submitted'.freeze
Expand Down Expand Up @@ -113,7 +114,6 @@ def browser
PERSONAL_KEY_VIEWED = 'Personal Key Viewed'.freeze
PHONE_CHANGE_REQUESTED = 'Phone Number Change: requested'.freeze
PHONE_DELETION_REQUESTED = 'Phone Number Deletion: requested'.freeze
PLATFORM_AUTHENTICATOR = 'Platform Authenticator'.freeze
PROFILE_ENCRYPTION_INVALID = 'Profile Encryption: Invalid'.freeze
PROFILE_PERSONAL_KEY_CREATE = 'Profile: Created new personal key'.freeze
RATE_LIMIT_TRIGGERED = 'Rate Limit Triggered'.freeze
Expand Down
35 changes: 0 additions & 35 deletions spec/controllers/analytics_controller_spec.rb

This file was deleted.

13 changes: 2 additions & 11 deletions spec/requests/edit_user_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,9 @@ def user_session
session['warden.user.user.session']
end

def sign_in_as_a_valid_user
post new_user_session_path, params: { user: { email: user.email, password: user.password } }
get otp_send_path, params: { otp_delivery_selection_form: { otp_delivery_preference: 'sms' } }
follow_redirect!
post login_two_factor_path, params: {
otp_delivery_preference: 'sms', code: user.reload.direct_otp
}
end

context 'user changes email address' do
before do
sign_in_as_a_valid_user
sign_in_user(user)
put manage_email_path, params: { update_user_email_form: { email: 'new_email@example.com' } }
end

Expand Down Expand Up @@ -51,7 +42,7 @@ def sign_in_as_a_valid_user

context 'user submits email address with invalid encoding' do
it 'returns a 400 error and logs the user uuid' do
sign_in_as_a_valid_user
sign_in_user(user)
params = { update_user_email_form: { email: "test\xFFbar\xF8@test.com" } }
headers = { CONTENT_TYPE: 'application/x-www-form-urlencoded;foo' }

Expand Down
72 changes: 72 additions & 0 deletions spec/requests/frontend_analytics_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
require 'rails_helper'

describe 'frontend analytics requests' do
describe 'platform authenticators' do
let(:analytics) { FakeAnalytics.new }

before do
allow(analytics).to receive(:track_event)
allow(Analytics).to receive(:new).and_return(analytics)
end

it 'does not log anything if the user is not authed' do
expect(analytics).to_not receive(:track_event).
with(Analytics::FRONTEND_BROWSER_CAPABILITIES, any_args)

post analytics_path, params: { platform_authenticator: { available: true } }
end

it 'logs true if the platform authenticator is available' do
sign_in_user

post analytics_path, params: { platform_authenticator: { available: true } }

expect(analytics).to have_received(:track_event).
with(Analytics::FRONTEND_BROWSER_CAPABILITIES, hash_including(platform_authenticator: true))
end

it 'logs false if the platform authenticator is not available' do
sign_in_user

post analytics_path, params: { platform_authenticator: { available: false } }

expect(analytics).to have_received(:track_event).
with(
Analytics::FRONTEND_BROWSER_CAPABILITIES,
hash_including(platform_authenticator: false)
)
end

it 'only logs 1 platform authenticator event per session' do
sign_in_user

post analytics_path, params: { platform_authenticator: { available: true } }
post analytics_path, params: { platform_authenticator: { available: true } }

expect(analytics).to have_received(:track_event).
with(
Analytics::FRONTEND_BROWSER_CAPABILITIES,
hash_including(platform_authenticator: true)
).
once
end

it 'logs ignores garbage values' do
sign_in_user

post analytics_path, params: { platform_authenticator: { available: 'blah blah blah' } }

expect(analytics).to_not have_received(:track_event).
with(Analytics::FRONTEND_BROWSER_CAPABILITIES, any_args)
end

it 'supports the legacy API format' do
sign_in_user

post analytics_path, params: { available: true }

expect(analytics).to have_received(:track_event).
with(Analytics::FRONTEND_BROWSER_CAPABILITIES, hash_including(platform_authenticator: true))
end
end
end
20 changes: 20 additions & 0 deletions spec/support/request_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
module RequestHelper
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these changes just piggybacking on this PR?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I added a helper to authenticate a user in the specs. The analytics request specs require you be authed.

VALID_PASSWORD = 'Val!d Pass w0rd'.freeze

def user_with_2fa
create(:user, :signed_up, with: { phone: '+1 202-555-1212' }, password: VALID_PASSWORD)
end

def sign_in_user(user = user_with_2fa)
post new_user_session_path, params: { user: { email: user.email, password: user.password } }
get otp_send_path, params: { otp_delivery_selection_form: { otp_delivery_preference: 'sms' } }
follow_redirect!
post login_two_factor_path, params: {
otp_delivery_preference: 'sms', code: user.reload.direct_otp
}
end
end

RSpec.configure do |config|
config.include RequestHelper, type: :request
end