Skip to content

Commit

Permalink
[IMPROVE] Add OTR Room States (#24565)
Browse files Browse the repository at this point in the history
* WIP: OTR Room States

* lint

* remove logs

* new OTR components, remove modals

* updating stories

* convert js files to ts

* correct a type

* add missing translation

* fix review

* chore: remove OTRModal

* fix: review

Co-authored-by: dougfabris <devfabris@gmail.com>
  • Loading branch information
yash-rajpal and dougfabris committed Apr 20, 2022
1 parent d1318e2 commit 9e712ea
Show file tree
Hide file tree
Showing 12 changed files with 280 additions and 180 deletions.
9 changes: 9 additions & 0 deletions apps/meteor/app/otr/client/OtrRoomState.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export enum OtrRoomState {
DISABLED = 'DISABLED',
NOT_STARTED = 'NOT_STARTED',
ESTABLISHING = 'ESTABLISHING',
ESTABLISHED = 'ESTABLISHED',
ERROR = 'ERROR',
TIMEOUT = 'TIMEOUT',
DECLINED = 'DECLINED',
}
13 changes: 11 additions & 2 deletions apps/meteor/app/otr/client/rocketchat.otr.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { Notifications } from '../../notifications';
import { t } from '../../utils';
import { onClientMessageReceived } from '../../../client/lib/onClientMessageReceived';
import { onClientBeforeSendMessage } from '../../../client/lib/onClientBeforeSendMessage';
import { OtrRoomState } from './OtrRoomState';

class OTRClass {
constructor() {
Expand Down Expand Up @@ -56,7 +57,11 @@ Meteor.startup(function () {
});

onClientBeforeSendMessage.use(function (message) {
if (message.rid && OTR.getInstanceByRoomId(message.rid) && OTR.getInstanceByRoomId(message.rid).established.get()) {
if (
message.rid &&
OTR.getInstanceByRoomId(message.rid) &&
OTR.getInstanceByRoomId(message.rid).state.get() === OtrRoomState.ESTABLISHED
) {
return OTR.getInstanceByRoomId(message.rid)
.encrypt(message)
.then((msg) => {
Expand All @@ -69,7 +74,11 @@ Meteor.startup(function () {
});

onClientMessageReceived.use(function (message) {
if (message.rid && OTR.getInstanceByRoomId(message.rid) && OTR.getInstanceByRoomId(message.rid).established.get()) {
if (
message.rid &&
OTR.getInstanceByRoomId(message.rid) &&
OTR.getInstanceByRoomId(message.rid).state.get() === OtrRoomState.ESTABLISHED
) {
if (message.notification) {
message.msg = t('Encrypted_message');
return Promise.resolve(message);
Expand Down
60 changes: 34 additions & 26 deletions apps/meteor/app/otr/client/rocketchat.otr.room.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { goToRoomById } from '../../../client/lib/utils/goToRoomById';
import { imperativeModal } from '../../../client/lib/imperativeModal';
import GenericModal from '../../../client/components/GenericModal';
import { dispatchToastMessage } from '../../../client/lib/toast';
import { OtrRoomState } from './OtrRoomState';
import { otrSystemMessages } from '../lib/constants';
import { APIClient } from '../../utils/client';

Expand All @@ -23,8 +24,8 @@ OTR.Room = class {
this.userId = userId;
this.roomId = roomId;
this.peerId = getUidDirectMessage(roomId);
this.established = new ReactiveVar(false);
this.establishing = new ReactiveVar(false);
this.state = new ReactiveVar(OtrRoomState.NOT_STARTED);

this.isFirstOTR = true;

this.userOnlineComputation = null;
Expand All @@ -34,8 +35,17 @@ OTR.Room = class {
this.sessionKey = null;
}

setState(nextState) {
const currentState = this.state.get();
if (currentState === nextState) {
return;
}

this.state.set(nextState);
}

handshake(refresh) {
this.establishing.set(true);
this.setState(OtrRoomState.ESTABLISHING);
this.firstPeer = true;
this.generateKeyPair().then(() => {
Notifications.notifyUser(this.peerId, 'otr', 'handshake', {
Expand Down Expand Up @@ -63,6 +73,7 @@ OTR.Room = class {

deny() {
this.reset();
this.setState(OtrRoomState.DECLINED);
Notifications.notifyUser(this.peerId, 'otr', 'deny', {
roomId: this.roomId,
userId: this.userId,
Expand All @@ -72,15 +83,14 @@ OTR.Room = class {
end() {
this.isFirstOTR = true;
this.reset();
this.setState(OtrRoomState.NOT_STARTED);
Notifications.notifyUser(this.peerId, 'otr', 'end', {
roomId: this.roomId,
userId: this.userId,
});
}

reset() {
this.establishing.set(false);
this.established.set(false);
this.keyPair = null;
this.exportedPublicKey = null;
this.sessionKey = null;
Expand All @@ -95,7 +105,7 @@ OTR.Room = class {
this.userOnlineComputation = Tracker.autorun(() => {
const $room = $(`#chat-window-${this.roomId}`);
const $title = $('.rc-header__title', $room);
if (this.established.get()) {
if (this.state.get() === OtrRoomState.ESTABLISHED) {
if ($room.length && $title.length && !$('.otr-icon', $title).length) {
$title.prepend("<i class='otr-icon icon-key'></i>");
}
Expand Down Expand Up @@ -125,6 +135,7 @@ OTR.Room = class {
Meteor.call('deleteOldOTRMessages', this.roomId);
})
.catch((e) => {
this.setState(OtrRoomState.ERROR);
dispatchToastMessage({ type: 'error', message: e });
});
}
Expand Down Expand Up @@ -202,6 +213,7 @@ OTR.Room = class {
return EJSON.stringify(output);
})
.catch(() => {
this.setState(OtrRoomState.ERROR);
throw new Meteor.Error('encryption-error', 'Encryption error.');
});
}
Expand Down Expand Up @@ -247,6 +259,7 @@ OTR.Room = class {
})
.catch((e) => {
dispatchToastMessage({ type: 'error', message: e });
this.setState(OtrRoomState.ERROR);
return message;
});
}
Expand All @@ -256,14 +269,14 @@ OTR.Room = class {
case 'handshake':
let timeout = null;
const establishConnection = () => {
this.establishing.set(true);
this.setState(OtrRoomState.ESTABLISHING);
Meteor.clearTimeout(timeout);
this.generateKeyPair().then(() => {
this.importPublicKey(data.publicKey).then(() => {
this.firstPeer = false;
goToRoomById(data.roomId);
Meteor.defer(() => {
this.established.set(true);
this.setState(OtrRoomState.ESTABLISHED);
this.acknowledge();
if (data.refresh) {
Meteor.call('sendSystemMessages', this.roomId, Meteor.user(), otrSystemMessages.USER_KEY_REFRESHED_SUCCESSFULLY);
Expand All @@ -275,11 +288,11 @@ OTR.Room = class {

(async () => {
const { username } = await Presence.get(data.userId);
if (data.refresh && this.established.get()) {
if (data.refresh && this.state.get() === OtrRoomState.ESTABLISHED) {
this.reset();
establishConnection();
} else {
if (this.established.get()) {
if (this.state.get() === OtrRoomState.ESTABLISHED) {
this.reset();
}

Expand All @@ -293,7 +306,11 @@ OTR.Room = class {
}),
confirmText: TAPi18n.__('Yes'),
cancelText: TAPi18n.__('No'),
onClose: () => imperativeModal.close,
onClose: () => {
Meteor.clearTimeout(timeout);
this.deny();
imperativeModal.close();
},
onCancel: () => {
Meteor.clearTimeout(timeout);
this.deny();
Expand All @@ -308,15 +325,15 @@ OTR.Room = class {
}

timeout = Meteor.setTimeout(() => {
this.establishing.set(false);
this.setState(OtrRoomState.TIMEOUT);
imperativeModal.close();
}, 10000);
})();
break;

case 'acknowledge':
this.importPublicKey(data.publicKey).then(() => {
this.established.set(true);
this.setState(OtrRoomState.ESTABLISHED);
});
if (this.isFirstOTR) {
Meteor.call('sendSystemMessages', this.roomId, Meteor.user(), otrSystemMessages.USER_JOINED_OTR);
Expand All @@ -326,19 +343,9 @@ OTR.Room = class {

case 'deny':
(async () => {
const { username } = await Presence.get(this.peerId);
if (this.establishing.get()) {
if (this.state.get() === OtrRoomState.ESTABLISHING) {
this.reset();
imperativeModal.open({
component: GenericModal,
props: {
variant: 'warning',
title: TAPi18n.__('OTR'),
children: TAPi18n.__('Username_denied_the_OTR_session', { username }),
onClose: imperativeModal.close,
onConfirm: imperativeModal.close,
},
});
this.setState(OtrRoomState.DECLINED);
}
})();
break;
Expand All @@ -347,8 +354,9 @@ OTR.Room = class {
(async () => {
const { username } = await Presence.get(this.peerId);

if (this.established.get()) {
if (this.state.get() === OtrRoomState.ESTABLISHED) {
this.reset();
this.setState(OtrRoomState.NOT_STARTED);
imperativeModal.open({
component: GenericModal,
props: {
Expand Down
53 changes: 0 additions & 53 deletions apps/meteor/client/views/room/contextualBar/OTR/OTR.js

This file was deleted.

20 changes: 18 additions & 2 deletions apps/meteor/client/views/room/contextualBar/OTR/OTR.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { ComponentMeta, ComponentStory } from '@storybook/react';
import React from 'react';

import { OtrRoomState } from '../../../../../app/otr/client/OtrRoomState';
import VerticalBar from '../../../../components/VerticalBar';
import OTR from './OTR';

Expand All @@ -19,21 +20,36 @@ const Template: ComponentStory<typeof OTR> = (args) => <OTR {...args} />;
export const Default = Template.bind({});
Default.args = {
isOnline: true,
otrState: OtrRoomState.NOT_STARTED,
};

export const Establishing = Template.bind({});
Establishing.args = {
isOnline: true,
isEstablishing: true,
otrState: OtrRoomState.ESTABLISHING,
};

export const Established = Template.bind({});
Established.args = {
isOnline: true,
isEstablished: true,
otrState: OtrRoomState.ESTABLISHED,
};

export const Unavailable = Template.bind({});
Unavailable.args = {
isOnline: false,
};

export const Timeout = Template.bind({});
Timeout.args = {
isOnline: true,
otrState: OtrRoomState.TIMEOUT,
peerUsername: 'testUser',
};

export const Declined = Template.bind({});
Declined.args = {
isOnline: true,
otrState: OtrRoomState.DECLINED,
peerUsername: 'testUser',
};
Loading

0 comments on commit 9e712ea

Please sign in to comment.