New global push/ module mirroring mail/ and files/storage/: - PushProvider abstraction; default LogPushProvider (no delivery, logs), PUSH_PROVIDER=fcm switches to FcmPushProvider — Firebase Cloud Messaging HTTP v1, authenticated by a service-account JWT exchanged for an OAuth token (no extra dependency; jsonwebtoken does the signing). Prunes tokens FCM reports as invalid. - DeviceToken model (token + platform, bound to a User or GuestAccount), migration + added to the sync log. - POST /api/push/register + /unregister (any of the three token kinds). - PushService.notifyChannel() resolves a channel's readable audience (DIREKT participants / LT / Gemeinde members + guests / whole KC for broadcast), looks up their device tokens (minus the sender), sends. - ChatService.sendMessage() fires it best-effort after persisting. New env: PUSH_PROVIDER, FCM_PROJECT_ID (default konfi-castle-app), GOOGLE_APPLICATION_CREDENTIALS. Verified against local Postgres: register a token, send a Gemeinde-group chat message from another member -> log-push logs "would push ... to 1 device". Real FCM send needs the service-account JSON. npm test 56. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
16 lines
589 B
TypeScript
16 lines
589 B
TypeScript
import { Logger } from '@nestjs/common';
|
|
import { PushNotification, PushProvider, PushResult } from './push-provider';
|
|
|
|
/// Default provider: doesn't send, just logs. Keeps the app working before
|
|
/// FCM credentials are configured.
|
|
export class LogPushProvider implements PushProvider {
|
|
private readonly logger = new Logger('PushProvider');
|
|
|
|
async sendToTokens(tokens: string[], n: PushNotification): Promise<PushResult> {
|
|
this.logger.log(
|
|
`[log-only] would push "${n.title}" to ${tokens.length} device(s): ${n.body}`,
|
|
);
|
|
return { sent: 0, invalidTokens: [] };
|
|
}
|
|
}
|