From 0f2e2ea069e9cdd5f05319370744aa354d450758 Mon Sep 17 00:00:00 2001 From: Zoe Date: Fri, 27 Mar 2020 11:58:54 +0000 Subject: [PATCH 1/7] Update shield display rules --- src/components/structures/RoomView.js | 8 +++++++- src/components/views/rooms/RoomTile.js | 7 ++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index 5fd5f42f788..dd453667e03 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -40,6 +40,7 @@ import rate_limited_func from '../../ratelimitedfunc'; import * as ObjectUtils from '../../ObjectUtils'; import * as Rooms from '../../Rooms'; import eventSearch from '../../Searching'; +import DMRoomMap from '../../utils/DMRoomMap'; import {isOnlyCtrlOrCmdKeyEvent, Key} from '../../Keyboard'; @@ -833,7 +834,12 @@ export default createReactClass({ /* Check all verified user devices. */ /* Don't alarm if no other users are verified */ - const targets = (verified.length > 0) ? [...verified, this.context.getUserId()] : verified; + const isDM = !!DMRoomMap.shared().getUserIdForRoomId(this.props.room.roomId); + const includeUser = (verified.length > 0) && // Don't alarm for self in rooms where nobody else is verified + !isDM && // Don't alarm for self in DMs with other users + (e2eMembers.length != 2) || // Don't alarm for self in 1:1 chats with other users + (e2eMembers.length == 1); // Do alarm for self if we're alone in a room + const targets = includeUser ? [...verified, this.context.getUserId()] : verified; for (const userId of targets) { const devices = await this.context.getStoredDevicesForUser(userId); const anyDeviceNotVerified = devices.some(({deviceId}) => { diff --git a/src/components/views/rooms/RoomTile.js b/src/components/views/rooms/RoomTile.js index 0f44f5077a3..6f9cd7f1be5 100644 --- a/src/components/views/rooms/RoomTile.js +++ b/src/components/views/rooms/RoomTile.js @@ -167,7 +167,12 @@ export default createReactClass({ /* Check all verified user devices. */ /* Don't alarm if no other users are verified */ - const targets = (verified.length > 0) ? [...verified, cli.getUserId()] : verified; + const isDM = DMRoomMap.shared().getUserIdForRoomId(this.props.room.roomId); + const includeUser = (verified.length > 0) && // Don't alarm for self in rooms where nobody else is verified + !isDM && // Don't alarm for self in DMs with other users + (e2eMembers.length != 2) || // Don't alarm for self in 1:1 chats with other users + (e2eMembers.length == 1); // Do alarm for self if we're alone in a room + const targets = includeUser ? [...verified, cli.getUserId()] : verified; for (const userId of targets) { const devices = await cli.getStoredDevicesForUser(userId); const allDevicesVerified = devices.every(({deviceId}) => { From 5d7adef0a2a7d5de0ca9a7d7931c90e5fb52a213 Mon Sep 17 00:00:00 2001 From: Zoe Date: Fri, 27 Mar 2020 13:45:21 +0000 Subject: [PATCH 2/7] Factor out shield display rules into one file --- src/components/structures/RoomView.js | 39 ++-------------------- src/components/views/rooms/RoomTile.js | 36 ++------------------- src/utils/ShieldUtils.ts | 45 ++++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 70 deletions(-) create mode 100644 src/utils/ShieldUtils.ts diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index dd453667e03..7ce50348c90 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -56,6 +56,7 @@ import RightPanelStore from "../../stores/RightPanelStore"; import {haveTileForEvent} from "../views/rooms/EventTile"; import RoomContext from "../../contexts/RoomContext"; import MatrixClientContext from "../../contexts/MatrixClientContext"; +import { shieldStatusForMembership } from '../../utils/ShieldUtils'; const DEBUG = false; let debuglog = function() {}; @@ -818,45 +819,9 @@ export default createReactClass({ return; } - // Duplication between here and _updateE2eStatus in RoomTile /* At this point, the user has encryption on and cross-signing on */ - const e2eMembers = await room.getEncryptionTargetMembers(); - const verified = []; - const unverified = []; - e2eMembers.map(({userId}) => userId) - .filter((userId) => userId !== this.context.getUserId()) - .forEach((userId) => { - (this.context.checkUserTrust(userId).isCrossSigningVerified() ? - verified : unverified).push(userId); - }); - - debuglog("e2e verified", verified, "unverified", unverified); - - /* Check all verified user devices. */ - /* Don't alarm if no other users are verified */ - const isDM = !!DMRoomMap.shared().getUserIdForRoomId(this.props.room.roomId); - const includeUser = (verified.length > 0) && // Don't alarm for self in rooms where nobody else is verified - !isDM && // Don't alarm for self in DMs with other users - (e2eMembers.length != 2) || // Don't alarm for self in 1:1 chats with other users - (e2eMembers.length == 1); // Do alarm for self if we're alone in a room - const targets = includeUser ? [...verified, this.context.getUserId()] : verified; - for (const userId of targets) { - const devices = await this.context.getStoredDevicesForUser(userId); - const anyDeviceNotVerified = devices.some(({deviceId}) => { - return !this.context.checkDeviceTrust(userId, deviceId).isVerified(); - }); - if (anyDeviceNotVerified) { - this.setState({ - e2eStatus: "warning", - }); - debuglog("e2e status set to warning as not all users trust all of their sessions." + - " Aborted on user", userId); - return; - } - } - this.setState({ - e2eStatus: unverified.length === 0 ? "verified" : "normal", + e2eStatus: await shieldStatusForMembership(this.context, room), }); }, diff --git a/src/components/views/rooms/RoomTile.js b/src/components/views/rooms/RoomTile.js index 6f9cd7f1be5..478d6703b44 100644 --- a/src/components/views/rooms/RoomTile.js +++ b/src/components/views/rooms/RoomTile.js @@ -37,6 +37,7 @@ import E2EIcon from './E2EIcon'; import InviteOnlyIcon from './InviteOnlyIcon'; // eslint-disable-next-line camelcase import rate_limited_func from '../../../ratelimitedfunc'; +import { shieldStatusForMembership } from '../../../utils/ShieldUtils'; export default createReactClass({ displayName: 'RoomTile', @@ -154,40 +155,9 @@ export default createReactClass({ return; } - // Duplication between here and _updateE2eStatus in RoomView - const e2eMembers = await this.props.room.getEncryptionTargetMembers(); - const verified = []; - const unverified = []; - e2eMembers.map(({userId}) => userId) - .filter((userId) => userId !== cli.getUserId()) - .forEach((userId) => { - (cli.checkUserTrust(userId).isCrossSigningVerified() ? - verified : unverified).push(userId); - }); - - /* Check all verified user devices. */ - /* Don't alarm if no other users are verified */ - const isDM = DMRoomMap.shared().getUserIdForRoomId(this.props.room.roomId); - const includeUser = (verified.length > 0) && // Don't alarm for self in rooms where nobody else is verified - !isDM && // Don't alarm for self in DMs with other users - (e2eMembers.length != 2) || // Don't alarm for self in 1:1 chats with other users - (e2eMembers.length == 1); // Do alarm for self if we're alone in a room - const targets = includeUser ? [...verified, cli.getUserId()] : verified; - for (const userId of targets) { - const devices = await cli.getStoredDevicesForUser(userId); - const allDevicesVerified = devices.every(({deviceId}) => { - return cli.checkDeviceTrust(userId, deviceId).isVerified(); - }); - if (!allDevicesVerified) { - this.setState({ - e2eStatus: "warning", - }); - return; - } - } - + /* At this point, the user has encryption on and cross-signing on */ this.setState({ - e2eStatus: unverified.length === 0 ? "verified" : "normal", + e2eStatus: await shieldStatusForMembership(cli, this.props.room), }); }, diff --git a/src/utils/ShieldUtils.ts b/src/utils/ShieldUtils.ts new file mode 100644 index 00000000000..407dae8e97e --- /dev/null +++ b/src/utils/ShieldUtils.ts @@ -0,0 +1,45 @@ +import DMRoomMap from './DMRoomMap'; + +/* For now, a cut-down type spec for the client */ +interface Client { + getUserId: () => string; + checkUserTrust: (userId: string) => { + isCrossSigningVerified: () => boolean + }; + getStoredDevicesForUser: (userId: string) => Promise<[{ deviceId: string }]>; + checkDeviceTrust: (userId: string, deviceId: string) => { + isVerified: () => boolean + } +} + +export async function shieldStatusForMembership(client: Client, room) { + const members = (await room.getEncryptionTargetMembers()).map(({userId}) => userId); + const inDMMap = !!DMRoomMap.shared().getUserIdForRoomId(room.roomId); + + const verified = []; + const unverified = []; + members.filter((userId) => userId !== client.getUserId()) + .forEach((userId) => { + (client.checkUserTrust(userId).isCrossSigningVerified() ? + verified : unverified).push(userId); + }); + + /* Check all verified user devices. */ + /* Don't alarm if no other users are verified */ + const includeUser = (verified.length > 0) && // Don't alarm for self in rooms where nobody else is verified + !inDMMap && // Don't alarm for self in DMs with other users + (members.length != 2) || // Don't alarm for self in 1:1 chats with other users + (members.length == 1); // Do alarm for self if we're alone in a room + const targets = includeUser ? [...verified, client.getUserId()] : verified; + for (const userId of targets) { + const devices = await client.getStoredDevicesForUser(userId); + const anyDeviceNotVerified = devices.some(({deviceId}) => { + return !client.checkDeviceTrust(userId, deviceId).isVerified(); + }); + if (anyDeviceNotVerified) { + return "warning"; + } + } + + return unverified.length === 0 ? "verified" : "normal"; +} From 5b7e7f49d1cbc4733769f16a042b0a383d21c6c5 Mon Sep 17 00:00:00 2001 From: Zoe Date: Fri, 27 Mar 2020 13:50:03 +0000 Subject: [PATCH 3/7] lint --- src/components/structures/RoomView.js | 1 - src/utils/ShieldUtils.ts | 15 ++++++++++----- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index 7ce50348c90..74572b962a5 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -40,7 +40,6 @@ import rate_limited_func from '../../ratelimitedfunc'; import * as ObjectUtils from '../../ObjectUtils'; import * as Rooms from '../../Rooms'; import eventSearch from '../../Searching'; -import DMRoomMap from '../../utils/DMRoomMap'; import {isOnlyCtrlOrCmdKeyEvent, Key} from '../../Keyboard'; diff --git a/src/utils/ShieldUtils.ts b/src/utils/ShieldUtils.ts index 407dae8e97e..30b1dab7fce 100644 --- a/src/utils/ShieldUtils.ts +++ b/src/utils/ShieldUtils.ts @@ -12,12 +12,17 @@ interface Client { } } -export async function shieldStatusForMembership(client: Client, room) { +interface Room { + getEncryptionTargetMembers: () => Promise<[{userId: string}]>; + roomId: string; +} + +export async function shieldStatusForMembership(client: Client, room: Room) { const members = (await room.getEncryptionTargetMembers()).map(({userId}) => userId); const inDMMap = !!DMRoomMap.shared().getUserIdForRoomId(room.roomId); - const verified = []; - const unverified = []; + const verified: string[] = []; + const unverified: string[] = []; members.filter((userId) => userId !== client.getUserId()) .forEach((userId) => { (client.checkUserTrust(userId).isCrossSigningVerified() ? @@ -28,8 +33,8 @@ export async function shieldStatusForMembership(client: Client, room) { /* Don't alarm if no other users are verified */ const includeUser = (verified.length > 0) && // Don't alarm for self in rooms where nobody else is verified !inDMMap && // Don't alarm for self in DMs with other users - (members.length != 2) || // Don't alarm for self in 1:1 chats with other users - (members.length == 1); // Do alarm for self if we're alone in a room + (members.length !== 2) || // Don't alarm for self in 1:1 chats with other users + (members.length === 1); // Do alarm for self if we're alone in a room const targets = includeUser ? [...verified, client.getUserId()] : verified; for (const userId of targets) { const devices = await client.getStoredDevicesForUser(userId); From 1f0d7923d71fa1bc35d5774e5957a332ac427938 Mon Sep 17 00:00:00 2001 From: Zoe Date: Fri, 27 Mar 2020 13:51:30 +0000 Subject: [PATCH 4/7] with output type --- src/utils/ShieldUtils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/ShieldUtils.ts b/src/utils/ShieldUtils.ts index 30b1dab7fce..3c7cae8c8de 100644 --- a/src/utils/ShieldUtils.ts +++ b/src/utils/ShieldUtils.ts @@ -17,7 +17,7 @@ interface Room { roomId: string; } -export async function shieldStatusForMembership(client: Client, room: Room) { +export async function shieldStatusForMembership(client: Client, room: Room): Promise { const members = (await room.getEncryptionTargetMembers()).map(({userId}) => userId); const inDMMap = !!DMRoomMap.shared().getUserIdForRoomId(room.roomId); From fda533ab48321e09de49ccb3b356171a09918bda Mon Sep 17 00:00:00 2001 From: Zoe Date: Fri, 27 Mar 2020 15:25:44 +0000 Subject: [PATCH 5/7] test for shield behaviour --- test/utils/ShieldUtils-test.js | 170 +++++++++++++++++++++++++++++++++ 1 file changed, 170 insertions(+) create mode 100644 test/utils/ShieldUtils-test.js diff --git a/test/utils/ShieldUtils-test.js b/test/utils/ShieldUtils-test.js new file mode 100644 index 00000000000..5030d9c5c82 --- /dev/null +++ b/test/utils/ShieldUtils-test.js @@ -0,0 +1,170 @@ +import { shieldStatusForMembership } from '../../src/utils/ShieldUtils'; +import DMRoomMap from '../../src/utils/DMRoomMap'; + +function mkClient (selfTrust) { + return { + getUserId: () => "@self:localhost", + checkUserTrust: (userId) => ({ + isCrossSigningVerified: () => userId[1] == "T" + }), + checkDeviceTrust: (userId, deviceId) => ({ + isVerified: () => userId === "@self:localhost" ? selfTrust : userId[2] == "T" + }), + getStoredDevicesForUser: async (userId) => ["DEVICE"], + } +} + +describe("mkClient self-test", function () { + test.each([true, false])("behaves well for self-trust=%s", (v) => { + const client = mkClient(v); + expect(client.checkDeviceTrust("@self:localhost", "DEVICE").isVerified()).toBe(v); + }); + + test.each([ + ["@TT:h", true], + ["@TF:h", true], + ["@FT:h", false], + ["@FF:h", false]]) + ("behaves well for user trust %s", (userId, trust) => { + expect(mkClient().checkUserTrust(userId).isCrossSigningVerified()).toBe(trust); + }); + + test.each([ + ["@TT:h", true], + ["@TF:h", false], + ["@FT:h", true], + ["@FF:h", false]]) + ("behaves well for device trust %s", (userId, trust) => { + expect(mkClient().checkDeviceTrust(userId, "device").isVerified()).toBe(trust); + }); +}); + +describe("shieldStatusForMembership self-trust behaviour", function () { + beforeAll(() => { + DMRoomMap._sharedInstance = { + getUserIdForRoomId: (roomId) => roomId === "DM" ? "@any:h" : null, + }; + }); + + it.each( + [[true, true], [true, false], + [false, true], [false, false]] + )("2 unverified: returns 'normal', self-trust = %s, DM = %s", async (trusted, dm) => { + const client = mkClient(trusted); + const room = { + roomId: dm ? "DM" : "other", + getEncryptionTargetMembers: () => ["@self:localhost", "@FF1:h", "@FF2:h"].map((userId) => ({userId})), + } + const status = await shieldStatusForMembership(client, room); + expect(status).toEqual("normal"); + }); + + it.each( + [["verified", true, true], ["verified", true, false], + ["verified", false, true], ["warning", false, false]] + )("2 verified: returns '%s', self-trust = %s, DM = %s", async (result, trusted, dm) => { + const client = mkClient(trusted); + const room = { + roomId: dm ? "DM" : "other", + getEncryptionTargetMembers: () => ["@self:localhost", "@TT1:h", "@TT2:h"].map((userId) => ({userId})), + } + const status = await shieldStatusForMembership(client, room); + expect(status).toEqual(result); + }); + + it.each( + [["normal", true, true], ["normal", true, false], + ["normal", false, true], ["warning", false, false]] + )("2 mixed: returns '%s', self-trust = %s, DM = %s", async (result, trusted, dm) => { + const client = mkClient(trusted); + const room = { + roomId: dm ? "DM" : "other", + getEncryptionTargetMembers: () => ["@self:localhost", "@TT1:h", "@FF2:h"].map((userId) => ({userId})), + } + const status = await shieldStatusForMembership(client, room); + expect(status).toEqual(result); + }); + + it.each( + [["verified", true, true], ["verified", true, false], + ["warning", false, true], ["warning", false, false]] + )("0 others: returns '%s', self-trust = %s, DM = %s", async (result, trusted, dm) => { + const client = mkClient(trusted); + const room = { + roomId: dm ? "DM" : "other", + getEncryptionTargetMembers: () => ["@self:localhost"].map((userId) => ({userId})), + } + const status = await shieldStatusForMembership(client, room); + expect(status).toEqual(result); + }); + + it.each( + [["verified", true, true], ["verified", true, false], + ["verified", false, true], ["verified", false, false]] + )("1 verified: returns '%s', self-trust = %s, DM = %s", async (result, trusted, dm) => { + const client = mkClient(trusted); + const room = { + roomId: dm ? "DM" : "other", + getEncryptionTargetMembers: () => ["@self:localhost", "@TT:h"].map((userId) => ({userId})), + } + const status = await shieldStatusForMembership(client, room); + expect(status).toEqual(result); + }); + + it.each( + [["normal", true, true], ["normal", true, false], + ["normal", false, true], ["normal", false, false]] + )("1 unverified: returns '%s', self-trust = %s, DM = %s", async (result, trusted, dm) => { + const client = mkClient(trusted); + const room = { + roomId: dm ? "DM" : "other", + getEncryptionTargetMembers: () => ["@self:localhost", "@FF:h"].map((userId) => ({userId})), + } + const status = await shieldStatusForMembership(client, room); + expect(status).toEqual(result); + }); +}); + +describe("shieldStatusForMembership other-trust behaviour", function () { + beforeAll(() => { + DMRoomMap._sharedInstance = { + getUserIdForRoomId: (roomId) => roomId === "DM" ? "@any:h" : null, + }; + }); + + it.each( + [["warning", true], ["warning", false]] + )("1 verified/untrusted: returns '%s', DM = %s", async (result, dm) => { + const client = mkClient(true); + const room = { + roomId: dm ? "DM" : "other", + getEncryptionTargetMembers: () => ["@self:localhost", "@TF:h"].map((userId) => ({userId})), + } + const status = await shieldStatusForMembership(client, room); + expect(status).toEqual(result); + }); + + it.each( + [["warning", true], ["warning", false]] + )("2 verified/untrusted: returns '%s', DM = %s", async (result, dm) => { + const client = mkClient(true); + const room = { + roomId: dm ? "DM" : "other", + getEncryptionTargetMembers: () => ["@self:localhost", "@TF:h", "@TT: h"].map((userId) => ({userId})), + } + const status = await shieldStatusForMembership(client, room); + expect(status).toEqual(result); + }); + + it.each( + [["normal", true], ["normal", false]] + )("2 unverified/untrusted: returns '%s', DM = %s", async (result, dm) => { + const client = mkClient(true); + const room = { + roomId: dm ? "DM" : "other", + getEncryptionTargetMembers: () => ["@self:localhost", "@FF:h", "@FT: h"].map((userId) => ({userId})), + } + const status = await shieldStatusForMembership(client, room); + expect(status).toEqual(result); + }); +}); From 4f3d4426ea05a9d7a8a0846f3422d13039eab27d Mon Sep 17 00:00:00 2001 From: Zoe Date: Fri, 27 Mar 2020 15:37:59 +0000 Subject: [PATCH 6/7] lint --- test/utils/ShieldUtils-test.js | 58 +++++++++++++++++----------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/test/utils/ShieldUtils-test.js b/test/utils/ShieldUtils-test.js index 5030d9c5c82..973798fa4bf 100644 --- a/test/utils/ShieldUtils-test.js +++ b/test/utils/ShieldUtils-test.js @@ -1,20 +1,20 @@ import { shieldStatusForMembership } from '../../src/utils/ShieldUtils'; import DMRoomMap from '../../src/utils/DMRoomMap'; -function mkClient (selfTrust) { +function mkClient(selfTrust) { return { getUserId: () => "@self:localhost", checkUserTrust: (userId) => ({ - isCrossSigningVerified: () => userId[1] == "T" + isCrossSigningVerified: () => userId[1] == "T", }), checkDeviceTrust: (userId, deviceId) => ({ - isVerified: () => userId === "@self:localhost" ? selfTrust : userId[2] == "T" + isVerified: () => userId === "@self:localhost" ? selfTrust : userId[2] == "T", }), getStoredDevicesForUser: async (userId) => ["DEVICE"], - } + }; } -describe("mkClient self-test", function () { +describe("mkClient self-test", function() { test.each([true, false])("behaves well for self-trust=%s", (v) => { const client = mkClient(v); expect(client.checkDeviceTrust("@self:localhost", "DEVICE").isVerified()).toBe(v); @@ -24,8 +24,8 @@ describe("mkClient self-test", function () { ["@TT:h", true], ["@TF:h", true], ["@FT:h", false], - ["@FF:h", false]]) - ("behaves well for user trust %s", (userId, trust) => { + ["@FF:h", false]], + )("behaves well for user trust %s", (userId, trust) => { expect(mkClient().checkUserTrust(userId).isCrossSigningVerified()).toBe(trust); }); @@ -33,13 +33,13 @@ describe("mkClient self-test", function () { ["@TT:h", true], ["@TF:h", false], ["@FT:h", true], - ["@FF:h", false]]) - ("behaves well for device trust %s", (userId, trust) => { + ["@FF:h", false]], + )("behaves well for device trust %s", (userId, trust) => { expect(mkClient().checkDeviceTrust(userId, "device").isVerified()).toBe(trust); }); }); -describe("shieldStatusForMembership self-trust behaviour", function () { +describe("shieldStatusForMembership self-trust behaviour", function() { beforeAll(() => { DMRoomMap._sharedInstance = { getUserIdForRoomId: (roomId) => roomId === "DM" ? "@any:h" : null, @@ -48,84 +48,84 @@ describe("shieldStatusForMembership self-trust behaviour", function () { it.each( [[true, true], [true, false], - [false, true], [false, false]] + [false, true], [false, false]], )("2 unverified: returns 'normal', self-trust = %s, DM = %s", async (trusted, dm) => { const client = mkClient(trusted); const room = { roomId: dm ? "DM" : "other", getEncryptionTargetMembers: () => ["@self:localhost", "@FF1:h", "@FF2:h"].map((userId) => ({userId})), - } + }; const status = await shieldStatusForMembership(client, room); expect(status).toEqual("normal"); }); it.each( [["verified", true, true], ["verified", true, false], - ["verified", false, true], ["warning", false, false]] + ["verified", false, true], ["warning", false, false]], )("2 verified: returns '%s', self-trust = %s, DM = %s", async (result, trusted, dm) => { const client = mkClient(trusted); const room = { roomId: dm ? "DM" : "other", getEncryptionTargetMembers: () => ["@self:localhost", "@TT1:h", "@TT2:h"].map((userId) => ({userId})), - } + }; const status = await shieldStatusForMembership(client, room); expect(status).toEqual(result); }); it.each( [["normal", true, true], ["normal", true, false], - ["normal", false, true], ["warning", false, false]] + ["normal", false, true], ["warning", false, false]], )("2 mixed: returns '%s', self-trust = %s, DM = %s", async (result, trusted, dm) => { const client = mkClient(trusted); const room = { roomId: dm ? "DM" : "other", getEncryptionTargetMembers: () => ["@self:localhost", "@TT1:h", "@FF2:h"].map((userId) => ({userId})), - } + }; const status = await shieldStatusForMembership(client, room); expect(status).toEqual(result); }); it.each( [["verified", true, true], ["verified", true, false], - ["warning", false, true], ["warning", false, false]] + ["warning", false, true], ["warning", false, false]], )("0 others: returns '%s', self-trust = %s, DM = %s", async (result, trusted, dm) => { const client = mkClient(trusted); const room = { roomId: dm ? "DM" : "other", getEncryptionTargetMembers: () => ["@self:localhost"].map((userId) => ({userId})), - } + }; const status = await shieldStatusForMembership(client, room); expect(status).toEqual(result); }); it.each( [["verified", true, true], ["verified", true, false], - ["verified", false, true], ["verified", false, false]] + ["verified", false, true], ["verified", false, false]], )("1 verified: returns '%s', self-trust = %s, DM = %s", async (result, trusted, dm) => { const client = mkClient(trusted); const room = { roomId: dm ? "DM" : "other", getEncryptionTargetMembers: () => ["@self:localhost", "@TT:h"].map((userId) => ({userId})), - } + }; const status = await shieldStatusForMembership(client, room); expect(status).toEqual(result); }); it.each( [["normal", true, true], ["normal", true, false], - ["normal", false, true], ["normal", false, false]] + ["normal", false, true], ["normal", false, false]], )("1 unverified: returns '%s', self-trust = %s, DM = %s", async (result, trusted, dm) => { const client = mkClient(trusted); const room = { roomId: dm ? "DM" : "other", getEncryptionTargetMembers: () => ["@self:localhost", "@FF:h"].map((userId) => ({userId})), - } + }; const status = await shieldStatusForMembership(client, room); expect(status).toEqual(result); }); }); -describe("shieldStatusForMembership other-trust behaviour", function () { +describe("shieldStatusForMembership other-trust behaviour", function() { beforeAll(() => { DMRoomMap._sharedInstance = { getUserIdForRoomId: (roomId) => roomId === "DM" ? "@any:h" : null, @@ -133,37 +133,37 @@ describe("shieldStatusForMembership other-trust behaviour", function () { }); it.each( - [["warning", true], ["warning", false]] + [["warning", true], ["warning", false]], )("1 verified/untrusted: returns '%s', DM = %s", async (result, dm) => { const client = mkClient(true); const room = { roomId: dm ? "DM" : "other", getEncryptionTargetMembers: () => ["@self:localhost", "@TF:h"].map((userId) => ({userId})), - } + }; const status = await shieldStatusForMembership(client, room); expect(status).toEqual(result); }); it.each( - [["warning", true], ["warning", false]] + [["warning", true], ["warning", false]], )("2 verified/untrusted: returns '%s', DM = %s", async (result, dm) => { const client = mkClient(true); const room = { roomId: dm ? "DM" : "other", getEncryptionTargetMembers: () => ["@self:localhost", "@TF:h", "@TT: h"].map((userId) => ({userId})), - } + }; const status = await shieldStatusForMembership(client, room); expect(status).toEqual(result); }); it.each( - [["normal", true], ["normal", false]] + [["normal", true], ["normal", false]], )("2 unverified/untrusted: returns '%s', DM = %s", async (result, dm) => { const client = mkClient(true); const room = { roomId: dm ? "DM" : "other", getEncryptionTargetMembers: () => ["@self:localhost", "@FF:h", "@FT: h"].map((userId) => ({userId})), - } + }; const status = await shieldStatusForMembership(client, room); expect(status).toEqual(result); }); From 098df07c67ed41b7698b9cda0b0beaa2ecf525db Mon Sep 17 00:00:00 2001 From: Zoe Date: Mon, 30 Mar 2020 10:18:47 +0100 Subject: [PATCH 7/7] review feedback --- src/components/structures/RoomView.js | 4 ++-- src/components/views/rooms/RoomTile.js | 4 ++-- src/utils/ShieldUtils.ts | 6 +++--- test/utils/ShieldUtils-test.js | 20 ++++++++++---------- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index 74572b962a5..1a1f60c7bdc 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -55,7 +55,7 @@ import RightPanelStore from "../../stores/RightPanelStore"; import {haveTileForEvent} from "../views/rooms/EventTile"; import RoomContext from "../../contexts/RoomContext"; import MatrixClientContext from "../../contexts/MatrixClientContext"; -import { shieldStatusForMembership } from '../../utils/ShieldUtils'; +import { shieldStatusForRoom } from '../../utils/ShieldUtils'; const DEBUG = false; let debuglog = function() {}; @@ -820,7 +820,7 @@ export default createReactClass({ /* At this point, the user has encryption on and cross-signing on */ this.setState({ - e2eStatus: await shieldStatusForMembership(this.context, room), + e2eStatus: await shieldStatusForRoom(this.context, room), }); }, diff --git a/src/components/views/rooms/RoomTile.js b/src/components/views/rooms/RoomTile.js index 478d6703b44..0c913b32da9 100644 --- a/src/components/views/rooms/RoomTile.js +++ b/src/components/views/rooms/RoomTile.js @@ -37,7 +37,7 @@ import E2EIcon from './E2EIcon'; import InviteOnlyIcon from './InviteOnlyIcon'; // eslint-disable-next-line camelcase import rate_limited_func from '../../../ratelimitedfunc'; -import { shieldStatusForMembership } from '../../../utils/ShieldUtils'; +import { shieldStatusForRoom } from '../../../utils/ShieldUtils'; export default createReactClass({ displayName: 'RoomTile', @@ -157,7 +157,7 @@ export default createReactClass({ /* At this point, the user has encryption on and cross-signing on */ this.setState({ - e2eStatus: await shieldStatusForMembership(cli, this.props.room), + e2eStatus: await shieldStatusForRoom(cli, this.props.room), }); }, diff --git a/src/utils/ShieldUtils.ts b/src/utils/ShieldUtils.ts index 3c7cae8c8de..ef2d4752939 100644 --- a/src/utils/ShieldUtils.ts +++ b/src/utils/ShieldUtils.ts @@ -17,7 +17,7 @@ interface Room { roomId: string; } -export async function shieldStatusForMembership(client: Client, room: Room): Promise { +export async function shieldStatusForRoom(client: Client, room: Room): Promise { const members = (await room.getEncryptionTargetMembers()).map(({userId}) => userId); const inDMMap = !!DMRoomMap.shared().getUserIdForRoomId(room.roomId); @@ -33,8 +33,8 @@ export async function shieldStatusForMembership(client: Client, room: Room): Pro /* Don't alarm if no other users are verified */ const includeUser = (verified.length > 0) && // Don't alarm for self in rooms where nobody else is verified !inDMMap && // Don't alarm for self in DMs with other users - (members.length !== 2) || // Don't alarm for self in 1:1 chats with other users - (members.length === 1); // Do alarm for self if we're alone in a room + (members.length !== 2) || // Don't alarm for self in 1:1 chats with other users + (members.length === 1); // Do alarm for self if we're alone in a room const targets = includeUser ? [...verified, client.getUserId()] : verified; for (const userId of targets) { const devices = await client.getStoredDevicesForUser(userId); diff --git a/test/utils/ShieldUtils-test.js b/test/utils/ShieldUtils-test.js index 973798fa4bf..949f0ed42bc 100644 --- a/test/utils/ShieldUtils-test.js +++ b/test/utils/ShieldUtils-test.js @@ -1,4 +1,4 @@ -import { shieldStatusForMembership } from '../../src/utils/ShieldUtils'; +import { shieldStatusForRoom } from '../../src/utils/ShieldUtils'; import DMRoomMap from '../../src/utils/DMRoomMap'; function mkClient(selfTrust) { @@ -55,7 +55,7 @@ describe("shieldStatusForMembership self-trust behaviour", function() { roomId: dm ? "DM" : "other", getEncryptionTargetMembers: () => ["@self:localhost", "@FF1:h", "@FF2:h"].map((userId) => ({userId})), }; - const status = await shieldStatusForMembership(client, room); + const status = await shieldStatusForRoom(client, room); expect(status).toEqual("normal"); }); @@ -68,7 +68,7 @@ describe("shieldStatusForMembership self-trust behaviour", function() { roomId: dm ? "DM" : "other", getEncryptionTargetMembers: () => ["@self:localhost", "@TT1:h", "@TT2:h"].map((userId) => ({userId})), }; - const status = await shieldStatusForMembership(client, room); + const status = await shieldStatusForRoom(client, room); expect(status).toEqual(result); }); @@ -81,7 +81,7 @@ describe("shieldStatusForMembership self-trust behaviour", function() { roomId: dm ? "DM" : "other", getEncryptionTargetMembers: () => ["@self:localhost", "@TT1:h", "@FF2:h"].map((userId) => ({userId})), }; - const status = await shieldStatusForMembership(client, room); + const status = await shieldStatusForRoom(client, room); expect(status).toEqual(result); }); @@ -94,7 +94,7 @@ describe("shieldStatusForMembership self-trust behaviour", function() { roomId: dm ? "DM" : "other", getEncryptionTargetMembers: () => ["@self:localhost"].map((userId) => ({userId})), }; - const status = await shieldStatusForMembership(client, room); + const status = await shieldStatusForRoom(client, room); expect(status).toEqual(result); }); @@ -107,7 +107,7 @@ describe("shieldStatusForMembership self-trust behaviour", function() { roomId: dm ? "DM" : "other", getEncryptionTargetMembers: () => ["@self:localhost", "@TT:h"].map((userId) => ({userId})), }; - const status = await shieldStatusForMembership(client, room); + const status = await shieldStatusForRoom(client, room); expect(status).toEqual(result); }); @@ -120,7 +120,7 @@ describe("shieldStatusForMembership self-trust behaviour", function() { roomId: dm ? "DM" : "other", getEncryptionTargetMembers: () => ["@self:localhost", "@FF:h"].map((userId) => ({userId})), }; - const status = await shieldStatusForMembership(client, room); + const status = await shieldStatusForRoom(client, room); expect(status).toEqual(result); }); }); @@ -140,7 +140,7 @@ describe("shieldStatusForMembership other-trust behaviour", function() { roomId: dm ? "DM" : "other", getEncryptionTargetMembers: () => ["@self:localhost", "@TF:h"].map((userId) => ({userId})), }; - const status = await shieldStatusForMembership(client, room); + const status = await shieldStatusForRoom(client, room); expect(status).toEqual(result); }); @@ -152,7 +152,7 @@ describe("shieldStatusForMembership other-trust behaviour", function() { roomId: dm ? "DM" : "other", getEncryptionTargetMembers: () => ["@self:localhost", "@TF:h", "@TT: h"].map((userId) => ({userId})), }; - const status = await shieldStatusForMembership(client, room); + const status = await shieldStatusForRoom(client, room); expect(status).toEqual(result); }); @@ -164,7 +164,7 @@ describe("shieldStatusForMembership other-trust behaviour", function() { roomId: dm ? "DM" : "other", getEncryptionTargetMembers: () => ["@self:localhost", "@FF:h", "@FT: h"].map((userId) => ({userId})), }; - const status = await shieldStatusForMembership(client, room); + const status = await shieldStatusForRoom(client, room); expect(status).toEqual(result); }); });