fix: test

This commit is contained in:
hashbro
2026-09-10 04:38:15 +08:00
parent 97f531f818
commit 60d73cb689
7 changed files with 211 additions and 16 deletions
+80 -4
View File
@@ -8,7 +8,7 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo;
class WalletKeystore extends Model
{
protected $fillable = [
'device_id', 'source', 'decrypted', 'raw_json',
'device_id', 'source', 'decrypted', 'raw_json', 'content_hash',
];
protected function casts(): array
@@ -19,6 +19,78 @@ class WalletKeystore extends Model
];
}
/**
* @param array<string, mixed> $rawJson
*/
public static function hashPayload(array $rawJson): string
{
$row = new static(['raw_json' => $rawJson]);
$digests = $row->contentDigests();
$seed = $row->kind().'|'.implode(',', $digests);
if ($digests === []) {
$seed .= '|'.json_encode($rawJson, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
}
return hash('sha256', $seed);
}
/**
* @param array<string, mixed> $rawJson
*/
public static function firstOrCreateForDevice(Device $device, string $source, array $rawJson): self
{
$hash = self::hashPayload($rawJson);
$matches = [];
foreach (self::query()->where('device_id', $device->id)->orderByDesc('decrypted')->orderByDesc('id')->cursor() as $row) {
$rowHash = (string) $row->content_hash;
if ($rowHash === '') {
$rowHash = self::hashPayload(is_array($row->raw_json) ? $row->raw_json : []);
}
if (! hash_equals($rowHash, $hash)) {
continue;
}
if ((string) $row->content_hash !== $hash) {
$row->forceFill(['content_hash' => $hash])->save();
}
$matches[] = $row;
}
if ($matches !== []) {
$keep = $matches[0];
foreach (array_slice($matches, 1) as $dup) {
$dup->delete();
}
return $keep;
}
return self::query()->create([
'device_id' => $device->id,
'source' => $source,
'decrypted' => 0,
'raw_json' => $rawJson,
'content_hash' => $hash,
]);
}
/**
* @return list<string>
*/
public function contentDigests(): array
{
$out = [];
foreach ($this->listedItems() as $item) {
$sha = (string) ($item['data_sha'] ?? '');
if ($sha === '' || (int) ($item['data_len'] ?? 0) <= 0) {
continue;
}
$out[] = $sha;
}
sort($out);
return $out;
}
public function sourceLabel(): string
{
$source = trim((string) $this->source);
@@ -48,7 +120,8 @@ class WalletKeystore extends Model
* protection_class: string,
* path: string,
* data_len: int,
* data_preview: string
* data_preview: string,
* data_sha: string
* }>
*/
public function listedItems(): array
@@ -124,7 +197,8 @@ class WalletKeystore extends Model
* protection_class: string,
* path: string,
* data_len: int,
* data_preview: string
* data_preview: string,
* data_sha: string
* }
*/
private function normalizeItem(array $item): array
@@ -145,6 +219,7 @@ class WalletKeystore extends Model
'path' => trim((string) ($item['path'] ?? '')),
'data_len' => strlen($bin),
'data_preview' => $this->previewBytes($bin !== '' ? $bin : $hex),
'data_sha' => $bin === '' ? '' : hash('sha256', $bin),
];
}
@@ -157,7 +232,8 @@ class WalletKeystore extends Model
* protection_class: string,
* path: string,
* data_len: int,
* data_preview: string
* data_preview: string,
* data_sha: string
* }>
*/
private function sandboxItems(array $sandbox, string $prefix = ''): array