You've already forked matrix-js-sdk
mirror of
https://github.com/matrix-org/matrix-js-sdk.git
synced 2025-07-08 05:01:59 +03:00
Rewrite megolm integration tests with async arrow functions (#2519)
This commit is contained in:
@ -24,13 +24,13 @@ import {
|
|||||||
IContent,
|
IContent,
|
||||||
IEvent,
|
IEvent,
|
||||||
IClaimOTKsResult,
|
IClaimOTKsResult,
|
||||||
|
IJoinedRoom,
|
||||||
ISyncResponse,
|
ISyncResponse,
|
||||||
IDownloadKeyResult,
|
IDownloadKeyResult,
|
||||||
MatrixEvent,
|
MatrixEvent,
|
||||||
MatrixEventEvent,
|
MatrixEventEvent,
|
||||||
} from "../../src/matrix";
|
} from "../../src/matrix";
|
||||||
import { IDeviceKeys } from "../../src/crypto/dehydration";
|
import { IDeviceKeys } from "../../src/crypto/dehydration";
|
||||||
import { ISignatures } from "../../src/@types/signed";
|
|
||||||
|
|
||||||
const ROOM_ID = "!room:id";
|
const ROOM_ID = "!room:id";
|
||||||
|
|
||||||
@ -75,18 +75,17 @@ function encryptOlmEvent(opts: {
|
|||||||
type: opts.plaintype || 'm.test',
|
type: opts.plaintype || 'm.test',
|
||||||
};
|
};
|
||||||
|
|
||||||
const event = {
|
return {
|
||||||
content: {
|
content: {
|
||||||
algorithm: 'm.olm.v1.curve25519-aes-sha2',
|
algorithm: 'm.olm.v1.curve25519-aes-sha2',
|
||||||
ciphertext: {},
|
ciphertext: {
|
||||||
|
[opts.recipient.getDeviceKey()]: opts.p2pSession.encrypt(JSON.stringify(plaintext)),
|
||||||
|
},
|
||||||
sender_key: opts.senderKey,
|
sender_key: opts.senderKey,
|
||||||
},
|
},
|
||||||
sender: opts.sender || '@bob:xyz',
|
sender: opts.sender || '@bob:xyz',
|
||||||
type: 'm.room.encrypted',
|
type: 'm.room.encrypted',
|
||||||
};
|
};
|
||||||
event.content.ciphertext[opts.recipient.getDeviceKey()] =
|
|
||||||
opts.p2pSession.encrypt(JSON.stringify(plaintext));
|
|
||||||
return event;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// encrypt an event with megolm
|
// encrypt an event with megolm
|
||||||
@ -151,43 +150,54 @@ function encryptGroupSessionKey(opts: {
|
|||||||
|
|
||||||
// get a /sync response which contains a single room (ROOM_ID), with the members given
|
// get a /sync response which contains a single room (ROOM_ID), with the members given
|
||||||
function getSyncResponse(roomMembers: string[]): ISyncResponse {
|
function getSyncResponse(roomMembers: string[]): ISyncResponse {
|
||||||
const roomResponse = {
|
const roomResponse: IJoinedRoom = {
|
||||||
|
summary: {
|
||||||
|
"m.heroes": [],
|
||||||
|
"m.joined_member_count": roomMembers.length,
|
||||||
|
"m.invited_member_count": roomMembers.length,
|
||||||
|
},
|
||||||
state: {
|
state: {
|
||||||
events: [
|
events: [
|
||||||
testUtils.mkEvent({
|
testUtils.mkEventCustom({
|
||||||
|
sender: roomMembers[0],
|
||||||
type: 'm.room.encryption',
|
type: 'm.room.encryption',
|
||||||
skey: '',
|
state_key: '',
|
||||||
content: {
|
content: {
|
||||||
algorithm: 'm.megolm.v1.aes-sha2',
|
algorithm: 'm.megolm.v1.aes-sha2',
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
timeline: {
|
||||||
|
events: [],
|
||||||
|
prev_batch: '',
|
||||||
|
},
|
||||||
|
ephemeral: { events: [] },
|
||||||
|
account_data: { events: [] },
|
||||||
|
unread_notifications: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
for (let i = 0; i < roomMembers.length; i++) {
|
for (let i = 0; i < roomMembers.length; i++) {
|
||||||
roomResponse.state.events.push(
|
roomResponse.state.events.push(
|
||||||
testUtils.mkMembership({
|
testUtils.mkMembershipCustom({
|
||||||
mship: 'join',
|
membership: 'join',
|
||||||
sender: roomMembers[i],
|
sender: roomMembers[i],
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const syncResponse = {
|
return {
|
||||||
next_batch: "1",
|
next_batch: "1",
|
||||||
rooms: {
|
rooms: {
|
||||||
join: {},
|
join: { [ROOM_ID]: roomResponse },
|
||||||
invite: {},
|
invite: {},
|
||||||
leave: {},
|
leave: {},
|
||||||
},
|
},
|
||||||
account_data: { events: [] },
|
account_data: { events: [] },
|
||||||
};
|
};
|
||||||
syncResponse.rooms.join[ROOM_ID] = roomResponse;
|
|
||||||
return syncResponse;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
describe("megolm", function() {
|
describe("megolm", () => {
|
||||||
if (!global.Olm) {
|
if (!global.Olm) {
|
||||||
logger.warn('not running megolm tests: Olm not present');
|
logger.warn('not running megolm tests: Olm not present');
|
||||||
return;
|
return;
|
||||||
@ -218,21 +228,12 @@ describe("megolm", function() {
|
|||||||
};
|
};
|
||||||
const j = anotherjson.stringify(testDeviceKeys);
|
const j = anotherjson.stringify(testDeviceKeys);
|
||||||
const sig = testOlmAccount.sign(j);
|
const sig = testOlmAccount.sign(j);
|
||||||
testDeviceKeys.signatures = {};
|
testDeviceKeys.signatures = { [userId]: { 'ed25519:DEVICE_ID': sig } };
|
||||||
testDeviceKeys.signatures[userId] = {
|
|
||||||
'ed25519:DEVICE_ID': sig,
|
|
||||||
};
|
|
||||||
|
|
||||||
const queryResponse = {
|
return {
|
||||||
device_keys: {},
|
device_keys: { [userId]: { 'DEVICE_ID': testDeviceKeys } },
|
||||||
failures: {},
|
failures: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
queryResponse.device_keys[userId] = {
|
|
||||||
'DEVICE_ID': testDeviceKeys,
|
|
||||||
};
|
|
||||||
|
|
||||||
return queryResponse;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -249,26 +250,21 @@ describe("megolm", function() {
|
|||||||
|
|
||||||
const keyId = Object.keys(testOneTimeKeys.curve25519)[0];
|
const keyId = Object.keys(testOneTimeKeys.curve25519)[0];
|
||||||
const oneTimeKey: string = testOneTimeKeys.curve25519[keyId];
|
const oneTimeKey: string = testOneTimeKeys.curve25519[keyId];
|
||||||
const keyResult: { key: string, signatures: ISignatures } = {
|
const unsignedKeyResult = { key: oneTimeKey };
|
||||||
key: oneTimeKey,
|
const j = anotherjson.stringify(unsignedKeyResult);
|
||||||
signatures: {},
|
|
||||||
};
|
|
||||||
const j = anotherjson.stringify({ key: oneTimeKey });
|
|
||||||
const sig = testOlmAccount.sign(j);
|
const sig = testOlmAccount.sign(j);
|
||||||
keyResult.signatures[userId] = {
|
const keyResult = {
|
||||||
'ed25519:DEVICE_ID': sig,
|
...unsignedKeyResult,
|
||||||
|
signatures: { [userId]: { 'ed25519:DEVICE_ID': sig } },
|
||||||
};
|
};
|
||||||
|
|
||||||
const claimResponse = { one_time_keys: {}, failures: {} };
|
return {
|
||||||
claimResponse.one_time_keys[userId] = {
|
one_time_keys: { [userId]: { 'DEVICE_ID': { ['signed_curve25519:' + keyId]: keyResult } } },
|
||||||
'DEVICE_ID': {},
|
failures: {},
|
||||||
};
|
};
|
||||||
claimResponse.one_time_keys[userId].DEVICE_ID['signed_curve25519:' + keyId] =
|
|
||||||
keyResult;
|
|
||||||
return claimResponse;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
beforeEach(async function() {
|
beforeEach(async () => {
|
||||||
aliceTestClient = new TestClient(
|
aliceTestClient = new TestClient(
|
||||||
"@alice:localhost", "xzcvb", "akjgkrgjs",
|
"@alice:localhost", "xzcvb", "akjgkrgjs",
|
||||||
);
|
);
|
||||||
@ -280,14 +276,11 @@ describe("megolm", function() {
|
|||||||
testSenderKey = testE2eKeys.curve25519;
|
testSenderKey = testE2eKeys.curve25519;
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(function() {
|
afterEach(() => aliceTestClient.stop());
|
||||||
return aliceTestClient.stop();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Alice receives a megolm message", function() {
|
it("Alice receives a megolm message", async () => {
|
||||||
return aliceTestClient.start().then(() => {
|
await aliceTestClient.start();
|
||||||
return createOlmSession(testOlmAccount, aliceTestClient);
|
const p2pSession = await createOlmSession(testOlmAccount, aliceTestClient);
|
||||||
}).then((p2pSession) => {
|
|
||||||
const groupSession = new Olm.OutboundGroupSession();
|
const groupSession = new Olm.OutboundGroupSession();
|
||||||
groupSession.create();
|
groupSession.create();
|
||||||
|
|
||||||
@ -314,39 +307,31 @@ describe("megolm", function() {
|
|||||||
events: [roomKeyEncrypted],
|
events: [roomKeyEncrypted],
|
||||||
},
|
},
|
||||||
rooms: {
|
rooms: {
|
||||||
join: {},
|
join: {
|
||||||
|
[ROOM_ID]: { timeline: { events: [messageEncrypted] } },
|
||||||
},
|
},
|
||||||
};
|
|
||||||
syncResponse.rooms.join[ROOM_ID] = {
|
|
||||||
timeline: {
|
|
||||||
events: [messageEncrypted],
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
aliceTestClient.httpBackend.when("GET", "/sync").respond(200, syncResponse);
|
aliceTestClient.httpBackend.when("GET", "/sync").respond(200, syncResponse);
|
||||||
return aliceTestClient.flushSync();
|
await aliceTestClient.flushSync();
|
||||||
}).then(function() {
|
|
||||||
const room = aliceTestClient.client.getRoom(ROOM_ID);
|
const room = aliceTestClient.client.getRoom(ROOM_ID);
|
||||||
const event = room.getLiveTimeline().getEvents()[0];
|
const event = room.getLiveTimeline().getEvents()[0];
|
||||||
expect(event.isEncrypted()).toBe(true);
|
expect(event.isEncrypted()).toBe(true);
|
||||||
return testUtils.awaitDecryption(event);
|
const decryptedEvent = await testUtils.awaitDecryption(event);
|
||||||
}).then((event) => {
|
expect(decryptedEvent.getContent().body).toEqual('42');
|
||||||
expect(event.getContent().body).toEqual('42');
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Alice receives a megolm message before the session keys", function() {
|
it("Alice receives a megolm message before the session keys", async () => {
|
||||||
// https://github.com/vector-im/element-web/issues/2273
|
// https://github.com/vector-im/element-web/issues/2273
|
||||||
let roomKeyEncrypted;
|
await aliceTestClient.start();
|
||||||
|
const p2pSession = await createOlmSession(testOlmAccount, aliceTestClient);
|
||||||
return aliceTestClient.start().then(() => {
|
|
||||||
return createOlmSession(testOlmAccount, aliceTestClient);
|
|
||||||
}).then((p2pSession) => {
|
|
||||||
const groupSession = new Olm.OutboundGroupSession();
|
const groupSession = new Olm.OutboundGroupSession();
|
||||||
groupSession.create();
|
groupSession.create();
|
||||||
|
|
||||||
// make the room_key event, but don't send it yet
|
// make the room_key event, but don't send it yet
|
||||||
roomKeyEncrypted = encryptGroupSessionKey({
|
const roomKeyEncrypted = encryptGroupSessionKey({
|
||||||
senderKey: testSenderKey,
|
senderKey: testSenderKey,
|
||||||
recipient: aliceTestClient,
|
recipient: aliceTestClient,
|
||||||
p2pSession: p2pSession,
|
p2pSession: p2pSession,
|
||||||
@ -362,58 +347,43 @@ describe("megolm", function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Alice just gets the message event to start with
|
// Alice just gets the message event to start with
|
||||||
const syncResponse = {
|
aliceTestClient.httpBackend.when("GET", "/sync").respond(200, {
|
||||||
next_batch: 1,
|
next_batch: 1,
|
||||||
rooms: {
|
rooms: { join: { [ROOM_ID]: { timeline: { events: [messageEncrypted] } } } },
|
||||||
join: {},
|
});
|
||||||
},
|
await aliceTestClient.flushSync();
|
||||||
};
|
|
||||||
syncResponse.rooms.join[ROOM_ID] = {
|
|
||||||
timeline: {
|
|
||||||
events: [messageEncrypted],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
aliceTestClient.httpBackend.when("GET", "/sync").respond(200, syncResponse);
|
|
||||||
return aliceTestClient.flushSync();
|
|
||||||
}).then(function() {
|
|
||||||
const room = aliceTestClient.client.getRoom(ROOM_ID);
|
const room = aliceTestClient.client.getRoom(ROOM_ID);
|
||||||
const event = room.getLiveTimeline().getEvents()[0];
|
expect(room.getLiveTimeline().getEvents()[0].getContent().msgtype).toEqual('m.bad.encrypted');
|
||||||
expect(event.getContent().msgtype).toEqual('m.bad.encrypted');
|
|
||||||
|
|
||||||
// now she gets the room_key event
|
// now she gets the room_key event
|
||||||
const syncResponse = {
|
aliceTestClient.httpBackend.when("GET", "/sync").respond(200, {
|
||||||
next_batch: 2,
|
next_batch: 2,
|
||||||
to_device: {
|
to_device: {
|
||||||
events: [roomKeyEncrypted],
|
events: [roomKeyEncrypted],
|
||||||
},
|
},
|
||||||
};
|
});
|
||||||
|
await aliceTestClient.flushSync();
|
||||||
|
|
||||||
aliceTestClient.httpBackend.when("GET", "/sync").respond(200, syncResponse);
|
|
||||||
return aliceTestClient.flushSync();
|
|
||||||
}).then(function() {
|
|
||||||
const room = aliceTestClient.client.getRoom(ROOM_ID);
|
|
||||||
const event = room.getLiveTimeline().getEvents()[0];
|
const event = room.getLiveTimeline().getEvents()[0];
|
||||||
|
|
||||||
|
let decryptedEvent: MatrixEvent;
|
||||||
if (event.getContent().msgtype != 'm.bad.encrypted') {
|
if (event.getContent().msgtype != 'm.bad.encrypted') {
|
||||||
return event;
|
decryptedEvent = event;
|
||||||
}
|
} else {
|
||||||
|
decryptedEvent = await new Promise<MatrixEvent>((resolve) => {
|
||||||
return new Promise<MatrixEvent>((resolve, reject) => {
|
|
||||||
event.once(MatrixEventEvent.Decrypted, (ev) => {
|
event.once(MatrixEventEvent.Decrypted, (ev) => {
|
||||||
logger.log(`${Date.now()} event ${event.getId()} now decrypted`);
|
logger.log(`${Date.now()} event ${event.getId()} now decrypted`);
|
||||||
resolve(ev);
|
resolve(ev);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}).then((event) => {
|
}
|
||||||
expect(event.getContent().body).toEqual('42');
|
expect(decryptedEvent.getContent().body).toEqual('42');
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Alice gets a second room_key message", function() {
|
it("Alice gets a second room_key message", async () => {
|
||||||
return aliceTestClient.start().then(() => {
|
await aliceTestClient.start();
|
||||||
return createOlmSession(testOlmAccount, aliceTestClient);
|
const p2pSession = await createOlmSession(testOlmAccount, aliceTestClient);
|
||||||
}).then((p2pSession) => {
|
|
||||||
const groupSession = new Olm.OutboundGroupSession();
|
const groupSession = new Olm.OutboundGroupSession();
|
||||||
groupSession.create();
|
groupSession.create();
|
||||||
|
|
||||||
@ -460,37 +430,26 @@ describe("megolm", function() {
|
|||||||
events: [roomKeyEncrypted2],
|
events: [roomKeyEncrypted2],
|
||||||
},
|
},
|
||||||
rooms: {
|
rooms: {
|
||||||
join: {},
|
join: { [ROOM_ID]: { timeline: { events: [messageEncrypted] } } },
|
||||||
},
|
|
||||||
};
|
|
||||||
syncResponse2.rooms.join[ROOM_ID] = {
|
|
||||||
timeline: {
|
|
||||||
events: [messageEncrypted],
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
aliceTestClient.httpBackend.when("GET", "/sync").respond(200, syncResponse2);
|
aliceTestClient.httpBackend.when("GET", "/sync").respond(200, syncResponse2);
|
||||||
|
|
||||||
// flush both syncs
|
// flush both syncs
|
||||||
return aliceTestClient.flushSync().then(() => {
|
await aliceTestClient.flushSync();
|
||||||
return aliceTestClient.flushSync();
|
await aliceTestClient.flushSync();
|
||||||
});
|
|
||||||
}).then(async function() {
|
|
||||||
const room = aliceTestClient.client.getRoom(ROOM_ID);
|
const room = aliceTestClient.client.getRoom(ROOM_ID);
|
||||||
await room.decryptCriticalEvents();
|
await room.decryptCriticalEvents();
|
||||||
const event = room.getLiveTimeline().getEvents()[0];
|
const event = room.getLiveTimeline().getEvents()[0];
|
||||||
expect(event.getContent().body).toEqual('42');
|
expect(event.getContent().body).toEqual('42');
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
it('Alice sends a megolm message', function() {
|
|
||||||
let p2pSession;
|
|
||||||
|
|
||||||
|
it('Alice sends a megolm message', async () => {
|
||||||
aliceTestClient.expectKeyQuery({ device_keys: { '@alice:localhost': {} }, failures: {} });
|
aliceTestClient.expectKeyQuery({ device_keys: { '@alice:localhost': {} }, failures: {} });
|
||||||
return aliceTestClient.start().then(() => {
|
await aliceTestClient.start();
|
||||||
// establish an olm session with alice
|
// establish an olm session with alice
|
||||||
return createOlmSession(testOlmAccount, aliceTestClient);
|
const p2pSession = await createOlmSession(testOlmAccount, aliceTestClient);
|
||||||
}).then((_p2pSession) => {
|
|
||||||
p2pSession = _p2pSession;
|
|
||||||
|
|
||||||
const syncResponse = getSyncResponse(['@bob:xyz']);
|
const syncResponse = getSyncResponse(['@bob:xyz']);
|
||||||
|
|
||||||
@ -503,14 +462,14 @@ describe("megolm", function() {
|
|||||||
syncResponse.to_device = { events: [olmEvent] };
|
syncResponse.to_device = { events: [olmEvent] };
|
||||||
|
|
||||||
aliceTestClient.httpBackend.when('GET', '/sync').respond(200, syncResponse);
|
aliceTestClient.httpBackend.when('GET', '/sync').respond(200, syncResponse);
|
||||||
return aliceTestClient.flushSync();
|
await aliceTestClient.flushSync();
|
||||||
}).then(function() {
|
|
||||||
// start out with the device unknown - the send should be rejected.
|
// start out with the device unknown - the send should be rejected.
|
||||||
aliceTestClient.httpBackend.when('POST', '/keys/query').respond(
|
aliceTestClient.httpBackend.when('POST', '/keys/query').respond(
|
||||||
200, getTestKeysQueryResponse('@bob:xyz'),
|
200, getTestKeysQueryResponse('@bob:xyz'),
|
||||||
);
|
);
|
||||||
|
|
||||||
return Promise.all([
|
await Promise.all([
|
||||||
aliceTestClient.client.sendTextMessage(ROOM_ID, 'test').then(() => {
|
aliceTestClient.client.sendTextMessage(ROOM_ID, 'test').then(() => {
|
||||||
throw new Error("sendTextMessage failed on an unknown device");
|
throw new Error("sendTextMessage failed on an unknown device");
|
||||||
}, (e) => {
|
}, (e) => {
|
||||||
@ -518,14 +477,14 @@ describe("megolm", function() {
|
|||||||
}),
|
}),
|
||||||
aliceTestClient.httpBackend.flushAllExpected(),
|
aliceTestClient.httpBackend.flushAllExpected(),
|
||||||
]);
|
]);
|
||||||
}).then(function() {
|
|
||||||
// mark the device as known, and resend.
|
// mark the device as known, and resend.
|
||||||
aliceTestClient.client.setDeviceKnown('@bob:xyz', 'DEVICE_ID');
|
aliceTestClient.client.setDeviceKnown('@bob:xyz', 'DEVICE_ID');
|
||||||
|
|
||||||
let inboundGroupSession;
|
let inboundGroupSession: Olm.InboundGroupSession;
|
||||||
aliceTestClient.httpBackend.when(
|
aliceTestClient.httpBackend.when(
|
||||||
'PUT', '/sendToDevice/m.room.encrypted/',
|
'PUT', '/sendToDevice/m.room.encrypted/',
|
||||||
).respond(200, function(path, content) {
|
).respond(200, function(_path, content) {
|
||||||
const m = content.messages['@bob:xyz'].DEVICE_ID;
|
const m = content.messages['@bob:xyz'].DEVICE_ID;
|
||||||
const ct = m.ciphertext[testSenderKey];
|
const ct = m.ciphertext[testSenderKey];
|
||||||
const decrypted = JSON.parse(p2pSession.decrypt(ct.type, ct.body));
|
const decrypted = JSON.parse(p2pSession.decrypt(ct.type, ct.body));
|
||||||
@ -538,9 +497,9 @@ describe("megolm", function() {
|
|||||||
|
|
||||||
aliceTestClient.httpBackend.when(
|
aliceTestClient.httpBackend.when(
|
||||||
'PUT', '/send/',
|
'PUT', '/send/',
|
||||||
).respond(200, function(path, content) {
|
).respond(200, (_path, content: IContent) => {
|
||||||
const ct = content.ciphertext;
|
const ct = content.ciphertext;
|
||||||
const r = inboundGroupSession.decrypt(ct);
|
const r: any = inboundGroupSession.decrypt(ct);
|
||||||
logger.log('Decrypted received megolm message', r);
|
logger.log('Decrypted received megolm message', r);
|
||||||
|
|
||||||
expect(r.message_index).toEqual(0);
|
expect(r.message_index).toEqual(0);
|
||||||
@ -548,31 +507,25 @@ describe("megolm", function() {
|
|||||||
expect(decrypted.type).toEqual('m.room.message');
|
expect(decrypted.type).toEqual('m.room.message');
|
||||||
expect(decrypted.content.body).toEqual('test');
|
expect(decrypted.content.body).toEqual('test');
|
||||||
|
|
||||||
return {
|
return { event_id: '$event_id' };
|
||||||
event_id: '$event_id',
|
|
||||||
};
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const room = aliceTestClient.client.getRoom(ROOM_ID);
|
const room = aliceTestClient.client.getRoom(ROOM_ID);
|
||||||
const pendingMsg = room.getPendingEvents()[0];
|
const pendingMsg = room.getPendingEvents()[0];
|
||||||
|
|
||||||
return Promise.all([
|
await Promise.all([
|
||||||
aliceTestClient.client.resendEvent(pendingMsg, room),
|
aliceTestClient.client.resendEvent(pendingMsg, room),
|
||||||
|
|
||||||
// the crypto stuff can take a while, so give the requests a whole second.
|
// the crypto stuff can take a while, so give the requests a whole second.
|
||||||
aliceTestClient.httpBackend.flushAllExpected({
|
aliceTestClient.httpBackend.flushAllExpected({ timeout: 1000 }),
|
||||||
timeout: 1000,
|
|
||||||
}),
|
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
it("We shouldn't attempt to send to blocked devices", function() {
|
it("We shouldn't attempt to send to blocked devices", async () => {
|
||||||
aliceTestClient.expectKeyQuery({ device_keys: { '@alice:localhost': {} }, failures: {} });
|
aliceTestClient.expectKeyQuery({ device_keys: { '@alice:localhost': {} }, failures: {} });
|
||||||
return aliceTestClient.start().then(() => {
|
await aliceTestClient.start();
|
||||||
// establish an olm session with alice
|
// establish an olm session with alice
|
||||||
return createOlmSession(testOlmAccount, aliceTestClient);
|
const p2pSession = await createOlmSession(testOlmAccount, aliceTestClient);
|
||||||
}).then((p2pSession) => {
|
|
||||||
const syncResponse = getSyncResponse(['@bob:xyz']);
|
const syncResponse = getSyncResponse(['@bob:xyz']);
|
||||||
|
|
||||||
const olmEvent = encryptOlmEvent({
|
const olmEvent = encryptOlmEvent({
|
||||||
@ -584,19 +537,19 @@ describe("megolm", function() {
|
|||||||
syncResponse.to_device = { events: [olmEvent] };
|
syncResponse.to_device = { events: [olmEvent] };
|
||||||
aliceTestClient.httpBackend.when('GET', '/sync').respond(200, syncResponse);
|
aliceTestClient.httpBackend.when('GET', '/sync').respond(200, syncResponse);
|
||||||
|
|
||||||
return aliceTestClient.flushSync();
|
await aliceTestClient.flushSync();
|
||||||
}).then(function() {
|
|
||||||
logger.log('Forcing alice to download our device keys');
|
logger.log('Forcing alice to download our device keys');
|
||||||
|
|
||||||
aliceTestClient.httpBackend.when('POST', '/keys/query').respond(
|
aliceTestClient.httpBackend.when('POST', '/keys/query').respond(
|
||||||
200, getTestKeysQueryResponse('@bob:xyz'),
|
200, getTestKeysQueryResponse('@bob:xyz'),
|
||||||
);
|
);
|
||||||
|
|
||||||
return Promise.all([
|
await Promise.all([
|
||||||
aliceTestClient.client.downloadKeys(['@bob:xyz']),
|
aliceTestClient.client.downloadKeys(['@bob:xyz']),
|
||||||
aliceTestClient.httpBackend.flush('/keys/query', 1),
|
aliceTestClient.httpBackend.flush('/keys/query', 1),
|
||||||
]);
|
]);
|
||||||
}).then(function() {
|
|
||||||
logger.log('Telling alice to block our device');
|
logger.log('Telling alice to block our device');
|
||||||
aliceTestClient.client.setDeviceBlocked('@bob:xyz', 'DEVICE_ID');
|
aliceTestClient.client.setDeviceBlocked('@bob:xyz', 'DEVICE_ID');
|
||||||
|
|
||||||
@ -610,27 +563,19 @@ describe("megolm", function() {
|
|||||||
'PUT', '/sendToDevice/m.room_key.withheld/',
|
'PUT', '/sendToDevice/m.room_key.withheld/',
|
||||||
).respond(200, {});
|
).respond(200, {});
|
||||||
|
|
||||||
return Promise.all([
|
await Promise.all([
|
||||||
aliceTestClient.client.sendTextMessage(ROOM_ID, 'test'),
|
aliceTestClient.client.sendTextMessage(ROOM_ID, 'test'),
|
||||||
|
|
||||||
// the crypto stuff can take a while, so give the requests a whole second.
|
// the crypto stuff can take a while, so give the requests a whole second.
|
||||||
aliceTestClient.httpBackend.flushAllExpected({
|
aliceTestClient.httpBackend.flushAllExpected({ timeout: 1000 }),
|
||||||
timeout: 1000,
|
|
||||||
}),
|
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
it("We should start a new megolm session when a device is blocked", function() {
|
|
||||||
let p2pSession;
|
|
||||||
let megolmSessionId;
|
|
||||||
|
|
||||||
|
it("We should start a new megolm session when a device is blocked", async () => {
|
||||||
aliceTestClient.expectKeyQuery({ device_keys: { '@alice:localhost': {} }, failures: {} });
|
aliceTestClient.expectKeyQuery({ device_keys: { '@alice:localhost': {} }, failures: {} });
|
||||||
return aliceTestClient.start().then(() => {
|
await aliceTestClient.start();
|
||||||
// establish an olm session with alice
|
// establish an olm session with alice
|
||||||
return createOlmSession(testOlmAccount, aliceTestClient);
|
const p2pSession = await createOlmSession(testOlmAccount, aliceTestClient);
|
||||||
}).then((_p2pSession) => {
|
|
||||||
p2pSession = _p2pSession;
|
|
||||||
|
|
||||||
const syncResponse = getSyncResponse(['@bob:xyz']);
|
const syncResponse = getSyncResponse(['@bob:xyz']);
|
||||||
|
|
||||||
@ -643,26 +588,26 @@ describe("megolm", function() {
|
|||||||
syncResponse.to_device = { events: [olmEvent] };
|
syncResponse.to_device = { events: [olmEvent] };
|
||||||
aliceTestClient.httpBackend.when('GET', '/sync').respond(200, syncResponse);
|
aliceTestClient.httpBackend.when('GET', '/sync').respond(200, syncResponse);
|
||||||
|
|
||||||
return aliceTestClient.flushSync();
|
await aliceTestClient.flushSync();
|
||||||
}).then(function() {
|
|
||||||
logger.log("Fetching bob's devices and marking known");
|
logger.log("Fetching bob's devices and marking known");
|
||||||
|
|
||||||
aliceTestClient.httpBackend.when('POST', '/keys/query').respond(
|
aliceTestClient.httpBackend.when('POST', '/keys/query').respond(
|
||||||
200, getTestKeysQueryResponse('@bob:xyz'),
|
200, getTestKeysQueryResponse('@bob:xyz'),
|
||||||
);
|
);
|
||||||
|
|
||||||
return Promise.all([
|
await Promise.all([
|
||||||
aliceTestClient.client.downloadKeys(['@bob:xyz']),
|
aliceTestClient.client.downloadKeys(['@bob:xyz']),
|
||||||
aliceTestClient.httpBackend.flushAllExpected(),
|
aliceTestClient.httpBackend.flushAllExpected(),
|
||||||
]).then((keys) => {
|
]);
|
||||||
aliceTestClient.client.setDeviceKnown('@bob:xyz', 'DEVICE_ID');
|
await aliceTestClient.client.setDeviceKnown('@bob:xyz', 'DEVICE_ID');
|
||||||
});
|
|
||||||
}).then(function() {
|
|
||||||
logger.log('Telling alice to send a megolm message');
|
logger.log('Telling alice to send a megolm message');
|
||||||
|
|
||||||
|
let megolmSessionId: string;
|
||||||
aliceTestClient.httpBackend.when(
|
aliceTestClient.httpBackend.when(
|
||||||
'PUT', '/sendToDevice/m.room.encrypted/',
|
'PUT', '/sendToDevice/m.room.encrypted/',
|
||||||
).respond(200, function(path, content) {
|
).respond(200, function(_path, content) {
|
||||||
logger.log('sendToDevice: ', content);
|
logger.log('sendToDevice: ', content);
|
||||||
const m = content.messages['@bob:xyz'].DEVICE_ID;
|
const m = content.messages['@bob:xyz'].DEVICE_ID;
|
||||||
const ct = m.ciphertext[testSenderKey];
|
const ct = m.ciphertext[testSenderKey];
|
||||||
@ -676,7 +621,7 @@ describe("megolm", function() {
|
|||||||
|
|
||||||
aliceTestClient.httpBackend.when(
|
aliceTestClient.httpBackend.when(
|
||||||
'PUT', '/send/',
|
'PUT', '/send/',
|
||||||
).respond(200, function(path, content) {
|
).respond(200, function(_path, content) {
|
||||||
logger.log('/send:', content);
|
logger.log('/send:', content);
|
||||||
expect(content.session_id).toEqual(megolmSessionId);
|
expect(content.session_id).toEqual(megolmSessionId);
|
||||||
return {
|
return {
|
||||||
@ -684,22 +629,20 @@ describe("megolm", function() {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
return Promise.all([
|
await Promise.all([
|
||||||
aliceTestClient.client.sendTextMessage(ROOM_ID, 'test'),
|
aliceTestClient.client.sendTextMessage(ROOM_ID, 'test'),
|
||||||
|
|
||||||
// the crypto stuff can take a while, so give the requests a whole second.
|
// the crypto stuff can take a while, so give the requests a whole second.
|
||||||
aliceTestClient.httpBackend.flushAllExpected({
|
aliceTestClient.httpBackend.flushAllExpected({ timeout: 1000 }),
|
||||||
timeout: 1000,
|
|
||||||
}),
|
|
||||||
]);
|
]);
|
||||||
}).then(function() {
|
|
||||||
logger.log('Telling alice to block our device');
|
logger.log('Telling alice to block our device');
|
||||||
aliceTestClient.client.setDeviceBlocked('@bob:xyz', 'DEVICE_ID');
|
aliceTestClient.client.setDeviceBlocked('@bob:xyz', 'DEVICE_ID');
|
||||||
|
|
||||||
logger.log('Telling alice to send another megolm message');
|
logger.log('Telling alice to send another megolm message');
|
||||||
aliceTestClient.httpBackend.when(
|
aliceTestClient.httpBackend.when(
|
||||||
'PUT', '/send/',
|
'PUT', '/send/',
|
||||||
).respond(200, function(path, content) {
|
).respond(200, function(_path, content) {
|
||||||
logger.log('/send:', content);
|
logger.log('/send:', content);
|
||||||
expect(content.session_id).not.toEqual(megolmSessionId);
|
expect(content.session_id).not.toEqual(megolmSessionId);
|
||||||
return {
|
return {
|
||||||
@ -710,80 +653,68 @@ describe("megolm", function() {
|
|||||||
'PUT', '/sendToDevice/m.room_key.withheld/',
|
'PUT', '/sendToDevice/m.room_key.withheld/',
|
||||||
).respond(200, {});
|
).respond(200, {});
|
||||||
|
|
||||||
return Promise.all([
|
await Promise.all([
|
||||||
aliceTestClient.client.sendTextMessage(ROOM_ID, 'test2'),
|
aliceTestClient.client.sendTextMessage(ROOM_ID, 'test2'),
|
||||||
aliceTestClient.httpBackend.flushAllExpected(),
|
aliceTestClient.httpBackend.flushAllExpected(),
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
// https://github.com/vector-im/element-web/issues/2676
|
// https://github.com/vector-im/element-web/issues/2676
|
||||||
it("Alice should send to her other devices", function() {
|
it("Alice should send to her other devices", async () => {
|
||||||
// for this test, we make the testOlmAccount be another of Alice's devices.
|
// for this test, we make the testOlmAccount be another of Alice's devices.
|
||||||
// it ought to get included in messages Alice sends.
|
// it ought to get included in messages Alice sends.
|
||||||
|
await aliceTestClient.start();
|
||||||
let p2pSession;
|
|
||||||
let inboundGroupSession;
|
|
||||||
let decrypted;
|
|
||||||
|
|
||||||
return aliceTestClient.start().then(function() {
|
|
||||||
// an encrypted room with just alice
|
// an encrypted room with just alice
|
||||||
const syncResponse = {
|
const syncResponse = {
|
||||||
next_batch: 1,
|
next_batch: 1,
|
||||||
rooms: {
|
rooms: { join: { [ROOM_ID]: { state: { events: [
|
||||||
join: {},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
syncResponse.rooms.join[ROOM_ID] = {
|
|
||||||
state: {
|
|
||||||
events: [
|
|
||||||
testUtils.mkEvent({
|
testUtils.mkEvent({
|
||||||
type: 'm.room.encryption',
|
type: 'm.room.encryption',
|
||||||
skey: '',
|
skey: '',
|
||||||
content: {
|
content: { algorithm: 'm.megolm.v1.aes-sha2' },
|
||||||
algorithm: 'm.megolm.v1.aes-sha2',
|
|
||||||
},
|
|
||||||
}),
|
}),
|
||||||
testUtils.mkMembership({
|
testUtils.mkMembership({
|
||||||
mship: 'join',
|
mship: 'join',
|
||||||
sender: aliceTestClient.userId,
|
sender: aliceTestClient.userId,
|
||||||
}),
|
}),
|
||||||
],
|
] } } } },
|
||||||
},
|
|
||||||
};
|
};
|
||||||
aliceTestClient.httpBackend.when('GET', '/sync').respond(200, syncResponse);
|
aliceTestClient.httpBackend.when('GET', '/sync').respond(200, syncResponse);
|
||||||
|
|
||||||
// the completion of the first initialsync hould make Alice
|
// the completion of the first initialsync should make Alice
|
||||||
// invalidate the device cache for all members in e2e rooms (ie,
|
// invalidate the device cache for all members in e2e rooms (ie,
|
||||||
// herself), and do a key query.
|
// herself), and do a key query.
|
||||||
aliceTestClient.expectKeyQuery(
|
aliceTestClient.expectKeyQuery(
|
||||||
getTestKeysQueryResponse(aliceTestClient.userId),
|
getTestKeysQueryResponse(aliceTestClient.userId),
|
||||||
);
|
);
|
||||||
|
|
||||||
return aliceTestClient.httpBackend.flushAllExpected();
|
await aliceTestClient.httpBackend.flushAllExpected();
|
||||||
}).then(function() {
|
|
||||||
// start out with the device unknown - the send should be rejected.
|
// start out with the device unknown - the send should be rejected.
|
||||||
return aliceTestClient.client.sendTextMessage(ROOM_ID, 'test').then(() => {
|
try {
|
||||||
throw new Error("sendTextMessage failed on an unknown device");
|
await aliceTestClient.client.sendTextMessage(ROOM_ID, 'test');
|
||||||
}, (e) => {
|
throw new Error("sendTextMessage succeeded on an unknown device");
|
||||||
|
} catch (e) {
|
||||||
expect(e.name).toEqual("UnknownDeviceError");
|
expect(e.name).toEqual("UnknownDeviceError");
|
||||||
expect(Object.keys(e.devices)).toEqual([aliceTestClient.userId]);
|
expect(Object.keys(e.devices)).toEqual([aliceTestClient.userId]);
|
||||||
expect(Object.keys(e.devices[aliceTestClient.userId])).
|
expect(Object.keys(e.devices[aliceTestClient.userId])).
|
||||||
toEqual(['DEVICE_ID']);
|
toEqual(['DEVICE_ID']);
|
||||||
});
|
}
|
||||||
}).then(function() {
|
|
||||||
// mark the device as known, and resend.
|
// mark the device as known, and resend.
|
||||||
aliceTestClient.client.setDeviceKnown(aliceTestClient.userId, 'DEVICE_ID');
|
aliceTestClient.client.setDeviceKnown(aliceTestClient.userId, 'DEVICE_ID');
|
||||||
aliceTestClient.httpBackend.when('POST', '/keys/claim').respond(
|
aliceTestClient.httpBackend.when('POST', '/keys/claim').respond(
|
||||||
200, function(path, content) {
|
200, function(_path, content) {
|
||||||
expect(content.one_time_keys[aliceTestClient.userId].DEVICE_ID)
|
expect(content.one_time_keys[aliceTestClient.userId].DEVICE_ID)
|
||||||
.toEqual("signed_curve25519");
|
.toEqual("signed_curve25519");
|
||||||
return getTestKeysClaimResponse(aliceTestClient.userId);
|
return getTestKeysClaimResponse(aliceTestClient.userId);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let p2pSession: Olm.Session;
|
||||||
|
let inboundGroupSession: Olm.InboundGroupSession;
|
||||||
aliceTestClient.httpBackend.when(
|
aliceTestClient.httpBackend.when(
|
||||||
'PUT', '/sendToDevice/m.room.encrypted/',
|
'PUT', '/sendToDevice/m.room.encrypted/',
|
||||||
).respond(200, function(path, content) {
|
).respond(200, function(_path, content) {
|
||||||
logger.log("sendToDevice: ", content);
|
logger.log("sendToDevice: ", content);
|
||||||
const m = content.messages[aliceTestClient.userId].DEVICE_ID;
|
const m = content.messages[aliceTestClient.userId].DEVICE_ID;
|
||||||
const ct = m.ciphertext[testSenderKey];
|
const ct = m.ciphertext[testSenderKey];
|
||||||
@ -799,11 +730,12 @@ describe("megolm", function() {
|
|||||||
return {};
|
return {};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let decrypted: IEvent;
|
||||||
aliceTestClient.httpBackend.when(
|
aliceTestClient.httpBackend.when(
|
||||||
'PUT', '/send/',
|
'PUT', '/send/',
|
||||||
).respond(200, function(path, content) {
|
).respond(200, function(_path, content: IContent) {
|
||||||
const ct = content.ciphertext;
|
const ct = content.ciphertext;
|
||||||
const r = inboundGroupSession.decrypt(ct);
|
const r: any = inboundGroupSession.decrypt(ct);
|
||||||
logger.log('Decrypted received megolm message', r);
|
logger.log('Decrypted received megolm message', r);
|
||||||
decrypted = JSON.parse(r.plaintext);
|
decrypted = JSON.parse(r.plaintext);
|
||||||
|
|
||||||
@ -818,7 +750,7 @@ describe("megolm", function() {
|
|||||||
expect(pendingEvents.length).toEqual(1);
|
expect(pendingEvents.length).toEqual(1);
|
||||||
const unsentEvent = pendingEvents[0];
|
const unsentEvent = pendingEvents[0];
|
||||||
|
|
||||||
return Promise.all([
|
await Promise.all([
|
||||||
aliceTestClient.client.resendEvent(unsentEvent, room),
|
aliceTestClient.client.resendEvent(unsentEvent, room),
|
||||||
|
|
||||||
// the crypto stuff can take a while, so give the requests a whole second.
|
// the crypto stuff can take a while, so give the requests a whole second.
|
||||||
@ -826,21 +758,17 @@ describe("megolm", function() {
|
|||||||
timeout: 1000,
|
timeout: 1000,
|
||||||
}),
|
}),
|
||||||
]);
|
]);
|
||||||
}).then(function() {
|
|
||||||
expect(decrypted.type).toEqual('m.room.message');
|
expect(decrypted.type).toEqual('m.room.message');
|
||||||
expect(decrypted.content.body).toEqual('test');
|
expect(decrypted.content.body).toEqual('test');
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
it('Alice should wait for device list to complete when sending a megolm message', function() {
|
|
||||||
let downloadPromise;
|
|
||||||
let sendPromise;
|
|
||||||
|
|
||||||
|
it('Alice should wait for device list to complete when sending a megolm message', async () => {
|
||||||
aliceTestClient.expectKeyQuery({ device_keys: { '@alice:localhost': {} }, failures: {} });
|
aliceTestClient.expectKeyQuery({ device_keys: { '@alice:localhost': {} }, failures: {} });
|
||||||
return aliceTestClient.start().then(() => {
|
await aliceTestClient.start();
|
||||||
// establish an olm session with alice
|
// establish an olm session with alice
|
||||||
return createOlmSession(testOlmAccount, aliceTestClient);
|
const p2pSession = await createOlmSession(testOlmAccount, aliceTestClient);
|
||||||
}).then((p2pSession) => {
|
|
||||||
const syncResponse = getSyncResponse(['@bob:xyz']);
|
const syncResponse = getSyncResponse(['@bob:xyz']);
|
||||||
|
|
||||||
const olmEvent = encryptOlmEvent({
|
const olmEvent = encryptOlmEvent({
|
||||||
@ -852,14 +780,14 @@ describe("megolm", function() {
|
|||||||
syncResponse.to_device = { events: [olmEvent] };
|
syncResponse.to_device = { events: [olmEvent] };
|
||||||
|
|
||||||
aliceTestClient.httpBackend.when('GET', '/sync').respond(200, syncResponse);
|
aliceTestClient.httpBackend.when('GET', '/sync').respond(200, syncResponse);
|
||||||
return aliceTestClient.flushSync();
|
await aliceTestClient.flushSync();
|
||||||
}).then(function() {
|
|
||||||
// this will block
|
// this will block
|
||||||
logger.log('Forcing alice to download our device keys');
|
logger.log('Forcing alice to download our device keys');
|
||||||
downloadPromise = aliceTestClient.client.downloadKeys(['@bob:xyz']);
|
const downloadPromise = aliceTestClient.client.downloadKeys(['@bob:xyz']);
|
||||||
|
|
||||||
// so will this.
|
// so will this.
|
||||||
sendPromise = aliceTestClient.client.sendTextMessage(ROOM_ID, 'test')
|
const sendPromise = aliceTestClient.client.sendTextMessage(ROOM_ID, 'test')
|
||||||
.then(() => {
|
.then(() => {
|
||||||
throw new Error("sendTextMessage failed on an unknown device");
|
throw new Error("sendTextMessage failed on an unknown device");
|
||||||
}, (e) => {
|
}, (e) => {
|
||||||
@ -870,20 +798,16 @@ describe("megolm", function() {
|
|||||||
200, getTestKeysQueryResponse('@bob:xyz'),
|
200, getTestKeysQueryResponse('@bob:xyz'),
|
||||||
);
|
);
|
||||||
|
|
||||||
return aliceTestClient.httpBackend.flushAllExpected();
|
await aliceTestClient.httpBackend.flushAllExpected();
|
||||||
}).then(function() {
|
await Promise.all([downloadPromise, sendPromise]);
|
||||||
return Promise.all([downloadPromise, sendPromise]);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Alice exports megolm keys and imports them to a new device", function() {
|
it("Alice exports megolm keys and imports them to a new device", async () => {
|
||||||
let messageEncrypted;
|
|
||||||
|
|
||||||
aliceTestClient.expectKeyQuery({ device_keys: { '@alice:localhost': {} }, failures: {} });
|
aliceTestClient.expectKeyQuery({ device_keys: { '@alice:localhost': {} }, failures: {} });
|
||||||
return aliceTestClient.start().then(() => {
|
await aliceTestClient.start();
|
||||||
// establish an olm session with alice
|
// establish an olm session with alice
|
||||||
return createOlmSession(testOlmAccount, aliceTestClient);
|
const p2pSession = await createOlmSession(testOlmAccount, aliceTestClient);
|
||||||
}).then((p2pSession) => {
|
|
||||||
const groupSession = new Olm.OutboundGroupSession();
|
const groupSession = new Olm.OutboundGroupSession();
|
||||||
groupSession.create();
|
groupSession.create();
|
||||||
|
|
||||||
@ -897,74 +821,56 @@ describe("megolm", function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// encrypt a message with the group session
|
// encrypt a message with the group session
|
||||||
messageEncrypted = encryptMegolmEvent({
|
const messageEncrypted = encryptMegolmEvent({
|
||||||
senderKey: testSenderKey,
|
senderKey: testSenderKey,
|
||||||
groupSession: groupSession,
|
groupSession: groupSession,
|
||||||
room_id: ROOM_ID,
|
room_id: ROOM_ID,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Alice gets both the events in a single sync
|
// Alice gets both the events in a single sync
|
||||||
const syncResponse = {
|
aliceTestClient.httpBackend.when("GET", "/sync").respond(200, {
|
||||||
next_batch: 1,
|
next_batch: 1,
|
||||||
to_device: {
|
to_device: {
|
||||||
events: [roomKeyEncrypted],
|
events: [roomKeyEncrypted],
|
||||||
},
|
},
|
||||||
rooms: {
|
rooms: {
|
||||||
join: {},
|
join: { [ROOM_ID]: { timeline: { events: [messageEncrypted] } } },
|
||||||
},
|
},
|
||||||
};
|
});
|
||||||
syncResponse.rooms.join[ROOM_ID] = {
|
await aliceTestClient.flushSync();
|
||||||
timeline: {
|
|
||||||
events: [messageEncrypted],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
aliceTestClient.httpBackend.when("GET", "/sync").respond(200, syncResponse);
|
|
||||||
return aliceTestClient.flushSync();
|
|
||||||
}).then(async function() {
|
|
||||||
const room = aliceTestClient.client.getRoom(ROOM_ID);
|
const room = aliceTestClient.client.getRoom(ROOM_ID);
|
||||||
await room.decryptCriticalEvents();
|
await room.decryptCriticalEvents();
|
||||||
const event = room.getLiveTimeline().getEvents()[0];
|
expect(room.getLiveTimeline().getEvents()[0].getContent().body).toEqual('42');
|
||||||
expect(event.getContent().body).toEqual('42');
|
|
||||||
|
const exported = await aliceTestClient.client.exportRoomKeys();
|
||||||
|
|
||||||
return aliceTestClient.client.exportRoomKeys();
|
|
||||||
}).then(function(exported) {
|
|
||||||
// start a new client
|
// start a new client
|
||||||
aliceTestClient.stop();
|
aliceTestClient.stop();
|
||||||
|
|
||||||
aliceTestClient = new TestClient(
|
aliceTestClient = new TestClient(
|
||||||
"@alice:localhost", "device2", "access_token2",
|
"@alice:localhost", "device2", "access_token2",
|
||||||
);
|
);
|
||||||
return aliceTestClient.client.initCrypto().then(() => {
|
await aliceTestClient.client.initCrypto();
|
||||||
aliceTestClient.client.importRoomKeys(exported);
|
await aliceTestClient.client.importRoomKeys(exported);
|
||||||
return aliceTestClient.start();
|
await aliceTestClient.start();
|
||||||
});
|
|
||||||
}).then(function() {
|
|
||||||
const syncResponse = {
|
const syncResponse = {
|
||||||
next_batch: 1,
|
next_batch: 1,
|
||||||
rooms: {
|
rooms: {
|
||||||
join: {},
|
join: { [ROOM_ID]: { timeline: { events: [messageEncrypted] } } },
|
||||||
},
|
|
||||||
};
|
|
||||||
syncResponse.rooms.join[ROOM_ID] = {
|
|
||||||
timeline: {
|
|
||||||
events: [messageEncrypted],
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
aliceTestClient.httpBackend.when("GET", "/sync").respond(200, syncResponse);
|
aliceTestClient.httpBackend.when("GET", "/sync").respond(200, syncResponse);
|
||||||
return aliceTestClient.flushSync();
|
await aliceTestClient.flushSync();
|
||||||
}).then(function() {
|
|
||||||
const room = aliceTestClient.client.getRoom(ROOM_ID);
|
|
||||||
const event = room.getLiveTimeline().getEvents()[0];
|
const event = room.getLiveTimeline().getEvents()[0];
|
||||||
expect(event.getContent().body).toEqual('42');
|
expect(event.getContent().body).toEqual('42');
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
it("Alice receives an untrusted megolm key, only to receive the trusted one shortly after", function() {
|
it("Alice receives an untrusted megolm key, only to receive the trusted one shortly after", async () => {
|
||||||
const testClient = new TestClient(
|
const testClient = new TestClient("@alice:localhost", "device2", "access_token2");
|
||||||
"@alice:localhost", "device2", "access_token2",
|
|
||||||
);
|
|
||||||
const groupSession = new Olm.OutboundGroupSession();
|
const groupSession = new Olm.OutboundGroupSession();
|
||||||
groupSession.create();
|
groupSession.create();
|
||||||
const inboundGroupSession = new Olm.InboundGroupSession();
|
const inboundGroupSession = new Olm.InboundGroupSession();
|
||||||
@ -974,7 +880,7 @@ describe("megolm", function() {
|
|||||||
groupSession: groupSession,
|
groupSession: groupSession,
|
||||||
room_id: ROOM_ID,
|
room_id: ROOM_ID,
|
||||||
});
|
});
|
||||||
return testClient.client.initCrypto().then(() => {
|
await testClient.client.initCrypto();
|
||||||
const keys = [{
|
const keys = [{
|
||||||
room_id: ROOM_ID,
|
room_id: ROOM_ID,
|
||||||
algorithm: 'm.megolm.v1.aes-sha2',
|
algorithm: 'm.megolm.v1.aes-sha2',
|
||||||
@ -984,18 +890,17 @@ describe("megolm", function() {
|
|||||||
forwarding_curve25519_key_chain: [],
|
forwarding_curve25519_key_chain: [],
|
||||||
sender_claimed_keys: {},
|
sender_claimed_keys: {},
|
||||||
}];
|
}];
|
||||||
return testClient.client.importRoomKeys(keys, { untrusted: true });
|
await testClient.client.importRoomKeys(keys, { untrusted: true });
|
||||||
}).then(() => {
|
|
||||||
const event = testUtils.mkEvent({
|
const event1 = testUtils.mkEvent({
|
||||||
event: true,
|
event: true,
|
||||||
...rawEvent,
|
...rawEvent,
|
||||||
room: ROOM_ID,
|
room: ROOM_ID,
|
||||||
});
|
});
|
||||||
return event.attemptDecryption(testClient.client.crypto, { isRetry: true }).then(() => {
|
await event1.attemptDecryption(testClient.client.crypto, { isRetry: true });
|
||||||
expect(event.isKeySourceUntrusted()).toBeTruthy();
|
expect(event1.isKeySourceUntrusted()).toBeTruthy();
|
||||||
});
|
|
||||||
}).then(() => {
|
const event2 = testUtils.mkEvent({
|
||||||
const event = testUtils.mkEvent({
|
|
||||||
type: 'm.room_key',
|
type: 'm.room_key',
|
||||||
content: {
|
content: {
|
||||||
room_id: ROOM_ID,
|
room_id: ROOM_ID,
|
||||||
@ -1006,26 +911,23 @@ describe("megolm", function() {
|
|||||||
event: true,
|
event: true,
|
||||||
});
|
});
|
||||||
// @ts-ignore - private
|
// @ts-ignore - private
|
||||||
event.senderCurve25519Key = testSenderKey;
|
event2.senderCurve25519Key = testSenderKey;
|
||||||
// @ts-ignore - private
|
// @ts-ignore - private
|
||||||
return testClient.client.crypto.onRoomKeyEvent(event);
|
testClient.client.crypto.onRoomKeyEvent(event2);
|
||||||
}).then(() => {
|
|
||||||
const event = testUtils.mkEvent({
|
const event3 = testUtils.mkEvent({
|
||||||
event: true,
|
event: true,
|
||||||
...rawEvent,
|
...rawEvent,
|
||||||
room: ROOM_ID,
|
room: ROOM_ID,
|
||||||
});
|
});
|
||||||
return event.attemptDecryption(testClient.client.crypto, { isRetry: true }).then(() => {
|
await event3.attemptDecryption(testClient.client.crypto, { isRetry: true });
|
||||||
expect(event.isKeySourceUntrusted()).toBeFalsy();
|
expect(event3.isKeySourceUntrusted()).toBeFalsy();
|
||||||
testClient.stop();
|
testClient.stop();
|
||||||
});
|
});
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Alice can decrypt a message with falsey content", function() {
|
it("Alice can decrypt a message with falsey content", async () => {
|
||||||
return aliceTestClient.start().then(() => {
|
await aliceTestClient.start();
|
||||||
return createOlmSession(testOlmAccount, aliceTestClient);
|
const p2pSession = await createOlmSession(testOlmAccount, aliceTestClient);
|
||||||
}).then((p2pSession) => {
|
|
||||||
const groupSession = new Olm.OutboundGroupSession();
|
const groupSession = new Olm.OutboundGroupSession();
|
||||||
groupSession.create();
|
groupSession.create();
|
||||||
|
|
||||||
@ -1063,26 +965,19 @@ describe("megolm", function() {
|
|||||||
events: [roomKeyEncrypted],
|
events: [roomKeyEncrypted],
|
||||||
},
|
},
|
||||||
rooms: {
|
rooms: {
|
||||||
join: {},
|
join: { [ROOM_ID]: { timeline: { events: [messageEncrypted] } } },
|
||||||
},
|
|
||||||
};
|
|
||||||
syncResponse.rooms.join[ROOM_ID] = {
|
|
||||||
timeline: {
|
|
||||||
events: [messageEncrypted],
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
aliceTestClient.httpBackend.when("GET", "/sync").respond(200, syncResponse);
|
aliceTestClient.httpBackend.when("GET", "/sync").respond(200, syncResponse);
|
||||||
return aliceTestClient.flushSync();
|
await aliceTestClient.flushSync();
|
||||||
}).then(function() {
|
|
||||||
const room = aliceTestClient.client.getRoom(ROOM_ID);
|
const room = aliceTestClient.client.getRoom(ROOM_ID);
|
||||||
const event = room.getLiveTimeline().getEvents()[0];
|
const event = room.getLiveTimeline().getEvents()[0];
|
||||||
expect(event.isEncrypted()).toBe(true);
|
expect(event.isEncrypted()).toBe(true);
|
||||||
return testUtils.awaitDecryption(event);
|
const decryptedEvent = await testUtils.awaitDecryption(event);
|
||||||
}).then((event) => {
|
expect(decryptedEvent.getRoomId()).toEqual(ROOM_ID);
|
||||||
expect(event.getRoomId()).toEqual(ROOM_ID);
|
expect(decryptedEvent.getContent()).toEqual({});
|
||||||
expect(event.getContent()).toEqual({});
|
expect(decryptedEvent.getClearContent()).toBeUndefined();
|
||||||
expect(event.getClearContent()).toBeUndefined();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -129,6 +129,21 @@ export function mkEvent(opts: IEventOpts & { event?: boolean }, client?: MatrixC
|
|||||||
return opts.event ? new MatrixEvent(event) : event;
|
return opts.event ? new MatrixEvent(event) : event;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type GeneratedMetadata = {
|
||||||
|
event_id: string;
|
||||||
|
txn_id: string;
|
||||||
|
origin_server_ts: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function mkEventCustom<T>(base: T): T & GeneratedMetadata {
|
||||||
|
return {
|
||||||
|
event_id: "$" + testEventIndex++ + "-" + Math.random() + "-" + Math.random(),
|
||||||
|
txn_id: "~" + Math.random(),
|
||||||
|
origin_server_ts: Date.now(),
|
||||||
|
...base,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
interface IPresenceOpts {
|
interface IPresenceOpts {
|
||||||
user?: string;
|
user?: string;
|
||||||
sender?: string;
|
sender?: string;
|
||||||
@ -208,6 +223,18 @@ export function mkMembership(opts: IMembershipOpts & { event?: boolean }): Parti
|
|||||||
return mkEvent(eventOpts);
|
return mkEvent(eventOpts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function mkMembershipCustom<T>(
|
||||||
|
base: T & { membership: string, sender: string, content?: IContent },
|
||||||
|
): T & { type: EventType, sender: string, state_key: string, content: IContent } & GeneratedMetadata {
|
||||||
|
const content = base.content || {};
|
||||||
|
return mkEventCustom({
|
||||||
|
...base,
|
||||||
|
content: { ...content, membership: base.membership },
|
||||||
|
type: EventType.RoomMember,
|
||||||
|
state_key: base.sender,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
interface IMessageOpts {
|
interface IMessageOpts {
|
||||||
room?: string;
|
room?: string;
|
||||||
user: string;
|
user: string;
|
||||||
|
Reference in New Issue
Block a user