c413004930
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>
32 lines
1.0 KiB
PHP
32 lines
1.0 KiB
PHP
<?php
|
|
|
|
use Illuminate\Database\Migrations\Migration;
|
|
use Illuminate\Database\Schema\Blueprint;
|
|
use Illuminate\Support\Facades\Schema;
|
|
|
|
return new class extends Migration
|
|
{
|
|
public function up(): void
|
|
{
|
|
Schema::create('push_subscriptions', function (Blueprint $t) {
|
|
$t->id();
|
|
$t->foreignId('company_id')->nullable()->constrained()->cascadeOnDelete();
|
|
$t->foreignId('user_id')->nullable()->constrained()->cascadeOnDelete();
|
|
$t->string('endpoint', 500);
|
|
$t->string('public_key')->nullable(); // p256dh
|
|
$t->string('auth_token')->nullable(); // auth
|
|
$t->string('content_encoding', 32)->default('aesgcm');
|
|
$t->string('user_agent')->nullable();
|
|
$t->timestamps();
|
|
|
|
$t->unique('endpoint', 'push_subscriptions_endpoint_unique');
|
|
$t->index(['company_id', 'user_id']);
|
|
});
|
|
}
|
|
|
|
public function down(): void
|
|
{
|
|
Schema::dropIfExists('push_subscriptions');
|
|
}
|
|
};
|