From 3c838b2f4a50588dd448c1dffc1cceccb1b8c838 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 22 Dec 2022 16:11:49 +0100 Subject: [PATCH 01/12] =?UTF-8?q?feat(crypto-js):=20Request=20types=20have?= =?UTF-8?q?=20fields=20from=20their=20=E2=80=9Cbody=E2=80=9D=20directly.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bindings/matrix-sdk-crypto-js/src/requests.rs | 269 +++++++++++------- 1 file changed, 168 insertions(+), 101 deletions(-) diff --git a/bindings/matrix-sdk-crypto-js/src/requests.rs b/bindings/matrix-sdk-crypto-js/src/requests.rs index aec419ae0..f4c692f50 100644 --- a/bindings/matrix-sdk-crypto-js/src/requests.rs +++ b/bindings/matrix-sdk-crypto-js/src/requests.rs @@ -33,21 +33,34 @@ pub struct KeysUploadRequest { #[wasm_bindgen(readonly)] pub id: Option, - /// A JSON-encoded object of form: + /// A JSON-encoded string representing identity keys for the device. /// - /// ```json - /// {"device_keys": …, "one_time_keys": …, "fallback_keys": …} - /// ``` + /// May be absent if no new identity keys are required. #[wasm_bindgen(readonly)] - pub body: JsString, + pub device_keys: JsString, + + /// A JSON-encoded string representing one-time public keys for “pre-key” + /// messages. + #[wasm_bindgen(readonly)] + pub one_time_keys: JsString, + + /// A JSON-encoded string representing fallback public keys for “pre-key” + /// messages. + #[wasm_bindgen(readonly)] + pub fallback_keys: JsString, } #[wasm_bindgen] impl KeysUploadRequest { /// Create a new `KeysUploadRequest`. #[wasm_bindgen(constructor)] - pub fn new(id: JsString, body: JsString) -> KeysUploadRequest { - Self { id: Some(id), body } + pub fn new( + id: JsString, + device_keys: JsString, + one_time_keys: JsString, + fallback_keys: JsString, + ) -> KeysUploadRequest { + Self { id: Some(id), device_keys, one_time_keys, fallback_keys } } /// Get its request type. @@ -70,21 +83,37 @@ pub struct KeysQueryRequest { #[wasm_bindgen(readonly)] pub id: Option, - /// A JSON-encoded object of form: - /// - /// ```json - /// {"timeout": …, "device_keys": …, "token": …} - /// ``` + /// An optional integer representing the time (in milliseconds) to wait when + /// downloading keys from remote servers. 10 seconds is the recommended + /// default. #[wasm_bindgen(readonly)] - pub body: JsString, + pub timeout: Option, + + /// A JSON-encoded string representing the keys to be downloaded. An empty + /// list indicates all devices for the corresponding user. + #[wasm_bindgen(readonly)] + pub device_keys: JsString, + + /// An optional string representing if the client is fetching keys as a + /// result of a device update received in a sync request, this should be the + /// `since` token of that sync request, or any later sync token. This allows + /// the server to ensure its response contains the keys advertised by the + /// notification in that sync. + #[wasm_bindgen(readonly)] + pub token: Option, } #[wasm_bindgen] impl KeysQueryRequest { /// Create a new `KeysQueryRequest`. #[wasm_bindgen(constructor)] - pub fn new(id: JsString, body: JsString) -> KeysQueryRequest { - Self { id: Some(id), body } + pub fn new( + id: JsString, + timeout: Option, + device_keys: JsString, + token: Option, + ) -> KeysQueryRequest { + Self { id: Some(id), timeout, device_keys, token } } /// Get its request type. @@ -108,21 +137,23 @@ pub struct KeysClaimRequest { #[wasm_bindgen(readonly)] pub id: Option, - /// A JSON-encoded object of form: - /// - /// ```json - /// {"timeout": …, "one_time_keys": …} - /// ``` + /// An optional integer representing the time (in milliseconds) to wait when + /// downloading keys from remote servers. 10 seconds is the recommended + /// default. #[wasm_bindgen(readonly)] - pub body: JsString, + pub timeout: Option, + + /// A JSON-encoded string representing the keys to be claimed. + #[wasm_bindgen(readonly)] + pub one_time_keys: JsString, } #[wasm_bindgen] impl KeysClaimRequest { /// Create a new `KeysClaimRequest`. #[wasm_bindgen(constructor)] - pub fn new(id: JsString, body: JsString) -> KeysClaimRequest { - Self { id: Some(id), body } + pub fn new(id: JsString, timeout: Option, one_time_keys: JsString) -> KeysClaimRequest { + Self { id: Some(id), timeout, one_time_keys } } /// Get its request type. @@ -145,21 +176,34 @@ pub struct ToDeviceRequest { #[wasm_bindgen(readonly)] pub id: Option, - /// A JSON-encoded object of form: - /// - /// ```json - /// {"event_type": …, "txn_id": …, "messages": …} - /// ``` + /// A string representing the type of event being sent to each devices. #[wasm_bindgen(readonly)] - pub body: JsString, + pub event_type: JsString, + + /// A string representing a request identifier unique to the access token + /// used to send the request. + #[wasm_bindgen(readonly)] + pub txn_id: JsString, + + /// A JSON-encoded string representing a map of users to devices to a + /// content for a message event to be sent to the user's device. Individual + /// message events can be sent to devices, but all events must be of the + /// same type. + #[wasm_bindgen(readonly)] + pub messages: JsString, } #[wasm_bindgen] impl ToDeviceRequest { /// Create a new `ToDeviceRequest`. #[wasm_bindgen(constructor)] - pub fn new(id: JsString, body: JsString) -> ToDeviceRequest { - Self { id: Some(id), body } + pub fn new( + id: JsString, + event_type: JsString, + txn_id: JsString, + messages: JsString, + ) -> ToDeviceRequest { + Self { id: Some(id), event_type, txn_id, messages } } /// Get its request type. @@ -182,21 +226,17 @@ pub struct SignatureUploadRequest { #[wasm_bindgen(readonly)] pub id: Option, - /// A JSON-encoded object of form: - /// - /// ```json - /// {"signed_keys": …, "txn_id": …, "messages": …} - /// ``` + /// A JSON-encoded string representing the signed keys. #[wasm_bindgen(readonly)] - pub body: JsString, + pub signed_keys: JsString, } #[wasm_bindgen] impl SignatureUploadRequest { /// Create a new `SignatureUploadRequest`. #[wasm_bindgen(constructor)] - pub fn new(id: JsString, body: JsString) -> SignatureUploadRequest { - Self { id: Some(id), body } + pub fn new(id: JsString, signed_keys: JsString) -> SignatureUploadRequest { + Self { id: Some(id), signed_keys } } /// Get its request type. @@ -217,21 +257,34 @@ pub struct RoomMessageRequest { #[wasm_bindgen(readonly)] pub id: Option, - /// A JSON-encoded object of form: - /// - /// ```json - /// {"room_id": …, "txn_id": …, "content": …} - /// ``` + /// A string representing the room to send the event to. #[wasm_bindgen(readonly)] - pub body: JsString, + pub room_id: JsString, + + /// A string representing the transaction ID for this event. + /// + /// Clients should generate an ID unique across requests with the same + /// access token; it will be used by the server to ensure idempotency of + /// requests. + #[wasm_bindgen(readonly)] + pub txn_id: JsString, + + /// A JSON-encoded string representing the event content to send. + #[wasm_bindgen(readonly)] + pub content: JsString, } #[wasm_bindgen] impl RoomMessageRequest { /// Create a new `RoomMessageRequest`. #[wasm_bindgen(constructor)] - pub fn new(id: JsString, body: JsString) -> RoomMessageRequest { - Self { id: Some(id), body } + pub fn new( + id: JsString, + room_id: JsString, + txn_id: JsString, + content: JsString, + ) -> RoomMessageRequest { + Self { id: Some(id), room_id, txn_id, content } } /// Get its request type. @@ -252,13 +305,25 @@ pub struct KeysBackupRequest { #[wasm_bindgen(readonly)] pub id: Option, - /// A JSON-encoded object of form: - /// - /// ```json - /// {"rooms": …} - /// ``` + /// A JSON-encoded string representing the map from room ID to a backed up + /// room key that we're going to upload to the server. #[wasm_bindgen(readonly)] - pub body: JsString, + pub rooms: JsString, +} + +#[wasm_bindgen] +impl KeysBackupRequest { + /// Create a new `KeysBackupRequest`. + #[wasm_bindgen(constructor)] + pub fn new(id: JsString, rooms: JsString) -> KeysBackupRequest { + Self { id: Some(id), rooms } + } + + /// Get its request type. + #[wasm_bindgen(getter, js_name = "type")] + pub fn request_type(&self) -> RequestType { + RequestType::KeysBackup + } } /** Other Requests * */ @@ -273,52 +338,30 @@ pub struct SigningKeysUploadRequest { #[wasm_bindgen(readonly)] pub id: Option, - /// A JSON-encoded object of form: - /// - /// ```json - /// {"master_key": …, "self_signing_key": …, "user_signing_key": …} - /// ``` + /// A JSON-encoded string representing the user's master key.. #[wasm_bindgen(readonly)] - pub body: JsString, -} + pub master_key: JsString, -#[wasm_bindgen] -impl KeysBackupRequest { - /// Create a new `KeysBackupRequest`. - #[wasm_bindgen(constructor)] - pub fn new(id: JsString, body: JsString) -> KeysBackupRequest { - Self { id: Some(id), body } - } + /// A JSON-encoded string representing the user's self-signing key. Must + /// be signed with the accompanied master, or by the user's most recently + /// uploaded master key if no master key is included in the request. + #[wasm_bindgen(readonly)] + pub self_signing_key: JsString, - /// Get its request type. - #[wasm_bindgen(getter, js_name = "type")] - pub fn request_type(&self) -> RequestType { - RequestType::KeysBackup - } + /// A JSON-encoded string representing the user's user-signing key. Must + /// be signed with the accompanied master, or by the user's most recently + /// uploaded master key if no master key is included in the request. + #[wasm_bindgen(readonly)] + pub user_signing_key: JsString, } macro_rules! request { - ($destination_request:ident from $source_request:ident maps fields $( $field:ident ),+ $(,)? ) => { - impl $destination_request { - pub(crate) fn to_json(request: &$source_request) -> Result { - let mut map = serde_json::Map::new(); - $( - map.insert(stringify!($field).to_owned(), serde_json::to_value(&request.$field).unwrap()); - )+ - let object = serde_json::Value::Object(map); - - serde_json::to_string(&object) - } - } - + ( $destination_request:ident from $source_request:ident maps fields $( $field:ident: $field_type:ident ),+ $(,)? ) => { impl TryFrom<&$source_request> for $destination_request { type Error = serde_json::Error; fn try_from(request: &$source_request) -> Result { - Ok($destination_request { - id: None, - body: Self::to_json(request)?.into(), - }) + request!(@__try_from $destination_request from $source_request (request_id = None, request = request) maps fields $( $field: $field_type, )+ ) } } @@ -328,26 +371,50 @@ macro_rules! request { fn try_from( (request_id, request): (String, &$source_request), ) -> Result { - Ok($destination_request { - id: Some(request_id.into()), - body: Self::to_json(request)?.into(), - }) + request!(@__try_from $destination_request from $source_request (request_id = Some(request_id.into()), request = request) maps fields $( $field: $field_type, )+ ) } } }; + + ( @__try_from $destination_request:ident from $source_request:ident (request_id = $request_id:expr, request = $request:expr) maps fields $( $field:ident: $field_type:ident ),+ $(,)? ) => { + { + Ok($destination_request { + id: $request_id, + $( + $field: request!(@__field as $field_type (request = $request, field = $field)), + )+ + }) + } + }; + + ( @__field as json (request = $request:expr, field = $field:ident) ) => { + serde_json::to_string(&$request.$field)?.into() + }; + + ( @__field as string (request = $request:expr, field = $field:ident) ) => { + $request.$field.to_string().into() + }; + + ( @__field as duration (request = $request:expr, field = $field:ident) ) => { + $request.$field.map(|duration| duration.as_millis() as u64) + }; + + ( @__field as native (request = $request:expr, field = $field:ident) ) => { + $request.$field.clone() + }; } // Outgoing Requests -request!(KeysUploadRequest from OriginalKeysUploadRequest maps fields device_keys, one_time_keys, fallback_keys); -request!(KeysQueryRequest from OriginalKeysQueryRequest maps fields timeout, device_keys, token); -request!(KeysClaimRequest from OriginalKeysClaimRequest maps fields timeout, one_time_keys); -request!(ToDeviceRequest from OriginalToDeviceRequest maps fields event_type, txn_id, messages); -request!(SignatureUploadRequest from OriginalSignatureUploadRequest maps fields signed_keys); -request!(RoomMessageRequest from OriginalRoomMessageRequest maps fields room_id, txn_id, content); -request!(KeysBackupRequest from OriginalKeysBackupRequest maps fields rooms); +request!(KeysUploadRequest from OriginalKeysUploadRequest maps fields device_keys: json, one_time_keys: json, fallback_keys: json); +request!(KeysQueryRequest from OriginalKeysQueryRequest maps fields timeout: duration, device_keys: json, token: native); +request!(KeysClaimRequest from OriginalKeysClaimRequest maps fields timeout: duration, one_time_keys: json); +request!(ToDeviceRequest from OriginalToDeviceRequest maps fields event_type: string, txn_id: string, messages: json); +request!(SignatureUploadRequest from OriginalSignatureUploadRequest maps fields signed_keys: json); +request!(RoomMessageRequest from OriginalRoomMessageRequest maps fields room_id: string, txn_id: string, content: json); +request!(KeysBackupRequest from OriginalKeysBackupRequest maps fields rooms: json); // Other Requests -request!(SigningKeysUploadRequest from OriginalUploadSigningKeysRequest maps fields master_key, self_signing_key, user_signing_key); +request!(SigningKeysUploadRequest from OriginalUploadSigningKeysRequest maps fields master_key: json, self_signing_key: json, user_signing_key: json); // JavaScript has no complex enums like Rust. To return structs of // different types, we have no choice that hiding everything behind a From b125b2e9da44e7618713b4d9351034e32f9b49c7 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 22 Dec 2022 16:12:09 +0100 Subject: [PATCH 02/12] test(crypto-js): Update tests according to previous commit. --- .../matrix-sdk-crypto-js/tests/device.test.js | 67 +++++-------------- bindings/matrix-sdk-crypto-js/tests/helper.js | 16 ++--- .../tests/machine.test.js | 14 ++-- .../tests/requests.test.js | 22 ------ 4 files changed, 30 insertions(+), 89 deletions(-) diff --git a/bindings/matrix-sdk-crypto-js/tests/device.test.js b/bindings/matrix-sdk-crypto-js/tests/device.test.js index a3fa80742..c9f84cf90 100644 --- a/bindings/matrix-sdk-crypto-js/tests/device.test.js +++ b/bindings/matrix-sdk-crypto-js/tests/device.test.js @@ -172,14 +172,12 @@ describe('Key Verification', () => { expect(verificationRequest1.isCancelled()).toStrictEqual(false); expect(outgoingVerificationRequest).toBeInstanceOf(ToDeviceRequest); - - outgoingVerificationRequest = JSON.parse(outgoingVerificationRequest.body); expect(outgoingVerificationRequest.event_type).toStrictEqual('m.key.verification.request'); const toDeviceEvents = [{ sender: userId1.toString(), type: outgoingVerificationRequest.event_type, - content: outgoingVerificationRequest.messages[userId2.toString()][deviceId2.toString()], + content: JSON.parse(outgoingVerificationRequest.messages)[userId2.toString()][deviceId2.toString()], }]; // Let's send the verification request to `m2`. @@ -225,13 +223,12 @@ describe('Key Verification', () => { expect(outgoingVerificationRequest).toBeInstanceOf(ToDeviceRequest); // The request verification is ready. - outgoingVerificationRequest = JSON.parse(outgoingVerificationRequest.body); expect(outgoingVerificationRequest.event_type).toStrictEqual('m.key.verification.ready'); const toDeviceEvents = [{ sender: userId2.toString(), type: outgoingVerificationRequest.event_type, - content: outgoingVerificationRequest.messages[userId1.toString()][deviceId1.toString()], + content: JSON.parse(outgoingVerificationRequest.messages)[userId1.toString()][deviceId1.toString()], }]; // Let's send the verification ready to `m1`. @@ -279,14 +276,12 @@ describe('Key Verification', () => { expect(sas2.decimals()).toBeUndefined(); expect(outgoingVerificationRequest).toBeInstanceOf(ToDeviceRequest); - - outgoingVerificationRequest = JSON.parse(outgoingVerificationRequest.body); expect(outgoingVerificationRequest.event_type).toStrictEqual('m.key.verification.start'); const toDeviceEvents = [{ sender: userId2.toString(), type: outgoingVerificationRequest.event_type, - content: outgoingVerificationRequest.messages[userId1.toString()][deviceId1.toString()], + content: JSON.parse(outgoingVerificationRequest.messages)[userId1.toString()][deviceId1.toString()], }]; // Let's send the SAS start to `m1`. @@ -324,15 +319,14 @@ describe('Key Verification', () => { // Let's accept thet SAS start request. let outgoingVerificationRequest = sas1.accept(); - expect(outgoingVerificationRequest).toBeInstanceOf(ToDeviceRequest); - outgoingVerificationRequest = JSON.parse(outgoingVerificationRequest.body); + expect(outgoingVerificationRequest).toBeInstanceOf(ToDeviceRequest); expect(outgoingVerificationRequest.event_type).toStrictEqual('m.key.verification.accept'); const toDeviceEvents = [{ sender: userId1.toString(), type: outgoingVerificationRequest.event_type, - content: outgoingVerificationRequest.messages[userId2.toString()][deviceId2.toString()], + content: JSON.parse(outgoingVerificationRequest.messages)[userId2.toString()][deviceId2.toString()], }]; // Let's send the SAS accept to `m2`. @@ -350,22 +344,18 @@ describe('Key Verification', () => { let toDeviceRequest = outgoingRequests.find((request) => request.type == RequestType.ToDevice); expect(toDeviceRequest).toBeInstanceOf(ToDeviceRequest); - const toDeviceRequestId = toDeviceRequest.id; - const toDeviceRequestType = toDeviceRequest.type; - - toDeviceRequest = JSON.parse(toDeviceRequest.body); expect(toDeviceRequest.event_type).toStrictEqual('m.key.verification.key'); const toDeviceEvents = [{ sender: userId2.toString(), type: toDeviceRequest.event_type, - content: toDeviceRequest.messages[userId1.toString()][deviceId1.toString()], + content: JSON.parse(toDeviceRequest.messages)[userId1.toString()][deviceId1.toString()], }]; // Let's send te SAS key to `m1`. await m1.receiveSyncChanges(JSON.stringify(toDeviceEvents), new DeviceLists(), new Map(), new Set()); - m2.markRequestAsSent(toDeviceRequestId, toDeviceRequestType, '{}'); + m2.markRequestAsSent(toDeviceRequest.id, toDeviceRequest.type, '{}'); }); test('other side sends back verification key (`m.key.verification.key`)', async () => { @@ -374,22 +364,18 @@ describe('Key Verification', () => { let toDeviceRequest = outgoingRequests.find((request) => request.type == RequestType.ToDevice); expect(toDeviceRequest).toBeInstanceOf(ToDeviceRequest); - const toDeviceRequestId = toDeviceRequest.id; - const toDeviceRequestType = toDeviceRequest.type; - - toDeviceRequest = JSON.parse(toDeviceRequest.body); expect(toDeviceRequest.event_type).toStrictEqual('m.key.verification.key'); const toDeviceEvents = [{ sender: userId1.toString(), type: toDeviceRequest.event_type, - content: toDeviceRequest.messages[userId2.toString()][deviceId2.toString()], + content: JSON.parse(toDeviceRequest.messages)[userId2.toString()][deviceId2.toString()], }]; // Let's send te SAS key to `m2`. await m2.receiveSyncChanges(JSON.stringify(toDeviceEvents), new DeviceLists(), new Map(), new Set()); - m1.markRequestAsSent(toDeviceRequestId, toDeviceRequestType, '{}'); + m1.markRequestAsSent(toDeviceRequest.id, toDeviceRequest.type, '{}'); }); test('emojis match from both sides', () => { @@ -447,14 +433,12 @@ describe('Key Verification', () => { let outgoingVerificationRequest = outgoingVerificationRequests[0]; expect(outgoingVerificationRequest).toBeInstanceOf(ToDeviceRequest); - - outgoingVerificationRequest = JSON.parse(outgoingVerificationRequest.body); expect(outgoingVerificationRequest.event_type).toStrictEqual('m.key.verification.mac'); const toDeviceEvents = [{ sender: userId1.toString(), type: outgoingVerificationRequest.event_type, - content: outgoingVerificationRequest.messages[userId2.toString()][deviceId2.toString()], + content: JSON.parse(outgoingVerificationRequest.messages)[userId2.toString()][deviceId2.toString()], }]; // Let's send te SAS confirmation to `m2`. @@ -473,14 +457,12 @@ describe('Key Verification', () => { let outgoingVerificationRequest = outgoingVerificationRequests[0]; expect(outgoingVerificationRequest).toBeInstanceOf(ToDeviceRequest); - - outgoingVerificationRequest = JSON.parse(outgoingVerificationRequest.body); expect(outgoingVerificationRequest.event_type).toStrictEqual('m.key.verification.mac'); const toDeviceEvents = [{ sender: userId2.toString(), type: outgoingVerificationRequest.event_type, - content: outgoingVerificationRequest.messages[userId1.toString()][deviceId1.toString()], + content: JSON.parse(outgoingVerificationRequest.messages)[userId1.toString()][deviceId1.toString()], }]; // Let's send te SAS confirmation to `m1`. @@ -492,14 +474,12 @@ describe('Key Verification', () => { let outgoingVerificationRequest = outgoingVerificationRequests[1]; expect(outgoingVerificationRequest).toBeInstanceOf(ToDeviceRequest); - - outgoingVerificationRequest = JSON.parse(outgoingVerificationRequest.body); expect(outgoingVerificationRequest.event_type).toStrictEqual('m.key.verification.done'); const toDeviceEvents = [{ sender: userId2.toString(), type: outgoingVerificationRequest.event_type, - content: outgoingVerificationRequest.messages[userId1.toString()][deviceId1.toString()], + content: JSON.parse(outgoingVerificationRequest.messages)[userId1.toString()][deviceId1.toString()], }]; // Let's send te SAS done to `m1`. @@ -514,22 +494,18 @@ describe('Key Verification', () => { let toDeviceRequest = outgoingRequests.find((request) => request.type == RequestType.ToDevice); expect(toDeviceRequest).toBeInstanceOf(ToDeviceRequest); - const toDeviceRequestId = toDeviceRequest.id; - const toDeviceRequestType = toDeviceRequest.type; - - toDeviceRequest = JSON.parse(toDeviceRequest.body); expect(toDeviceRequest.event_type).toStrictEqual('m.key.verification.done'); const toDeviceEvents = [{ sender: userId1.toString(), type: toDeviceRequest.event_type, - content: toDeviceRequest.messages[userId2.toString()][deviceId2.toString()], + content: JSON.parse(toDeviceRequest.messages)[userId2.toString()][deviceId2.toString()], }]; // Let's send te SAS key to `m2`. await m2.receiveSyncChanges(JSON.stringify(toDeviceEvents), new DeviceLists(), new Map(), new Set()); - m1.markRequestAsSent(toDeviceRequestId, toDeviceRequestType, '{}'); + m1.markRequestAsSent(toDeviceRequest.id, toDeviceRequest.type, '{}'); }); test('can see if verification is done', () => { @@ -604,14 +580,12 @@ describe('Key Verification', () => { expect(verificationRequest1.isCancelled()).toStrictEqual(false); expect(outgoingVerificationRequest).toBeInstanceOf(ToDeviceRequest); - - outgoingVerificationRequest = JSON.parse(outgoingVerificationRequest.body); expect(outgoingVerificationRequest.event_type).toStrictEqual('m.key.verification.request'); const toDeviceEvents = [{ sender: userId1.toString(), type: outgoingVerificationRequest.event_type, - content: outgoingVerificationRequest.messages[userId2.toString()][deviceId2.toString()], + content: JSON.parse(outgoingVerificationRequest.messages)[userId2.toString()][deviceId2.toString()], }]; // Let's send the verification request to `m2`. @@ -660,13 +634,12 @@ describe('Key Verification', () => { expect(outgoingVerificationRequest).toBeInstanceOf(ToDeviceRequest); // The request verification is ready. - outgoingVerificationRequest = JSON.parse(outgoingVerificationRequest.body); expect(outgoingVerificationRequest.event_type).toStrictEqual('m.key.verification.ready'); const toDeviceEvents = [{ sender: userId2.toString(), type: outgoingVerificationRequest.event_type, - content: outgoingVerificationRequest.messages[userId1.toString()][deviceId1.toString()], + content: JSON.parse(outgoingVerificationRequest.messages)[userId1.toString()][deviceId1.toString()], }]; // Let's send the verification ready to `m1`. @@ -818,14 +791,12 @@ describe('Key Verification', () => { let outgoingVerificationRequest = qr1.reciprocate(); expect(outgoingVerificationRequest).toBeInstanceOf(ToDeviceRequest); - - outgoingVerificationRequest = JSON.parse(outgoingVerificationRequest.body); expect(outgoingVerificationRequest.event_type).toStrictEqual('m.key.verification.start'); const toDeviceEvents = [{ sender: userId1.toString(), type: outgoingVerificationRequest.event_type, - content: outgoingVerificationRequest.messages[userId2.toString()][deviceId2.toString()], + content: JSON.parse(outgoingVerificationRequest.messages)[userId2.toString()][deviceId2.toString()], }]; // Let's send the verification request to `m2`. @@ -840,14 +811,12 @@ describe('Key Verification', () => { let outgoingVerificationRequest = qr2.confirmScanning(); expect(outgoingVerificationRequest).toBeInstanceOf(ToDeviceRequest); - - outgoingVerificationRequest = JSON.parse(outgoingVerificationRequest.body); expect(outgoingVerificationRequest.event_type).toStrictEqual('m.key.verification.done'); const toDeviceEvents = [{ sender: userId2.toString(), type: outgoingVerificationRequest.event_type, - content: outgoingVerificationRequest.messages[userId1.toString()][deviceId1.toString()], + content: JSON.parse(outgoingVerificationRequest.messages)[userId1.toString()][deviceId1.toString()], }]; // Let's send the verification request to `m2`. diff --git a/bindings/matrix-sdk-crypto-js/tests/helper.js b/bindings/matrix-sdk-crypto-js/tests/helper.js index 29f21b61a..767210669 100644 --- a/bindings/matrix-sdk-crypto-js/tests/helper.js +++ b/bindings/matrix-sdk-crypto-js/tests/helper.js @@ -31,9 +31,8 @@ async function addMachineToMachine(machineToAdd, machine) { expect(outgoingRequests[0].id).toBeDefined(); expect(outgoingRequests[0].type).toStrictEqual(RequestType.KeysUpload); - const body = JSON.parse(outgoingRequests[0].body); - expect(body.device_keys).toBeDefined(); - expect(body.one_time_keys).toBeDefined(); + expect(outgoingRequests[0].device_keys).toBeDefined(); + expect(outgoingRequests[0].one_time_keys).toBeDefined(); // https://spec.matrix.org/v1.2/client-server-api/#post_matrixclientv3keysupload const hypothetical_response = JSON.stringify({ @@ -45,14 +44,13 @@ async function addMachineToMachine(machineToAdd, machine) { const marked = await machineToAdd.markRequestAsSent(outgoingRequests[0].id, outgoingRequests[0].type, hypothetical_response); expect(marked).toStrictEqual(true); - keysUploadRequest = body; + keysUploadRequest = outgoingRequests[0]; } { expect(outgoingRequests[1]).toBeInstanceOf(KeysQueryRequest); let [signingKeysUploadRequest, _] = await machineToAdd.bootstrapCrossSigning(true); - signingKeysUploadRequest = JSON.parse(signingKeysUploadRequest.body); // Let's forge a `KeysQuery`'s response. let keyQueryResponse = { @@ -64,10 +62,10 @@ async function addMachineToMachine(machineToAdd, machine) { const userId = machineToAdd.userId.toString(); const deviceId = machineToAdd.deviceId.toString(); keyQueryResponse.device_keys[userId] = {}; - keyQueryResponse.device_keys[userId][deviceId] = keysUploadRequest.device_keys; - keyQueryResponse.master_keys[userId] = signingKeysUploadRequest.master_key; - keyQueryResponse.self_signing_keys[userId] = signingKeysUploadRequest.self_signing_key; - keyQueryResponse.user_signing_keys[userId] = signingKeysUploadRequest.user_signing_key; + keyQueryResponse.device_keys[userId][deviceId] = JSON.parse(keysUploadRequest.device_keys); + keyQueryResponse.master_keys[userId] = JSON.parse(signingKeysUploadRequest.master_key); + keyQueryResponse.self_signing_keys[userId] = JSON.parse(signingKeysUploadRequest.self_signing_key); + keyQueryResponse.user_signing_keys[userId] = JSON.parse(signingKeysUploadRequest.user_signing_key); const marked = await machine.markRequestAsSent(outgoingRequests[1].id, outgoingRequests[1].type, JSON.stringify(keyQueryResponse)); expect(marked).toStrictEqual(true); diff --git a/bindings/matrix-sdk-crypto-js/tests/machine.test.js b/bindings/matrix-sdk-crypto-js/tests/machine.test.js index 5cff5e262..4c6b3d5ca 100644 --- a/bindings/matrix-sdk-crypto-js/tests/machine.test.js +++ b/bindings/matrix-sdk-crypto-js/tests/machine.test.js @@ -198,21 +198,17 @@ describe(OlmMachine.name, () => { expect(outgoingRequests[0]).toBeInstanceOf(KeysUploadRequest); expect(outgoingRequests[0].id).toBeDefined(); expect(outgoingRequests[0].type).toStrictEqual(RequestType.KeysUpload); - - const body = JSON.parse(outgoingRequests[0].body); - expect(body.device_keys).toBeDefined(); - expect(body.one_time_keys).toBeDefined(); + expect(outgoingRequests[0].device_keys).toBeDefined(); + expect(outgoingRequests[0].one_time_keys).toBeDefined(); } { expect(outgoingRequests[1]).toBeInstanceOf(KeysQueryRequest); expect(outgoingRequests[1].id).toBeDefined(); expect(outgoingRequests[1].type).toStrictEqual(RequestType.KeysQuery); - - const body = JSON.parse(outgoingRequests[1].body); - expect(body.timeout).toBeDefined(); - expect(body.device_keys).toBeDefined(); - expect(body.token).toBeDefined(); + expect(outgoingRequests[1].timeout).toBeUndefined(); + expect(outgoingRequests[1].device_keys).toBeDefined(); + expect(outgoingRequests[1].token).toBeUndefined(); } }); diff --git a/bindings/matrix-sdk-crypto-js/tests/requests.test.js b/bindings/matrix-sdk-crypto-js/tests/requests.test.js index eb595ccc8..a69b7b392 100644 --- a/bindings/matrix-sdk-crypto-js/tests/requests.test.js +++ b/bindings/matrix-sdk-crypto-js/tests/requests.test.js @@ -11,25 +11,3 @@ describe('RequestType', () => { expect(RequestType.KeysBackup).toStrictEqual(6); }); }); - -for (const [request, requestType] of [ - [KeysUploadRequest, RequestType.KeysUpload], - [KeysQueryRequest, RequestType.KeysQuery], - [KeysClaimRequest, RequestType.KeysClaim], - [ToDeviceRequest, RequestType.ToDevice], - [SignatureUploadRequest, RequestType.SignatureUpload], - [RoomMessageRequest, RequestType.RoomMessage], - [KeysBackupRequest, RequestType.KeysBackup], -]) { - describe(request.name, () => { - test('can be instantiated', () => { - const r = new (request)('foo', '{"bar": "baz"}'); - - expect(r).toBeInstanceOf(request); - expect(r.id).toStrictEqual('foo'); - expect(r.body).toStrictEqual('{"bar": "baz"}'); - expect(r.type).toStrictEqual(requestType); - }); - }) - -} From c0ccd55df8c31bd94a4aa94c9f461c29ffb130a5 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 22 Dec 2022 17:42:23 +0100 Subject: [PATCH 03/12] =?UTF-8?q?feat(crypto-js):=20`request!`=20different?= =?UTF-8?q?iates=20=E2=80=9Cextracted=E2=80=9D=20and=20=E2=80=9Cgrouped?= =?UTF-8?q?=E2=80=9D=20fields.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bindings/matrix-sdk-crypto-js/src/requests.rs | 183 ++++++++---------- 1 file changed, 80 insertions(+), 103 deletions(-) diff --git a/bindings/matrix-sdk-crypto-js/src/requests.rs b/bindings/matrix-sdk-crypto-js/src/requests.rs index f4c692f50..198a22930 100644 --- a/bindings/matrix-sdk-crypto-js/src/requests.rs +++ b/bindings/matrix-sdk-crypto-js/src/requests.rs @@ -33,34 +33,18 @@ pub struct KeysUploadRequest { #[wasm_bindgen(readonly)] pub id: Option, - /// A JSON-encoded string representing identity keys for the device. - /// - /// May be absent if no new identity keys are required. + /// A JSON-encoded string containing the rest of the payload: `device_keys`, + /// `one_time_keys`, `fallback_keys`. #[wasm_bindgen(readonly)] - pub device_keys: JsString, - - /// A JSON-encoded string representing one-time public keys for “pre-key” - /// messages. - #[wasm_bindgen(readonly)] - pub one_time_keys: JsString, - - /// A JSON-encoded string representing fallback public keys for “pre-key” - /// messages. - #[wasm_bindgen(readonly)] - pub fallback_keys: JsString, + pub body: JsString, } #[wasm_bindgen] impl KeysUploadRequest { /// Create a new `KeysUploadRequest`. #[wasm_bindgen(constructor)] - pub fn new( - id: JsString, - device_keys: JsString, - one_time_keys: JsString, - fallback_keys: JsString, - ) -> KeysUploadRequest { - Self { id: Some(id), device_keys, one_time_keys, fallback_keys } + pub fn new(id: JsString, body: JsString) -> KeysUploadRequest { + Self { id: Some(id), body } } /// Get its request type. @@ -83,37 +67,18 @@ pub struct KeysQueryRequest { #[wasm_bindgen(readonly)] pub id: Option, - /// An optional integer representing the time (in milliseconds) to wait when - /// downloading keys from remote servers. 10 seconds is the recommended - /// default. + /// A JSON-encoded string containing the rest of the payload: `timeout`, + /// `device_keys`, `token`. #[wasm_bindgen(readonly)] - pub timeout: Option, - - /// A JSON-encoded string representing the keys to be downloaded. An empty - /// list indicates all devices for the corresponding user. - #[wasm_bindgen(readonly)] - pub device_keys: JsString, - - /// An optional string representing if the client is fetching keys as a - /// result of a device update received in a sync request, this should be the - /// `since` token of that sync request, or any later sync token. This allows - /// the server to ensure its response contains the keys advertised by the - /// notification in that sync. - #[wasm_bindgen(readonly)] - pub token: Option, + pub body: JsString, } #[wasm_bindgen] impl KeysQueryRequest { /// Create a new `KeysQueryRequest`. #[wasm_bindgen(constructor)] - pub fn new( - id: JsString, - timeout: Option, - device_keys: JsString, - token: Option, - ) -> KeysQueryRequest { - Self { id: Some(id), timeout, device_keys, token } + pub fn new(id: JsString, body: JsString) -> KeysQueryRequest { + Self { id: Some(id), body } } /// Get its request type. @@ -137,23 +102,18 @@ pub struct KeysClaimRequest { #[wasm_bindgen(readonly)] pub id: Option, - /// An optional integer representing the time (in milliseconds) to wait when - /// downloading keys from remote servers. 10 seconds is the recommended - /// default. + /// A JSON-encoded string containing the rest of the payload: `timeout`, + /// `one_time_keys`. #[wasm_bindgen(readonly)] - pub timeout: Option, - - /// A JSON-encoded string representing the keys to be claimed. - #[wasm_bindgen(readonly)] - pub one_time_keys: JsString, + pub body: JsString, } #[wasm_bindgen] impl KeysClaimRequest { /// Create a new `KeysClaimRequest`. #[wasm_bindgen(constructor)] - pub fn new(id: JsString, timeout: Option, one_time_keys: JsString) -> KeysClaimRequest { - Self { id: Some(id), timeout, one_time_keys } + pub fn new(id: JsString, body: JsString) -> KeysClaimRequest { + Self { id: Some(id), body } } /// Get its request type. @@ -185,12 +145,9 @@ pub struct ToDeviceRequest { #[wasm_bindgen(readonly)] pub txn_id: JsString, - /// A JSON-encoded string representing a map of users to devices to a - /// content for a message event to be sent to the user's device. Individual - /// message events can be sent to devices, but all events must be of the - /// same type. + /// A JSON-encoded string containing the rest of the payload: `messages`. #[wasm_bindgen(readonly)] - pub messages: JsString, + pub body: JsString, } #[wasm_bindgen] @@ -201,9 +158,9 @@ impl ToDeviceRequest { id: JsString, event_type: JsString, txn_id: JsString, - messages: JsString, + body: JsString, ) -> ToDeviceRequest { - Self { id: Some(id), event_type, txn_id, messages } + Self { id: Some(id), event_type, txn_id, body } } /// Get its request type. @@ -226,17 +183,17 @@ pub struct SignatureUploadRequest { #[wasm_bindgen(readonly)] pub id: Option, - /// A JSON-encoded string representing the signed keys. + /// A JSON-encoded string containing the rest of the payload: `signed_keys`. #[wasm_bindgen(readonly)] - pub signed_keys: JsString, + pub body: JsString, } #[wasm_bindgen] impl SignatureUploadRequest { /// Create a new `SignatureUploadRequest`. #[wasm_bindgen(constructor)] - pub fn new(id: JsString, signed_keys: JsString) -> SignatureUploadRequest { - Self { id: Some(id), signed_keys } + pub fn new(id: JsString, body: JsString) -> SignatureUploadRequest { + Self { id: Some(id), body } } /// Get its request type. @@ -269,9 +226,9 @@ pub struct RoomMessageRequest { #[wasm_bindgen(readonly)] pub txn_id: JsString, - /// A JSON-encoded string representing the event content to send. + /// A JSON-encoded string containing the rest of the payload: `content`. #[wasm_bindgen(readonly)] - pub content: JsString, + pub body: JsString, } #[wasm_bindgen] @@ -282,9 +239,9 @@ impl RoomMessageRequest { id: JsString, room_id: JsString, txn_id: JsString, - content: JsString, + body: JsString, ) -> RoomMessageRequest { - Self { id: Some(id), room_id, txn_id, content } + Self { id: Some(id), room_id, txn_id, body } } /// Get its request type. @@ -305,18 +262,17 @@ pub struct KeysBackupRequest { #[wasm_bindgen(readonly)] pub id: Option, - /// A JSON-encoded string representing the map from room ID to a backed up - /// room key that we're going to upload to the server. + /// A JSON-encoded string containing the rest of the payload: `rooms`. #[wasm_bindgen(readonly)] - pub rooms: JsString, + pub body: JsString, } #[wasm_bindgen] impl KeysBackupRequest { /// Create a new `KeysBackupRequest`. #[wasm_bindgen(constructor)] - pub fn new(id: JsString, rooms: JsString) -> KeysBackupRequest { - Self { id: Some(id), rooms } + pub fn new(id: JsString, body: JsString) -> KeysBackupRequest { + Self { id: Some(id), body } } /// Get its request type. @@ -338,30 +294,28 @@ pub struct SigningKeysUploadRequest { #[wasm_bindgen(readonly)] pub id: Option, - /// A JSON-encoded string representing the user's master key.. + /// A JSON-encoded string containing the rest of the payload: `master_key`, + /// `self_signing_key`, `user_signing_key`. #[wasm_bindgen(readonly)] - pub master_key: JsString, - - /// A JSON-encoded string representing the user's self-signing key. Must - /// be signed with the accompanied master, or by the user's most recently - /// uploaded master key if no master key is included in the request. - #[wasm_bindgen(readonly)] - pub self_signing_key: JsString, - - /// A JSON-encoded string representing the user's user-signing key. Must - /// be signed with the accompanied master, or by the user's most recently - /// uploaded master key if no master key is included in the request. - #[wasm_bindgen(readonly)] - pub user_signing_key: JsString, + pub body: JsString, } macro_rules! request { - ( $destination_request:ident from $source_request:ident maps fields $( $field:ident: $field_type:ident ),+ $(,)? ) => { + ( + $destination_request:ident from $source_request:ident + $( extracts fields $( $field:ident: $field_type:ident ),+ $(,)? )? + $( $( and )? groups fields $( $grouped_field:ident ),+ $(,)? )? + ) => { impl TryFrom<&$source_request> for $destination_request { type Error = serde_json::Error; fn try_from(request: &$source_request) -> Result { - request!(@__try_from $destination_request from $source_request (request_id = None, request = request) maps fields $( $field: $field_type, )+ ) + request!( + @__try_from $destination_request from $source_request + (request_id = None, request = request) + $( extracts [ $( $field: $field_type, )+ ] )? + $( groups [ $( $grouped_field, )+ ] )? + ) } } @@ -371,18 +325,41 @@ macro_rules! request { fn try_from( (request_id, request): (String, &$source_request), ) -> Result { - request!(@__try_from $destination_request from $source_request (request_id = Some(request_id.into()), request = request) maps fields $( $field: $field_type, )+ ) + request!( + @__try_from $destination_request from $source_request + (request_id = Some(request_id.into()), request = request) + $( extracts [ $( $field: $field_type, )+ ] )? + $( groups [ $( $grouped_field, )+ ] )? + ) } } }; - ( @__try_from $destination_request:ident from $source_request:ident (request_id = $request_id:expr, request = $request:expr) maps fields $( $field:ident: $field_type:ident ),+ $(,)? ) => { + ( + @__try_from $destination_request:ident from $source_request:ident + (request_id = $request_id:expr, request = $request:expr) + $( extracts [ $( $field:ident: $field_type:ident ),* $(,)? ] )? + $( groups [ $( $grouped_field:ident ),* $(,)? ] )? + ) => { { Ok($destination_request { id: $request_id, $( - $field: request!(@__field as $field_type (request = $request, field = $field)), - )+ + $( + $field: request!(@__field as $field_type (request = $request, field = $field)), + )* + )? + $( + body: { + let mut map = serde_json::Map::new(); + $( + map.insert(stringify!($grouped_field).to_owned(), serde_json::to_value(&$request.$grouped_field).unwrap()); + )* + let object = serde_json::Value::Object(map); + + serde_json::to_string(&object)?.into() + } + )? }) } }; @@ -405,16 +382,16 @@ macro_rules! request { } // Outgoing Requests -request!(KeysUploadRequest from OriginalKeysUploadRequest maps fields device_keys: json, one_time_keys: json, fallback_keys: json); -request!(KeysQueryRequest from OriginalKeysQueryRequest maps fields timeout: duration, device_keys: json, token: native); -request!(KeysClaimRequest from OriginalKeysClaimRequest maps fields timeout: duration, one_time_keys: json); -request!(ToDeviceRequest from OriginalToDeviceRequest maps fields event_type: string, txn_id: string, messages: json); -request!(SignatureUploadRequest from OriginalSignatureUploadRequest maps fields signed_keys: json); -request!(RoomMessageRequest from OriginalRoomMessageRequest maps fields room_id: string, txn_id: string, content: json); -request!(KeysBackupRequest from OriginalKeysBackupRequest maps fields rooms: json); +request!(KeysUploadRequest from OriginalKeysUploadRequest groups fields device_keys, one_time_keys, fallback_keys); +request!(KeysQueryRequest from OriginalKeysQueryRequest groups fields timeout, device_keys, token); +request!(KeysClaimRequest from OriginalKeysClaimRequest groups fields timeout, one_time_keys); +request!(ToDeviceRequest from OriginalToDeviceRequest extracts fields event_type: string, txn_id: string and groups fields messages); +request!(SignatureUploadRequest from OriginalSignatureUploadRequest groups fields signed_keys); +request!(RoomMessageRequest from OriginalRoomMessageRequest extracts fields room_id: string, txn_id: string and groups fields content); +request!(KeysBackupRequest from OriginalKeysBackupRequest groups fields rooms); // Other Requests -request!(SigningKeysUploadRequest from OriginalUploadSigningKeysRequest maps fields master_key: json, self_signing_key: json, user_signing_key: json); +request!(SigningKeysUploadRequest from OriginalUploadSigningKeysRequest groups fields master_key, self_signing_key, user_signing_key); // JavaScript has no complex enums like Rust. To return structs of // different types, we have no choice that hiding everything behind a From 6248e2bc68e6d139c3d39434d47c89d301e0f665 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 22 Dec 2022 17:50:43 +0100 Subject: [PATCH 04/12] test(crypto-js): Update tests according to previous commit. --- .../tests/attachment.test.js | 2 +- .../matrix-sdk-crypto-js/tests/device.test.js | 28 +++++++++---------- bindings/matrix-sdk-crypto-js/tests/helper.js | 16 +++++++---- .../tests/machine.test.js | 16 +++++++---- 4 files changed, 36 insertions(+), 26 deletions(-) diff --git a/bindings/matrix-sdk-crypto-js/tests/attachment.test.js b/bindings/matrix-sdk-crypto-js/tests/attachment.test.js index 0cc49e1be..a614ef0dc 100644 --- a/bindings/matrix-sdk-crypto-js/tests/attachment.test.js +++ b/bindings/matrix-sdk-crypto-js/tests/attachment.test.js @@ -6,7 +6,7 @@ describe(Attachment.name, () => { const textDecoder = new TextDecoder(); let encryptedAttachment; - + test('can encrypt data', () => { encryptedAttachment = Attachment.encrypt(textEncoder.encode(originalData)); diff --git a/bindings/matrix-sdk-crypto-js/tests/device.test.js b/bindings/matrix-sdk-crypto-js/tests/device.test.js index c9f84cf90..14ecc2051 100644 --- a/bindings/matrix-sdk-crypto-js/tests/device.test.js +++ b/bindings/matrix-sdk-crypto-js/tests/device.test.js @@ -177,7 +177,7 @@ describe('Key Verification', () => { const toDeviceEvents = [{ sender: userId1.toString(), type: outgoingVerificationRequest.event_type, - content: JSON.parse(outgoingVerificationRequest.messages)[userId2.toString()][deviceId2.toString()], + content: JSON.parse(outgoingVerificationRequest.body).messages[userId2.toString()][deviceId2.toString()], }]; // Let's send the verification request to `m2`. @@ -228,7 +228,7 @@ describe('Key Verification', () => { const toDeviceEvents = [{ sender: userId2.toString(), type: outgoingVerificationRequest.event_type, - content: JSON.parse(outgoingVerificationRequest.messages)[userId1.toString()][deviceId1.toString()], + content: JSON.parse(outgoingVerificationRequest.body).messages[userId1.toString()][deviceId1.toString()], }]; // Let's send the verification ready to `m1`. @@ -281,7 +281,7 @@ describe('Key Verification', () => { const toDeviceEvents = [{ sender: userId2.toString(), type: outgoingVerificationRequest.event_type, - content: JSON.parse(outgoingVerificationRequest.messages)[userId1.toString()][deviceId1.toString()], + content: JSON.parse(outgoingVerificationRequest.body).messages[userId1.toString()][deviceId1.toString()], }]; // Let's send the SAS start to `m1`. @@ -326,7 +326,7 @@ describe('Key Verification', () => { const toDeviceEvents = [{ sender: userId1.toString(), type: outgoingVerificationRequest.event_type, - content: JSON.parse(outgoingVerificationRequest.messages)[userId2.toString()][deviceId2.toString()], + content: JSON.parse(outgoingVerificationRequest.body).messages[userId2.toString()][deviceId2.toString()], }]; // Let's send the SAS accept to `m2`. @@ -349,7 +349,7 @@ describe('Key Verification', () => { const toDeviceEvents = [{ sender: userId2.toString(), type: toDeviceRequest.event_type, - content: JSON.parse(toDeviceRequest.messages)[userId1.toString()][deviceId1.toString()], + content: JSON.parse(toDeviceRequest.body).messages[userId1.toString()][deviceId1.toString()], }]; // Let's send te SAS key to `m1`. @@ -369,7 +369,7 @@ describe('Key Verification', () => { const toDeviceEvents = [{ sender: userId1.toString(), type: toDeviceRequest.event_type, - content: JSON.parse(toDeviceRequest.messages)[userId2.toString()][deviceId2.toString()], + content: JSON.parse(toDeviceRequest.body).messages[userId2.toString()][deviceId2.toString()], }]; // Let's send te SAS key to `m2`. @@ -438,7 +438,7 @@ describe('Key Verification', () => { const toDeviceEvents = [{ sender: userId1.toString(), type: outgoingVerificationRequest.event_type, - content: JSON.parse(outgoingVerificationRequest.messages)[userId2.toString()][deviceId2.toString()], + content: JSON.parse(outgoingVerificationRequest.body).messages[userId2.toString()][deviceId2.toString()], }]; // Let's send te SAS confirmation to `m2`. @@ -462,7 +462,7 @@ describe('Key Verification', () => { const toDeviceEvents = [{ sender: userId2.toString(), type: outgoingVerificationRequest.event_type, - content: JSON.parse(outgoingVerificationRequest.messages)[userId1.toString()][deviceId1.toString()], + content: JSON.parse(outgoingVerificationRequest.body).messages[userId1.toString()][deviceId1.toString()], }]; // Let's send te SAS confirmation to `m1`. @@ -479,7 +479,7 @@ describe('Key Verification', () => { const toDeviceEvents = [{ sender: userId2.toString(), type: outgoingVerificationRequest.event_type, - content: JSON.parse(outgoingVerificationRequest.messages)[userId1.toString()][deviceId1.toString()], + content: JSON.parse(outgoingVerificationRequest.body).messages[userId1.toString()][deviceId1.toString()], }]; // Let's send te SAS done to `m1`. @@ -499,7 +499,7 @@ describe('Key Verification', () => { const toDeviceEvents = [{ sender: userId1.toString(), type: toDeviceRequest.event_type, - content: JSON.parse(toDeviceRequest.messages)[userId2.toString()][deviceId2.toString()], + content: JSON.parse(toDeviceRequest.body).messages[userId2.toString()][deviceId2.toString()], }]; // Let's send te SAS key to `m2`. @@ -585,7 +585,7 @@ describe('Key Verification', () => { const toDeviceEvents = [{ sender: userId1.toString(), type: outgoingVerificationRequest.event_type, - content: JSON.parse(outgoingVerificationRequest.messages)[userId2.toString()][deviceId2.toString()], + content: JSON.parse(outgoingVerificationRequest.body).messages[userId2.toString()][deviceId2.toString()], }]; // Let's send the verification request to `m2`. @@ -639,7 +639,7 @@ describe('Key Verification', () => { const toDeviceEvents = [{ sender: userId2.toString(), type: outgoingVerificationRequest.event_type, - content: JSON.parse(outgoingVerificationRequest.messages)[userId1.toString()][deviceId1.toString()], + content: JSON.parse(outgoingVerificationRequest.body).messages[userId1.toString()][deviceId1.toString()], }]; // Let's send the verification ready to `m1`. @@ -796,7 +796,7 @@ describe('Key Verification', () => { const toDeviceEvents = [{ sender: userId1.toString(), type: outgoingVerificationRequest.event_type, - content: JSON.parse(outgoingVerificationRequest.messages)[userId2.toString()][deviceId2.toString()], + content: JSON.parse(outgoingVerificationRequest.body).messages[userId2.toString()][deviceId2.toString()], }]; // Let's send the verification request to `m2`. @@ -816,7 +816,7 @@ describe('Key Verification', () => { const toDeviceEvents = [{ sender: userId2.toString(), type: outgoingVerificationRequest.event_type, - content: JSON.parse(outgoingVerificationRequest.messages)[userId1.toString()][deviceId1.toString()], + content: JSON.parse(outgoingVerificationRequest.body).messages[userId1.toString()][deviceId1.toString()], }]; // Let's send the verification request to `m2`. diff --git a/bindings/matrix-sdk-crypto-js/tests/helper.js b/bindings/matrix-sdk-crypto-js/tests/helper.js index 767210669..0d3136bed 100644 --- a/bindings/matrix-sdk-crypto-js/tests/helper.js +++ b/bindings/matrix-sdk-crypto-js/tests/helper.js @@ -30,9 +30,11 @@ async function addMachineToMachine(machineToAdd, machine) { expect(outgoingRequests[0]).toBeInstanceOf(KeysUploadRequest); expect(outgoingRequests[0].id).toBeDefined(); expect(outgoingRequests[0].type).toStrictEqual(RequestType.KeysUpload); + expect(outgoingRequests[0].body).toBeDefined(); - expect(outgoingRequests[0].device_keys).toBeDefined(); - expect(outgoingRequests[0].one_time_keys).toBeDefined(); + const body = JSON.parse(outgoingRequests[0].body); + expect(body.device_keys).toBeDefined(); + expect(body.one_time_keys).toBeDefined(); // https://spec.matrix.org/v1.2/client-server-api/#post_matrixclientv3keysupload const hypothetical_response = JSON.stringify({ @@ -62,10 +64,12 @@ async function addMachineToMachine(machineToAdd, machine) { const userId = machineToAdd.userId.toString(); const deviceId = machineToAdd.deviceId.toString(); keyQueryResponse.device_keys[userId] = {}; - keyQueryResponse.device_keys[userId][deviceId] = JSON.parse(keysUploadRequest.device_keys); - keyQueryResponse.master_keys[userId] = JSON.parse(signingKeysUploadRequest.master_key); - keyQueryResponse.self_signing_keys[userId] = JSON.parse(signingKeysUploadRequest.self_signing_key); - keyQueryResponse.user_signing_keys[userId] = JSON.parse(signingKeysUploadRequest.user_signing_key); + keyQueryResponse.device_keys[userId][deviceId] = JSON.parse(keysUploadRequest.body).device_keys; + + const keys = JSON.parse(signingKeysUploadRequest.body); + keyQueryResponse.master_keys[userId] = keys.master_key; + keyQueryResponse.self_signing_keys[userId] = keys.self_signing_key; + keyQueryResponse.user_signing_keys[userId] = keys.user_signing_key; const marked = await machine.markRequestAsSent(outgoingRequests[1].id, outgoingRequests[1].type, JSON.stringify(keyQueryResponse)); expect(marked).toStrictEqual(true); diff --git a/bindings/matrix-sdk-crypto-js/tests/machine.test.js b/bindings/matrix-sdk-crypto-js/tests/machine.test.js index 4c6b3d5ca..dbbd7f723 100644 --- a/bindings/matrix-sdk-crypto-js/tests/machine.test.js +++ b/bindings/matrix-sdk-crypto-js/tests/machine.test.js @@ -198,17 +198,23 @@ describe(OlmMachine.name, () => { expect(outgoingRequests[0]).toBeInstanceOf(KeysUploadRequest); expect(outgoingRequests[0].id).toBeDefined(); expect(outgoingRequests[0].type).toStrictEqual(RequestType.KeysUpload); - expect(outgoingRequests[0].device_keys).toBeDefined(); - expect(outgoingRequests[0].one_time_keys).toBeDefined(); + expect(outgoingRequests[0].body).toBeDefined(); + + const body = JSON.parse(outgoingRequests[0].body) + expect(body.device_keys).toBeDefined(); + expect(body.one_time_keys).toBeDefined(); } { expect(outgoingRequests[1]).toBeInstanceOf(KeysQueryRequest); expect(outgoingRequests[1].id).toBeDefined(); expect(outgoingRequests[1].type).toStrictEqual(RequestType.KeysQuery); - expect(outgoingRequests[1].timeout).toBeUndefined(); - expect(outgoingRequests[1].device_keys).toBeDefined(); - expect(outgoingRequests[1].token).toBeUndefined(); + expect(outgoingRequests[1].body).toBeDefined(); + + const body = JSON.parse(outgoingRequests[1].body); + expect(body.timeout).toBeDefined(); + expect(body.device_keys).toBeDefined(); + expect(body.token).toBeDefined(); } }); From 8f9859c41c5e1edc641e1a0177dcd8632968dc8b Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 5 Jan 2023 11:45:17 +0100 Subject: [PATCH 05/12] feat(crypto-js): Rename the `body` fields to `extra` to avoid confusion with HTTP terminology. --- bindings/matrix-sdk-crypto-js/src/requests.rs | 58 ++++++++----------- .../matrix-sdk-crypto-js/tests/device.test.js | 28 ++++----- bindings/matrix-sdk-crypto-js/tests/helper.js | 8 +-- .../tests/machine.test.js | 8 +-- 4 files changed, 45 insertions(+), 57 deletions(-) diff --git a/bindings/matrix-sdk-crypto-js/src/requests.rs b/bindings/matrix-sdk-crypto-js/src/requests.rs index 198a22930..f6bc3671c 100644 --- a/bindings/matrix-sdk-crypto-js/src/requests.rs +++ b/bindings/matrix-sdk-crypto-js/src/requests.rs @@ -36,15 +36,15 @@ pub struct KeysUploadRequest { /// A JSON-encoded string containing the rest of the payload: `device_keys`, /// `one_time_keys`, `fallback_keys`. #[wasm_bindgen(readonly)] - pub body: JsString, + pub extra: JsString, } #[wasm_bindgen] impl KeysUploadRequest { /// Create a new `KeysUploadRequest`. #[wasm_bindgen(constructor)] - pub fn new(id: JsString, body: JsString) -> KeysUploadRequest { - Self { id: Some(id), body } + pub fn new(id: JsString, extra: JsString) -> KeysUploadRequest { + Self { id: Some(id), extra } } /// Get its request type. @@ -70,15 +70,15 @@ pub struct KeysQueryRequest { /// A JSON-encoded string containing the rest of the payload: `timeout`, /// `device_keys`, `token`. #[wasm_bindgen(readonly)] - pub body: JsString, + pub extra: JsString, } #[wasm_bindgen] impl KeysQueryRequest { /// Create a new `KeysQueryRequest`. #[wasm_bindgen(constructor)] - pub fn new(id: JsString, body: JsString) -> KeysQueryRequest { - Self { id: Some(id), body } + pub fn new(id: JsString, extra: JsString) -> KeysQueryRequest { + Self { id: Some(id), extra } } /// Get its request type. @@ -105,15 +105,15 @@ pub struct KeysClaimRequest { /// A JSON-encoded string containing the rest of the payload: `timeout`, /// `one_time_keys`. #[wasm_bindgen(readonly)] - pub body: JsString, + pub extra: JsString, } #[wasm_bindgen] impl KeysClaimRequest { /// Create a new `KeysClaimRequest`. #[wasm_bindgen(constructor)] - pub fn new(id: JsString, body: JsString) -> KeysClaimRequest { - Self { id: Some(id), body } + pub fn new(id: JsString, extra: JsString) -> KeysClaimRequest { + Self { id: Some(id), extra } } /// Get its request type. @@ -147,7 +147,7 @@ pub struct ToDeviceRequest { /// A JSON-encoded string containing the rest of the payload: `messages`. #[wasm_bindgen(readonly)] - pub body: JsString, + pub extra: JsString, } #[wasm_bindgen] @@ -158,9 +158,9 @@ impl ToDeviceRequest { id: JsString, event_type: JsString, txn_id: JsString, - body: JsString, + extra: JsString, ) -> ToDeviceRequest { - Self { id: Some(id), event_type, txn_id, body } + Self { id: Some(id), event_type, txn_id, extra } } /// Get its request type. @@ -185,15 +185,15 @@ pub struct SignatureUploadRequest { /// A JSON-encoded string containing the rest of the payload: `signed_keys`. #[wasm_bindgen(readonly)] - pub body: JsString, + pub extra: JsString, } #[wasm_bindgen] impl SignatureUploadRequest { /// Create a new `SignatureUploadRequest`. #[wasm_bindgen(constructor)] - pub fn new(id: JsString, body: JsString) -> SignatureUploadRequest { - Self { id: Some(id), body } + pub fn new(id: JsString, extra: JsString) -> SignatureUploadRequest { + Self { id: Some(id), extra } } /// Get its request type. @@ -228,7 +228,7 @@ pub struct RoomMessageRequest { /// A JSON-encoded string containing the rest of the payload: `content`. #[wasm_bindgen(readonly)] - pub body: JsString, + pub extra: JsString, } #[wasm_bindgen] @@ -239,9 +239,9 @@ impl RoomMessageRequest { id: JsString, room_id: JsString, txn_id: JsString, - body: JsString, + extra: JsString, ) -> RoomMessageRequest { - Self { id: Some(id), room_id, txn_id, body } + Self { id: Some(id), room_id, txn_id, extra } } /// Get its request type. @@ -264,15 +264,15 @@ pub struct KeysBackupRequest { /// A JSON-encoded string containing the rest of the payload: `rooms`. #[wasm_bindgen(readonly)] - pub body: JsString, + pub extra: JsString, } #[wasm_bindgen] impl KeysBackupRequest { /// Create a new `KeysBackupRequest`. #[wasm_bindgen(constructor)] - pub fn new(id: JsString, body: JsString) -> KeysBackupRequest { - Self { id: Some(id), body } + pub fn new(id: JsString, extra: JsString) -> KeysBackupRequest { + Self { id: Some(id), extra } } /// Get its request type. @@ -297,7 +297,7 @@ pub struct SigningKeysUploadRequest { /// A JSON-encoded string containing the rest of the payload: `master_key`, /// `self_signing_key`, `user_signing_key`. #[wasm_bindgen(readonly)] - pub body: JsString, + pub extra: JsString, } macro_rules! request { @@ -350,7 +350,7 @@ macro_rules! request { )* )? $( - body: { + extra: { let mut map = serde_json::Map::new(); $( map.insert(stringify!($grouped_field).to_owned(), serde_json::to_value(&$request.$grouped_field).unwrap()); @@ -364,21 +364,9 @@ macro_rules! request { } }; - ( @__field as json (request = $request:expr, field = $field:ident) ) => { - serde_json::to_string(&$request.$field)?.into() - }; - ( @__field as string (request = $request:expr, field = $field:ident) ) => { $request.$field.to_string().into() }; - - ( @__field as duration (request = $request:expr, field = $field:ident) ) => { - $request.$field.map(|duration| duration.as_millis() as u64) - }; - - ( @__field as native (request = $request:expr, field = $field:ident) ) => { - $request.$field.clone() - }; } // Outgoing Requests diff --git a/bindings/matrix-sdk-crypto-js/tests/device.test.js b/bindings/matrix-sdk-crypto-js/tests/device.test.js index 14ecc2051..73c3a78cd 100644 --- a/bindings/matrix-sdk-crypto-js/tests/device.test.js +++ b/bindings/matrix-sdk-crypto-js/tests/device.test.js @@ -177,7 +177,7 @@ describe('Key Verification', () => { const toDeviceEvents = [{ sender: userId1.toString(), type: outgoingVerificationRequest.event_type, - content: JSON.parse(outgoingVerificationRequest.body).messages[userId2.toString()][deviceId2.toString()], + content: JSON.parse(outgoingVerificationRequest.extra).messages[userId2.toString()][deviceId2.toString()], }]; // Let's send the verification request to `m2`. @@ -228,7 +228,7 @@ describe('Key Verification', () => { const toDeviceEvents = [{ sender: userId2.toString(), type: outgoingVerificationRequest.event_type, - content: JSON.parse(outgoingVerificationRequest.body).messages[userId1.toString()][deviceId1.toString()], + content: JSON.parse(outgoingVerificationRequest.extra).messages[userId1.toString()][deviceId1.toString()], }]; // Let's send the verification ready to `m1`. @@ -281,7 +281,7 @@ describe('Key Verification', () => { const toDeviceEvents = [{ sender: userId2.toString(), type: outgoingVerificationRequest.event_type, - content: JSON.parse(outgoingVerificationRequest.body).messages[userId1.toString()][deviceId1.toString()], + content: JSON.parse(outgoingVerificationRequest.extra).messages[userId1.toString()][deviceId1.toString()], }]; // Let's send the SAS start to `m1`. @@ -326,7 +326,7 @@ describe('Key Verification', () => { const toDeviceEvents = [{ sender: userId1.toString(), type: outgoingVerificationRequest.event_type, - content: JSON.parse(outgoingVerificationRequest.body).messages[userId2.toString()][deviceId2.toString()], + content: JSON.parse(outgoingVerificationRequest.extra).messages[userId2.toString()][deviceId2.toString()], }]; // Let's send the SAS accept to `m2`. @@ -349,7 +349,7 @@ describe('Key Verification', () => { const toDeviceEvents = [{ sender: userId2.toString(), type: toDeviceRequest.event_type, - content: JSON.parse(toDeviceRequest.body).messages[userId1.toString()][deviceId1.toString()], + content: JSON.parse(toDeviceRequest.extra).messages[userId1.toString()][deviceId1.toString()], }]; // Let's send te SAS key to `m1`. @@ -369,7 +369,7 @@ describe('Key Verification', () => { const toDeviceEvents = [{ sender: userId1.toString(), type: toDeviceRequest.event_type, - content: JSON.parse(toDeviceRequest.body).messages[userId2.toString()][deviceId2.toString()], + content: JSON.parse(toDeviceRequest.extra).messages[userId2.toString()][deviceId2.toString()], }]; // Let's send te SAS key to `m2`. @@ -438,7 +438,7 @@ describe('Key Verification', () => { const toDeviceEvents = [{ sender: userId1.toString(), type: outgoingVerificationRequest.event_type, - content: JSON.parse(outgoingVerificationRequest.body).messages[userId2.toString()][deviceId2.toString()], + content: JSON.parse(outgoingVerificationRequest.extra).messages[userId2.toString()][deviceId2.toString()], }]; // Let's send te SAS confirmation to `m2`. @@ -462,7 +462,7 @@ describe('Key Verification', () => { const toDeviceEvents = [{ sender: userId2.toString(), type: outgoingVerificationRequest.event_type, - content: JSON.parse(outgoingVerificationRequest.body).messages[userId1.toString()][deviceId1.toString()], + content: JSON.parse(outgoingVerificationRequest.extra).messages[userId1.toString()][deviceId1.toString()], }]; // Let's send te SAS confirmation to `m1`. @@ -479,7 +479,7 @@ describe('Key Verification', () => { const toDeviceEvents = [{ sender: userId2.toString(), type: outgoingVerificationRequest.event_type, - content: JSON.parse(outgoingVerificationRequest.body).messages[userId1.toString()][deviceId1.toString()], + content: JSON.parse(outgoingVerificationRequest.extra).messages[userId1.toString()][deviceId1.toString()], }]; // Let's send te SAS done to `m1`. @@ -499,7 +499,7 @@ describe('Key Verification', () => { const toDeviceEvents = [{ sender: userId1.toString(), type: toDeviceRequest.event_type, - content: JSON.parse(toDeviceRequest.body).messages[userId2.toString()][deviceId2.toString()], + content: JSON.parse(toDeviceRequest.extra).messages[userId2.toString()][deviceId2.toString()], }]; // Let's send te SAS key to `m2`. @@ -585,7 +585,7 @@ describe('Key Verification', () => { const toDeviceEvents = [{ sender: userId1.toString(), type: outgoingVerificationRequest.event_type, - content: JSON.parse(outgoingVerificationRequest.body).messages[userId2.toString()][deviceId2.toString()], + content: JSON.parse(outgoingVerificationRequest.extra).messages[userId2.toString()][deviceId2.toString()], }]; // Let's send the verification request to `m2`. @@ -639,7 +639,7 @@ describe('Key Verification', () => { const toDeviceEvents = [{ sender: userId2.toString(), type: outgoingVerificationRequest.event_type, - content: JSON.parse(outgoingVerificationRequest.body).messages[userId1.toString()][deviceId1.toString()], + content: JSON.parse(outgoingVerificationRequest.extra).messages[userId1.toString()][deviceId1.toString()], }]; // Let's send the verification ready to `m1`. @@ -796,7 +796,7 @@ describe('Key Verification', () => { const toDeviceEvents = [{ sender: userId1.toString(), type: outgoingVerificationRequest.event_type, - content: JSON.parse(outgoingVerificationRequest.body).messages[userId2.toString()][deviceId2.toString()], + content: JSON.parse(outgoingVerificationRequest.extra).messages[userId2.toString()][deviceId2.toString()], }]; // Let's send the verification request to `m2`. @@ -816,7 +816,7 @@ describe('Key Verification', () => { const toDeviceEvents = [{ sender: userId2.toString(), type: outgoingVerificationRequest.event_type, - content: JSON.parse(outgoingVerificationRequest.body).messages[userId1.toString()][deviceId1.toString()], + content: JSON.parse(outgoingVerificationRequest.extra).messages[userId1.toString()][deviceId1.toString()], }]; // Let's send the verification request to `m2`. diff --git a/bindings/matrix-sdk-crypto-js/tests/helper.js b/bindings/matrix-sdk-crypto-js/tests/helper.js index 0d3136bed..9be52c9e1 100644 --- a/bindings/matrix-sdk-crypto-js/tests/helper.js +++ b/bindings/matrix-sdk-crypto-js/tests/helper.js @@ -30,9 +30,9 @@ async function addMachineToMachine(machineToAdd, machine) { expect(outgoingRequests[0]).toBeInstanceOf(KeysUploadRequest); expect(outgoingRequests[0].id).toBeDefined(); expect(outgoingRequests[0].type).toStrictEqual(RequestType.KeysUpload); - expect(outgoingRequests[0].body).toBeDefined(); + expect(outgoingRequests[0].extra).toBeDefined(); - const body = JSON.parse(outgoingRequests[0].body); + const body = JSON.parse(outgoingRequests[0].extra); expect(body.device_keys).toBeDefined(); expect(body.one_time_keys).toBeDefined(); @@ -64,9 +64,9 @@ async function addMachineToMachine(machineToAdd, machine) { const userId = machineToAdd.userId.toString(); const deviceId = machineToAdd.deviceId.toString(); keyQueryResponse.device_keys[userId] = {}; - keyQueryResponse.device_keys[userId][deviceId] = JSON.parse(keysUploadRequest.body).device_keys; + keyQueryResponse.device_keys[userId][deviceId] = JSON.parse(keysUploadRequest.extra).device_keys; - const keys = JSON.parse(signingKeysUploadRequest.body); + const keys = JSON.parse(signingKeysUploadRequest.extra); keyQueryResponse.master_keys[userId] = keys.master_key; keyQueryResponse.self_signing_keys[userId] = keys.self_signing_key; keyQueryResponse.user_signing_keys[userId] = keys.user_signing_key; diff --git a/bindings/matrix-sdk-crypto-js/tests/machine.test.js b/bindings/matrix-sdk-crypto-js/tests/machine.test.js index dbbd7f723..448b1da97 100644 --- a/bindings/matrix-sdk-crypto-js/tests/machine.test.js +++ b/bindings/matrix-sdk-crypto-js/tests/machine.test.js @@ -198,9 +198,9 @@ describe(OlmMachine.name, () => { expect(outgoingRequests[0]).toBeInstanceOf(KeysUploadRequest); expect(outgoingRequests[0].id).toBeDefined(); expect(outgoingRequests[0].type).toStrictEqual(RequestType.KeysUpload); - expect(outgoingRequests[0].body).toBeDefined(); + expect(outgoingRequests[0].extra).toBeDefined(); - const body = JSON.parse(outgoingRequests[0].body) + const body = JSON.parse(outgoingRequests[0].extra) expect(body.device_keys).toBeDefined(); expect(body.one_time_keys).toBeDefined(); } @@ -209,9 +209,9 @@ describe(OlmMachine.name, () => { expect(outgoingRequests[1]).toBeInstanceOf(KeysQueryRequest); expect(outgoingRequests[1].id).toBeDefined(); expect(outgoingRequests[1].type).toStrictEqual(RequestType.KeysQuery); - expect(outgoingRequests[1].body).toBeDefined(); + expect(outgoingRequests[1].extra).toBeDefined(); - const body = JSON.parse(outgoingRequests[1].body); + const body = JSON.parse(outgoingRequests[1].extra); expect(body.timeout).toBeDefined(); expect(body.device_keys).toBeDefined(); expect(body.token).toBeDefined(); From efde81646b0699957ee38a383e5f1e8ec2a58c1c Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 5 Jan 2023 12:02:33 +0100 Subject: [PATCH 06/12] feat(crypto-js): Extract `RoomMessageRequest.content` as a JSON-encoded string. --- bindings/matrix-sdk-crypto-js/src/requests.rs | 38 ++++++++++--------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/bindings/matrix-sdk-crypto-js/src/requests.rs b/bindings/matrix-sdk-crypto-js/src/requests.rs index f6bc3671c..325bd051a 100644 --- a/bindings/matrix-sdk-crypto-js/src/requests.rs +++ b/bindings/matrix-sdk-crypto-js/src/requests.rs @@ -226,9 +226,9 @@ pub struct RoomMessageRequest { #[wasm_bindgen(readonly)] pub txn_id: JsString, - /// A JSON-encoded string containing the rest of the payload: `content`. + /// A JSON-encoded string containing the `content` field of this event. #[wasm_bindgen(readonly)] - pub extra: JsString, + pub content: JsString, } #[wasm_bindgen] @@ -239,9 +239,9 @@ impl RoomMessageRequest { id: JsString, room_id: JsString, txn_id: JsString, - extra: JsString, + content: JsString, ) -> RoomMessageRequest { - Self { id: Some(id), room_id, txn_id, extra } + Self { id: Some(id), room_id, txn_id, content } } /// Get its request type. @@ -303,8 +303,8 @@ pub struct SigningKeysUploadRequest { macro_rules! request { ( $destination_request:ident from $source_request:ident - $( extracts fields $( $field:ident: $field_type:ident ),+ $(,)? )? - $( $( and )? groups fields $( $grouped_field:ident ),+ $(,)? )? + $( extracts fields $( $field_name:ident : $field_type:ident ),+ $(,)? )? + $( $( and )? groups fields $( $grouped_field_name:ident ),+ $(,)? )? ) => { impl TryFrom<&$source_request> for $destination_request { type Error = serde_json::Error; @@ -313,8 +313,8 @@ macro_rules! request { request!( @__try_from $destination_request from $source_request (request_id = None, request = request) - $( extracts [ $( $field: $field_type, )+ ] )? - $( groups [ $( $grouped_field, )+ ] )? + $( extracts [ $( $field_name : $field_type, )+ ] )? + $( groups [ $( $grouped_field_name, )+ ] )? ) } } @@ -328,8 +328,8 @@ macro_rules! request { request!( @__try_from $destination_request from $source_request (request_id = Some(request_id.into()), request = request) - $( extracts [ $( $field: $field_type, )+ ] )? - $( groups [ $( $grouped_field, )+ ] )? + $( extracts [ $( $field_name : $field_type, )+ ] )? + $( groups [ $( $grouped_field_name, )+ ] )? ) } } @@ -338,22 +338,22 @@ macro_rules! request { ( @__try_from $destination_request:ident from $source_request:ident (request_id = $request_id:expr, request = $request:expr) - $( extracts [ $( $field:ident: $field_type:ident ),* $(,)? ] )? - $( groups [ $( $grouped_field:ident ),* $(,)? ] )? + $( extracts [ $( $field_name:ident : $field_type:ident ),* $(,)? ] )? + $( groups [ $( $grouped_field_name:ident ),* $(,)? ] )? ) => { { Ok($destination_request { id: $request_id, $( $( - $field: request!(@__field as $field_type (request = $request, field = $field)), + $field_name: request!(@__field as $field_type (request = $request, field = $field_name)), )* )? $( extra: { let mut map = serde_json::Map::new(); $( - map.insert(stringify!($grouped_field).to_owned(), serde_json::to_value(&$request.$grouped_field).unwrap()); + map.insert(stringify!($grouped_field_name).to_owned(), serde_json::to_value(&$request.$grouped_field_name).unwrap()); )* let object = serde_json::Value::Object(map); @@ -364,9 +364,13 @@ macro_rules! request { } }; - ( @__field as string (request = $request:expr, field = $field:ident) ) => { - $request.$field.to_string().into() + ( @__field as string (request = $request:expr, field = $field_name:ident) ) => { + $request.$field_name.to_string().into() }; + + ( @__field as json (request = $request:expr, field = $field_name:ident) ) => { + serde_json::to_string(&$request.$field_name)?.into() + } } // Outgoing Requests @@ -375,7 +379,7 @@ request!(KeysQueryRequest from OriginalKeysQueryRequest groups fields timeout, d request!(KeysClaimRequest from OriginalKeysClaimRequest groups fields timeout, one_time_keys); request!(ToDeviceRequest from OriginalToDeviceRequest extracts fields event_type: string, txn_id: string and groups fields messages); request!(SignatureUploadRequest from OriginalSignatureUploadRequest groups fields signed_keys); -request!(RoomMessageRequest from OriginalRoomMessageRequest extracts fields room_id: string, txn_id: string and groups fields content); +request!(RoomMessageRequest from OriginalRoomMessageRequest extracts fields room_id: string, txn_id: string, content: json); request!(KeysBackupRequest from OriginalKeysBackupRequest groups fields rooms); // Other Requests From 3ad675db5cd4e5350c24448047696408e1865b66 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 5 Jan 2023 16:05:03 +0100 Subject: [PATCH 07/12] feat(crypto-js): Extract `RoomMessageRequest.event_type` from `EventContent`. --- bindings/matrix-sdk-crypto-js/src/requests.rs | 67 +++++++++++++------ 1 file changed, 46 insertions(+), 21 deletions(-) diff --git a/bindings/matrix-sdk-crypto-js/src/requests.rs b/bindings/matrix-sdk-crypto-js/src/requests.rs index 325bd051a..1c4de8f84 100644 --- a/bindings/matrix-sdk-crypto-js/src/requests.rs +++ b/bindings/matrix-sdk-crypto-js/src/requests.rs @@ -11,10 +11,13 @@ use matrix_sdk_crypto::{ }, OutgoingRequests, }; -use ruma::api::client::keys::{ - claim_keys::v3::Request as OriginalKeysClaimRequest, - upload_keys::v3::Request as OriginalKeysUploadRequest, - upload_signatures::v3::Request as OriginalSignatureUploadRequest, +use ruma::{ + api::client::keys::{ + claim_keys::v3::Request as OriginalKeysClaimRequest, + upload_keys::v3::Request as OriginalKeysUploadRequest, + upload_signatures::v3::Request as OriginalSignatureUploadRequest, + }, + events::EventContent, }; use wasm_bindgen::prelude::*; @@ -226,7 +229,11 @@ pub struct RoomMessageRequest { #[wasm_bindgen(readonly)] pub txn_id: JsString, - /// A JSON-encoded string containing the `content` field of this event. + /// A string representing the type of even from the message's content. + #[wasm_bindgen(readonly)] + pub event_type: JsString, + + /// A JSON-encoded string containing the message's content. #[wasm_bindgen(readonly)] pub content: JsString, } @@ -239,9 +246,10 @@ impl RoomMessageRequest { id: JsString, room_id: JsString, txn_id: JsString, + event_type: JsString, content: JsString, ) -> RoomMessageRequest { - Self { id: Some(id), room_id, txn_id, content } + Self { id: Some(id), room_id, txn_id, event_type, content } } /// Get its request type. @@ -303,8 +311,8 @@ pub struct SigningKeysUploadRequest { macro_rules! request { ( $destination_request:ident from $source_request:ident - $( extracts fields $( $field_name:ident : $field_type:ident ),+ $(,)? )? - $( $( and )? groups fields $( $grouped_field_name:ident ),+ $(,)? )? + $( extracts $( $field_name:ident : $field_type:tt ),+ $(,)? )? + $( $( and )? groups $( $grouped_field_name:ident ),+ $(,)? )? ) => { impl TryFrom<&$source_request> for $destination_request { type Error = serde_json::Error; @@ -338,7 +346,7 @@ macro_rules! request { ( @__try_from $destination_request:ident from $source_request:ident (request_id = $request_id:expr, request = $request:expr) - $( extracts [ $( $field_name:ident : $field_type:ident ),* $(,)? ] )? + $( extracts [ $( $field_name:ident : $field_type:tt ),* $(,)? ] )? $( groups [ $( $grouped_field_name:ident ),* $(,)? ] )? ) => { { @@ -346,7 +354,7 @@ macro_rules! request { id: $request_id, $( $( - $field_name: request!(@__field as $field_type (request = $request, field = $field_name)), + $field_name: request!(@__field $field_name : $field_type ; request = $request), )* )? $( @@ -364,26 +372,43 @@ macro_rules! request { } }; - ( @__field as string (request = $request:expr, field = $field_name:ident) ) => { + ( @__field $field_name:ident : $field_type:ident ; request = $request:expr ) => { + request!(@__field_type as $field_type ; request = $request, field_name = $field_name) + }; + + /* + ( @__field $field_name:ident : $field_mapper:block ; request = $request:expr ) => { + { + let mapper = $field_mapper; + mapper($request) + } + }; + */ + + ( @__field_type as string ; request = $request:expr, field_name = $field_name:ident ) => { $request.$field_name.to_string().into() }; - ( @__field as json (request = $request:expr, field = $field_name:ident) ) => { + ( @__field_type as json ; request = $request:expr, field_name = $field_name:ident ) => { serde_json::to_string(&$request.$field_name)?.into() - } + }; + + ( @__field_type as event_type ; request = $request:expr, field_name = $field_name:ident ) => { + $request.content.event_type().to_string().into() + }; } // Outgoing Requests -request!(KeysUploadRequest from OriginalKeysUploadRequest groups fields device_keys, one_time_keys, fallback_keys); -request!(KeysQueryRequest from OriginalKeysQueryRequest groups fields timeout, device_keys, token); -request!(KeysClaimRequest from OriginalKeysClaimRequest groups fields timeout, one_time_keys); -request!(ToDeviceRequest from OriginalToDeviceRequest extracts fields event_type: string, txn_id: string and groups fields messages); -request!(SignatureUploadRequest from OriginalSignatureUploadRequest groups fields signed_keys); -request!(RoomMessageRequest from OriginalRoomMessageRequest extracts fields room_id: string, txn_id: string, content: json); -request!(KeysBackupRequest from OriginalKeysBackupRequest groups fields rooms); +request!(KeysUploadRequest from OriginalKeysUploadRequest groups device_keys, one_time_keys, fallback_keys); +request!(KeysQueryRequest from OriginalKeysQueryRequest groups timeout, device_keys, token); +request!(KeysClaimRequest from OriginalKeysClaimRequest groups timeout, one_time_keys); +request!(ToDeviceRequest from OriginalToDeviceRequest extracts event_type: string, txn_id: string and groups messages); +request!(SignatureUploadRequest from OriginalSignatureUploadRequest groups signed_keys); +request!(RoomMessageRequest from OriginalRoomMessageRequest extracts room_id: string, txn_id: string, event_type: event_type, content: json); +request!(KeysBackupRequest from OriginalKeysBackupRequest groups rooms); // Other Requests -request!(SigningKeysUploadRequest from OriginalUploadSigningKeysRequest groups fields master_key, self_signing_key, user_signing_key); +request!(SigningKeysUploadRequest from OriginalUploadSigningKeysRequest groups master_key, self_signing_key, user_signing_key); // JavaScript has no complex enums like Rust. To return structs of // different types, we have no choice that hiding everything behind a From c427caf473f193aaebf4eef073428d553013d444 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 5 Jan 2023 17:03:13 +0100 Subject: [PATCH 08/12] feat(crypto-js): Rename requests `extra` field to `body`. --- bindings/matrix-sdk-crypto-js/src/requests.rs | 40 +++++++++---------- .../matrix-sdk-crypto-js/tests/device.test.js | 28 ++++++------- bindings/matrix-sdk-crypto-js/tests/helper.js | 8 ++-- .../tests/machine.test.js | 8 ++-- 4 files changed, 42 insertions(+), 42 deletions(-) diff --git a/bindings/matrix-sdk-crypto-js/src/requests.rs b/bindings/matrix-sdk-crypto-js/src/requests.rs index 1c4de8f84..f0e46a68e 100644 --- a/bindings/matrix-sdk-crypto-js/src/requests.rs +++ b/bindings/matrix-sdk-crypto-js/src/requests.rs @@ -39,15 +39,15 @@ pub struct KeysUploadRequest { /// A JSON-encoded string containing the rest of the payload: `device_keys`, /// `one_time_keys`, `fallback_keys`. #[wasm_bindgen(readonly)] - pub extra: JsString, + pub body: JsString, } #[wasm_bindgen] impl KeysUploadRequest { /// Create a new `KeysUploadRequest`. #[wasm_bindgen(constructor)] - pub fn new(id: JsString, extra: JsString) -> KeysUploadRequest { - Self { id: Some(id), extra } + pub fn new(id: JsString, body: JsString) -> KeysUploadRequest { + Self { id: Some(id), body } } /// Get its request type. @@ -73,15 +73,15 @@ pub struct KeysQueryRequest { /// A JSON-encoded string containing the rest of the payload: `timeout`, /// `device_keys`, `token`. #[wasm_bindgen(readonly)] - pub extra: JsString, + pub body: JsString, } #[wasm_bindgen] impl KeysQueryRequest { /// Create a new `KeysQueryRequest`. #[wasm_bindgen(constructor)] - pub fn new(id: JsString, extra: JsString) -> KeysQueryRequest { - Self { id: Some(id), extra } + pub fn new(id: JsString, body: JsString) -> KeysQueryRequest { + Self { id: Some(id), body } } /// Get its request type. @@ -108,15 +108,15 @@ pub struct KeysClaimRequest { /// A JSON-encoded string containing the rest of the payload: `timeout`, /// `one_time_keys`. #[wasm_bindgen(readonly)] - pub extra: JsString, + pub body: JsString, } #[wasm_bindgen] impl KeysClaimRequest { /// Create a new `KeysClaimRequest`. #[wasm_bindgen(constructor)] - pub fn new(id: JsString, extra: JsString) -> KeysClaimRequest { - Self { id: Some(id), extra } + pub fn new(id: JsString, body: JsString) -> KeysClaimRequest { + Self { id: Some(id), body } } /// Get its request type. @@ -150,7 +150,7 @@ pub struct ToDeviceRequest { /// A JSON-encoded string containing the rest of the payload: `messages`. #[wasm_bindgen(readonly)] - pub extra: JsString, + pub body: JsString, } #[wasm_bindgen] @@ -161,9 +161,9 @@ impl ToDeviceRequest { id: JsString, event_type: JsString, txn_id: JsString, - extra: JsString, + body: JsString, ) -> ToDeviceRequest { - Self { id: Some(id), event_type, txn_id, extra } + Self { id: Some(id), event_type, txn_id, body } } /// Get its request type. @@ -188,15 +188,15 @@ pub struct SignatureUploadRequest { /// A JSON-encoded string containing the rest of the payload: `signed_keys`. #[wasm_bindgen(readonly)] - pub extra: JsString, + pub body: JsString, } #[wasm_bindgen] impl SignatureUploadRequest { /// Create a new `SignatureUploadRequest`. #[wasm_bindgen(constructor)] - pub fn new(id: JsString, extra: JsString) -> SignatureUploadRequest { - Self { id: Some(id), extra } + pub fn new(id: JsString, body: JsString) -> SignatureUploadRequest { + Self { id: Some(id), body } } /// Get its request type. @@ -272,15 +272,15 @@ pub struct KeysBackupRequest { /// A JSON-encoded string containing the rest of the payload: `rooms`. #[wasm_bindgen(readonly)] - pub extra: JsString, + pub body: JsString, } #[wasm_bindgen] impl KeysBackupRequest { /// Create a new `KeysBackupRequest`. #[wasm_bindgen(constructor)] - pub fn new(id: JsString, extra: JsString) -> KeysBackupRequest { - Self { id: Some(id), extra } + pub fn new(id: JsString, body: JsString) -> KeysBackupRequest { + Self { id: Some(id), body } } /// Get its request type. @@ -305,7 +305,7 @@ pub struct SigningKeysUploadRequest { /// A JSON-encoded string containing the rest of the payload: `master_key`, /// `self_signing_key`, `user_signing_key`. #[wasm_bindgen(readonly)] - pub extra: JsString, + pub body: JsString, } macro_rules! request { @@ -358,7 +358,7 @@ macro_rules! request { )* )? $( - extra: { + body: { let mut map = serde_json::Map::new(); $( map.insert(stringify!($grouped_field_name).to_owned(), serde_json::to_value(&$request.$grouped_field_name).unwrap()); diff --git a/bindings/matrix-sdk-crypto-js/tests/device.test.js b/bindings/matrix-sdk-crypto-js/tests/device.test.js index 73c3a78cd..14ecc2051 100644 --- a/bindings/matrix-sdk-crypto-js/tests/device.test.js +++ b/bindings/matrix-sdk-crypto-js/tests/device.test.js @@ -177,7 +177,7 @@ describe('Key Verification', () => { const toDeviceEvents = [{ sender: userId1.toString(), type: outgoingVerificationRequest.event_type, - content: JSON.parse(outgoingVerificationRequest.extra).messages[userId2.toString()][deviceId2.toString()], + content: JSON.parse(outgoingVerificationRequest.body).messages[userId2.toString()][deviceId2.toString()], }]; // Let's send the verification request to `m2`. @@ -228,7 +228,7 @@ describe('Key Verification', () => { const toDeviceEvents = [{ sender: userId2.toString(), type: outgoingVerificationRequest.event_type, - content: JSON.parse(outgoingVerificationRequest.extra).messages[userId1.toString()][deviceId1.toString()], + content: JSON.parse(outgoingVerificationRequest.body).messages[userId1.toString()][deviceId1.toString()], }]; // Let's send the verification ready to `m1`. @@ -281,7 +281,7 @@ describe('Key Verification', () => { const toDeviceEvents = [{ sender: userId2.toString(), type: outgoingVerificationRequest.event_type, - content: JSON.parse(outgoingVerificationRequest.extra).messages[userId1.toString()][deviceId1.toString()], + content: JSON.parse(outgoingVerificationRequest.body).messages[userId1.toString()][deviceId1.toString()], }]; // Let's send the SAS start to `m1`. @@ -326,7 +326,7 @@ describe('Key Verification', () => { const toDeviceEvents = [{ sender: userId1.toString(), type: outgoingVerificationRequest.event_type, - content: JSON.parse(outgoingVerificationRequest.extra).messages[userId2.toString()][deviceId2.toString()], + content: JSON.parse(outgoingVerificationRequest.body).messages[userId2.toString()][deviceId2.toString()], }]; // Let's send the SAS accept to `m2`. @@ -349,7 +349,7 @@ describe('Key Verification', () => { const toDeviceEvents = [{ sender: userId2.toString(), type: toDeviceRequest.event_type, - content: JSON.parse(toDeviceRequest.extra).messages[userId1.toString()][deviceId1.toString()], + content: JSON.parse(toDeviceRequest.body).messages[userId1.toString()][deviceId1.toString()], }]; // Let's send te SAS key to `m1`. @@ -369,7 +369,7 @@ describe('Key Verification', () => { const toDeviceEvents = [{ sender: userId1.toString(), type: toDeviceRequest.event_type, - content: JSON.parse(toDeviceRequest.extra).messages[userId2.toString()][deviceId2.toString()], + content: JSON.parse(toDeviceRequest.body).messages[userId2.toString()][deviceId2.toString()], }]; // Let's send te SAS key to `m2`. @@ -438,7 +438,7 @@ describe('Key Verification', () => { const toDeviceEvents = [{ sender: userId1.toString(), type: outgoingVerificationRequest.event_type, - content: JSON.parse(outgoingVerificationRequest.extra).messages[userId2.toString()][deviceId2.toString()], + content: JSON.parse(outgoingVerificationRequest.body).messages[userId2.toString()][deviceId2.toString()], }]; // Let's send te SAS confirmation to `m2`. @@ -462,7 +462,7 @@ describe('Key Verification', () => { const toDeviceEvents = [{ sender: userId2.toString(), type: outgoingVerificationRequest.event_type, - content: JSON.parse(outgoingVerificationRequest.extra).messages[userId1.toString()][deviceId1.toString()], + content: JSON.parse(outgoingVerificationRequest.body).messages[userId1.toString()][deviceId1.toString()], }]; // Let's send te SAS confirmation to `m1`. @@ -479,7 +479,7 @@ describe('Key Verification', () => { const toDeviceEvents = [{ sender: userId2.toString(), type: outgoingVerificationRequest.event_type, - content: JSON.parse(outgoingVerificationRequest.extra).messages[userId1.toString()][deviceId1.toString()], + content: JSON.parse(outgoingVerificationRequest.body).messages[userId1.toString()][deviceId1.toString()], }]; // Let's send te SAS done to `m1`. @@ -499,7 +499,7 @@ describe('Key Verification', () => { const toDeviceEvents = [{ sender: userId1.toString(), type: toDeviceRequest.event_type, - content: JSON.parse(toDeviceRequest.extra).messages[userId2.toString()][deviceId2.toString()], + content: JSON.parse(toDeviceRequest.body).messages[userId2.toString()][deviceId2.toString()], }]; // Let's send te SAS key to `m2`. @@ -585,7 +585,7 @@ describe('Key Verification', () => { const toDeviceEvents = [{ sender: userId1.toString(), type: outgoingVerificationRequest.event_type, - content: JSON.parse(outgoingVerificationRequest.extra).messages[userId2.toString()][deviceId2.toString()], + content: JSON.parse(outgoingVerificationRequest.body).messages[userId2.toString()][deviceId2.toString()], }]; // Let's send the verification request to `m2`. @@ -639,7 +639,7 @@ describe('Key Verification', () => { const toDeviceEvents = [{ sender: userId2.toString(), type: outgoingVerificationRequest.event_type, - content: JSON.parse(outgoingVerificationRequest.extra).messages[userId1.toString()][deviceId1.toString()], + content: JSON.parse(outgoingVerificationRequest.body).messages[userId1.toString()][deviceId1.toString()], }]; // Let's send the verification ready to `m1`. @@ -796,7 +796,7 @@ describe('Key Verification', () => { const toDeviceEvents = [{ sender: userId1.toString(), type: outgoingVerificationRequest.event_type, - content: JSON.parse(outgoingVerificationRequest.extra).messages[userId2.toString()][deviceId2.toString()], + content: JSON.parse(outgoingVerificationRequest.body).messages[userId2.toString()][deviceId2.toString()], }]; // Let's send the verification request to `m2`. @@ -816,7 +816,7 @@ describe('Key Verification', () => { const toDeviceEvents = [{ sender: userId2.toString(), type: outgoingVerificationRequest.event_type, - content: JSON.parse(outgoingVerificationRequest.extra).messages[userId1.toString()][deviceId1.toString()], + content: JSON.parse(outgoingVerificationRequest.body).messages[userId1.toString()][deviceId1.toString()], }]; // Let's send the verification request to `m2`. diff --git a/bindings/matrix-sdk-crypto-js/tests/helper.js b/bindings/matrix-sdk-crypto-js/tests/helper.js index 9be52c9e1..0d3136bed 100644 --- a/bindings/matrix-sdk-crypto-js/tests/helper.js +++ b/bindings/matrix-sdk-crypto-js/tests/helper.js @@ -30,9 +30,9 @@ async function addMachineToMachine(machineToAdd, machine) { expect(outgoingRequests[0]).toBeInstanceOf(KeysUploadRequest); expect(outgoingRequests[0].id).toBeDefined(); expect(outgoingRequests[0].type).toStrictEqual(RequestType.KeysUpload); - expect(outgoingRequests[0].extra).toBeDefined(); + expect(outgoingRequests[0].body).toBeDefined(); - const body = JSON.parse(outgoingRequests[0].extra); + const body = JSON.parse(outgoingRequests[0].body); expect(body.device_keys).toBeDefined(); expect(body.one_time_keys).toBeDefined(); @@ -64,9 +64,9 @@ async function addMachineToMachine(machineToAdd, machine) { const userId = machineToAdd.userId.toString(); const deviceId = machineToAdd.deviceId.toString(); keyQueryResponse.device_keys[userId] = {}; - keyQueryResponse.device_keys[userId][deviceId] = JSON.parse(keysUploadRequest.extra).device_keys; + keyQueryResponse.device_keys[userId][deviceId] = JSON.parse(keysUploadRequest.body).device_keys; - const keys = JSON.parse(signingKeysUploadRequest.extra); + const keys = JSON.parse(signingKeysUploadRequest.body); keyQueryResponse.master_keys[userId] = keys.master_key; keyQueryResponse.self_signing_keys[userId] = keys.self_signing_key; keyQueryResponse.user_signing_keys[userId] = keys.user_signing_key; diff --git a/bindings/matrix-sdk-crypto-js/tests/machine.test.js b/bindings/matrix-sdk-crypto-js/tests/machine.test.js index 448b1da97..dbbd7f723 100644 --- a/bindings/matrix-sdk-crypto-js/tests/machine.test.js +++ b/bindings/matrix-sdk-crypto-js/tests/machine.test.js @@ -198,9 +198,9 @@ describe(OlmMachine.name, () => { expect(outgoingRequests[0]).toBeInstanceOf(KeysUploadRequest); expect(outgoingRequests[0].id).toBeDefined(); expect(outgoingRequests[0].type).toStrictEqual(RequestType.KeysUpload); - expect(outgoingRequests[0].extra).toBeDefined(); + expect(outgoingRequests[0].body).toBeDefined(); - const body = JSON.parse(outgoingRequests[0].extra) + const body = JSON.parse(outgoingRequests[0].body) expect(body.device_keys).toBeDefined(); expect(body.one_time_keys).toBeDefined(); } @@ -209,9 +209,9 @@ describe(OlmMachine.name, () => { expect(outgoingRequests[1]).toBeInstanceOf(KeysQueryRequest); expect(outgoingRequests[1].id).toBeDefined(); expect(outgoingRequests[1].type).toStrictEqual(RequestType.KeysQuery); - expect(outgoingRequests[1].extra).toBeDefined(); + expect(outgoingRequests[1].body).toBeDefined(); - const body = JSON.parse(outgoingRequests[1].extra); + const body = JSON.parse(outgoingRequests[1].body); expect(body.timeout).toBeDefined(); expect(body.device_keys).toBeDefined(); expect(body.token).toBeDefined(); From 90cce1a47c1bcad9d24de07320333dd247f9cd30 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Fri, 6 Jan 2023 17:28:44 +0100 Subject: [PATCH 09/12] chore(crypto-js): Improve documentation, and do a little clean up. --- bindings/matrix-sdk-crypto-js/src/requests.rs | 23 +++++++++++-------- .../tests/machine.test.js | 6 ++--- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/bindings/matrix-sdk-crypto-js/src/requests.rs b/bindings/matrix-sdk-crypto-js/src/requests.rs index f0e46a68e..ce0904195 100644 --- a/bindings/matrix-sdk-crypto-js/src/requests.rs +++ b/bindings/matrix-sdk-crypto-js/src/requests.rs @@ -38,6 +38,8 @@ pub struct KeysUploadRequest { /// A JSON-encoded string containing the rest of the payload: `device_keys`, /// `one_time_keys`, `fallback_keys`. + /// + /// It represents the body of the HTTP request. #[wasm_bindgen(readonly)] pub body: JsString, } @@ -72,6 +74,8 @@ pub struct KeysQueryRequest { /// A JSON-encoded string containing the rest of the payload: `timeout`, /// `device_keys`, `token`. + /// + /// It represents the body of the HTTP request. #[wasm_bindgen(readonly)] pub body: JsString, } @@ -107,6 +111,8 @@ pub struct KeysClaimRequest { /// A JSON-encoded string containing the rest of the payload: `timeout`, /// `one_time_keys`. + /// + /// It represents the body of the HTTP request. #[wasm_bindgen(readonly)] pub body: JsString, } @@ -149,6 +155,8 @@ pub struct ToDeviceRequest { pub txn_id: JsString, /// A JSON-encoded string containing the rest of the payload: `messages`. + /// + /// It represents the body of the HTTP request. #[wasm_bindgen(readonly)] pub body: JsString, } @@ -187,6 +195,8 @@ pub struct SignatureUploadRequest { pub id: Option, /// A JSON-encoded string containing the rest of the payload: `signed_keys`. + /// + /// It represents the body of the HTTP request. #[wasm_bindgen(readonly)] pub body: JsString, } @@ -271,6 +281,8 @@ pub struct KeysBackupRequest { pub id: Option, /// A JSON-encoded string containing the rest of the payload: `rooms`. + /// + /// It represents the body of the HTTP request. #[wasm_bindgen(readonly)] pub body: JsString, } @@ -304,6 +316,8 @@ pub struct SigningKeysUploadRequest { /// A JSON-encoded string containing the rest of the payload: `master_key`, /// `self_signing_key`, `user_signing_key`. + /// + /// It represents the body of the HTTP request. #[wasm_bindgen(readonly)] pub body: JsString, } @@ -376,15 +390,6 @@ macro_rules! request { request!(@__field_type as $field_type ; request = $request, field_name = $field_name) }; - /* - ( @__field $field_name:ident : $field_mapper:block ; request = $request:expr ) => { - { - let mapper = $field_mapper; - mapper($request) - } - }; - */ - ( @__field_type as string ; request = $request:expr, field_name = $field_name:ident ) => { $request.$field_name.to_string().into() }; diff --git a/bindings/matrix-sdk-crypto-js/tests/machine.test.js b/bindings/matrix-sdk-crypto-js/tests/machine.test.js index dbbd7f723..82e39c3f9 100644 --- a/bindings/matrix-sdk-crypto-js/tests/machine.test.js +++ b/bindings/matrix-sdk-crypto-js/tests/machine.test.js @@ -99,7 +99,7 @@ describe(OlmMachine.name, () => { test('can drop/close', async () => { m = await machine(); m.close(); - }) + }); test('can drop/close with a store', async () => { let store_name = 'temporary'; @@ -133,7 +133,7 @@ describe(OlmMachine.name, () => { deleting.onerror = () => { throw new Error('failed to remove the database (error)') }; deleting.onblocked = () => { throw new Error('failed to remove the database (blocked)') }; } - }) + }); test('can read user ID', async () => { expect((await machine()).userId.toString()).toStrictEqual(user.toString()); @@ -200,7 +200,7 @@ describe(OlmMachine.name, () => { expect(outgoingRequests[0].type).toStrictEqual(RequestType.KeysUpload); expect(outgoingRequests[0].body).toBeDefined(); - const body = JSON.parse(outgoingRequests[0].body) + const body = JSON.parse(outgoingRequests[0].body); expect(body.device_keys).toBeDefined(); expect(body.one_time_keys).toBeDefined(); } From ca00112804be6e8b296ee4144fb8b0b7bdce5191 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Wed, 18 Jan 2023 11:42:34 +0100 Subject: [PATCH 10/12] test(crypto-js): Add test for in-room verification (w/ `RoomMessageRequest`). --- .../matrix-sdk-crypto-js/src/identities.rs | 2 +- bindings/matrix-sdk-crypto-js/src/machine.rs | 11 +- .../tests/machine.test.js | 181 ++++++++++++++++++ 3 files changed, 191 insertions(+), 3 deletions(-) diff --git a/bindings/matrix-sdk-crypto-js/src/identities.rs b/bindings/matrix-sdk-crypto-js/src/identities.rs index fc72f2165..3e28e9aaf 100644 --- a/bindings/matrix-sdk-crypto-js/src/identities.rs +++ b/bindings/matrix-sdk-crypto-js/src/identities.rs @@ -130,7 +130,7 @@ impl UserIdentity { } /// Create a `VerificationRequest` object after the verification - /// request content has been sent out. } + /// request content has been sent out. #[wasm_bindgen(js_name = "requestVerification")] pub fn request_verification( &self, diff --git a/bindings/matrix-sdk-crypto-js/src/machine.rs b/bindings/matrix-sdk-crypto-js/src/machine.rs index eeedc7514..e55e169b3 100644 --- a/bindings/matrix-sdk-crypto-js/src/machine.rs +++ b/bindings/matrix-sdk-crypto-js/src/machine.rs @@ -638,8 +638,15 @@ impl OlmMachine { /// This method can be used to pass verification events that are happening /// in rooms to the `OlmMachine`. The event should be in the decrypted form. #[wasm_bindgen(js_name = "receiveVerificationEvent")] - pub fn receive_verification_event(&self, event: &str) -> Result { - let event: ruma::events::AnyMessageLikeEvent = serde_json::from_str(event)?; + pub fn receive_verification_event( + &self, + event: &str, + room_id: &identifiers::RoomId, + ) -> Result { + let room_id = room_id.inner.clone(); + let event: ruma::events::AnySyncMessageLikeEvent = serde_json::from_str(event)?; + let event = event.into_full_event(room_id); + let me = self.inner.clone(); Ok(future_to_promise(async move { diff --git a/bindings/matrix-sdk-crypto-js/tests/machine.test.js b/bindings/matrix-sdk-crypto-js/tests/machine.test.js index 82e39c3f9..245bb9654 100644 --- a/bindings/matrix-sdk-crypto-js/tests/machine.test.js +++ b/bindings/matrix-sdk-crypto-js/tests/machine.test.js @@ -5,6 +5,7 @@ const { DeviceKeyId, DeviceLists, EncryptionSettings, + EventId, InboundGroupSession, KeysClaimRequest, KeysQueryRequest, @@ -14,9 +15,11 @@ const { OwnUserIdentity, RequestType, RoomId, + RoomMessageRequest, SignatureUploadRequest, ToDeviceRequest, UserId, + UserIdentity, VerificationRequest, VerificationState, } = require('../pkg/matrix_sdk_crypto_js'); @@ -624,4 +627,182 @@ describe(OlmMachine.name, () => { }); }); }); + + describe('can do in-room verification', () => { + let m; + const user = new UserId('@alice:example.org'); + const device = new DeviceId('JLAFKJWSCS'); + const room = new RoomId('!test:localhost'); + + beforeAll(async () => { + m = await machine(user, device); + }); + + test('can inject devices from someone else', async () => { + { + const hypothetical_response = JSON.stringify({ + "device_keys": { + "@example:morpheus.localhost": { + "ATRLDCRXAC": { + "algorithms": [ + "m.olm.v1.curve25519-aes-sha2", + "m.megolm.v1.aes-sha2" + ], + "device_id": "ATRLDCRXAC", + "keys": { + "curve25519:ATRLDCRXAC": "cAVT5Es3Z3F5pFD+2w3HT7O9+R3PstzYVkzD51X/FWQ", + "ed25519:ATRLDCRXAC": "V2w/T/x7i7AXiCCtS6JldrpbvRliRoef3CqTUNqMRHA" + }, + "signatures": { + "@example:morpheus.localhost": { + "ed25519:ATRLDCRXAC": "ro2BjO5J6089B/JOANHnFmGrogrC2TIdMlgJbJO00DjOOcGxXfvOezCFIORTwZNHvkHU617YIGl/4keTDIWvBQ" + } + }, + "user_id": "@example:morpheus.localhost", + "unsigned": { + "device_display_name": "Element Desktop: Linux" + } + }, + "EYYGYTCTNC": { + "algorithms": [ + "m.olm.v1.curve25519-aes-sha2", + "m.megolm.v1.aes-sha2" + ], + "device_id": "EYYGYTCTNC", + "keys": { + "curve25519:EYYGYTCTNC": "Pqu50fo472wgb6NjKkaUxjuqoAIEAmhln2gw/zSQ7Ek", + "ed25519:EYYGYTCTNC": "Pf/2QPvui8lDty6TCTglVPRVM+irNHYavNNkyv5yFpU" + }, + "signatures": { + "@example:morpheus.localhost": { + "ed25519:EYYGYTCTNC": "pnP5BYLEUUaxDgrvdzCznkjNDbvY1/MFBr1JejdnLiXlcmxRULQpIWZUCO7QTbULsCwMsYQNGn50nfmjBQX3CQ" + } + }, + "user_id": "@example:morpheus.localhost", + "unsigned": { + "device_display_name": "WeeChat-Matrix-rs" + } + }, + "SUMODVLSIU": { + "algorithms": [ + "m.olm.v1.curve25519-aes-sha2", + "m.megolm.v1.aes-sha2" + ], + "device_id": "SUMODVLSIU", + "keys": { + "curve25519:SUMODVLSIU": "geQXWGWc++gcUHk0JcFmEVSjyzDOnk2mjVsUQwbNqQU", + "ed25519:SUMODVLSIU": "ccktaQ3g+B18E6FwVhTBYie26OlHbvDUzDEtxOQ4Qcs" + }, + "signatures": { + "@example:morpheus.localhost": { + "ed25519:SUMODVLSIU": "Yn+AOxHRt1GQpY2xT2Jcqqn8jh5+Vw23ctA7NXyDiWPsLPLNTpjGWHMjZdpUqflQvpiKfhODPICoIa7Pu0iSAg", + "ed25519:rUiMNDjIu6gqsrhJPbj3phyIzuEtuQGrLOEa9mCbtTM": "Cio6k/sq289XNTOvTCWre7Q6zg+A3euzMUe7Uy1T3gPqYFzX+kt7EAxrhbPqx1HyXAEz9zD0D/uw9VEXFCvWBQ" + } + }, + "user_id": "@example:morpheus.localhost", + "unsigned": { + "device_display_name": "Element Desktop (Linux)" + } + } + } + }, + "failures": {}, + "master_keys": { + "@example:morpheus.localhost": { + "user_id": "@example:morpheus.localhost", + "usage": [ + "master" + ], + "keys": { + "ed25519:ZzU4WCyBfOFitdGmfKCq6F39iQCDk/zhNNTsi+tWH7A": "ZzU4WCyBfOFitdGmfKCq6F39iQCDk/zhNNTsi+tWH7A" + }, + "signatures": { + "@example:morpheus.localhost": { + "ed25519:SUMODVLSIU": "RL6WOuuzB/mZ+edfUFG/KeEcmKh+NaWpM6m2bUYmDnJrtTCYyoU+pgHJuL2/6nynemmONo18JEHBuqtNcMq2AQ" + } + } + } + }, + "self_signing_keys": { + "@example:morpheus.localhost": { + "user_id": "@example:morpheus.localhost", + "usage": [ + "self_signing" + ], + "keys": { + "ed25519:rUiMNDjIu6gqsrhJPbj3phyIzuEtuQGrLOEa9mCbtTM": "rUiMNDjIu6gqsrhJPbj3phyIzuEtuQGrLOEa9mCbtTM" + }, + "signatures": { + "@example:morpheus.localhost": { + "ed25519:ZzU4WCyBfOFitdGmfKCq6F39iQCDk/zhNNTsi+tWH7A": "uCBn9rpeg6umY8H97ejN26UMp6QDwNL98869t1DoVGL50J8adLN05OZd8lYk9QzwTr2d56ZTGYSYX8kv28SDDA" + } + } + } + }, + "user_signing_keys": { + "@example:morpheus.localhost": { + "user_id": "@example:morpheus.localhost", + "usage": [ + "user_signing" + ], + "keys": { + "ed25519:GLhEKLQ50jnF6IMEPsO2ucpHUNIUEnbBXs5gYbHg4Aw": "GLhEKLQ50jnF6IMEPsO2ucpHUNIUEnbBXs5gYbHg4Aw" + }, + "signatures": { + "@example:morpheus.localhost": { + "ed25519:ZzU4WCyBfOFitdGmfKCq6F39iQCDk/zhNNTsi+tWH7A": "4fIyWlVzuz1pgoegNLZASycORXqKycVS0dNq5vmmwsVEudp1yrPhndnaIJ3fjF8LDHvwzXTvohOid7DiU1j0AA" + } + } + } + } + }); + const marked = await m.markRequestAsSent('foo', RequestType.KeysQuery, hypothetical_response); + } + }); + + test('can start an in-room SAS verification', async () => { + let _ = m.bootstrapCrossSigning(true); + const identity = await m.getIdentity(new UserId('@example:morpheus.localhost')); + + expect(identity).toBeInstanceOf(UserIdentity); + expect(identity.isVerified()).toStrictEqual(false); + + const eventId = new EventId('$Rqnc-F-dvnEYJTyHq_iKxU2bZ1CI92-kuZq3a5lr5Zg'); + const verificationRequest = await identity.requestVerification(room, eventId); + expect(verificationRequest).toBeInstanceOf(VerificationRequest); + + await m.receiveVerificationEvent( + JSON.stringify({ + "sender": "@example:morpheus.localhost", + "type": "m.key.verification.ready", + "event_id": "$QguWmaeMt6Hao7Ea6XHDInvr8ndknev79t9a2eBxlz0", + "origin_server_ts": 1674037263075, + "content": { + "methods": [ + "m.sas.v1", + "m.qr_code.show.v1", + "m.reciprocate.v1" + ], + "from_device": "SUMODVLSIU", + "m.relates_to": { + "rel_type": "m.reference", + "event_id": eventId.toString(), + } + } + }), + room + ); + + expect(verificationRequest.roomId.toString()).toStrictEqual(room.toString()); + + const [_sas, outgoingVerificationRequest] = await verificationRequest.startSas(); + + expect(outgoingVerificationRequest).toBeInstanceOf(RoomMessageRequest); + expect(outgoingVerificationRequest.id).toBeDefined(); + expect(outgoingVerificationRequest.room_id).toStrictEqual(room.toString()); + expect(outgoingVerificationRequest.txn_id).toBeDefined(); + expect(outgoingVerificationRequest.event_type).toStrictEqual('m.key.verification.start'); + expect(outgoingVerificationRequest.content).toBeDefined(); + }) + }); }); From 7c01f8490fcc048f61ab9b4d17aea1ddb1d9e775 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Wed, 18 Jan 2023 13:14:06 +0100 Subject: [PATCH 11/12] test(crypto-js): Test `RoomMessageRequest.content. --- .../matrix-sdk-crypto-js/tests/machine.test.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/bindings/matrix-sdk-crypto-js/tests/machine.test.js b/bindings/matrix-sdk-crypto-js/tests/machine.test.js index 245bb9654..a74135d0d 100644 --- a/bindings/matrix-sdk-crypto-js/tests/machine.test.js +++ b/bindings/matrix-sdk-crypto-js/tests/machine.test.js @@ -803,6 +803,20 @@ describe(OlmMachine.name, () => { expect(outgoingVerificationRequest.txn_id).toBeDefined(); expect(outgoingVerificationRequest.event_type).toStrictEqual('m.key.verification.start'); expect(outgoingVerificationRequest.content).toBeDefined(); + + const content = JSON.parse(outgoingVerificationRequest.content); + expect(content).toMatchObject({ + from_device: expect.any(String), + method: 'm.sas.v1', + key_agreement_protocols: [expect.any(String)], + hashes: [expect.any(String)], + message_authentication_codes: [expect.any(String), expect.any(String)], + short_authentication_string: ['decimal', 'emoji'], + 'm.relates_to': { + rel_type: 'm.reference', + event_id: eventId.toString(), + } + }); }) }); }); From 94fadf74b99e4ffbaaad618dde1cbba7921b81fc Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Wed, 18 Jan 2023 13:31:26 +0100 Subject: [PATCH 12/12] feat(crypto-js): Rename `RoomMessageRequest.content` to `.body`. --- bindings/matrix-sdk-crypto-js/src/requests.rs | 4 ++-- bindings/matrix-sdk-crypto-js/tests/machine.test.js | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/bindings/matrix-sdk-crypto-js/src/requests.rs b/bindings/matrix-sdk-crypto-js/src/requests.rs index ce0904195..00b51731d 100644 --- a/bindings/matrix-sdk-crypto-js/src/requests.rs +++ b/bindings/matrix-sdk-crypto-js/src/requests.rs @@ -243,8 +243,8 @@ pub struct RoomMessageRequest { #[wasm_bindgen(readonly)] pub event_type: JsString, - /// A JSON-encoded string containing the message's content. - #[wasm_bindgen(readonly)] + /// A JSON-encoded string containing the message's body. + #[wasm_bindgen(readonly, js_name = "body")] pub content: JsString, } diff --git a/bindings/matrix-sdk-crypto-js/tests/machine.test.js b/bindings/matrix-sdk-crypto-js/tests/machine.test.js index a74135d0d..32e46086a 100644 --- a/bindings/matrix-sdk-crypto-js/tests/machine.test.js +++ b/bindings/matrix-sdk-crypto-js/tests/machine.test.js @@ -802,10 +802,10 @@ describe(OlmMachine.name, () => { expect(outgoingVerificationRequest.room_id).toStrictEqual(room.toString()); expect(outgoingVerificationRequest.txn_id).toBeDefined(); expect(outgoingVerificationRequest.event_type).toStrictEqual('m.key.verification.start'); - expect(outgoingVerificationRequest.content).toBeDefined(); + expect(outgoingVerificationRequest.body).toBeDefined(); - const content = JSON.parse(outgoingVerificationRequest.content); - expect(content).toMatchObject({ + const body = JSON.parse(outgoingVerificationRequest.body); + expect(body).toMatchObject({ from_device: expect.any(String), method: 'm.sas.v1', key_agreement_protocols: [expect.any(String)],