fix: Imagick in der Betriebsüberwachung, Scanner-Anfragen an Livewire als 400, abgebrochene Alpine-Übergänge nicht mehr melden
Auf Live fehlte die PHP-Erweiterung imagick: Herkunftsprüfung und
KI-Vorab-Check der Bilder scheiterten still und ließen jedes Bild durch.
AdminSystemHealth zeigt jetzt die Zeile „PHP-Erweiterung Imagick“ (rot bei
eingeschaltetem Vorab-Check, sonst gelb).
GlitchTip server-pressekonto, Issues 38 und 39: gebaute Livewire-Anfragen
setzen gesperrte Properties (portal/language im Meldungs-Feed und in der
Suche) oder schicken Uploads an Komponenten ohne Upload. Livewire weist sie
korrekt ab; statt 500 bzw. 419 (das als „Seite abgelaufen“ gemeldet wurde)
antworten sie jetzt mit 400 und werden nicht mehr gemeldet.
Browser (Issue 18): Alpine bricht x-transition-Übergänge mit
{isFromCancelledTransition: true} ab — keine Fehlermeldung mehr.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
65086cafd2
commit
bbc2b6048f
5 changed files with 90 additions and 0 deletions
|
|
@ -238,6 +238,19 @@ class AdminSystemHealth
|
|||
: 'SESSION_SECURE_COOKIE ist aus'.($isLocal ? ' (lokal ok).' : ' — in https-Umgebungen aktivieren.'),
|
||||
];
|
||||
|
||||
// Imagick trägt Herkunftsprüfung und KI-Vorab-Check der Bilder. Fehlt
|
||||
// die Erweiterung, scheitern beide still (Bilder werden durchgelassen)
|
||||
// — so geschehen auf Live bis 08.10.2026.
|
||||
$precheckEnabled = (bool) config('images.precheck.enabled');
|
||||
$checks[] = [
|
||||
'key' => 'imagick',
|
||||
'label' => 'PHP-Erweiterung Imagick',
|
||||
'status' => $this->imagickAvailable() ? self::StatusOk : ($precheckEnabled ? self::StatusCritical : self::StatusWarn),
|
||||
'detail' => $this->imagickAvailable()
|
||||
? 'Imagick ist geladen (Herkunftsprüfung und KI-Vorab-Check der Bilder).'
|
||||
: 'Imagick fehlt — Herkunftsprüfung'.($precheckEnabled ? ' und KI-Vorab-Check' : '').' der Bilder laufen ins Leere. Auf dem Server php8.4-imagick installieren und PHP-FPM neu laden.',
|
||||
];
|
||||
|
||||
// Herkunftsprüfung der Bild-Uploads (Bildkennzeichnung E.7): Fehler
|
||||
// der letzten sieben Tage zählen; Zustand D im Formular blockiert
|
||||
// nichts, muss aber sichtbar bleiben.
|
||||
|
|
@ -341,6 +354,11 @@ class AdminSystemHealth
|
|||
return $checks;
|
||||
}
|
||||
|
||||
protected function imagickAvailable(): bool
|
||||
{
|
||||
return class_exists(\Imagick::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $queue
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -21,8 +21,11 @@ use Illuminate\Http\Request;
|
|||
use Illuminate\Support\Facades\Route;
|
||||
use Laravel\Sanctum\Http\Middleware\CheckAbilities;
|
||||
use Laravel\Sanctum\Http\Middleware\CheckForAnyAbility;
|
||||
use Livewire\Features\SupportFileUploads\MissingFileUploadsTraitException;
|
||||
use Livewire\Features\SupportLockedProperties\CannotUpdateLockedPropertyException;
|
||||
use Sentry\Laravel\Integration;
|
||||
use Symfony\Component\Console\Exception\CommandNotFoundException;
|
||||
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
||||
|
||||
return Application::configure(basePath: dirname(__DIR__))
|
||||
->withRouting(
|
||||
|
|
@ -177,4 +180,18 @@ return Application::configure(basePath: dirname(__DIR__))
|
|||
// Vertippte artisan-Befehle sind kein Anwendungsfehler (GlitchTip
|
||||
// server-pressekonto, Issue 9: „config:cachels“ auf Live).
|
||||
$exceptions->dontReport(CommandNotFoundException::class);
|
||||
|
||||
// Manipulierte Livewire-Anfragen (Scanner, die gesperrte Properties
|
||||
// setzen oder Uploads an Komponenten ohne Upload schicken) als 400
|
||||
// beantworten statt als 500 bzw. 419 — Livewire weist sie korrekt ab,
|
||||
// sie sind kein Anwendungsfehler und kein abgelaufenes Formular
|
||||
// (GlitchTip server-pressekonto, Issues 38 und 39, 08.10.2026).
|
||||
$exceptions->map(
|
||||
CannotUpdateLockedPropertyException::class,
|
||||
fn (CannotUpdateLockedPropertyException $e): BadRequestHttpException => new BadRequestHttpException('Ungültige Livewire-Anfrage.', $e),
|
||||
);
|
||||
$exceptions->map(
|
||||
MissingFileUploadsTraitException::class,
|
||||
fn (MissingFileUploadsTraitException $e): BadRequestHttpException => new BadRequestHttpException('Ungültige Livewire-Anfrage.', $e),
|
||||
);
|
||||
})->create();
|
||||
|
|
|
|||
|
|
@ -123,6 +123,12 @@ if (config?.dsn) {
|
|||
});
|
||||
|
||||
window.addEventListener('unhandledrejection', (event) => {
|
||||
// Alpine bricht laufende x-transition-Übergänge mit diesem Objekt ab
|
||||
// (GlitchTip browser-pressekonto, Issue 18) — kein Fehler.
|
||||
if (event.reason?.isFromCancelledTransition === true) {
|
||||
return;
|
||||
}
|
||||
|
||||
capture(rejectionToError(event.reason));
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -124,3 +124,28 @@ test('snapshot flags pending media privatization', function () {
|
|||
expect($checks['media_privatization']['status'])->toBe('warn')
|
||||
->and($checks['media_privatization']['detail'])->toContain('1');
|
||||
});
|
||||
|
||||
test('snapshot flags a missing imagick extension', function (bool $precheckEnabled, string $status) {
|
||||
config()->set('images.precheck.enabled', $precheckEnabled);
|
||||
app()->bind(AdminSystemHealth::class, fn () => new class extends AdminSystemHealth
|
||||
{
|
||||
protected function imagickAvailable(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
$checks = collect(app(AdminSystemHealth::class)->snapshot()['checks'])->keyBy('key');
|
||||
|
||||
expect($checks['imagick']['status'])->toBe($status)
|
||||
->and($checks['imagick']['detail'])->toContain('php8.4-imagick');
|
||||
})->with([
|
||||
'precheck off' => [false, 'warn'],
|
||||
'precheck on' => [true, 'critical'],
|
||||
]);
|
||||
|
||||
test('snapshot reports imagick as ok when it is loaded', function () {
|
||||
$checks = collect(app(AdminSystemHealth::class)->snapshot()['checks'])->keyBy('key');
|
||||
|
||||
expect($checks['imagick']['status'])->toBe(class_exists(Imagick::class) ? 'ok' : 'warn');
|
||||
});
|
||||
|
|
|
|||
|
|
@ -2,7 +2,10 @@
|
|||
|
||||
use App\Models\User;
|
||||
use App\Support\Monitoring\ErrorReportScrubber;
|
||||
use Illuminate\Contracts\Debug\ExceptionHandler;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use Livewire\Features\SupportFileUploads\MissingFileUploadsTraitException;
|
||||
use Livewire\Features\SupportLockedProperties\CannotUpdateLockedPropertyException;
|
||||
use Sentry\Event;
|
||||
use Sentry\ExceptionDataBag;
|
||||
use Sentry\SentrySdk;
|
||||
|
|
@ -44,6 +47,27 @@ test('a mistyped artisan command is not reported', function () {
|
|||
expect($glitchTip->events)->toBe([]);
|
||||
});
|
||||
|
||||
test('tampered livewire requests are answered with 400 and not reported', function (Closure $makeException) {
|
||||
$glitchTip = FakeGlitchTip::install();
|
||||
$exception = $makeException();
|
||||
|
||||
report($exception);
|
||||
|
||||
$response = app(ExceptionHandler::class)->render(request(), $exception);
|
||||
|
||||
expect($glitchTip->events)->toBe([])
|
||||
->and($response->getStatusCode())->toBe(400);
|
||||
})->with([
|
||||
'locked property' => fn () => new CannotUpdateLockedPropertyException('portal'),
|
||||
'upload without trait' => fn () => new MissingFileUploadsTraitException(new class
|
||||
{
|
||||
public function getName(): string
|
||||
{
|
||||
return 'web.press-release-feed';
|
||||
}
|
||||
}),
|
||||
]);
|
||||
|
||||
test('request data loses tokens, signatures and bodies', function () {
|
||||
$scrubbed = ErrorReportScrubber::scrubRequest([
|
||||
'url' => 'https://pressekonto.test/newsroom/claim/5?signature=abc123&expires=1700000000&src=mail_publish',
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue