From f1f59cf0861adb8f753f3685ff3c82c048ed4838 Mon Sep 17 00:00:00 2001
From: Dan Brown <ssddanbrown@googlemail.com>
Date: Sun, 8 Aug 2021 14:24:44 +0100
Subject: [PATCH] Extracted text to translation files

Also aligned mfa method delete route to align with others.
---
 .../Auth/MfaBackupCodesController.php         |  2 +-
 resources/lang/en/auth.php                    | 34 ++++++++-
 resources/lang/en/common.php                  |  1 +
 resources/lang/en/settings.php                |  4 +
 .../views/mfa/backup-codes-generate.blade.php | 14 ++--
 .../views/mfa/setup-method-row.blade.php      | 30 ++++++++
 resources/views/mfa/setup.blade.php           | 73 ++-----------------
 resources/views/mfa/totp-generate.blade.php   | 22 ++----
 resources/views/mfa/verify.blade.php          | 20 ++---
 .../views/mfa/verify/backup_codes.blade.php   |  8 +-
 resources/views/mfa/verify/totp.blade.php     |  8 +-
 resources/views/users/edit.blade.php          | 10 +--
 routes/web.php                                |  2 +-
 tests/Auth/MfaConfigurationTest.php           |  4 +-
 14 files changed, 104 insertions(+), 128 deletions(-)
 create mode 100644 resources/views/mfa/setup-method-row.blade.php

diff --git a/app/Http/Controllers/Auth/MfaBackupCodesController.php b/app/Http/Controllers/Auth/MfaBackupCodesController.php
index 41c161d7c..65c809196 100644
--- a/app/Http/Controllers/Auth/MfaBackupCodesController.php
+++ b/app/Http/Controllers/Auth/MfaBackupCodesController.php
@@ -81,7 +81,7 @@ class MfaBackupCodesController extends Controller
         $loginService->reattemptLoginFor($user);
 
         if ($codeService->countCodesInSet($updatedCodes) < 5) {
-            $this->showWarningNotification('You have less than 5 backup codes remaining, Please generate and store a new set before you run out of codes to prevent being locked out of your account.');
+            $this->showWarningNotification(trans('auth.mfa_backup_codes_usage_limit_warning'));
         }
 
         return redirect()->intended();
diff --git a/resources/lang/en/auth.php b/resources/lang/en/auth.php
index 2159cfb3b..a24ededd7 100644
--- a/resources/lang/en/auth.php
+++ b/resources/lang/en/auth.php
@@ -76,6 +76,36 @@ return [
     'user_invite_success' => 'Password set, you now have access to :appName!',
 
     // Multi-factor Authentication
-    'mfa_use_totp' => 'Verify using a mobile app',
-    'mfa_use_backup_codes' => 'Verify using a backup code',
+    'mfa_setup' => 'Setup Multi-Factor Authentication',
+    'mfa_setup_desc' => 'Setup multi-factor authentication as an extra layer of security for your user account.',
+    'mfa_setup_configured' => 'Already Configured',
+    'mfa_setup_reconfigure' => 'Reconfigure',
+    'mfa_setup_remove_confirmation' => 'Are you sure you want to remove this multi-factor authentication method?',
+    'mfa_setup_action' => 'Setup',
+    'mfa_backup_codes_usage_limit_warning' => 'You have less than 5 backup codes remaining, Please generate and store a new set before you run out of codes to prevent being locked out of your account.',
+    'mfa_option_totp_title' => 'Mobile App',
+    'mfa_option_totp_desc' => 'To use multi-factor authentication you\'ll need a mobile application that supports TOTP such as Google Authenticator, Authy or Microsoft Authenticator.',
+    'mfa_option_backup_codes_title' => 'Backup Codes',
+    'mfa_option_backup_codes_desc' => 'Securely store a set of one-time-use backup codes which you can enter to verify your identity.',
+    'mfa_gen_confirm_and_enable' => 'Confirm and Enable',
+    'mfa_gen_backup_codes_title' => 'Backup Codes Setup',
+    'mfa_gen_backup_codes_desc' => 'Store the below list of codes in a safe place. When accessing the system you\'ll be able to use one of the codes as a second authentication mechanism.',
+    'mfa_gen_backup_codes_download' => 'Download Codes',
+    'mfa_gen_backup_codes_usage_warning' => 'Each code can only be used once',
+    'mfa_gen_totp_title' => 'Mobile App Setup',
+    'mfa_gen_totp_desc' => 'To use multi-factor authentication you\'ll need a mobile application that supports TOTP such as Google Authenticator, Authy or Microsoft Authenticator.',
+    'mfa_gen_totp_scan' => 'Scan the QR code below using your preferred authentication app to get started.',
+    'mfa_gen_totp_verify_setup' => 'Verify Setup',
+    'mfa_gen_totp_verify_setup_desc' => 'Verify that all is working by entering a code, generated within your authentication app, in the input box below:',
+    'mfa_gen_totp_provide_code_here' => 'Provide your app generated code here',
+    'mfa_verify_access' => 'Verify Access',
+    'mfa_verify_access_desc' => 'Your user account requires you to confirm your identity via an additional level of verification before you\'re granted access. Verify using one of your configured methods to continue.',
+    'mfa_verify_no_methods' => 'No Methods Configured',
+    'mfa_verify_no_methods_desc' => 'No multi-factor authentication methods could be found for your account. You\'ll need to set up at least one method before you gain access.',
+    'mfa_verify_use_totp' => 'Verify using a mobile app',
+    'mfa_verify_use_backup_codes' => 'Verify using a backup code',
+    'mfa_verify_backup_code' => 'Backup Code',
+    'mfa_verify_backup_code_desc' => 'Enter one of your remaining backup codes below:',
+    'mfa_verify_backup_code_enter_here' => 'Enter backup code here',
+    'mfa_verify_totp_desc' => 'Enter the code, generated using your mobile app, below:',
 ];
\ No newline at end of file
diff --git a/resources/lang/en/common.php b/resources/lang/en/common.php
index 1861869e3..f93fb034b 100644
--- a/resources/lang/en/common.php
+++ b/resources/lang/en/common.php
@@ -39,6 +39,7 @@ return [
     'reset' => 'Reset',
     'remove' => 'Remove',
     'add' => 'Add',
+    'configure' => 'Configure',
     'fullscreen' => 'Fullscreen',
     'favourite' => 'Favourite',
     'unfavourite' => 'Unfavourite',
diff --git a/resources/lang/en/settings.php b/resources/lang/en/settings.php
index d9b4854fe..87f672e4d 100755
--- a/resources/lang/en/settings.php
+++ b/resources/lang/en/settings.php
@@ -205,6 +205,10 @@ return [
     'users_api_tokens_create' => 'Create Token',
     'users_api_tokens_expires' => 'Expires',
     'users_api_tokens_docs' => 'API Documentation',
+    'users_mfa' => 'Multi-Factor Authentication',
+    'users_mfa_desc' => 'Setup multi-factor authentication as an extra layer of security for your user account.',
+    'users_mfa_x_methods' => ':count method configured|:count methods configured',
+    'users_mfa_configure' => 'Configure Methods',
 
     // API Tokens
     'user_api_token_create' => 'Create API Token',
diff --git a/resources/views/mfa/backup-codes-generate.blade.php b/resources/views/mfa/backup-codes-generate.blade.php
index 6a491fc07..279ca68a0 100644
--- a/resources/views/mfa/backup-codes-generate.blade.php
+++ b/resources/views/mfa/backup-codes-generate.blade.php
@@ -4,12 +4,8 @@
 
     <div class="container very-small py-xl">
         <div class="card content-wrap auto-height">
-            <h1 class="list-heading">Backup Codes</h1>
-            <p>
-                Store the below list of codes in a safe place.
-                When accessing the system you'll be able to use one of the codes
-                as a second authentication mechanism.
-            </p>
+            <h1 class="list-heading">{{ trans('auth.mfa_gen_backup_codes_title') }}</h1>
+            <p>{{ trans('auth.mfa_gen_backup_codes_desc') }}</p>
 
             <div class="text-center mb-xs">
                 <div class="text-bigger code-base p-m" style="column-count: 2">
@@ -20,18 +16,18 @@
             </div>
 
             <p class="text-right">
-                <a href="{{ $downloadUrl }}" download="backup-codes.txt" class="button outline small">Download Codes</a>
+                <a href="{{ $downloadUrl }}" download="backup-codes.txt" class="button outline small">{{ trans('auth.mfa_gen_backup_codes_download') }}</a>
             </p>
 
             <p class="callout warning">
-                Each code can only be used once
+                {{ trans('auth.mfa_gen_backup_codes_usage_warning') }}
             </p>
 
             <form action="{{ url('/mfa/backup_codes/confirm') }}" method="POST">
                 {{ csrf_field() }}
                 <div class="mt-s text-right">
                     <a href="{{ url('/mfa/setup') }}" class="button outline">{{ trans('common.cancel') }}</a>
-                    <button class="button">Confirm and Enable</button>
+                    <button class="button">{{ trans('auth.mfa_gen_confirm_and_enable') }}</button>
                 </div>
             </form>
         </div>
diff --git a/resources/views/mfa/setup-method-row.blade.php b/resources/views/mfa/setup-method-row.blade.php
new file mode 100644
index 000000000..e195174c1
--- /dev/null
+++ b/resources/views/mfa/setup-method-row.blade.php
@@ -0,0 +1,30 @@
+<div class="grid half gap-xl">
+    <div>
+        <div class="setting-list-label">{{ trans('auth.mfa_option_' . $method . '_title') }}</div>
+        <p class="small">
+            {{ trans('auth.mfa_option_' . $method . '_desc') }}
+        </p>
+    </div>
+    <div class="pt-m">
+        @if($userMethods->has($method))
+            <div class="text-pos">
+                @icon('check-circle')
+                {{ trans('auth.mfa_setup_configured') }}
+            </div>
+            <a href="{{ url('/mfa/' . $method . '/generate') }}" class="button outline small">{{ trans('auth.mfa_setup_reconfigure') }}</a>
+            <div component="dropdown" class="inline relative">
+                <button type="button" refs="dropdown@toggle" class="button outline small">{{ trans('common.remove') }}</button>
+                <div refs="dropdown@menu" class="dropdown-menu">
+                    <p class="text-neg small px-m mb-xs">{{ trans('auth.mfa_setup_remove_confirmation') }}</p>
+                    <form action="{{ url('/mfa/' . $method . '/remove') }}" method="post">
+                        {{ csrf_field() }}
+                        {{ method_field('delete') }}
+                        <button class="text-primary small delete">{{ trans('common.confirm') }}</button>
+                    </form>
+                </div>
+            </div>
+        @else
+            <a href="{{ url('/mfa/' . $method . '/generate') }}" class="button outline">{{ trans('auth.mfa_setup_action') }}</a>
+        @endif
+    </div>
+</div>
\ No newline at end of file
diff --git a/resources/views/mfa/setup.blade.php b/resources/views/mfa/setup.blade.php
index f670541bf..f3f290d4b 100644
--- a/resources/views/mfa/setup.blade.php
+++ b/resources/views/mfa/setup.blade.php
@@ -4,76 +4,13 @@
     <div class="container small py-xl">
 
         <div class="card content-wrap auto-height">
-            <h1 class="list-heading">Setup Multi-Factor Authentication</h1>
-            <p class="mb-none">
-                Setup multi-factor authentication as an extra layer of security
-                for your user account.
-            </p>
+            <h1 class="list-heading">{{ trans('auth.mfa_setup') }}</h1>
+            <p class="mb-none"> {{ trans('auth.mfa_setup_desc') }}</p>
 
             <div class="setting-list">
-                <div class="grid half gap-xl">
-                    <div>
-                        <div class="setting-list-label">Mobile App</div>
-                        <p class="small">
-                            To use multi-factor authentication you'll need a mobile application
-                            that supports TOTP such as Google Authenticator, Authy or Microsoft Authenticator.
-                        </p>
-                    </div>
-                    <div class="pt-m">
-                        @if($userMethods->has('totp'))
-                            <div class="text-pos">
-                                @icon('check-circle')
-                                Already configured
-                            </div>
-                            <a href="{{ url('/mfa/totp/generate') }}" class="button outline small">Reconfigure</a>
-                            <div component="dropdown" class="inline relative">
-                                <button type="button" refs="dropdown@toggle" class="button outline small">Remove</button>
-                                <div refs="dropdown@menu" class="dropdown-menu">
-                                    <p class="text-neg small px-m mb-xs">Are you sure you want to remove this multi-factor authentication method?</p>
-                                    <form action="{{ url('/mfa/remove/totp') }}" method="post">
-                                        {{ csrf_field() }}
-                                        {{ method_field('delete') }}
-                                        <button class="text-primary small delete">{{ trans('common.confirm') }}</button>
-                                    </form>
-                                </div>
-                            </div>
-                        @else
-                            <a href="{{ url('/mfa/totp/generate') }}" class="button outline">Setup</a>
-                        @endif
-                    </div>
-                </div>
-
-                <div class="grid half gap-xl">
-                    <div>
-                        <div class="setting-list-label">Backup Codes</div>
-                        <p class="small">
-                            Securely store a set of one-time-use backup codes
-                            which you can enter to verify your identity.
-                        </p>
-                    </div>
-                    <div class="pt-m">
-                        @if($userMethods->has('backup_codes'))
-                            <div class="text-pos">
-                                @icon('check-circle')
-                                Already configured
-                            </div>
-                            <a href="{{ url('/mfa/backup_codes/generate') }}" class="button outline small">Reconfigure</a>
-                            <div component="dropdown" class="inline relative">
-                                <button type="button" refs="dropdown@toggle" class="button outline small">Remove</button>
-                                <div refs="dropdown@menu" class="dropdown-menu">
-                                    <p class="text-neg small px-m mb-xs">Are you sure you want to remove this multi-factor authentication method?</p>
-                                    <form action="{{ url('/mfa/remove/backup_codes') }}" method="post">
-                                        {{ csrf_field() }}
-                                        {{ method_field('delete') }}
-                                        <button class="text-primary small delete">{{ trans('common.confirm') }}</button>
-                                    </form>
-                                </div>
-                            </div>
-                        @else
-                            <a href="{{ url('/mfa/backup_codes/generate') }}" class="button outline">Setup</a>
-                        @endif
-                    </div>
-                </div>
+                @foreach(['totp', 'backup_codes'] as $method)
+                    @include('mfa.setup-method-row', ['method' => $method])
+                @endforeach
             </div>
 
         </div>
diff --git a/resources/views/mfa/totp-generate.blade.php b/resources/views/mfa/totp-generate.blade.php
index 2ed2677d1..8c470516f 100644
--- a/resources/views/mfa/totp-generate.blade.php
+++ b/resources/views/mfa/totp-generate.blade.php
@@ -4,14 +4,9 @@
 
     <div class="container very-small py-xl">
         <div class="card content-wrap auto-height">
-            <h1 class="list-heading">Mobile App Setup</h1>
-            <p>
-                To use multi-factor authentication you'll need a mobile application
-                that supports TOTP such as Google Authenticator, Authy or Microsoft Authenticator.
-            </p>
-            <p>
-                Scan the QR code below using your preferred authentication app to get started.
-            </p>
+            <h1 class="list-heading">{{ trans('auth.mfa_gen_totp_title') }}</h1>
+            <p>{{ trans('auth.mfa_gen_totp_desc') }}</p>
+            <p>{{ trans('auth.mfa_gen_totp_scan') }}</p>
 
             <div class="text-center">
                 <div class="block inline">
@@ -19,24 +14,21 @@
                 </div>
             </div>
 
-            <h2 class="list-heading">Verify Setup</h2>
-            <p id="totp-verify-input-details" class="mb-s">
-                Verify that all is working by entering a code, generated within your
-                authentication app, in the input box below:
-            </p>
+            <h2 class="list-heading">{{ trans('auth.mfa_gen_totp_verify_setup') }}</h2>
+            <p id="totp-verify-input-details" class="mb-s">{{ trans('auth.mfa_gen_totp_verify_setup_desc') }}</p>
             <form action="{{ url('/mfa/totp/confirm') }}" method="POST">
                 {{ csrf_field() }}
                 <input type="text"
                        name="code"
                        aria-labelledby="totp-verify-input-details"
-                       placeholder="Provide your app generated code here"
+                       placeholder="{{ trans('auth.mfa_gen_totp_provide_code_here') }}"
                        class="input-fill-width {{ $errors->has('code') ? 'neg' : '' }}">
                 @if($errors->has('code'))
                     <div class="text-neg text-small px-xs">{{ $errors->first('code') }}</div>
                 @endif
                 <div class="mt-s text-right">
                     <a href="{{ url('/mfa/setup') }}" class="button outline">{{ trans('common.cancel') }}</a>
-                    <button class="button">Confirm and Enable</button>
+                    <button class="button">{{ trans('auth.mfa_gen_confirm_and_enable') }}</button>
                 </div>
             </form>
         </div>
diff --git a/resources/views/mfa/verify.blade.php b/resources/views/mfa/verify.blade.php
index 7cab2edc4..3a1905e97 100644
--- a/resources/views/mfa/verify.blade.php
+++ b/resources/views/mfa/verify.blade.php
@@ -4,26 +4,18 @@
     <div class="container very-small py-xl">
 
         <div class="card content-wrap auto-height">
-            <h1 class="list-heading">Verify Access</h1>
-            <p class="mb-none">
-                Your user account requires you to confirm your identity via an additional level
-                of verification before you're granted access.
-                Verify using one of your configured methods to continue.
-            </p>
+            <h1 class="list-heading">{{ trans('auth.mfa_verify_access') }}</h1>
+            <p class="mb-none">{{ trans('auth.mfa_verify_access_desc') }}</p>
 
             @if(!$method)
                 <hr class="my-l">
-                <h5>No Methods Configured</h5>
-                <p class="small">
-                    No multi-factor authentication methods could be found for your account.
-                    You'll need to set up at least one method before you gain access.
-                </p>
+                <h5>{{ trans('auth.mfa_verify_no_methods') }}</h5>
+                <p class="small">{{ trans('auth.mfa_verify_no_methods_desc') }}</p>
                 <div>
-                    <a href="{{ url('/mfa/setup') }}" class="button outline">Configure</a>
+                    <a href="{{ url('/mfa/setup') }}" class="button outline">{{ trans('common.configure') }}</a>
                 </div>
             @endif
 
-
             @if($method)
                 <hr class="my-l">
                 @include('mfa.verify.' . $method)
@@ -33,7 +25,7 @@
                 <hr class="my-l">
                 @foreach($otherMethods as $otherMethod)
                     <div class="text-center">
-                        <a href="{{ url("/mfa/verify?method={$otherMethod}") }}">{{ trans('auth.mfa_use_' . $otherMethod) }}</a>
+                        <a href="{{ url("/mfa/verify?method={$otherMethod}") }}">{{ trans('auth.mfa_verify_use_' . $otherMethod) }}</a>
                     </div>
                 @endforeach
             @endif
diff --git a/resources/views/mfa/verify/backup_codes.blade.php b/resources/views/mfa/verify/backup_codes.blade.php
index 7179696cb..0e5b82086 100644
--- a/resources/views/mfa/verify/backup_codes.blade.php
+++ b/resources/views/mfa/verify/backup_codes.blade.php
@@ -1,14 +1,12 @@
-<div class="setting-list-label">Backup Code</div>
+<div class="setting-list-label">{{ trans('auth.mfa_verify_backup_code') }}</div>
 
-<p class="small mb-m">
-    Enter one of your remaining backup codes below:
-</p>
+<p class="small mb-m">{{ trans('auth.mfa_verify_backup_code_desc') }}</p>
 
 <form action="{{ url('/mfa/backup_codes/verify') }}" method="post">
     {{ csrf_field() }}
     <input type="text"
            name="code"
-           placeholder="Enter backup code here"
+           placeholder="{{ trans('auth.mfa_verify_backup_code_enter_here') }}"
            class="input-fill-width {{ $errors->has('code') ? 'neg' : '' }}">
     @if($errors->has('code'))
         <div class="text-neg text-small px-xs">{{ $errors->first('code') }}</div>
diff --git a/resources/views/mfa/verify/totp.blade.php b/resources/views/mfa/verify/totp.blade.php
index fffd30352..9a861fc6c 100644
--- a/resources/views/mfa/verify/totp.blade.php
+++ b/resources/views/mfa/verify/totp.blade.php
@@ -1,14 +1,12 @@
-<div class="setting-list-label">Mobile App</div>
+<div class="setting-list-label">{{ trans('auth.mfa_option_totp_title') }}</div>
 
-<p class="small mb-m">
-    Enter the code, generated using your mobile app, below:
-</p>
+<p class="small mb-m">{{ trans('auth.mfa_verify_totp_desc') }}</p>
 
 <form action="{{ url('/mfa/totp/verify') }}" method="post">
     {{ csrf_field() }}
     <input type="text"
            name="code"
-           placeholder="Provide your app generated code here"
+           placeholder="{{ trans('auth.mfa_gen_totp_provide_code_here') }}"
            class="input-fill-width {{ $errors->has('code') ? 'neg' : '' }}">
     @if($errors->has('code'))
         <div class="text-neg text-small px-xs">{{ $errors->first('code') }}</div>
diff --git a/resources/views/users/edit.blade.php b/resources/views/users/edit.blade.php
index 2d719668f..4c733e6f6 100644
--- a/resources/views/users/edit.blade.php
+++ b/resources/views/users/edit.blade.php
@@ -64,11 +64,8 @@
         </section>
 
         <section class="card content-wrap auto-height">
-            <h2 class="list-heading">Multi-Factor Authentication</h2>
-            <p>
-                Setup multi-factor authentication as an extra layer of security
-                for your user account.
-            </p>
+            <h2 class="list-heading">{{ trans('settings.users_mfa') }}</h2>
+            <p>{{ trans('settings.users_mfa_desc') }}</p>
             <div class="grid half gap-xl v-center pb-s">
                 <div>
                     @if ($mfaMethods->count() > 0)
@@ -76,11 +73,12 @@
                     @else
                         <span class="text-neg">@icon('cancel')</span>
                     @endif
+                    {{ trans_choice('settings.users_mfa_x_methods', $mfaMethods->count()) }}
                     {{ $mfaMethods->count() }} {{ $mfaMethods->count() === 1 ? 'method' : 'methods' }} configured
                 </div>
                 <div class="text-m-right">
                     @if($user->id === user()->id)
-                        <a href="{{ url('/mfa/setup')  }}" class="button outline">Configure Methods</a>
+                        <a href="{{ url('/mfa/setup')  }}" class="button outline">{{ trans('settings.users_mfa_configure') }}</a>
                     @endif
                 </div>
             </div>
diff --git a/routes/web.php b/routes/web.php
index b6590429c..a70d0d818 100644
--- a/routes/web.php
+++ b/routes/web.php
@@ -239,7 +239,7 @@ Route::group(['middleware' => 'guest'], function() {
     Route::post('/mfa/totp/verify', 'Auth\MfaTotpController@verify');
     Route::post('/mfa/backup_codes/verify', 'Auth\MfaBackupCodesController@verify');
 });
-Route::delete('/mfa/remove/{method}', 'Auth\MfaController@remove')->middleware('auth');
+Route::delete('/mfa/{method}/remove', 'Auth\MfaController@remove')->middleware('auth');
 
 // Social auth routes
 Route::get('/login/service/{socialDriver}', 'Auth\SocialController@login');
diff --git a/tests/Auth/MfaConfigurationTest.php b/tests/Auth/MfaConfigurationTest.php
index 63a5fa4dd..bdf26fb20 100644
--- a/tests/Auth/MfaConfigurationTest.php
+++ b/tests/Auth/MfaConfigurationTest.php
@@ -153,9 +153,9 @@ class MfaConfigurationTest extends TestCase
         MfaValue::upsertWithValue($admin, MfaValue::METHOD_TOTP, 'test');
         $this->assertEquals(1, $admin->mfaValues()->count());
         $resp = $this->actingAs($admin)->get('/mfa/setup');
-        $resp->assertElementExists('form[action$="/mfa/remove/totp"]');
+        $resp->assertElementExists('form[action$="/mfa/totp/remove"]');
 
-        $resp = $this->delete("/mfa/remove/totp");
+        $resp = $this->delete("/mfa/totp/remove");
         $resp->assertRedirect("/mfa/setup");
         $resp = $this->followRedirects($resp);
         $resp->assertSee('Multi-factor method successfully removed');