Files
moonwell-web/tests/Feature/LauncherManifestFeatureTest.php

73 lines
2.8 KiB
PHP

<?php
namespace Tests\Feature;
use App\Http\Controllers\Api\LauncherController;
use Illuminate\Support\Facades\Storage;
use Tests\TestCase;
class LauncherManifestFeatureTest extends TestCase
{
protected function setUp(): void
{
parent::setUp();
Storage::fake('launcher-test');
config([
'moonwell.launcher.disk' => 'launcher-test',
'moonwell.launcher.base_path' => 'World of Warcraft 1.12.1',
'moonwell.launcher.manifest_key' => 'manifest-1.12.1.json',
]);
Storage::disk('launcher-test')->buildTemporaryUrlsUsing(
fn ($path) => 'https://download.example/'.rawurlencode($path),
);
}
public function test_download_resolves_the_file_from_the_active_release(): void
{
$key = 'World of Warcraft 1.12.1/releases/build-a/MoonWell.exe';
$this->putManifest([['path' => 'MoonWell.exe', 'objectKey' => $key]]);
Storage::disk('launcher-test')->put($key, 'player binary');
$response = app(LauncherController::class)->download('MoonWell.exe');
$this->assertSame(200, $response->getStatusCode());
$this->assertSame('https://download.example/'.rawurlencode($key), $response->getData(true)['url']);
}
public function test_legacy_manifest_without_object_keys_still_works(): void
{
$key = 'World of Warcraft 1.12.1/Data/dbc.MPQ';
$this->putManifest([['path' => 'Data/dbc.MPQ']]);
Storage::disk('launcher-test')->put($key, 'vanilla data');
$response = app(LauncherController::class)->download('Data/dbc.MPQ');
$this->assertSame(200, $response->getStatusCode());
$this->assertSame('https://download.example/'.rawurlencode($key), $response->getData(true)['url']);
}
public function test_unlisted_objects_and_path_traversal_cannot_be_downloaded(): void
{
$this->putManifest([]);
Storage::disk('launcher-test')->put('World of Warcraft 1.12.1/secret.txt', 'secret');
$controller = app(LauncherController::class);
$this->assertSame(404, $controller->download('secret.txt')->getStatusCode());
foreach (['../secret.txt', '/secret.txt', 'Data/../secret.txt', 'Data\\secret.txt', 'C:/secret.txt'] as $path) {
$this->assertSame(422, $controller->download($path)->getStatusCode());
}
}
public function test_manifest_cannot_reference_an_object_outside_the_client_prefix(): void
{
$this->putManifest([['path' => 'MoonWell.exe', 'objectKey' => 'another-project/secret.txt']]);
$this->assertSame(500, app(LauncherController::class)->download('MoonWell.exe')->getStatusCode());
}
private function putManifest(array $files): void
{
Storage::disk('launcher-test')->put('manifest-1.12.1.json', json_encode(['files' => $files]));
}
}