Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions class-two-factor-core.php
Original file line number Diff line number Diff line change
Expand Up @@ -2128,7 +2128,9 @@ public static function user_two_factor_options( $user ) {
self::add_error(
new WP_Error(
'two_factor_suggest_backup',
__( 'To prevent being locked out of your account, consider enabling a backup method like Recovery Codes in case you lose access to your primary authentication method.', 'two-factor' ),
isset( $providers['Two_Factor_Backup_Codes'] )
? __( 'To prevent being locked out of your account, consider enabling a backup method like Recovery Codes in case you lose access to your primary authentication method.', 'two-factor' )
: __( 'To prevent being locked out of your account, consider enabling an additional two-factor method in case you lose access to your primary authentication method.', 'two-factor' ),
array(
'type' => 'warning',
)
Expand Down Expand Up @@ -2238,7 +2240,13 @@ private static function render_user_providers_form( $user, $providers ) {

?>
<p>
<?php esc_html_e( 'Configure a primary two-factor method along with a backup method, such as Recovery Codes, to avoid being locked out if you lose access to your primary method. Methods marked as recommended are more secure and easier to use.', 'two-factor' ); ?>
<?php
echo esc_html(
isset( $providers['Two_Factor_Backup_Codes'] )
? __( 'Configure a primary two-factor method along with a backup method, such as Recovery Codes, to avoid being locked out if you lose access to your primary method. Methods marked as recommended are more secure and easier to use.', 'two-factor' )
: __( 'Configure a primary two-factor method along with an additional two-factor method to avoid being locked out if you lose access to your primary method. Methods marked as recommended are more secure and easier to use.', 'two-factor' )
);
?>
</p>

<?php if ( function_exists( 'wp_is_application_passwords_available_for_user' ) && wp_is_application_passwords_available_for_user( $user ) ) : ?>
Expand Down
89 changes: 89 additions & 0 deletions tests/class-two-factor-core.php
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,30 @@ private function do_redirect_callable( $callback ) {
return $intercepted_url;
}

/**
* Reset stored profile errors between tests.
*/
private function reset_profile_errors() {
$reflection = new ReflectionClass( Two_Factor_Core::class );
$prop = $reflection->getProperty( 'profile_errors' );
$prop->setAccessible( true );
$prop->setValue( null, array() );
}

/**
* Render the user two-factor settings UI and return the markup.
*
* @param WP_User $user User instance.
* @return string
*/
private function render_user_two_factor_options( WP_User $user ) {
$this->reset_profile_errors();

ob_start();
Two_Factor_Core::user_two_factor_options( $user );
return ob_get_clean();
}

/**
* Verify adding hooks.
*
Expand Down Expand Up @@ -2157,6 +2181,71 @@ public function test_get_supported_providers_for_user() {
$this->assertArrayHasKey( 'Two_Factor_Totp', $providers, 'TOTP provider is supported by default' );
}

/**
* Test user_two_factor_options output when backup codes are available.
*
* @covers Two_Factor_Core::user_two_factor_options
*/
public function test_user_two_factor_options_mentions_recovery_codes_when_backup_codes_are_available() {
$user = self::factory()->user->create_and_get();

Two_Factor_Core::enable_provider_for_user( $user->ID, 'Two_Factor_Email' );

try {
$output = $this->render_user_two_factor_options( $user );

$this->assertStringContainsString(
'consider enabling a backup method like Recovery Codes',
$output
);
$this->assertStringContainsString(
'Configure a primary two-factor method along with a backup method, such as Recovery Codes',
$output
);
$this->assertStringNotContainsString(
'consider enabling an additional two-factor method',
$output
);
} finally {
$this->reset_profile_errors();
}
}

/**
* Test user_two_factor_options output when backup codes are filtered out.
*
* @covers Two_Factor_Core::user_two_factor_options
*/
public function test_user_two_factor_options_uses_generic_wording_when_backup_codes_are_filtered_out() {
$filter = static function ( $providers ) {
unset( $providers['Two_Factor_Backup_Codes'] );
return $providers;
};

add_filter( 'two_factor_providers', $filter );

try {
$user = self::factory()->user->create_and_get();

Two_Factor_Core::enable_provider_for_user( $user->ID, 'Two_Factor_Email' );

$output = $this->render_user_two_factor_options( $user );

$this->assertStringContainsString(
'consider enabling an additional two-factor method',
$output
);
$this->assertStringContainsString(
'Configure a primary two-factor method along with an additional two-factor method',
$output
);
$this->assertStringNotContainsString( 'Recovery Codes', $output );
} finally {
remove_filter( 'two_factor_providers', $filter );
$this->reset_profile_errors();
}
}

/**
* Test is_user_using_two_factor with enabled provider.
*
Expand Down
Loading