From 2599626fb286a85eb1e8970289a961de0b7abf8c Mon Sep 17 00:00:00 2001
From: Will Hunt <will@half-shot.uk>
Date: Mon, 21 May 2018 15:40:44 +0100
Subject: [PATCH] Warn about encrypted rooms

---
 src/matrixroomhandler.ts       | 39 +++++++++++++++++++++++++++-------
 test/mocks/channel.ts          |  3 +++
 test/test_matrixroomhandler.ts | 31 ++++++++++++++++++++++-----
 3 files changed, 60 insertions(+), 13 deletions(-)

diff --git a/src/matrixroomhandler.ts b/src/matrixroomhandler.ts
index 5c8f9d1..2c04db5 100644
--- a/src/matrixroomhandler.ts
+++ b/src/matrixroomhandler.ts
@@ -93,21 +93,44 @@ export class MatrixRoomHandler {
     } else if (event.type === "m.room.redaction" && context.rooms.remote) {
       return this.discord.ProcessMatrixRedact(event);
     } else if (event.type === "m.room.message") {
-      log.verbose("MatrixRoomHandler", "Got m.room.message event");
-      if (event.content.body && event.content.body.startsWith("!discord")) {
-        return this.ProcessCommand(event, context);
-      } else if (context.rooms.remote) {
-        const srvChanPair = context.rooms.remote.roomId.substr("_discord".length).split("_", ROOM_NAME_PARTS);
-        return this.discord.ProcessMatrixMsgEvent(event, srvChanPair[0], srvChanPair[1]).catch((err) => {
-            log.warn("MatrixRoomHandler", "There was an error sending a matrix event", err);
+        log.verbose("MatrixRoomHandler", "Got m.room.message event");
+        if (event.content.body && event.content.body.startsWith("!discord")) {
+            return this.ProcessCommand(event, context);
+        } else if (context.rooms.remote) {
+            const srvChanPair = context.rooms.remote.roomId.substr("_discord".length).split("_", ROOM_NAME_PARTS);
+            return this.discord.ProcessMatrixMsgEvent(event, srvChanPair[0], srvChanPair[1]).catch((err) => {
+                log.warn("MatrixRoomHandler", "There was an error sending a matrix event", err);
+            });
+        }
+    } else if (event.type === "m.room.encryption" && context.rooms.remote) {
+        return this.HandleEncryptionWarning(event.room_id).catch((err) => {
+            return Promise.reject(`Failed to handle encrypted room, ${err}`);
         });
-      }
     } else {
       log.verbose("MatrixRoomHandler", "Got non m.room.message event");
     }
     return Promise.reject("Event not processed by bridge");
   }
 
+  public async HandleEncryptionWarning(roomId: string): Promise<void> {
+      const intent = this.bridge.getIntent();
+      log.info("MatrixRoomHandler", `User has turned on encryption in ${roomId}, so leaving.`);
+      /* N.B 'status' is not specced but https://github.com/matrix-org/matrix-doc/pull/828
+       has been open for over a year with no resolution. */
+      const sendPromise = intent.sendMessage(roomId, {
+          msgtype: "m.notice",
+          status: "critical",
+          body: "You have turned on encryption in this room, so the service will not bridge any new messages.",
+      });
+      const channel = await this.discord.GetChannelFromRoomId(roomId);
+      await (channel as Discord.TextChannel).send(
+        "Someone on Matrix has turned on encryption in this room, so the service will not bridge any new messages",
+      );
+      await sendPromise;
+      await intent.leave(roomId);
+      await this.bridge.getRoomStore().removeEntriesByMatrixRoomId(roomId);
+  }
+
   public HandleInvite(event: any) {
     log.info("MatrixRoomHandler", "Received invite for " + event.state_key + " in room " + event.room_id);
     if (event.state_key === this.botUserId) {
diff --git a/test/mocks/channel.ts b/test/mocks/channel.ts
index d979470..3af74ea 100644
--- a/test/mocks/channel.ts
+++ b/test/mocks/channel.ts
@@ -5,4 +5,7 @@ import {MockCollection} from "./collection";
 export class MockChannel {
     public members = new MockCollection<string, MockMember>();
     constructor (public id: string = "", public guild: any = null) { }
+    public send(data: any): Promise<any> {
+        return Promise.resolve(data);
+    }
 }
diff --git a/test/test_matrixroomhandler.ts b/test/test_matrixroomhandler.ts
index 36a0e70..fb8d5cc 100644
--- a/test/test_matrixroomhandler.ts
+++ b/test/test_matrixroomhandler.ts
@@ -102,11 +102,20 @@ function createRH(opts: any = {}) {
     };
     const handler = new MatrixRoomHandler(bot as any, config, "@botuser:localhost", provisioner as any);
     handler.setBridge({
-        getIntent: () => { return {
-            sendMessage: (roomId, content) => Promise.resolve(content),
-            getClient: () => mxClient,
-        }; },
-    });
+            getIntent: () => {
+                return {
+                    sendMessage: (roomId, content) => Promise.resolve(content),
+                    leave: (roomId) => Promise.resolve(roomId),
+                    getClient: () => mxClient,
+                };
+            },
+            getRoomStore: () => {
+                return {
+                    removeEntriesByMatrixRoomId: (roomId) => Promise.resolve(roomId),
+                };
+            },
+        },
+    );
     return handler;
 }
 
@@ -195,6 +204,18 @@ describe("MatrixRoomHandler", () => {
             return expect(handler.OnEvent(buildRequest({
                 type: "m.room.message", content: {body: "abc"}}), context)).to.eventually.equal("processed");
         });
+        it("should alert if encryption is turned on", () => {
+            const handler = createRH();
+            const context = {
+                rooms: {
+                    remote: {
+                        roomId: "_discord_123_456",
+                    },
+                },
+            };
+            return expect(handler.OnEvent(buildRequest({
+                type: "m.room.encryption", room_id: "!accept:localhost"}), context)).to.eventually.be.fulfilled;
+        });
         it("should process !discord commands", () => {
             const handler = createRH();
             handler.ProcessCommand = (ev) => Promise.resolve("processedcmd");
-- 
GitLab