Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

[Backport staging] Fix detection of encryption for all users in a room #10489

Merged
merged 1 commit into from
Mar 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 11 additions & 6 deletions src/createRoom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -398,16 +398,21 @@ export default async function createRoom(opts: IOpts): Promise<string | null> {
export async function canEncryptToAllUsers(client: MatrixClient, userIds: string[]): Promise<boolean> {
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
Expand Down
67 changes: 44 additions & 23 deletions test/createRoom-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<MatrixClient>;
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);
});
});