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');