Files
autocrm/app/Http/Controllers/PushSubscriptionController.php
T
Vasyka c413004930 Stage 15 — PWA complete: install prompt + Web Push notifications
Dependency:
- minishlink/web-push v10 (VAPID JWT + aes128gcm payload encryption)
- Dockerfile: add curl, mbstring, gmp extensions (web-push needs ext-curl)

VAPID:
- config/webpush.php from env; `php artisan push:vapid` generates keypair
- Shared platform keypair; .env.example has empty placeholders

Schema:
- push_subscriptions (user/company, endpoint unique, p256dh, auth, encoding)

WebPushService:
- send / sendToUser / dispatch via WebPush::flush
- Auto-prunes subscriptions reported expired (404/410)

Subscribe flow:
- POST /push/subscribe + /push/unsubscribe (auth, tenant)
- Tenant panel JS subscribes after SW registration with VAPID public key

Service worker (/sw.js):
- Cache v2, push listener → showNotification, notificationclick → focus/open

Install prompt:
- Floating "Instalează aplicația" button wired to beforeinstallprompt

Staff push:
- WorkOrder master_id change → push to assigned mechanic
- Settings "Test notificare push" action

Tests (6 new):
- subscribe stores + upserts; requires auth (401); validation (422);
  service configured; sendToUser with no subs returns zero

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 05:11:18 +00:00

45 lines
1.3 KiB
PHP

<?php
namespace App\Http\Controllers;
use App\Models\Tenant\PushSubscription;
use Illuminate\Http\Request;
class PushSubscriptionController extends Controller
{
public function subscribe(Request $request)
{
$data = $request->validate([
'endpoint' => 'required|string|max:500',
'keys.p256dh' => 'required|string',
'keys.auth' => 'required|string',
'contentEncoding' => 'nullable|string|max:32',
]);
$user = $request->user();
PushSubscription::updateOrCreate(
['endpoint' => $data['endpoint']],
[
'company_id' => $user?->company_id,
'user_id' => $user?->id,
'public_key' => $data['keys']['p256dh'],
'auth_token' => $data['keys']['auth'],
'content_encoding' => $data['contentEncoding'] ?? 'aesgcm',
'user_agent' => substr((string) $request->userAgent(), 0, 255),
]
);
return response()->json(['ok' => true]);
}
public function unsubscribe(Request $request)
{
$endpoint = $request->input('endpoint');
if ($endpoint) {
PushSubscription::where('endpoint', $endpoint)->delete();
}
return response()->json(['ok' => true]);
}
}