156 lines
5.8 KiB
PHP
156 lines
5.8 KiB
PHP
<?php
|
|
|
|
namespace Tests\Feature;
|
|
|
|
use App\Livewire\Auth\ForgotPassword;
|
|
use App\Livewire\Settings\Security;
|
|
use App\Models\User;
|
|
use Illuminate\Auth\Notifications\ResetPassword as ResetPasswordNotification;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Illuminate\Support\Facades\Hash;
|
|
use Illuminate\Support\Facades\Notification;
|
|
use Livewire\Livewire;
|
|
use PragmaRX\Google2FAQRCode\Google2FA;
|
|
use Tests\TestCase;
|
|
|
|
/**
|
|
* The forgot-password screen is mail-aware: with SMTP configured the e-mail reset link
|
|
* is the default path (with a secondary 2FA-fallback toggle); without SMTP only the
|
|
* inline 2FA-proof reset is shown. The public screen never advertises clusev:reset-admin
|
|
* — that last-resort recovery note lives in Settings → Security.
|
|
*/
|
|
class ForgotPasswordSmtpAwareTest extends TestCase
|
|
{
|
|
use RefreshDatabase;
|
|
|
|
// ── Token expiry ─────────────────────────────────────────────────────
|
|
public function test_reset_token_expires_in_15_minutes(): void
|
|
{
|
|
$this->assertSame(15, config('auth.passwords.users.expire'));
|
|
}
|
|
|
|
// ── SMTP configured: e-mail link is the default ──────────────────────
|
|
public function test_smtp_on_shows_send_link_button_and_hides_code_form_by_default(): void
|
|
{
|
|
config(['mail.default' => 'smtp']);
|
|
|
|
Livewire::test(ForgotPassword::class)
|
|
->assertSee(__('auth.forgot_send_email'))
|
|
->assertSee(__('auth.forgot_use_code_toggle'))
|
|
// the inline 2FA-proof form (new-password field) is hidden by default
|
|
->assertDontSee(__('auth.new_password'));
|
|
}
|
|
|
|
public function test_smtp_on_subtitle_advertises_the_email_link(): void
|
|
{
|
|
config(['mail.default' => 'smtp']);
|
|
|
|
Livewire::test(ForgotPassword::class)
|
|
->assertSee(__('auth.forgot_subtitle_mail'));
|
|
}
|
|
|
|
public function test_smtp_on_send_link_dispatches_reset_notification(): void
|
|
{
|
|
config(['mail.default' => 'smtp']);
|
|
Notification::fake();
|
|
$user = User::factory()->create(['email' => 'admin@clusev.local']);
|
|
|
|
Livewire::test(ForgotPassword::class)
|
|
->set('email', 'admin@clusev.local')
|
|
->call('sendResetLink')
|
|
->assertHasNoErrors();
|
|
|
|
Notification::assertSentTo($user, ResetPasswordNotification::class);
|
|
}
|
|
|
|
public function test_toggle_reveals_the_2fa_code_form(): void
|
|
{
|
|
config(['mail.default' => 'smtp']);
|
|
|
|
Livewire::test(ForgotPassword::class)
|
|
->assertDontSee(__('auth.new_password'))
|
|
->set('showCodeReset', true)
|
|
->assertSee(__('auth.new_password'))
|
|
->assertSee(__('auth.forgot_code'));
|
|
}
|
|
|
|
public function test_2fa_reset_still_works_with_smtp_on_via_toggle(): void
|
|
{
|
|
config(['mail.default' => 'smtp']);
|
|
$user = User::factory()->create([
|
|
'email' => 'admin@clusev.local',
|
|
'two_factor_secret' => (new Google2FA)->generateSecretKey(),
|
|
'two_factor_confirmed_at' => now(),
|
|
]);
|
|
$otp = (new Google2FA)->getCurrentOtp($user->two_factor_secret);
|
|
|
|
Livewire::test(ForgotPassword::class)
|
|
->set('showCodeReset', true)
|
|
->set('email', $user->email)->set('code', $otp)
|
|
->set('password', 'NewPassw0rd123')->set('password_confirmation', 'NewPassw0rd123')
|
|
->call('resetPassword')->assertHasNoErrors();
|
|
|
|
$this->assertTrue(Hash::check('NewPassw0rd123', $user->fresh()->password));
|
|
}
|
|
|
|
// ── No SMTP: inline 2FA-proof reset only ─────────────────────────────
|
|
public function test_smtp_off_shows_inline_2fa_form_and_no_send_link(): void
|
|
{
|
|
config(['mail.default' => 'log']);
|
|
|
|
Livewire::test(ForgotPassword::class)
|
|
->assertSee(__('auth.new_password'))
|
|
->assertSee(__('auth.forgot_code'))
|
|
->assertDontSee(__('auth.forgot_send_email'));
|
|
}
|
|
|
|
public function test_smtp_off_subtitle_keeps_the_2fa_copy(): void
|
|
{
|
|
config(['mail.default' => 'log']);
|
|
|
|
Livewire::test(ForgotPassword::class)
|
|
->assertSee(__('auth.forgot_subtitle'));
|
|
}
|
|
|
|
public function test_smtp_off_resets_with_a_valid_totp(): void
|
|
{
|
|
config(['mail.default' => 'log']);
|
|
$user = User::factory()->create([
|
|
'email' => 'admin@clusev.local',
|
|
'two_factor_secret' => (new Google2FA)->generateSecretKey(),
|
|
'two_factor_confirmed_at' => now(),
|
|
]);
|
|
$otp = (new Google2FA)->getCurrentOtp($user->two_factor_secret);
|
|
|
|
Livewire::test(ForgotPassword::class)
|
|
->set('email', $user->email)->set('code', $otp)
|
|
->set('password', 'NewPassw0rd123')->set('password_confirmation', 'NewPassw0rd123')
|
|
->call('resetPassword')->assertHasNoErrors();
|
|
|
|
$this->assertTrue(Hash::check('NewPassw0rd123', $user->fresh()->password));
|
|
}
|
|
|
|
// ── clusev:reset-admin recovery note placement ───────────────────────
|
|
public function test_public_forgot_view_does_not_advertise_reset_admin_command(): void
|
|
{
|
|
config(['mail.default' => 'log']);
|
|
|
|
Livewire::test(ForgotPassword::class)
|
|
->assertDontSee('clusev:reset-admin');
|
|
|
|
config(['mail.default' => 'smtp']);
|
|
|
|
Livewire::test(ForgotPassword::class)
|
|
->assertDontSee('clusev:reset-admin');
|
|
}
|
|
|
|
public function test_settings_security_shows_the_recovery_note_with_the_command(): void
|
|
{
|
|
$user = User::factory()->create();
|
|
|
|
Livewire::actingAs($user)->test(Security::class)
|
|
->assertSee(__('settings.recovery_note'))
|
|
->assertSee('clusev:reset-admin');
|
|
}
|
|
}
|