diff --git a/app/controllers/user_controller.rb b/app/controllers/user_controller.rb index 409dae43..36e4d42b 100644 --- a/app/controllers/user_controller.rb +++ b/app/controllers/user_controller.rb @@ -174,12 +174,14 @@ class UserController < ApplicationController end def edit_security - current_user.otp_secret_key = User.otp_random_secret(26) + if current_user.otp_module_disabled? + current_user.otp_secret_key = User.otp_random_secret(26) - @provisioning_uri = current_user.provisioning_uri(nil, issuer: APP_CONFIG[:hostname]) - qr_code = RQRCode::QRCode.new(current_user.provisioning_uri("Retrospring:#{current_user.screen_name}", issuer: "Retrospring")) + @provisioning_uri = current_user.provisioning_uri(nil, issuer: APP_CONFIG[:hostname]) + qr_code = RQRCode::QRCode.new(current_user.provisioning_uri("Retrospring:#{current_user.screen_name}", issuer: "Retrospring")) - @qr_svg = qr_code.as_svg({offset: 4, module_size: 4, color: '000;fill:var(--primary)'}).html_safe + @qr_svg = qr_code.as_svg({offset: 4, module_size: 4, color: '000;fill:var(--primary)'}).html_safe + end end def update_2fa diff --git a/app/views/settings/_security.haml b/app/views/settings/_security.haml index 90e7dc27..5217bc6a 100644 --- a/app/views/settings/_security.haml +++ b/app/views/settings/_security.haml @@ -2,49 +2,6 @@ .card-body %h2= t('views.settings.security.2fa.title') - if current_user.otp_module_disabled? - .totp-setup - .totp-setup__left - .totp-setup__card - .totp-setup__qr - = qr_svg - %p.totp-setup__text - If you cannot scan the QR code, use the following key instead: - %code= current_user.otp_secret_key.scan(/.{4}/).flatten.join(' ') - .totp-setup__right - = bootstrap_form_for(current_user, url: { action: :update_2fa, method: :post }) do |f| - %p - If you do not have an authenticator app already installed on your device, we suggest one of the following: - %ul.list-unstyled.pl-3 - %li - %i.fa.fa-android - Aegis Authenticator for Android - %ul.list-inline - %li.list-inline-item - %a{ href: 'https://play.google.com/store/apps/details?id=com.beemdevelopment.aegis' } Google Play - %li.list-inline-item - %a{ href: 'https://f-droid.org/app/com.beemdevelopment.aegis' } F-Droid - %li.list-inline-item - %a{ href: 'https://github.com/beemdevelopment/Aegis' } Source Code - %li - %i.fa.fa-apple - Strongbox Authenticator for iOS - %ul.list-inline - %li.list-inline-item - %a{ href: 'https://apps.apple.com/gb/app/strongbox-authenticator/id1023839880' } App Store - %li - %i.fa.fa-apple - %i.fa.fa-android - Microsoft Authenticator - %ul.list-inline - %li.list-inline-item - %a{ href: 'https://apps.apple.com/gb/app/microsoft-authenticator/id983156458' } App Store - %li.list-inline-item - %a{ href: 'https://play.google.com/store/apps/details?id=com.azure.authenticator' } Google Play - %p Once you have downloaded an authenticator app, add your Retrospring account by scanning the QR code displayed on the left. - = f.text_field :otp_validation, class: 'totp-setup__code-field', label: 'Enter the code displayed in the app here:' - = f.hidden_field :otp_secret_key, value: current_user.otp_secret_key - = f.submit t('views.actions.save'), class: 'btn btn-primary' + = render partial: 'settings/security/totp-setup', locals: { qr_svg: qr_svg } - else - %p Your account is set up to require the use of a one-time password in order to log in - = link_to t('views.actions.remove'), destroy_user_2fa_path, class: 'btn btn-primary', method: 'delete', - data: { confirm: t('views.settings.security.2fa.detach_confirm') } + = render partial: 'settings/security/totp-enabled' diff --git a/app/views/settings/security/_totp-enabled.haml b/app/views/settings/security/_totp-enabled.haml new file mode 100644 index 00000000..37cbc70a --- /dev/null +++ b/app/views/settings/security/_totp-enabled.haml @@ -0,0 +1,3 @@ +%p Your account is set up to require the use of a one-time password in order to log in += link_to t('views.actions.remove'), destroy_user_2fa_path, class: 'btn btn-primary', method: 'delete', + data: { confirm: t('views.settings.security.2fa.detach_confirm') } \ No newline at end of file diff --git a/app/views/settings/security/_totp-setup.haml b/app/views/settings/security/_totp-setup.haml new file mode 100644 index 00000000..5f82701a --- /dev/null +++ b/app/views/settings/security/_totp-setup.haml @@ -0,0 +1,42 @@ +.totp-setup + .totp-setup__left + .totp-setup__card + .totp-setup__qr + = qr_svg + %p.totp-setup__text + If you cannot scan the QR code, use the following key instead: + %code= current_user.otp_secret_key.scan(/.{4}/).flatten.join(' ') + .totp-setup__right + = bootstrap_form_for(current_user, url: { action: :update_2fa, method: :post }) do |f| + %p + If you do not have an authenticator app already installed on your device, we suggest one of the following: + %ul.list-unstyled.pl-3 + %li + %i.fa.fa-android + Aegis Authenticator for Android + %ul.list-inline + %li.list-inline-item + %a{ href: 'https://play.google.com/store/apps/details?id=com.beemdevelopment.aegis' } Google Play + %li.list-inline-item + %a{ href: 'https://f-droid.org/app/com.beemdevelopment.aegis' } F-Droid + %li.list-inline-item + %a{ href: 'https://github.com/beemdevelopment/Aegis' } Source Code + %li + %i.fa.fa-apple + Strongbox Authenticator for iOS + %ul.list-inline + %li.list-inline-item + %a{ href: 'https://apps.apple.com/gb/app/strongbox-authenticator/id1023839880' } App Store + %li + %i.fa.fa-apple + %i.fa.fa-android + Microsoft Authenticator + %ul.list-inline + %li.list-inline-item + %a{ href: 'https://apps.apple.com/gb/app/microsoft-authenticator/id983156458' } App Store + %li.list-inline-item + %a{ href: 'https://play.google.com/store/apps/details?id=com.azure.authenticator' } Google Play + %p Once you have downloaded an authenticator app, add your Retrospring account by scanning the QR code displayed on the left. + = f.text_field :otp_validation, class: 'totp-setup__code-field', label: 'Enter the code displayed in the app here:' + = f.hidden_field :otp_secret_key, value: current_user.otp_secret_key + = f.submit t('views.actions.save'), class: 'btn btn-primary' \ No newline at end of file diff --git a/spec/controllers/user_controller_spec.rb b/spec/controllers/user_controller_spec.rb index 08d2f53c..dea62bc3 100644 --- a/spec/controllers/user_controller_spec.rb +++ b/spec/controllers/user_controller_spec.rb @@ -3,7 +3,7 @@ require "rails_helper" describe UserController, type: :controller do - let(:user) { FactoryBot.create :user } + let(:user) { FactoryBot.create :user, otp_module: :disabled } describe "#edit" do subject { get :edit } @@ -63,4 +63,28 @@ describe UserController, type: :controller do end end end + + describe "#edit_security" do + subject { get :edit_security } + + context "user signed in" do + before(:each) { sign_in user } + render_views + + it "shows a setup form for users who don't have 2FA enabled" do + subject + expect(response).to have_rendered(:edit_security) + expect(response).to have_rendered(partial: 'settings/security/_totp-setup') + end + + it "shows the option to disable 2FA for users who have 2FA already enabled" do + user.otp_module = :enabled + user.save + + subject + expect(response).to have_rendered(:edit_security) + expect(response).to have_rendered(partial: 'settings/security/_totp-enabled') + end + end + end end