images: Lebenszyklus — Veröffentlichungsgate, published_ever_at, Snapshot der veröffentlichten Fassung, Sofortlöschung, Legacy-Bereinigung, Beweiszugriff, Korrekturweg (Bildkennzeichnung Block E)
- publish()/changeStatusFromAdmin(): kein Bild aus Formular v2 ohne gültige Bestätigung (ImageRightsConfirmationRequiredException, Admin-Seite meldet es); published_ever_at an PM und Bildern; PublishedImageSnapshot (Cover + JSON mit Nachweis/Kennzeichnung) - deleteFromAdmin() und press-releases:purge-drafts löschen Bilder nie veröffentlichter Meldungen samt Original und Bestätigung sofort (E4, O1) - press-releases:backfill-published-ever (Status-Log), press-release-images:purge-inactive-legacy (E-B11, Trockenlauf Standard) - Admin-Route für Beweisoriginal und veröffentlichte Fassung nur mit Zweck, ActivityType EvidenceAccess; Architekturtest: original_path nur in vier Dateien - ImageCorrectionService + image_declaration_corrections (insert-only), withheld_at blendet das Bild öffentlich aus (publiclyVisible-Scope), Korrekturpanel auf der Admin-Seite - Systemstatus: fehlgeschlagene Herkunftsprüfungen der letzten 7 Tage Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
parent
9f44546082
commit
da167b713b
24 changed files with 1202 additions and 12 deletions
|
|
@ -0,0 +1,63 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Admin;
|
||||
|
||||
use App\Enums\ActivityType;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\PressRelease;
|
||||
use App\Models\PressReleaseImage;
|
||||
use App\Scopes\PortalScope;
|
||||
use App\Services\ActivityLog;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Symfony\Component\HttpFoundation\StreamedResponse;
|
||||
|
||||
/**
|
||||
* Einziger Zugriffsweg auf Beweisoriginal und veröffentlichte Fassung
|
||||
* (Bildkennzeichnung E.4): nur Admins, nur mit angegebenem Zweck, jeder
|
||||
* Abruf im Aktivitätsverlauf. Medienroute, Vorschau-Signaturen und API
|
||||
* kennen diese Pfade nicht. Block F verlagert das Protokoll in
|
||||
* `archive_access_log`.
|
||||
*/
|
||||
class PressReleaseImageEvidenceController extends Controller
|
||||
{
|
||||
public function __construct(private readonly ActivityLog $activityLog) {}
|
||||
|
||||
public function original(Request $request, int $id, int $image): StreamedResponse
|
||||
{
|
||||
return $this->stream($request, $id, $image, 'original');
|
||||
}
|
||||
|
||||
public function published(Request $request, int $id, int $image): StreamedResponse
|
||||
{
|
||||
return $this->stream($request, $id, $image, 'published');
|
||||
}
|
||||
|
||||
private function stream(Request $request, int $pressReleaseId, int $imageId, string $kind): StreamedResponse
|
||||
{
|
||||
$purpose = trim((string) $request->query('purpose', ''));
|
||||
|
||||
abort_if($purpose === '', 422, 'Zweck des Zugriffs fehlt (purpose).');
|
||||
|
||||
$pressRelease = PressRelease::withoutGlobalScope(PortalScope::class)->findOrFail($pressReleaseId);
|
||||
$image = PressReleaseImage::query()->withTrashed()->where('press_release_id', $pressRelease->getKey())->findOrFail($imageId);
|
||||
|
||||
$path = $kind === 'original' ? $image->original_path : $image->published_snapshot_path;
|
||||
$disk = Storage::disk($image->original_disk ?? (string) config('images.originals_disk'));
|
||||
|
||||
abort_unless(is_string($path) && $path !== '' && $disk->exists($path), 404);
|
||||
|
||||
$this->activityLog->record(
|
||||
ActivityType::EvidenceAccess,
|
||||
sprintf('%s zu Bild #%d (PM #%d) abgerufen: %s', $kind === 'original' ? 'Beweisoriginal' : 'Veröffentlichte Fassung', $image->getKey(), $pressRelease->getKey(), $purpose),
|
||||
$request->user(),
|
||||
$image,
|
||||
['kind' => $kind, 'purpose' => $purpose, 'sha256' => $kind === 'original' ? $image->original_sha256 : $image->published_snapshot_sha256],
|
||||
);
|
||||
|
||||
return $disk->response($path, basename($path), [
|
||||
'Cache-Control' => 'private, no-store',
|
||||
'X-Content-Type-Options' => 'nosniff',
|
||||
]);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue