Fix tenant event form package selector so it no longer renders empty-value options, handles loading/empty
states, and pulls data from the authenticated /api/v1/tenant/packages endpoint.
(resources/js/admin/pages/EventFormPage.tsx, resources/js/admin/api.ts)
- Harden tenant-admin auth flow: prevent PKCE state loss, scope out StrictMode double-processing, add SPA
routes for /event-admin/login and /event-admin/logout, and tighten token/session clearing semantics (resources/js/admin/auth/{context,tokens}.tsx, resources/js/admin/pages/{AuthCallbackPage,LogoutPage}.tsx,
resources/js/admin/router.tsx, routes/web.php)
This commit is contained in:
85
app/Jobs/ProcessPhotoSecurityScan.php
Normal file
85
app/Jobs/ProcessPhotoSecurityScan.php
Normal file
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
namespace App\Jobs;
|
||||
|
||||
use App\Models\EventMediaAsset;
|
||||
use App\Models\Photo;
|
||||
use App\Services\Security\PhotoSecurityScanner;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class ProcessPhotoSecurityScan implements ShouldQueue
|
||||
{
|
||||
use Dispatchable;
|
||||
use InteractsWithQueue;
|
||||
use Queueable;
|
||||
use SerializesModels;
|
||||
|
||||
public function __construct(public int $photoId)
|
||||
{
|
||||
$this->queue = config('security.queue.name', 'default');
|
||||
}
|
||||
|
||||
public function handle(PhotoSecurityScanner $scanner): void
|
||||
{
|
||||
$photo = Photo::with('mediaAsset')->find($this->photoId);
|
||||
|
||||
if (! $photo) {
|
||||
Log::warning('[PhotoSecurity] Skipping missing photo', ['photo_id' => $this->photoId]);
|
||||
return;
|
||||
}
|
||||
|
||||
$asset = $photo->mediaAsset ?? EventMediaAsset::where('photo_id', $photo->id)->where('variant', 'original')->first();
|
||||
|
||||
if (! $asset) {
|
||||
Log::warning('[PhotoSecurity] No media asset available for scan', [
|
||||
'photo_id' => $photo->id,
|
||||
]);
|
||||
|
||||
$photo->forceFill([
|
||||
'security_scan_status' => 'error',
|
||||
'security_scan_message' => 'Media asset not available for scanning.',
|
||||
'security_scanned_at' => now(),
|
||||
])->save();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$disk = $asset->disk ?? config('filesystems.default', 'public');
|
||||
$path = $asset->path ?? $photo->file_path;
|
||||
|
||||
$scanResult = $scanner->scan($disk, $path);
|
||||
$status = $scanResult['status'] ?? 'error';
|
||||
$message = $scanResult['message'] ?? null;
|
||||
|
||||
$metadata = [
|
||||
'scan' => $scanResult,
|
||||
];
|
||||
|
||||
if ($status === 'clean' && config('security.exif.strip', true)) {
|
||||
$stripResult = $scanner->stripExif($disk, $path);
|
||||
$metadata['exif'] = $stripResult;
|
||||
}
|
||||
|
||||
$existingMeta = $photo->security_meta ?? [];
|
||||
|
||||
$photo->forceFill([
|
||||
'security_scan_status' => $status,
|
||||
'security_scan_message' => $message,
|
||||
'security_scanned_at' => now(),
|
||||
'security_meta' => array_merge(is_array($existingMeta) ? $existingMeta : [], $metadata),
|
||||
])->save();
|
||||
|
||||
if ($status === 'infected') {
|
||||
Log::alert('[PhotoSecurity] Infected photo detected', [
|
||||
'photo_id' => $photo->id,
|
||||
'event_id' => $photo->event_id,
|
||||
'message' => $message,
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user