diff --git a/src/createRoom.ts b/src/createRoom.ts index daf3d56c181..bf2bfdcd124 100644 --- a/src/createRoom.ts +++ b/src/createRoom.ts @@ -398,16 +398,21 @@ export default async function createRoom(opts: IOpts): Promise { export async function canEncryptToAllUsers(client: MatrixClient, userIds: string[]): Promise { try { const usersDeviceMap = await client.downloadKeys(userIds); - // { "@user:host": { "DEVICE": {...}, ... }, ... } - return Object.values(usersDeviceMap).every( - (userDevices) => - // { "DEVICE": {...}, ... } - Object.keys(userDevices).length > 0, - ); + + // There are no devices at all. + if (usersDeviceMap.size === 0) return false; + + for (const devices of usersDeviceMap.values()) { + if (devices.size === 0) { + return false; + } + } } catch (e) { logger.error("Error determining if it's possible to encrypt to all users: ", e); return false; // assume not } + + return true; } // Similar to ensureDMExists but also adds creation content diff --git a/test/createRoom-test.ts b/test/createRoom-test.ts index fc49c5656aa..d89ee82ddb1 100644 --- a/test/createRoom-test.ts +++ b/test/createRoom-test.ts @@ -147,35 +147,56 @@ describe("createRoom", () => { }); describe("canEncryptToAllUsers", () => { - const trueUser = new Map([ - [ - "@goodUser:localhost", - new Map([ - ["DEV1", {} as unknown as DeviceInfo], - ["DEV2", {} as unknown as DeviceInfo], - ]), - ], - ]); + const user1Id = "@user1:example.com"; + const user2Id = "@user2:example.com"; - const falseUser = { - "@badUser:localhost": {}, - }; + const devices = new Map([ + ["DEV1", {} as unknown as DeviceInfo], + ["DEV2", {} as unknown as DeviceInfo], + ]); let client: Mocked; - beforeEach(() => { - stubClient(); - client = mocked(MatrixClientPeg.get()); + + beforeAll(() => { + client = mocked(stubClient()); }); - it("returns true if all devices have crypto", async () => { - client.downloadKeys.mockResolvedValue(trueUser); - const response = await canEncryptToAllUsers(client, ["@goodUser:localhost"]); - expect(response).toBe(true); + it("should return false if download keys does not return any user", async () => { + client.downloadKeys.mockResolvedValue(new Map()); + const result = await canEncryptToAllUsers(client, [user1Id, user2Id]); + expect(result).toBe(false); }); - it("returns false if not all users have crypto", async () => { - client.downloadKeys.mockResolvedValue({ ...trueUser, ...falseUser }); - const response = await canEncryptToAllUsers(client, ["@goodUser:localhost", "@badUser:localhost"]); - expect(response).toBe(false); + it("should return false if none of the users has a device", async () => { + client.downloadKeys.mockResolvedValue( + new Map([ + [user1Id, new Map()], + [user2Id, new Map()], + ]), + ); + const result = await canEncryptToAllUsers(client, [user1Id, user2Id]); + expect(result).toBe(false); + }); + + it("should return false if some of the users don't have a device", async () => { + client.downloadKeys.mockResolvedValue( + new Map([ + [user1Id, new Map()], + [user2Id, devices], + ]), + ); + const result = await canEncryptToAllUsers(client, [user1Id, user2Id]); + expect(result).toBe(false); + }); + + it("should return true if all users have a device", async () => { + client.downloadKeys.mockResolvedValue( + new Map([ + [user1Id, devices], + [user2Id, devices], + ]), + ); + const result = await canEncryptToAllUsers(client, [user1Id, user2Id]); + expect(result).toBe(true); }); });