Browse Source

Follow-up 54f06204 - Fixes #4595 - Add password confirmation for removing of two factor authentication method in personal profile.

Co-authored-by: Dominik Klein <dk@zammad.com>
Co-authored-by: Florian Liebe <fl@zammad.com>
Dominik Klein 1 year ago
parent
commit
3512235ec0

+ 19 - 12
app/assets/javascripts/app/controllers/_profile/password.coffee

@@ -2,11 +2,12 @@ class ProfilePassword extends App.ControllerSubContent
   @requiredPermission: 'user_preferences.password'
   header: __('Password & Authentication')
   events:
-    'submit form': 'update'
-    'click [data-type="setup"]':   'twoFactorMethodSetup'
-    'click [data-type="edit"]':    'twoFactorMethodSetup'
-    'click [data-type="remove"]':  'twoFactorMethodRemove'
-    'click [data-type="default"]': 'twoFactorMethodDefault'
+    'submit form':                       'update'
+    'click .js-generate-recovery-codes': 'twoFactorMethodGenerateRecoveryCodes'
+    'click [data-type="setup"]':         'twoFactorMethodSetup'
+    'click [data-type="edit"]':          'twoFactorMethodSetup'
+    'click [data-type="remove"]':        'twoFactorMethodRemove'
+    'click [data-type="default"]':       'twoFactorMethodDefault'
 
   constructor: ->
     super
@@ -162,18 +163,16 @@ class ProfilePassword extends App.ControllerSubContent
       successCallback: @load
     )
 
-  twoFactorMethodRemove: (e) =>
+  twoFactorMethodRemove: (e) ->
     e.preventDefault()
 
     key     = e.currentTarget.closest('tr').dataset.twoFactorKey
     method  = App.TwoFactorMethods.methodByKey(key)
 
-    new App.ControllerConfirm(
-      head: __('Are you sure?')
-      message: App.i18n.translatePlain('Two-factor authentication method "%s" will be removed.', App.i18n.translatePlain(method.label))
-      container: @el.closest('.content')
-      small: true
-      callback: =>
+    new App.TwoFactorConfigurationModalPasswordCheck(
+      headPrefix: __('Remove two-factor authentication')
+      buttonSubmit: 'Remove'
+      successCallback: =>
         @ajax(
           id:   'profile_two_factor_removal'
           type: 'DELETE'
@@ -230,6 +229,14 @@ class ProfilePassword extends App.ControllerSubContent
           removeAll: true
     )
 
+  twoFactorMethodGenerateRecoveryCodes: (e) =>
+    e.preventDefault()
+
+    new App.TwoFactorConfigurationMethodRecoveryCodes(
+      container: @el.closest('.content')
+      successCallback: @load
+    )
+
 App.Config.set('Password', {
   prio: 2000,
   name: __('Password & Authentication'),

+ 4 - 0
app/assets/javascripts/app/controllers/widget/two_factor_configuration/method.coffee

@@ -1,5 +1,6 @@
 class App.TwoFactorConfigurationMethod extends App.Controller
   passwordCheck: true
+  passwordCheckHeadPrefix: null
 
   constructor: (params) ->
     super
@@ -27,6 +28,9 @@ class App.TwoFactorConfigurationMethod extends App.Controller
 
     # Show password check first, if requested.
     if @passwordCheck
+      if @passwordCheckHeadPrefix
+        modalOptions.headPrefix = @passwordCheckHeadPrefix
+
       return new App.TwoFactorConfigurationModalPasswordCheck(
         _.extend(
           {},

+ 2 - 0
app/assets/javascripts/app/controllers/widget/two_factor_configuration/method/recovery_codes.coffee

@@ -1,3 +1,5 @@
 class App.TwoFactorConfigurationMethodRecoveryCodes extends App.TwoFactorConfigurationMethod
+  passwordCheckHeadPrefix: __('Generate recovery codes')
+
   methodModalClass: ->
     App.TwoFactorConfigurationModalRecoveryCodes

+ 7 - 2
app/assets/javascripts/app/controllers/widget/two_factor_configuration/modal/password_check.coffee

@@ -1,7 +1,7 @@
 class App.TwoFactorConfigurationModalPasswordCheck extends App.TwoFactorConfigurationModal
   buttonSubmit: __('Next')
   buttonClass: 'btn--primary'
-  head: __('Password')
+  head: __('Confirm Password')
 
   content: ->
     configure_attributes = [
@@ -33,7 +33,12 @@ class App.TwoFactorConfigurationModalPasswordCheck extends App.TwoFactorConfigur
       processData: true
       success: (data, status, xhr) =>
         if data?.success
-          @next()
+          if @successCallback && !@container
+            @close()
+            @successCallback()
+          else
+            @next()
+
           return
 
         @formValidate( form: e.target, errors:

+ 2 - 1
app/assets/javascripts/app/controllers/widget/two_factor_configuration/modal/recovery_codes.coffee

@@ -11,7 +11,8 @@ class App.TwoFactorConfigurationModalRecoveryCodes extends App.TwoFactorConfigur
       text: __('Copy')
     }
   ]
-  head: __('Recovery Codes')
+  headPrefix: ''
+  head: __('Generated Recovery Codes')
   events:
     'click .js-print': 'print'
     'click .js-copy':  'copy'

+ 2 - 2
app/assets/javascripts/app/views/profile/password.jst.eco

@@ -106,13 +106,13 @@
           <p><%- @T('If you lose your recovery codes it\'s possible to generate new ones. This action is going to invalidate previous recovery codes.') %></p>
         <% end %>
 
-        <div data-type="setup" data-two-factor-key="recovery_codes" class="js-generate-recovery-codes btn btn--create settings-list--bottom-button">
+        <a class="js-generate-recovery-codes btn btn--create settings-list--bottom-button">
           <% if @recoveryCodesExist: %>
             <%= @T 'Regenerate recovery codes' %>
           <% else: %>
             <%= @T 'Generate recovery codes' %>
           <% end %>
-        </div>
+        </a>
       </div>
     <% end %>
   </div>

+ 13 - 6
i18n/zammad.pot

@@ -1239,7 +1239,6 @@ msgstr ""
 #: app/assets/javascripts/app/controllers/_channel/telegram.coffee
 #: app/assets/javascripts/app/controllers/_channel/twitter.coffee
 #: app/assets/javascripts/app/controllers/_integration/exchange.coffee
-#: app/assets/javascripts/app/controllers/_profile/password.coffee
 #: app/assets/javascripts/app/controllers/_profile/token_access.coffee
 #: app/assets/javascripts/app/controllers/_ui_element/ticket_selector.coffee
 #: app/assets/javascripts/app/controllers/data_privacy.coffee
@@ -2484,6 +2483,10 @@ msgstr ""
 msgid "Confirm"
 msgstr ""
 
+#: app/assets/javascripts/app/controllers/widget/two_factor_configuration/modal/password_check.coffee
+msgid "Confirm Password"
+msgstr ""
+
 #: app/frontend/apps/mobile/components/CommonConfirmation/CommonConfirmation.vue
 msgid "Confirm dialog"
 msgstr ""
@@ -5282,6 +5285,7 @@ msgstr ""
 msgid "Generate Token"
 msgstr ""
 
+#: app/assets/javascripts/app/controllers/widget/two_factor_configuration/method/recovery_codes.coffee
 #: app/assets/javascripts/app/views/profile/password.jst.eco
 msgid "Generate recovery codes"
 msgstr ""
@@ -5290,6 +5294,10 @@ msgstr ""
 msgid "Generate user-based stats."
 msgstr ""
 
+#: app/assets/javascripts/app/controllers/widget/two_factor_configuration/modal/recovery_codes.coffee
+msgid "Generated Recovery Codes"
+msgstr ""
+
 #: app/assets/javascripts/app/controllers/_integration/cti.coffee
 msgid "Generic API to integrate VoIP service provider with real-time push."
 msgstr ""
@@ -8879,7 +8887,6 @@ msgstr ""
 msgid "Recovery Code"
 msgstr ""
 
-#: app/assets/javascripts/app/controllers/widget/two_factor_configuration/modal/recovery_codes.coffee
 #: app/assets/javascripts/app/lib/app_post/two_factor_methods/recovery_codes.coffee
 msgid "Recovery Codes"
 msgstr ""
@@ -8991,6 +8998,10 @@ msgstr ""
 msgid "Remove selected values"
 msgstr ""
 
+#: app/assets/javascripts/app/controllers/_profile/password.coffee
+msgid "Remove two-factor authentication"
+msgstr ""
+
 #: app/assets/javascripts/app/controllers/_plugin/keyboard_shortcuts.coffee
 msgid "Removes any hyperlink"
 msgstr ""
@@ -12253,10 +12264,6 @@ msgstr ""
 msgid "Two-factor authentication is not supported with HTTP BasicAuth."
 msgstr ""
 
-#: app/assets/javascripts/app/controllers/_profile/password.coffee
-msgid "Two-factor authentication method \"%s\" will be removed."
-msgstr ""
-
 #: app/frontend/apps/mobile/pages/login/components/LoginTwoFactor.vue
 msgid "Two-factor authentication method could not be initiated."
 msgstr ""

+ 2 - 2
spec/system/examples/authenticator_app_setup_examples.rb

@@ -17,7 +17,7 @@ end
 def setup_authenticator_app_method(user:, password_check:, expect_recovery_codes: false)
   if password_check
     in_modal do
-      expect(page).to have_text('Set up two-factor authentication: Password')
+      expect(page).to have_text('Set up two-factor authentication: Confirm Password')
 
       fill_in 'Password', with: password_check
 
@@ -43,7 +43,7 @@ def setup_authenticator_app_method(user:, password_check:, expect_recovery_codes
       stored_codes_amount    = user.two_factor_preferences.recovery_codes.configuration[:codes].count
       displayed_codes_amount = find('.two-factor-auth code').text.tr("\n", ' ').split.count
 
-      expect(page).to have_text('Set up two-factor authentication: Recovery Codes')
+      expect(page).to have_text('Generated Recovery Codes')
       expect(stored_codes_amount).to eq(displayed_codes_amount)
 
       click_button "OK, I've saved my recovery codes"

+ 2 - 2
spec/system/examples/security_keys_setup_examples.rb

@@ -37,7 +37,7 @@ end
 def setup_security_keys_method(user:, password_check:)
   in_modal do
     if password_check
-      expect(page).to have_text('Set up two-factor authentication: Password')
+      expect(page).to have_text('Set up two-factor authentication: Confirm Password')
 
       fill_in 'Password', with: user.password_plain
 
@@ -56,7 +56,7 @@ def setup_security_keys_method(user:, password_check:)
 
     click_button 'Next'
 
-    expect(page).to have_text('Set up two-factor authentication: Recovery Codes')
+    expect(page).to have_text('Generated Recovery Codes')
 
     click_button "OK, I've saved my recovery codes"
   end

+ 5 - 3
spec/system/profile/password_spec.rb

@@ -153,7 +153,9 @@ RSpec.describe 'Profile > Password', authenticated_as: :user, type: :system do
         end
 
         in_modal do
-          click_on 'Yes'
+          fill_in 'Password', with: user.password_plain
+
+          click_on 'Remove'
         end
 
         within('tr[data-two-factor-key="authenticator_app"]') do
@@ -165,7 +167,7 @@ RSpec.describe 'Profile > Password', authenticated_as: :user, type: :system do
         click '.js-generate-recovery-codes'
 
         in_modal do
-          expect(page).to have_text('Set up two-factor authentication: Password')
+          expect(page).to have_text('Generate recovery codes: Confirm Password')
 
           fill_in 'Password', with: user.password_plain
 
@@ -173,7 +175,7 @@ RSpec.describe 'Profile > Password', authenticated_as: :user, type: :system do
         end
 
         in_modal do
-          expect(page).to have_text('Set up two-factor authentication: Recovery Codes')
+          expect(page).to have_text('Generated Recovery Codes')
 
           stored_codes_amount    = user.two_factor_preferences.recovery_codes.configuration[:codes].count
           displayed_codes_amount = find('.two-factor-auth code').text.tr("\n", ' ').split.count