feat(sprint7): Phase 1 — notifications enhancement + push infrastructure

Phase 1 (Notification Enhancement):
- Extended NotificationType enum (ADMIN_MESSAGE, INFO_BOARD_POST, FORUM_REPLY, FORUM_MENTION)
- Extended StaffPermission enum (SEND_NOTIFICATIONS, MANAGE_INFO_BOARD, MODERATE_FORUM)
- Extended AuditEventType with Sprint 7 events
- Flyway V11: notification_sends + notification_send_recipients tables
- NotificationSend + NotificationSendRecipient entities
- NotificationSendRepository + NotificationSendRecipientRepository
- Extended NotificationService with sendBroadcast() and sendToSelected()
- NotificationComposeController (POST /compose, GET /sends)
- ComposeNotificationRequest DTO

Phase 1B (Push Infrastructure):
- Flyway V12: device_tokens + notification_preferences tables
- DeviceToken entity + DevicePlatform enum
- NotificationPreference entity + NotificationChannel enum
- DeviceTokenRepository + NotificationPreferenceRepository
- DeviceRegistrationService (register/unregister/list devices, max 10 per user)
- NotificationPreferenceService (get/create defaults, update, IN_APP always on)
- NotificationDispatchService (multi-channel fan-out: WebSocket, Web Push, FCM, Email)
- WebPushSender (VAPID-based, simplified for MVP)
- FcmPushSender (graceful degradation if not configured)
- PushPayload DTO
- DeviceRegistrationController (POST/GET/DELETE /devices, GET /vapid-key)
- NotificationPreferenceController (GET/PUT /preferences)
- ConsentType extended (NOTIFICATION_PUSH, NOTIFICATION_EMAIL)
- TargetType enum (ALL, SELECTED)

Frontend:
- Updated sw.js with push event handler + notification click handler
- push-subscription.ts (subscribeToPush, unsubscribe, permission helpers)
- notification-compose.ts service (compose, sends, devices, preferences APIs)
- i18n keys (de.json + en.json) for compose, preferences, push, devices

Configuration:
- application-docker.properties: VAPID + FCM push config properties
- MemberRepository: added findAllActiveUserIds() for broadcast
This commit is contained in:
Patrick Plate
2026-06-13 19:25:19 +02:00
parent 329b7abb18
commit 706a6e257b
43 changed files with 6635 additions and 76 deletions
+46 -1
View File
@@ -499,7 +499,52 @@
"QUOTA_WARNING": "Kontingent-Warnung",
"BATCH_RECALLED": "Chargen-Rückruf",
"DISTRIBUTION_RECORDED": "Ausgabe erfasst",
"SUBSCRIPTION_EXPIRING": "Abo läuft bald ab"
"SUBSCRIPTION_EXPIRING": "Abo läuft bald ab",
"ADMIN_MESSAGE": "Vereins-Nachricht",
"INFO_BOARD_POST": "Neuer Aushang",
"FORUM_REPLY": "Forum-Antwort",
"FORUM_MENTION": "Forum-Erwähnung"
},
"compose": {
"title": "Benachrichtigung verfassen",
"titleField": "Titel",
"messageField": "Nachricht",
"linkField": "Link (optional)",
"targetAll": "Alle Mitglieder",
"targetSelected": "Ausgewählte Mitglieder",
"selectMembers": "Mitglieder auswählen",
"send": "Senden",
"sending": "Wird gesendet...",
"sent": "Benachrichtigung gesendet an {count} Mitglieder",
"history": "Verlauf",
"sentAt": "Gesendet am",
"recipients": "Empfänger",
"readCount": "Gelesen"
},
"preferences": {
"title": "Benachrichtigungs-Einstellungen",
"inApp": "In-App (immer aktiv)",
"email": "E-Mail",
"webPush": "Browser Push-Benachrichtigungen",
"mobilePush": "Mobile Push-Benachrichtigungen",
"enabled": "Aktiviert",
"disabled": "Deaktiviert"
},
"push": {
"promptTitle": "Push-Benachrichtigungen aktivieren?",
"promptBody": "Erhalte Benachrichtigungen über Ausgaben, Events und Vereins-News direkt auf dein Gerät.",
"accept": "Aktivieren",
"decline": "Nicht jetzt",
"granted": "Push-Benachrichtigungen aktiviert",
"denied": "Push-Benachrichtigungen abgelehnt"
},
"devices": {
"title": "Registrierte Geräte",
"noDevices": "Keine Geräte registriert",
"remove": "Entfernen",
"web": "Web-Browser",
"ios": "iPhone/iPad",
"android": "Android-Gerät"
}
},
"pwa": {
+46 -1
View File
@@ -499,7 +499,52 @@
"QUOTA_WARNING": "Quota Warning",
"BATCH_RECALLED": "Batch Recalled",
"DISTRIBUTION_RECORDED": "Distribution Recorded",
"SUBSCRIPTION_EXPIRING": "Subscription Expiring"
"SUBSCRIPTION_EXPIRING": "Subscription Expiring",
"ADMIN_MESSAGE": "Club Message",
"INFO_BOARD_POST": "New Announcement",
"FORUM_REPLY": "Forum Reply",
"FORUM_MENTION": "Forum Mention"
},
"compose": {
"title": "Compose Notification",
"titleField": "Title",
"messageField": "Message",
"linkField": "Link (optional)",
"targetAll": "All Members",
"targetSelected": "Selected Members",
"selectMembers": "Select members",
"send": "Send",
"sending": "Sending...",
"sent": "Notification sent to {count} members",
"history": "History",
"sentAt": "Sent at",
"recipients": "Recipients",
"readCount": "Read"
},
"preferences": {
"title": "Notification Settings",
"inApp": "In-App (always active)",
"email": "Email",
"webPush": "Browser Push Notifications",
"mobilePush": "Mobile Push Notifications",
"enabled": "Enabled",
"disabled": "Disabled"
},
"push": {
"promptTitle": "Enable Push Notifications?",
"promptBody": "Get notified about distributions, events, and club news directly on your device.",
"accept": "Enable",
"decline": "Not now",
"granted": "Push notifications enabled",
"denied": "Push notifications denied"
},
"devices": {
"title": "Registered Devices",
"noDevices": "No devices registered",
"remove": "Remove",
"web": "Web Browser",
"ios": "iPhone/iPad",
"android": "Android Device"
}
},
"pwa": {