From 85e0ddf518ec9c91f5c9e9e66cfdcf260040da2b Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Fri, 23 Jun 2023 16:12:37 +0100 Subject: [PATCH] Implement `VerificationRequest.cancel` --- spec/integ/crypto/verification.spec.ts | 36 +++++++++++++++++++++++++- src/crypto-api/verification.ts | 2 +- src/rust-crypto/verification.ts | 9 ++++--- 3 files changed, 42 insertions(+), 5 deletions(-) diff --git a/spec/integ/crypto/verification.spec.ts b/spec/integ/crypto/verification.spec.ts index 11be866b85b..e95a82fccbe 100644 --- a/spec/integ/crypto/verification.spec.ts +++ b/spec/integ/crypto/verification.spec.ts @@ -290,6 +290,10 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("verification (%s)", (backend: st await verificationPromise; expect(request.phase).toEqual(VerificationPhase.Done); + // at this point, cancelling should do nothing. + await request.cancel(); + expect(request.phase).toEqual(VerificationPhase.Done); + // we're done with the temporary keypair olmSAS.free(); }); @@ -406,11 +410,41 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("verification (%s)", (backend: st await verificationPromise; expect(request.phase).toEqual(VerificationPhase.Done); }); + }); + + describe("cancellation", () => { + beforeEach(async () => { + // pretend that we have another device, which we will start verifying + e2eKeyResponder.addDeviceKeys(TEST_USER_ID, TEST_DEVICE_ID, SIGNED_TEST_DEVICE_DATA); - it("can cancel during the SAS phase", async () => { aliceClient = await startTestClient(); await waitForDeviceList(); + }); + + it("can cancel during the Ready phase", async () => { + // have alice initiate a verification. She should send a m.key.verification.request + const [, request] = await Promise.all([ + expectSendToDeviceMessage("m.key.verification.request"), + aliceClient.getCrypto()!.requestDeviceVerification(TEST_USER_ID, TEST_DEVICE_ID), + ]); + const transactionId = request.transactionId!; + // The dummy device replies with an m.key.verification.ready... + returnToDeviceMessageFromSync(buildReadyMessage(transactionId, ["m.sas.v1"])); + await waitForVerificationRequestChanged(request); + + // now alice changes her mind + const [requestBody] = await Promise.all([ + expectSendToDeviceMessage("m.key.verification.cancel"), + request.cancel(), + ]); + const toDeviceMessage = requestBody.messages[TEST_USER_ID][TEST_DEVICE_ID]; + expect(toDeviceMessage.transaction_id).toEqual(transactionId); + expect(toDeviceMessage.code).toEqual("m.user"); + expect(request.phase).toEqual(VerificationPhase.Cancelled); + }); + + it("can cancel during the SAS phase", async () => { // have alice initiate a verification. She should send a m.key.verification.request const [, request] = await Promise.all([ expectSendToDeviceMessage("m.key.verification.request"), diff --git a/src/crypto-api/verification.ts b/src/crypto-api/verification.ts index daaf405b1d1..fc5c75bc7a0 100644 --- a/src/crypto-api/verification.ts +++ b/src/crypto-api/verification.ts @@ -108,7 +108,7 @@ export interface VerificationRequest * Cancels the request, sending a cancellation to the other party * * @param params - Details for the cancellation, including `reason` (defaults to "User declined"), and `code` - * (defaults to `m.user`). + * (defaults to `m.user`). **Deprecated**: this parameter is ignored by the Rust cryptography implementation. * * @returns Promise which resolves when the event has been sent. */ diff --git a/src/rust-crypto/verification.ts b/src/rust-crypto/verification.ts index f4c8f3697fd..7fb314c78d9 100644 --- a/src/rust-crypto/verification.ts +++ b/src/rust-crypto/verification.ts @@ -42,7 +42,7 @@ export class RustVerificationRequest public constructor( private readonly inner: RustSdkCryptoJs.VerificationRequest, - outgoingRequestProcessor: OutgoingRequestProcessor, + private readonly outgoingRequestProcessor: OutgoingRequestProcessor, ) { super(); @@ -210,8 +210,11 @@ export class RustVerificationRequest * * @returns Promise which resolves when the event has been sent. */ - public cancel(params?: { reason?: string; code?: string }): Promise { - throw new Error("not implemented"); + public async cancel(params?: { reason?: string; code?: string }): Promise { + const req: undefined | OutgoingRequest = this.inner.cancel(); + if (req) { + await this.outgoingRequestProcessor.makeOutgoingRequest(req); + } } /**