Add guest push notifications and queue alerts
This commit is contained in:
@@ -19,6 +19,7 @@ use App\Services\EventTasksCacheService;
|
||||
use App\Services\GuestNotificationService;
|
||||
use App\Services\Packages\PackageLimitEvaluator;
|
||||
use App\Services\Packages\PackageUsageTracker;
|
||||
use App\Services\PushSubscriptionService;
|
||||
use App\Services\Storage\EventStorageManager;
|
||||
use App\Support\ApiError;
|
||||
use App\Support\ImageHelper;
|
||||
@@ -49,6 +50,7 @@ class EventPublicController extends BaseController
|
||||
private readonly PackageUsageTracker $packageUsageTracker,
|
||||
private readonly EventTasksCacheService $eventTasksCache,
|
||||
private readonly GuestNotificationService $guestNotificationService,
|
||||
private readonly PushSubscriptionService $pushSubscriptions,
|
||||
) {}
|
||||
|
||||
/**
|
||||
@@ -1666,6 +1668,69 @@ class EventPublicController extends BaseController
|
||||
->header('Vary', 'X-Device-Id, Accept-Language');
|
||||
}
|
||||
|
||||
public function registerPushSubscription(Request $request, string $token)
|
||||
{
|
||||
$result = $this->resolvePublishedEvent($request, $token, ['id']);
|
||||
|
||||
if ($result instanceof JsonResponse) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
[$eventRecord] = $result;
|
||||
$validated = $request->validate([
|
||||
'endpoint' => ['required', 'url', 'max:500'],
|
||||
'keys.p256dh' => ['required', 'string', 'max:255'],
|
||||
'keys.auth' => ['required', 'string', 'max:255'],
|
||||
'expiration_time' => ['nullable'],
|
||||
'content_encoding' => ['nullable', 'string', 'max:32'],
|
||||
]);
|
||||
|
||||
$event = Event::findOrFail($eventRecord->id);
|
||||
$guestIdentifier = $this->resolveNotificationIdentifier($request);
|
||||
$deviceId = $this->resolveDeviceIdentifier($request);
|
||||
|
||||
$payload = [
|
||||
'endpoint' => $validated['endpoint'],
|
||||
'keys' => [
|
||||
'p256dh' => $validated['keys']['p256dh'],
|
||||
'auth' => $validated['keys']['auth'],
|
||||
],
|
||||
'expiration_time' => $validated['expiration_time'] ?? null,
|
||||
'content_encoding' => $validated['content_encoding'] ?? null,
|
||||
'language' => $request->getPreferredLanguage() ?? $request->headers->get('Accept-Language'),
|
||||
'user_agent' => (string) $request->userAgent(),
|
||||
];
|
||||
|
||||
$subscription = $this->pushSubscriptions->register($event, $guestIdentifier, $deviceId, $payload);
|
||||
|
||||
return response()->json([
|
||||
'id' => $subscription->id,
|
||||
'status' => $subscription->status,
|
||||
], Response::HTTP_CREATED);
|
||||
}
|
||||
|
||||
public function destroyPushSubscription(Request $request, string $token)
|
||||
{
|
||||
$result = $this->resolvePublishedEvent($request, $token, ['id']);
|
||||
|
||||
if ($result instanceof JsonResponse) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
[$eventRecord] = $result;
|
||||
|
||||
$validated = $request->validate([
|
||||
'endpoint' => ['required', 'url', 'max:500'],
|
||||
]);
|
||||
|
||||
$event = Event::findOrFail($eventRecord->id);
|
||||
$revoked = $this->pushSubscriptions->revoke($event, $validated['endpoint']);
|
||||
|
||||
return response()->json([
|
||||
'status' => $revoked ? 'revoked' : 'not_found',
|
||||
]);
|
||||
}
|
||||
|
||||
public function markNotificationRead(Request $request, string $token, GuestNotification $notification)
|
||||
{
|
||||
return $this->handleNotificationAction($request, $token, $notification, 'read');
|
||||
@@ -1831,10 +1896,16 @@ class EventPublicController extends BaseController
|
||||
return $identifier;
|
||||
}
|
||||
|
||||
$deviceId = (string) $request->headers->get('X-Device-Id', '');
|
||||
$deviceId = substr(preg_replace('/[^A-Za-z0-9 _\-]/', '', $deviceId) ?? '', 0, 120);
|
||||
return $this->resolveDeviceIdentifier($request);
|
||||
}
|
||||
|
||||
return $deviceId !== '' ? $deviceId : 'anonymous';
|
||||
private function resolveDeviceIdentifier(Request $request): string
|
||||
{
|
||||
$deviceId = (string) $request->headers->get('X-Device-Id', '');
|
||||
$normalized = preg_replace('/[^A-Za-z0-9 _\-]/', '', $deviceId) ?? '';
|
||||
$normalized = trim(substr($normalized, 0, 120));
|
||||
|
||||
return $normalized !== '' ? $normalized : 'anonymous';
|
||||
}
|
||||
|
||||
public function stats(Request $request, string $token)
|
||||
@@ -2216,8 +2287,7 @@ class EventPublicController extends BaseController
|
||||
$eventPackage = $this->packageLimitEvaluator
|
||||
->resolveEventPackageForPhotoUpload($tenantModel, $eventId, $eventModel);
|
||||
|
||||
$deviceId = (string) $request->header('X-Device-Id', 'anon');
|
||||
$deviceId = substr(preg_replace('/[^a-zA-Z0-9_-]/', '', $deviceId), 0, 64) ?: 'anon';
|
||||
$deviceId = $this->resolveDeviceIdentifier($request);
|
||||
|
||||
// Per-device cap per event (MVP: 50)
|
||||
$deviceCount = DB::table('photos')->where('event_id', $eventId)->where('guest_name', $deviceId)->count();
|
||||
|
||||
Reference in New Issue
Block a user