2022-05-02 07:57:35 +00:00
|
|
|
/*
|
|
|
|
Copyright 2022 The Matrix.org Foundation C.I.C.
|
|
|
|
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
you may not use this file except in compliance with the License.
|
|
|
|
You may obtain a copy of the License at
|
|
|
|
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
See the License for the specific language governing permissions and
|
|
|
|
limitations under the License.
|
|
|
|
*/
|
|
|
|
|
2022-12-12 11:24:14 +00:00
|
|
|
import { MatrixClient, Room } from "matrix-js-sdk/src/matrix";
|
2022-05-02 07:57:35 +00:00
|
|
|
|
2022-12-12 11:24:14 +00:00
|
|
|
import { shieldStatusForRoom } from "../../src/utils/ShieldUtils";
|
|
|
|
import DMRoomMap from "../../src/utils/DMRoomMap";
|
2020-03-27 15:25:44 +00:00
|
|
|
|
2022-05-02 07:57:35 +00:00
|
|
|
function mkClient(selfTrust = false) {
|
2020-03-27 15:25:44 +00:00
|
|
|
return {
|
|
|
|
getUserId: () => "@self:localhost",
|
2023-04-24 13:19:46 +00:00
|
|
|
getCrypto: () => ({
|
|
|
|
getDeviceVerificationStatus: (userId: string, deviceId: string) =>
|
|
|
|
Promise.resolve({
|
|
|
|
isVerified: () => (userId === "@self:localhost" ? selfTrust : userId[2] == "T"),
|
|
|
|
}),
|
|
|
|
}),
|
2023-02-13 11:39:16 +00:00
|
|
|
checkUserTrust: (userId: string) => ({
|
2020-03-27 15:37:59 +00:00
|
|
|
isCrossSigningVerified: () => userId[1] == "T",
|
2020-03-30 15:33:16 +00:00
|
|
|
wasCrossSigningVerified: () => userId[1] == "T" || userId[1] == "W",
|
2020-03-27 15:25:44 +00:00
|
|
|
}),
|
2023-02-13 11:39:16 +00:00
|
|
|
getStoredDevicesForUser: (userId: string) => ["DEVICE"],
|
2022-05-02 07:57:35 +00:00
|
|
|
} as unknown as MatrixClient;
|
2020-03-27 15:25:44 +00:00
|
|
|
}
|
|
|
|
|
2022-12-12 11:24:14 +00:00
|
|
|
describe("mkClient self-test", function () {
|
2023-04-24 13:19:46 +00:00
|
|
|
test.each([true, false])("behaves well for self-trust=%s", async (v) => {
|
2020-03-27 15:25:44 +00:00
|
|
|
const client = mkClient(v);
|
2023-04-24 13:19:46 +00:00
|
|
|
const status = await client.getCrypto()!.getDeviceVerificationStatus("@self:localhost", "DEVICE");
|
|
|
|
expect(status?.isVerified()).toBe(v);
|
2020-03-27 15:25:44 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
test.each([
|
|
|
|
["@TT:h", true],
|
|
|
|
["@TF:h", true],
|
|
|
|
["@FT:h", false],
|
2022-12-12 11:24:14 +00:00
|
|
|
["@FF:h", false],
|
|
|
|
])("behaves well for user trust %s", (userId, trust) => {
|
2020-03-27 15:25:44 +00:00
|
|
|
expect(mkClient().checkUserTrust(userId).isCrossSigningVerified()).toBe(trust);
|
|
|
|
});
|
|
|
|
|
|
|
|
test.each([
|
|
|
|
["@TT:h", true],
|
|
|
|
["@TF:h", false],
|
|
|
|
["@FT:h", true],
|
2022-12-12 11:24:14 +00:00
|
|
|
["@FF:h", false],
|
2023-04-24 13:19:46 +00:00
|
|
|
])("behaves well for device trust %s", async (userId, trust) => {
|
|
|
|
const status = await mkClient().getCrypto()!.getDeviceVerificationStatus(userId, "device");
|
|
|
|
expect(status?.isVerified()).toBe(trust);
|
2020-03-27 15:25:44 +00:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2022-12-12 11:24:14 +00:00
|
|
|
describe("shieldStatusForMembership self-trust behaviour", function () {
|
2020-03-27 15:25:44 +00:00
|
|
|
beforeAll(() => {
|
2022-05-02 07:57:35 +00:00
|
|
|
const mockInstance = {
|
2023-02-13 11:39:16 +00:00
|
|
|
getUserIdForRoomId: (roomId: string) => (roomId === "DM" ? "@any:h" : null),
|
2022-05-02 07:57:35 +00:00
|
|
|
} as unknown as DMRoomMap;
|
2022-12-12 11:24:14 +00:00
|
|
|
jest.spyOn(DMRoomMap, "shared").mockReturnValue(mockInstance);
|
2022-05-02 07:57:35 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
afterAll(() => {
|
2022-12-12 11:24:14 +00:00
|
|
|
jest.spyOn(DMRoomMap, "shared").mockRestore();
|
2020-03-27 15:25:44 +00:00
|
|
|
});
|
|
|
|
|
2022-12-12 11:24:14 +00:00
|
|
|
it.each([
|
|
|
|
[true, true],
|
|
|
|
[true, false],
|
|
|
|
[false, true],
|
|
|
|
[false, false],
|
|
|
|
])("2 unverified: returns 'normal', self-trust = %s, DM = %s", async (trusted, dm) => {
|
2020-03-27 15:25:44 +00:00
|
|
|
const client = mkClient(trusted);
|
|
|
|
const room = {
|
|
|
|
roomId: dm ? "DM" : "other",
|
2021-06-29 12:11:58 +00:00
|
|
|
getEncryptionTargetMembers: () => ["@self:localhost", "@FF1:h", "@FF2:h"].map((userId) => ({ userId })),
|
2022-05-02 07:57:35 +00:00
|
|
|
} as unknown as Room;
|
2020-03-30 09:18:47 +00:00
|
|
|
const status = await shieldStatusForRoom(client, room);
|
2020-03-27 15:25:44 +00:00
|
|
|
expect(status).toEqual("normal");
|
|
|
|
});
|
|
|
|
|
2022-12-12 11:24:14 +00:00
|
|
|
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) => {
|
2020-03-27 15:25:44 +00:00
|
|
|
const client = mkClient(trusted);
|
|
|
|
const room = {
|
|
|
|
roomId: dm ? "DM" : "other",
|
2021-06-29 12:11:58 +00:00
|
|
|
getEncryptionTargetMembers: () => ["@self:localhost", "@TT1:h", "@TT2:h"].map((userId) => ({ userId })),
|
2022-05-02 07:57:35 +00:00
|
|
|
} as unknown as Room;
|
2020-03-30 09:18:47 +00:00
|
|
|
const status = await shieldStatusForRoom(client, room);
|
2020-03-27 15:25:44 +00:00
|
|
|
expect(status).toEqual(result);
|
|
|
|
});
|
|
|
|
|
2022-12-12 11:24:14 +00:00
|
|
|
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) => {
|
2020-03-27 15:25:44 +00:00
|
|
|
const client = mkClient(trusted);
|
|
|
|
const room = {
|
|
|
|
roomId: dm ? "DM" : "other",
|
2021-06-29 12:11:58 +00:00
|
|
|
getEncryptionTargetMembers: () => ["@self:localhost", "@TT1:h", "@FF2:h"].map((userId) => ({ userId })),
|
2022-05-02 07:57:35 +00:00
|
|
|
} as unknown as Room;
|
2020-03-30 09:18:47 +00:00
|
|
|
const status = await shieldStatusForRoom(client, room);
|
2020-03-27 15:25:44 +00:00
|
|
|
expect(status).toEqual(result);
|
|
|
|
});
|
|
|
|
|
2022-12-12 11:24:14 +00:00
|
|
|
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) => {
|
2020-03-27 15:25:44 +00:00
|
|
|
const client = mkClient(trusted);
|
|
|
|
const room = {
|
|
|
|
roomId: dm ? "DM" : "other",
|
2021-06-29 12:11:58 +00:00
|
|
|
getEncryptionTargetMembers: () => ["@self:localhost"].map((userId) => ({ userId })),
|
2022-05-02 07:57:35 +00:00
|
|
|
} as unknown as Room;
|
2020-03-30 09:18:47 +00:00
|
|
|
const status = await shieldStatusForRoom(client, room);
|
2020-03-27 15:25:44 +00:00
|
|
|
expect(status).toEqual(result);
|
|
|
|
});
|
|
|
|
|
2022-12-12 11:24:14 +00:00
|
|
|
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) => {
|
2020-03-27 15:25:44 +00:00
|
|
|
const client = mkClient(trusted);
|
|
|
|
const room = {
|
|
|
|
roomId: dm ? "DM" : "other",
|
2021-06-29 12:11:58 +00:00
|
|
|
getEncryptionTargetMembers: () => ["@self:localhost", "@TT:h"].map((userId) => ({ userId })),
|
2022-05-02 07:57:35 +00:00
|
|
|
} as unknown as Room;
|
2020-03-30 09:18:47 +00:00
|
|
|
const status = await shieldStatusForRoom(client, room);
|
2020-03-27 15:25:44 +00:00
|
|
|
expect(status).toEqual(result);
|
|
|
|
});
|
|
|
|
|
2022-12-12 11:24:14 +00:00
|
|
|
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) => {
|
2020-03-27 15:25:44 +00:00
|
|
|
const client = mkClient(trusted);
|
|
|
|
const room = {
|
|
|
|
roomId: dm ? "DM" : "other",
|
2021-06-29 12:11:58 +00:00
|
|
|
getEncryptionTargetMembers: () => ["@self:localhost", "@FF:h"].map((userId) => ({ userId })),
|
2022-05-02 07:57:35 +00:00
|
|
|
} as unknown as Room;
|
2020-03-30 09:18:47 +00:00
|
|
|
const status = await shieldStatusForRoom(client, room);
|
2020-03-27 15:25:44 +00:00
|
|
|
expect(status).toEqual(result);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2022-12-12 11:24:14 +00:00
|
|
|
describe("shieldStatusForMembership other-trust behaviour", function () {
|
2020-03-27 15:25:44 +00:00
|
|
|
beforeAll(() => {
|
2022-05-02 07:57:35 +00:00
|
|
|
const mockInstance = {
|
2023-02-13 11:39:16 +00:00
|
|
|
getUserIdForRoomId: (roomId: string) => (roomId === "DM" ? "@any:h" : null),
|
2022-05-02 07:57:35 +00:00
|
|
|
} as unknown as DMRoomMap;
|
2022-12-12 11:24:14 +00:00
|
|
|
jest.spyOn(DMRoomMap, "shared").mockReturnValue(mockInstance);
|
2020-03-27 15:25:44 +00:00
|
|
|
});
|
|
|
|
|
2022-12-12 11:24:14 +00:00
|
|
|
it.each([
|
|
|
|
["warning", true],
|
|
|
|
["warning", false],
|
|
|
|
])("1 verified/untrusted: returns '%s', DM = %s", async (result, dm) => {
|
2020-03-27 15:25:44 +00:00
|
|
|
const client = mkClient(true);
|
|
|
|
const room = {
|
|
|
|
roomId: dm ? "DM" : "other",
|
2021-06-29 12:11:58 +00:00
|
|
|
getEncryptionTargetMembers: () => ["@self:localhost", "@TF:h"].map((userId) => ({ userId })),
|
2022-05-02 07:57:35 +00:00
|
|
|
} as unknown as Room;
|
2020-03-30 09:18:47 +00:00
|
|
|
const status = await shieldStatusForRoom(client, room);
|
2020-03-27 15:25:44 +00:00
|
|
|
expect(status).toEqual(result);
|
|
|
|
});
|
|
|
|
|
2022-12-12 11:24:14 +00:00
|
|
|
it.each([
|
|
|
|
["warning", true],
|
|
|
|
["warning", false],
|
|
|
|
])("2 verified/untrusted: returns '%s', DM = %s", async (result, dm) => {
|
2020-03-27 15:25:44 +00:00
|
|
|
const client = mkClient(true);
|
|
|
|
const room = {
|
|
|
|
roomId: dm ? "DM" : "other",
|
2021-06-29 12:11:58 +00:00
|
|
|
getEncryptionTargetMembers: () => ["@self:localhost", "@TF:h", "@TT:h"].map((userId) => ({ userId })),
|
2022-05-02 07:57:35 +00:00
|
|
|
} as unknown as Room;
|
2020-03-30 09:18:47 +00:00
|
|
|
const status = await shieldStatusForRoom(client, room);
|
2020-03-27 15:25:44 +00:00
|
|
|
expect(status).toEqual(result);
|
|
|
|
});
|
|
|
|
|
2022-12-12 11:24:14 +00:00
|
|
|
it.each([
|
|
|
|
["normal", true],
|
|
|
|
["normal", false],
|
|
|
|
])("2 unverified/untrusted: returns '%s', DM = %s", async (result, dm) => {
|
2020-03-27 15:25:44 +00:00
|
|
|
const client = mkClient(true);
|
|
|
|
const room = {
|
|
|
|
roomId: dm ? "DM" : "other",
|
2021-06-29 12:11:58 +00:00
|
|
|
getEncryptionTargetMembers: () => ["@self:localhost", "@FF:h", "@FT:h"].map((userId) => ({ userId })),
|
2022-05-02 07:57:35 +00:00
|
|
|
} as unknown as Room;
|
2020-03-30 15:33:16 +00:00
|
|
|
const status = await shieldStatusForRoom(client, room);
|
|
|
|
expect(status).toEqual(result);
|
|
|
|
});
|
|
|
|
|
2022-12-12 11:24:14 +00:00
|
|
|
it.each([
|
|
|
|
["warning", true],
|
|
|
|
["warning", false],
|
|
|
|
])("2 was verified: returns '%s', DM = %s", async (result, dm) => {
|
2020-03-30 15:33:16 +00:00
|
|
|
const client = mkClient(true);
|
|
|
|
const room = {
|
|
|
|
roomId: dm ? "DM" : "other",
|
2021-06-29 12:11:58 +00:00
|
|
|
getEncryptionTargetMembers: () => ["@self:localhost", "@WF:h", "@FT:h"].map((userId) => ({ userId })),
|
2022-05-02 07:57:35 +00:00
|
|
|
} as unknown as Room;
|
2020-03-30 09:18:47 +00:00
|
|
|
const status = await shieldStatusForRoom(client, room);
|
2020-03-27 15:25:44 +00:00
|
|
|
expect(status).toEqual(result);
|
|
|
|
});
|
|
|
|
});
|