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

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

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 48 491x 1x 1x 1x 1x 1x 1x 1x 115x 115x 115x 115x 115x 115x 115x 97x 97x 54x 97x 115x 115x 1x 1x 57x 57x 57x 57x 57x 57x 57x 57x 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";
import {errorMessage} from "../error/error.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: ${errorMessage(err)}`);
            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);
                }
            }
        }
    }
}