RocketChat/Rocket.Chat

View on GitHub
apps/meteor/client/startup/e2e.ts

Summary

Maintainability
A
0 mins
Test Coverage
import type { IMessage } from '@rocket.chat/core-typings';
import { isE2EEPinnedMessage } from '@rocket.chat/core-typings';
import { Meteor } from 'meteor/meteor';
import { Tracker } from 'meteor/tracker';

import { E2EEState } from '../../app/e2e/client/E2EEState';
import { e2e } from '../../app/e2e/client/rocketchat.e2e';
import { ChatRoom } from '../../app/models/client';
import { settings } from '../../app/settings/client';
import { onClientBeforeSendMessage } from '../lib/onClientBeforeSendMessage';
import { onClientMessageReceived } from '../lib/onClientMessageReceived';
import { isLayoutEmbedded } from '../lib/utils/isLayoutEmbedded';
import { waitUntilFind } from '../lib/utils/waitUntilFind';
import { router } from '../providers/RouterProvider';

Meteor.startup(() => {
    Tracker.autorun(() => {
        if (!Meteor.userId()) {
            e2e.log('Not logged in');
            return;
        }

        if (!window.crypto) {
            e2e.error('No crypto support');
            return;
        }

        const enabled = settings.get('E2E_Enable');
        // we don't care about the reactivity of this boolean
        const adminEmbedded = isLayoutEmbedded() && router.getLocationPathname().startsWith('/admin');

        if (enabled && !adminEmbedded) {
            e2e.log('E2E enabled starting client');
            e2e.startClient();
        } else {
            e2e.log('E2E disabled');
            e2e.setState(E2EEState.DISABLED);
            e2e.closeAlert();
        }
    });

    let offClientMessageReceived: undefined | (() => void);
    let offClientBeforeSendMessage: undefined | (() => void);
    let listenersAttached = false;

    Tracker.autorun(() => {
        if (!e2e.isReady()) {
            e2e.log('Not ready');
            offClientMessageReceived?.();
            offClientBeforeSendMessage?.();
            listenersAttached = false;
            return;
        }

        if (listenersAttached) {
            e2e.log('Listeners already attached');
            return;
        }

        offClientMessageReceived = onClientMessageReceived.use(async (msg: IMessage) => {
            const e2eRoom = await e2e.getInstanceByRoomId(msg.rid);
            if (!e2eRoom?.shouldConvertReceivedMessages()) {
                return msg;
            }

            if (isE2EEPinnedMessage(msg)) {
                return e2e.decryptPinnedMessage(msg);
            }

            return e2e.decryptMessage(msg);
        });

        // Encrypt messages before sending
        offClientBeforeSendMessage = onClientBeforeSendMessage.use(async (message) => {
            const e2eRoom = await e2e.getInstanceByRoomId(message.rid);

            if (!e2eRoom) {
                return message;
            }

            const subscription = await waitUntilFind(() => ChatRoom.findOne({ _id: message.rid }));

            subscription.encrypted ? e2eRoom.resume() : e2eRoom.pause();

            const shouldConvertSentMessages = await e2eRoom.shouldConvertSentMessages(message);

            if (!shouldConvertSentMessages) {
                return message;
            }

            // Should encrypt this message.
            return e2eRoom.encryptMessage(message);
        });

        listenersAttached = true;
        e2e.log('Listeners attached', listenersAttached);
    });
});