From 1200f70ae71abbabf25e639b1c056d963d57b0e9 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Thu, 12 Jun 2025 02:54:51 -0400 Subject: [PATCH] Simplify QR/OTP generation in 2FA/confirmations spec (#35019) --- .../confirmations_controller_spec.rb | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/spec/controllers/settings/two_factor_authentication/confirmations_controller_spec.rb b/spec/controllers/settings/two_factor_authentication/confirmations_controller_spec.rb index 0121c9433..db4fb1941 100644 --- a/spec/controllers/settings/two_factor_authentication/confirmations_controller_spec.rb +++ b/spec/controllers/settings/two_factor_authentication/confirmations_controller_spec.rb @@ -16,22 +16,30 @@ RSpec.describe Settings::TwoFactorAuthentication::ConfirmationsController do end def qr_code_markup - RQRCode::QRCode.new( - 'otpauth://totp/cb6e6126.ngrok.io:local-part%40domain?secret=thisisasecretforthespecofnewview&issuer=cb6e6126.ngrok.io' - ).as_svg(padding: 0, module_size: 4, use_path: true) + RQRCode::QRCode + .new(totp_provisioning_uri) + .as_svg(padding: 0, module_size: 4, use_path: true) + end + + def totp_provisioning_uri + ROTP::TOTP + .new(otp_secret_value, issuer: Rails.configuration.x.local_domain) + .provisioning_uri(user.email) end end [true, false].each do |with_otp_secret| let(:user) { Fabricate(:user, email: 'local-part@domain', otp_secret: with_otp_secret ? 'oldotpsecret' : nil) } + let(:otp_secret_value) { 'thisisasecretforthespecofnewview' } + context 'when signed in' do before { sign_in user, scope: :user } describe 'GET #new' do context 'when a new otp secret has been set in the session' do subject do - get :new, session: { challenge_passed_at: Time.now.utc, new_otp_secret: 'thisisasecretforthespecofnewview' } + get :new, session: { challenge_passed_at: Time.now.utc, new_otp_secret: otp_secret_value } end it_behaves_like 'renders expected page' @@ -47,7 +55,7 @@ RSpec.describe Settings::TwoFactorAuthentication::ConfirmationsController do describe 'POST #create' do describe 'when form_two_factor_confirmation parameter is not provided' do it 'raises ActionController::ParameterMissing' do - post :create, params: {}, session: { challenge_passed_at: Time.now.utc, new_otp_secret: 'thisisasecretforthespecofnewview' } + post :create, params: {}, session: { challenge_passed_at: Time.now.utc, new_otp_secret: otp_secret_value } expect(response).to have_http_status(400) end @@ -64,7 +72,7 @@ RSpec.describe Settings::TwoFactorAuthentication::ConfirmationsController do it 'renders page with success' do expect { post_create_with_options } - .to change { user.reload.otp_secret }.to 'thisisasecretforthespecofnewview' + .to change { user.reload.otp_secret }.to otp_secret_value expect(flash[:notice]) .to eq(I18n.t('two_factor_authentication.enabled_success')) @@ -102,7 +110,7 @@ RSpec.describe Settings::TwoFactorAuthentication::ConfirmationsController do def post_create_with_options post :create, params: { form_two_factor_confirmation: { otp_attempt: '123456' } }, - session: { challenge_passed_at: Time.now.utc, new_otp_secret: 'thisisasecretforthespecofnewview' } + session: { challenge_passed_at: Time.now.utc, new_otp_secret: otp_secret_value } end def prepare_user_otp_generation @@ -112,7 +120,7 @@ RSpec.describe Settings::TwoFactorAuthentication::ConfirmationsController do end def prepare_user_otp_consumption_response(result) - options = { otp_secret: 'thisisasecretforthespecofnewview' } + options = { otp_secret: otp_secret_value } allow(user) .to receive(:validate_and_consume_otp!) .with('123456', options)