134 lines
3.5 KiB
PHP
134 lines
3.5 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
use App\Models\Artwork;
|
|
use App\Models\User;
|
|
use Illuminate\Support\Facades\File;
|
|
|
|
beforeEach(function () {
|
|
$root = storage_path('framework/testing/artwork-downloads');
|
|
config(['uploads.storage_root' => $root]);
|
|
|
|
if (File::exists($root)) {
|
|
File::deleteDirectory($root);
|
|
}
|
|
|
|
File::makeDirectory($root, 0755, true);
|
|
});
|
|
|
|
afterEach(function () {
|
|
$root = storage_path('framework/testing/artwork-downloads');
|
|
if (File::exists($root)) {
|
|
File::deleteDirectory($root);
|
|
}
|
|
});
|
|
|
|
function makeOriginalFile(string $hash, string $ext, string $content = 'test-image-content'): string
|
|
{
|
|
$root = rtrim((string) config('uploads.storage_root'), DIRECTORY_SEPARATOR);
|
|
$firstDir = substr($hash, 0, 2);
|
|
$secondDir = substr($hash, 2, 2);
|
|
$dir = $root . DIRECTORY_SEPARATOR . 'original' . DIRECTORY_SEPARATOR . $firstDir . DIRECTORY_SEPARATOR . $secondDir;
|
|
|
|
File::makeDirectory($dir, 0755, true, true);
|
|
|
|
$path = $dir . DIRECTORY_SEPARATOR . $hash . '.' . $ext;
|
|
File::put($path, $content);
|
|
|
|
return $path;
|
|
}
|
|
|
|
it('downloads an existing artwork file', function () {
|
|
$hash = 'a9f3e6c1b8';
|
|
$ext = 'png';
|
|
makeOriginalFile($hash, $ext);
|
|
|
|
$artwork = Artwork::factory()->create([
|
|
'file_name' => 'Sky Sunset',
|
|
'hash' => $hash,
|
|
'file_ext' => $ext,
|
|
]);
|
|
|
|
$response = $this->get("/download/artwork/{$artwork->id}");
|
|
|
|
$response->assertOk();
|
|
$response->assertDownload('Sky Sunset.png');
|
|
});
|
|
|
|
it('forces the download filename using file_name and extension', function () {
|
|
$hash = 'b7c4d1e2f3';
|
|
$ext = 'jpg';
|
|
makeOriginalFile($hash, $ext);
|
|
|
|
$artwork = Artwork::factory()->create([
|
|
'file_name' => 'My Original Name',
|
|
'hash' => $hash,
|
|
'file_ext' => $ext,
|
|
]);
|
|
|
|
$response = $this->get("/download/artwork/{$artwork->id}");
|
|
|
|
$response->assertOk();
|
|
$response->assertDownload('My Original Name.jpg');
|
|
});
|
|
|
|
it('returns 404 for a missing artwork', function () {
|
|
$this->get('/download/artwork/999999')->assertNotFound();
|
|
});
|
|
|
|
it('returns 404 when the original file is missing', function () {
|
|
$artwork = Artwork::factory()->create([
|
|
'hash' => 'c1d2e3f4a5',
|
|
'file_ext' => 'webp',
|
|
]);
|
|
|
|
$this->get("/download/artwork/{$artwork->id}")->assertNotFound();
|
|
});
|
|
|
|
it('logs download metadata with user and request context', function () {
|
|
$hash = 'd4e5f6a7b8';
|
|
$ext = 'gif';
|
|
makeOriginalFile($hash, $ext);
|
|
|
|
$user = User::factory()->create();
|
|
$artwork = Artwork::factory()->create([
|
|
'hash' => $hash,
|
|
'file_ext' => $ext,
|
|
]);
|
|
|
|
$this->actingAs($user)
|
|
->withHeaders([
|
|
'User-Agent' => 'SkinbaseTestAgent/1.0',
|
|
'Referer' => 'https://example.test/art/' . $artwork->id,
|
|
])
|
|
->get("/download/artwork/{$artwork->id}")
|
|
->assertOk();
|
|
|
|
$this->assertDatabaseHas('artwork_downloads', [
|
|
'artwork_id' => $artwork->id,
|
|
'user_id' => $user->id,
|
|
'ip_address' => '127.0.0.1',
|
|
'user_agent' => 'SkinbaseTestAgent/1.0',
|
|
'referer' => 'https://example.test/art/' . $artwork->id,
|
|
]);
|
|
});
|
|
|
|
it('logs guest download with null user_id', function () {
|
|
$hash = 'e1f2a3b4c5';
|
|
$ext = 'png';
|
|
makeOriginalFile($hash, $ext);
|
|
|
|
$artwork = Artwork::factory()->create([
|
|
'hash' => $hash,
|
|
'file_ext' => $ext,
|
|
]);
|
|
|
|
$this->get("/download/artwork/{$artwork->id}")->assertOk();
|
|
|
|
$this->assertDatabaseHas('artwork_downloads', [
|
|
'artwork_id' => $artwork->id,
|
|
'user_id' => null,
|
|
]);
|
|
});
|