From 9576ca1b7f68e40d6634ff068f834c3853f275da Mon Sep 17 00:00:00 2001 From: Nils Caspar Date: Sat, 30 May 2015 13:23:55 +0200 Subject: [PATCH] Automatically calculate QR size, fixes #111 --- .../casino/two_factor_authenticators_helper.rb | 17 +++++++++++++++-- ...two_factor_authenticators_controller_spec.rb | 13 +++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/app/helpers/casino/two_factor_authenticators_helper.rb b/app/helpers/casino/two_factor_authenticators_helper.rb index b4487f8d..db47a8d0 100644 --- a/app/helpers/casino/two_factor_authenticators_helper.rb +++ b/app/helpers/casino/two_factor_authenticators_helper.rb @@ -1,3 +1,4 @@ +require 'rqrcode' require 'rqrcode_png' module CASino::TwoFactorAuthenticatorsHelper @@ -6,7 +7,19 @@ def otp_auth_url(two_factor_authenticator) end def otp_qr_code_data_url(two_factor_authenticator) - qr = RQRCode::QRCode.new(otp_auth_url(two_factor_authenticator), size: 5, level: :l) - qr.to_img.resize(250,250).to_data_url + auth_url = otp_auth_url(two_factor_authenticator) + size = otp_qr_code_suggested_size(auth_url) + qr = RQRCode::QRCode.new(auth_url, size: size, level: :l) + qr.to_img.resize(250, 250).to_data_url + end + + def otp_qr_code_suggested_size(data) + data_bits = data.length * 8 + (3..40).each do |size| + metadata_bits = 4 + RQRCode::QRUtil.get_length_in_bits(RQRCode::QRMODE[:mode_8bit_byte], size) + total_data_bits = metadata_bits + data_bits + max_data_bits = RQRCode::QRCode.count_max_data_bits(RQRCode::QRRSBlock.get_rs_blocks(size, 1)) + return size if total_data_bits < max_data_bits + end end end diff --git a/spec/controllers/two_factor_authenticators_controller_spec.rb b/spec/controllers/two_factor_authenticators_controller_spec.rb index d167d61b..6587a882 100644 --- a/spec/controllers/two_factor_authenticators_controller_spec.rb +++ b/spec/controllers/two_factor_authenticators_controller_spec.rb @@ -35,6 +35,19 @@ get :new, request_options response.should render_template(:new) end + + context 'with a really long service name' do + before(:each) do + CASino.config.frontend[:sso_name] = 'Na' * 200 + end + + render_views + + it 'renders the new template' do + get :new, request_options + response.should render_template(:new) + end + end end context 'without a ticket-granting ticket' do