All files / app/web-ui notification-pusher.ts

100% Statements 48/48
100% Branches 10/10
100% Functions 3/3
100% Lines 48/48

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 481x 1x 1x 1x 1x 1x 1x 96x 96x 96x 96x 96x 96x 96x 85x 85x 46x 85x 96x 96x 1x 1x 49x 49x 49x 49x 49x 49x 49x 49x 1x 1x 2x 2x 2x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 2x 1x
import {Resources} from "../../lib/resources/main.js";
import webpush from 'web-push';
import {SerializedState, StateTrigger, StateType} from "../../lib/resources/state-manager.js";
import {iCPSState} from "../../lib/resources/events-types.js";
 
export class NotificationPusher {
    constructor() {
        webpush.setVapidDetails(
            `mailto:${Resources.manager().username}`,
            Resources.manager().notificationVapidCredentials.publicKey,
            Resources.manager().notificationVapidCredentials.privateKey
        );
 
        Resources.events(this).on(iCPSState.STATE_CHANGED, (state: SerializedState) => {
            if((state.state === StateType.READY   && state.prevTrigger === StateTrigger.SYNC) || 
               (state.state === StateType.BLOCKED && state.progressMsg === `Waiting for MFA code...`)) {
                this.sendNotifications(state);
            } 
        });
    }
 
    async sendNotifications(state: SerializedState): Promise<void[]> {
        const notificationSubscriptions = Resources.manager().notificationSubscriptions;
        Resources.logger(this).info(`State changed to: ${state.state}, sending notifications to ${notificationSubscriptions.length} listeners.`);
        return Promise.all(
            notificationSubscriptions.map(
                subscription => this.sendPushNotification(subscription, state)
            )
        )
    }
 
    async sendPushNotification(subscription: webpush.PushSubscription, state: SerializedState) {
        try {
            Resources.logger(this).debug(`Sending notification to ${subscription.endpoint}`);
            await webpush.sendNotification(subscription, JSON.stringify(state));
        } catch (err) {
            Resources.logger(this).error(`Failed to send notification to subscription: ${err.message}`);
            if (err instanceof webpush.WebPushError) {
                Resources.logger(this).error(`WebPush error: ${err.statusCode} - ${err.body}`);
                if (err.statusCode === 410) {
                    // Subscription is no longer valid, remove it
                    Resources.logger(this).warn(`Removing subscription, because it has expired`);
                    Resources.manager().removeNotificationSubscription(subscription);
                }
            }
        }
    }
}