- Galerien sind nun eine Entität - es kann mehrere geben

- Neues Sparkbooth-Upload-Feature: Endpoint /api/sparkbooth/upload (Token-basiert pro Galerie), Controller Api/SparkboothUploadController, Migration 2026_01_21_000001_add_upload_fields_to_galleries_table.php mit Upload-Flags/Token/Expiry;
    Galerie-Modell und Factory/Seeder entsprechend erweitert.
  - Filament: Neue Setup-Seite SparkboothSetup (mit View) zur schnellen Galerie- und Token-Erstellung inkl. QR/Endpoint/Snippet;
    Galerie-Link-Views nutzen jetzt simple-qrcode (Composer-Dependency hinzugefügt) und bieten PNG-Download.
  - Galerie-Tabelle: Slug/Pfad-Spalten entfernt, Action „Link-Details“ mit Modal; Created-at-Spalte hinzugefügt.
  - Zugriffshärtung: Galerie-IDs in API (ImageController, Download/Print) geprüft; GalleryAccess/Middleware + Gallery-Modell/Slug-UUID
    eingeführt; GalleryAccess-Inertia-Seite.
  - UI/UX: LoadingSpinner/StyledImageDisplay verbessert, Delete-Confirm, Übersetzungen ergänzt.
This commit is contained in:
2025-12-04 07:52:50 +01:00
parent 52dc61ca16
commit f5da8ed877
49 changed files with 2243 additions and 165 deletions

View File

@@ -0,0 +1,63 @@
<?php
namespace Tests\Feature;
use App\Models\Gallery;
use Carbon\Carbon;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Hash;
use Tests\TestCase;
class GalleryAccessTest extends TestCase
{
use DatabaseTransactions;
protected function setUp(): void
{
parent::setUp();
Artisan::call('migrate');
}
public function test_redirects_to_access_page_when_password_is_required(): void
{
$gallery = Gallery::factory()->create([
'require_password' => true,
'password_hash' => Hash::make('secret123'),
'expires_at' => null,
'access_duration_minutes' => null,
]);
$response = $this->get(route('gallery.show', $gallery));
$response->assertRedirect(route('gallery.access.show', $gallery));
}
public function test_allows_access_after_correct_password(): void
{
$gallery = Gallery::factory()->create([
'require_password' => true,
'password_hash' => Hash::make('secret123'),
'expires_at' => null,
'access_duration_minutes' => null,
]);
$this->post(route('gallery.access.store', $gallery), ['password' => 'secret123'])
->assertRedirect(route('gallery.show', $gallery));
$this->get(route('gallery.show', $gallery))->assertOk();
$this->getJson('/api/images?gallery='.$gallery->slug)->assertOk();
}
public function test_denies_access_when_gallery_expired(): void
{
$gallery = Gallery::factory()->create([
'expires_at' => Carbon::now()->subMinute(),
'require_password' => false,
'access_duration_minutes' => null,
'password_hash' => null,
]);
$this->get(route('gallery.show', $gallery))->assertRedirect(route('gallery.access.show', $gallery));
$this->getJson('/api/images?gallery='.$gallery->slug)->assertForbidden();
}
}