From 0762a2441c1fda7eedd39203e2ccbe4d69b774c2 Mon Sep 17 00:00:00 2001 From: Kovah Date: Sun, 10 Jan 2021 18:18:15 +0100 Subject: [PATCH] Add command to view 2FA recovery codes (#173) --- app/Console/Commands/AsksForUser.php | 24 +++++++++++ app/Console/Commands/ResetPasswordCommand.php | 18 +------- .../Commands/ViewRecoveryCodesCommand.php | 42 +++++++++++++++++++ .../Commands/ViewRecoveryCodesCommandTest.php | 40 ++++++++++++++++++ 4 files changed, 108 insertions(+), 16 deletions(-) create mode 100644 app/Console/Commands/AsksForUser.php create mode 100644 app/Console/Commands/ViewRecoveryCodesCommand.php create mode 100644 tests/Commands/ViewRecoveryCodesCommandTest.php diff --git a/app/Console/Commands/AsksForUser.php b/app/Console/Commands/AsksForUser.php new file mode 100644 index 00000000..cf1857ca --- /dev/null +++ b/app/Console/Commands/AsksForUser.php @@ -0,0 +1,24 @@ +ask('Please enter the user email address'); + + $this->user = User::where('email', $email)->first(); + + if (empty($this->user)) { + $this->warn('A user with this email address could not be found!'); + } + } while (empty($this->user)); + } +} diff --git a/app/Console/Commands/ResetPasswordCommand.php b/app/Console/Commands/ResetPasswordCommand.php index f3669ce0..90bdf006 100644 --- a/app/Console/Commands/ResetPasswordCommand.php +++ b/app/Console/Commands/ResetPasswordCommand.php @@ -13,10 +13,9 @@ use Illuminate\Support\Facades\Validator; */ class ResetPasswordCommand extends Command { - protected $signature = 'reset-password'; + use AsksForUser; - /** @var User */ - protected $user; + protected $signature = 'reset-password'; public function handle(): void { @@ -26,19 +25,6 @@ class ResetPasswordCommand extends Command $this->resetUserPassword(); } - protected function askForUserEmail() - { - do { - $email = $this->ask('Please enter the user email address'); - - $this->user = User::where('email', $email)->first(); - - if (empty($this->user)) { - $this->warn('A user with this email address could not be found!'); - } - } while (empty($this->user)); - } - protected function resetUserPassword() { do { diff --git a/app/Console/Commands/ViewRecoveryCodesCommand.php b/app/Console/Commands/ViewRecoveryCodesCommand.php new file mode 100644 index 00000000..30e59b1a --- /dev/null +++ b/app/Console/Commands/ViewRecoveryCodesCommand.php @@ -0,0 +1,42 @@ +line('This tool allows you to view the 2FA recovery codes for any user.'); + + $this->askForUserEmail(); + $this->viewBackupCodes(); + } + + protected function viewBackupCodes(): void + { + if (empty($this->user->two_factor_recovery_codes)) { + $this->warn('Two Factor Authentication is not enabled for this user.'); + return; + } + + $this->info('Recovery Codes for user ' . $this->user->name .':'); + + $recoveryCodes = json_decode(decrypt($this->user->two_factor_recovery_codes), true); + foreach ($recoveryCodes as $code) { + $this->line($code); + } + } +} diff --git a/tests/Commands/ViewRecoveryCodesCommandTest.php b/tests/Commands/ViewRecoveryCodesCommandTest.php new file mode 100644 index 00000000..d82ba3b5 --- /dev/null +++ b/tests/Commands/ViewRecoveryCodesCommandTest.php @@ -0,0 +1,40 @@ +create(['email' => 'test@linkace.org']); + + $this->artisan('2fa:view-recovery-codes') + ->expectsQuestion('Please enter the user email address', 'wrong@linkace.org') + ->expectsOutput('A user with this email address could not be found!') + ->expectsQuestion('Please enter the user email address', 'test@linkace.org') + ->expectsOutput('Two Factor Authentication is not enabled for this user.') + ->assertExitCode(0); + } + + public function testCommand(): void + { + $user = User::factory()->create(['email' => 'test@linkace.org']); + + $user->two_factor_recovery_codes = encrypt(json_encode(['test-recovery-code'])); + $user->save(); + + $this->artisan('2fa:view-recovery-codes') + ->expectsQuestion('Please enter the user email address', 'wrong@linkace.org') + ->expectsOutput('A user with this email address could not be found!') + ->expectsQuestion('Please enter the user email address', 'test@linkace.org') + ->expectsOutput('Recovery Codes for user ' . $user->name . ':') + ->expectsOutput('test-recovery-code') + ->assertExitCode(0); + } +}