Skip to content

Commit

Permalink
Merge branch 'develop' into gsouquet/stuck-notifications-edits
Browse files Browse the repository at this point in the history
  • Loading branch information
germain-gg committed Dec 21, 2022
2 parents 9dbde34 + 1ebcac3 commit dd2feb0
Show file tree
Hide file tree
Showing 19 changed files with 4,254 additions and 4,070 deletions.
3 changes: 3 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,6 @@ out

.vscode
.vscode/

# This file is owned, parsed, and generated by allchange, which doesn't comply with prettier
/CHANGELOG.md
8,043 changes: 4,016 additions & 4,027 deletions CHANGELOG.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "matrix-js-sdk",
"version": "22.0.0",
"version": "23.0.0",
"description": "Matrix Client-Server SDK for Javascript",
"engines": {
"node": ">=16.0.0"
Expand Down
4 changes: 2 additions & 2 deletions post-release.sh
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ if [ "$(git branch -lr | grep origin/develop -c)" -ge 1 ]; then
# to the TypeScript source.
src_value=$(jq -r ".matrix_src_$i" package.json)
if [ "$src_value" != "null" ]; then
jq ".$i = .matrix_src_$i" package.json > package.json.new && mv package.json.new package.json
jq ".$i = .matrix_src_$i" package.json > package.json.new && mv package.json.new package.json && yarn prettier --write package.json
else
jq "del(.$i)" package.json > package.json.new && mv package.json.new package.json
jq "del(.$i)" package.json > package.json.new && mv package.json.new package.json && yarn prettier --write package.json
fi
fi
done
Expand Down
2 changes: 1 addition & 1 deletion release.sh
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ for i in main typings
do
lib_value=$(jq -r ".matrix_lib_$i" package.json)
if [ "$lib_value" != "null" ]; then
jq ".$i = .matrix_lib_$i" package.json > package.json.new && mv package.json.new package.json
jq ".$i = .matrix_lib_$i" package.json > package.json.new && mv package.json.new package.json && yarn prettier --write package.json
fi
done

Expand Down
96 changes: 96 additions & 0 deletions spec/integ/sliding-sync.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1418,6 +1418,102 @@ describe("SlidingSync", () => {
await httpBackend!.flushAllExpected();
slidingSync.stop();
});

it("should not be possible to add/modify an already added custom subscription", async () => {
const slidingSync = new SlidingSync(proxyBaseUrl, [], defaultSub, client!, 1);
slidingSync.addCustomSubscription(customSubName1, customSub1);
slidingSync.addCustomSubscription(customSubName1, customSub2);
slidingSync.useCustomSubscription(roomA, customSubName1);
slidingSync.modifyRoomSubscriptions(new Set<string>([roomA]));

httpBackend!
.when("POST", syncUrl)
.check(function (req) {
const body = req.data;
logger.log("custom subs", body);
expect(body.room_subscriptions).toBeTruthy();
expect(body.room_subscriptions[roomA]).toEqual(customSub1);
})
.respond(200, {
pos: "b",
lists: [],
extensions: {},
rooms: {},
});
slidingSync.start();
await httpBackend!.flushAllExpected();
slidingSync.stop();
});

it("should change the custom subscription if they are different", async () => {
const slidingSync = new SlidingSync(proxyBaseUrl, [], defaultSub, client!, 1);
slidingSync.addCustomSubscription(customSubName1, customSub1);
slidingSync.addCustomSubscription(customSubName2, customSub2);
slidingSync.useCustomSubscription(roomA, customSubName1);
slidingSync.modifyRoomSubscriptions(new Set<string>([roomA]));

httpBackend!
.when("POST", syncUrl)
.check(function (req) {
const body = req.data;
logger.log("custom subs", body);
expect(body.room_subscriptions).toBeTruthy();
expect(body.room_subscriptions[roomA]).toEqual(customSub1);
expect(body.unsubscribe_rooms).toBeUndefined();
})
.respond(200, {
pos: "b",
lists: [],
extensions: {},
rooms: {},
});
slidingSync.start();
await httpBackend!.flushAllExpected();

// using the same subscription doesn't unsub nor changes subscriptions
slidingSync.useCustomSubscription(roomA, customSubName1);
slidingSync.modifyRoomSubscriptions(new Set<string>([roomA]));

httpBackend!
.when("POST", syncUrl)
.check(function (req) {
const body = req.data;
logger.log("custom subs", body);
expect(body.room_subscriptions).toBeUndefined();
expect(body.unsubscribe_rooms).toBeUndefined();
})
.respond(200, {
pos: "b",
lists: [],
extensions: {},
rooms: {},
});
slidingSync.start();
await httpBackend!.flushAllExpected();

// Changing the subscription works
slidingSync.useCustomSubscription(roomA, customSubName2);
slidingSync.modifyRoomSubscriptions(new Set<string>([roomA]));

httpBackend!
.when("POST", syncUrl)
.check(function (req) {
const body = req.data;
logger.log("custom subs", body);
expect(body.room_subscriptions).toBeTruthy();
expect(body.room_subscriptions[roomA]).toEqual(customSub2);
expect(body.unsubscribe_rooms).toBeUndefined();
})
.respond(200, {
pos: "b",
lists: [],
extensions: {},
rooms: {},
});
slidingSync.start();
await httpBackend!.flushAllExpected();
slidingSync.stop();
});
});

describe("extensions", () => {
Expand Down
25 changes: 22 additions & 3 deletions spec/unit/event-timeline-set.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import {
} from "../../src";
import { FeatureSupport, Thread } from "../../src/models/thread";
import { ReEmitter } from "../../src/ReEmitter";
import { eventMapperFor } from "../../src/event-mapper";

describe("EventTimelineSet", () => {
const roomId = "!foo:bar";
Expand Down Expand Up @@ -206,6 +207,7 @@ describe("EventTimelineSet", () => {

it("should allow edits to be added to thread timeline", async () => {
jest.spyOn(client, "supportsExperimentalThreads").mockReturnValue(true);
jest.spyOn(client, "getEventMapper").mockReturnValue(eventMapperFor(client, {}));
Thread.hasServerSideSupport = FeatureSupport.Stable;

const sender = "@alice:matrix.org";
Expand Down Expand Up @@ -233,6 +235,25 @@ describe("EventTimelineSet", () => {
sender,
});

root.setUnsigned({
"m.relations": {
[RelationType.Thread]: {
count: 1,
latest_event: {
content: threadReply.getContent(),
origin_server_ts: 5,
room_id: room.roomId,
sender,
type: EventType.RoomMessage,
event_id: threadReply.getId()!,
user_id: sender,
age: 1,
},
current_user_participated: true,
},
},
});

const editToThreadReply = utils.mkEvent({
event: true,
content: {
Expand All @@ -251,9 +272,6 @@ describe("EventTimelineSet", () => {
sender,
});

const thread = room.createThread(root.getId()!, root, [threadReply, editToThreadReply], false);

jest.spyOn(thread, "processEvent").mockResolvedValue();
jest.spyOn(client, "paginateEventTimeline").mockImplementation(async () => {
thread.timelineSet.getLiveTimeline().addEvent(threadReply, { toStartOfTimeline: true });
return true;
Expand All @@ -262,6 +280,7 @@ describe("EventTimelineSet", () => {
events: [],
});

const thread = room.createThread(root.getId()!, root, [threadReply, editToThreadReply], false);
thread.once(RoomEvent.TimelineReset, () => {
const lastEvent = thread.timeline.at(-1)!;
expect(lastEvent.getContent().body).toBe(" * edit");
Expand Down
46 changes: 46 additions & 0 deletions spec/unit/rust-crypto.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
Copyright 2022 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

import "fake-indexeddb/auto";
import { IDBFactory } from "fake-indexeddb";

import { RustCrypto } from "../../src/rust-crypto/rust-crypto";
import { initRustCrypto } from "../../src/rust-crypto";

afterEach(() => {
// reset fake-indexeddb after each test, to make sure we don't leak connections
// cf https://github.com/dumbmatter/fakeIndexedDB#wipingresetting-the-indexeddb-for-a-fresh-state
// eslint-disable-next-line no-global-assign
indexedDB = new IDBFactory();
});

describe("RustCrypto", () => {
const TEST_USER = "@alice:example.com";
const TEST_DEVICE_ID = "TEST_DEVICE";

let rustCrypto: RustCrypto;

beforeEach(async () => {
rustCrypto = (await initRustCrypto(TEST_USER, TEST_DEVICE_ID)) as RustCrypto;
});

describe(".exportRoomKeys", () => {
it("should return a list", async () => {
const keys = await rustCrypto.exportRoomKeys();
expect(Array.isArray(keys)).toBeTruthy();
});
});
});
26 changes: 26 additions & 0 deletions src/@types/crypto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,29 @@ export interface IEventDecryptionResult {
claimedEd25519Key?: string;
untrusted?: boolean;
}

interface Extensible {
[key: string]: any;
}

/* eslint-disable camelcase */

/** The result of a call to {@link MatrixClient.exportRoomKeys} */
export interface IMegolmSessionData extends Extensible {
/** Sender's Curve25519 device key */
sender_key: string;
/** Devices which forwarded this session to us (normally empty). */
forwarding_curve25519_key_chain: string[];
/** Other keys the sender claims. */
sender_claimed_keys: Record<string, string>;
/** Room this session is used in */
room_id: string;
/** Unique id for the session */
session_id: string;
/** Base64'ed key data */
session_key: string;
algorithm?: string;
untrusted?: boolean;
}

/* eslint-enable camelcase */
6 changes: 3 additions & 3 deletions src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ limitations under the License.

import { EmoteEvent, IPartialEvent, MessageEvent, NoticeEvent, Optional } from "matrix-events-sdk";

import type { IMegolmSessionData } from "./@types/crypto";
import { ISyncStateData, SyncApi, SyncState } from "./sync";
import {
EventStatus,
Expand Down Expand Up @@ -74,7 +75,6 @@ import {
ICryptoCallbacks,
IBootstrapCrossSigningOpts,
ICheckOwnCrossSigningTrustOpts,
IMegolmSessionData,
isCryptoAvailable,
VerificationMethod,
IRoomKeyRequestBody,
Expand Down Expand Up @@ -3034,10 +3034,10 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
* session export objects
*/
public exportRoomKeys(): Promise<IMegolmSessionData[]> {
if (!this.crypto) {
if (!this.cryptoBackend) {
return Promise.reject(new Error("End-to-end encryption disabled"));
}
return this.crypto.exportRoomKeys();
return this.cryptoBackend.exportRoomKeys();
}

/**
Expand Down
12 changes: 11 additions & 1 deletion src/common-crypto/CryptoBackend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

import type { IEventDecryptionResult } from "../@types/crypto";
import type { IEventDecryptionResult, IMegolmSessionData } from "../@types/crypto";
import { MatrixEvent } from "../models/event";

/**
Expand Down Expand Up @@ -60,4 +60,14 @@ export interface CryptoBackend {
* Rejects with an error if there is a problem decrypting the event.
*/
decryptEvent(event: MatrixEvent): Promise<IEventDecryptionResult>;

/**
* Get a list containing all of the room keys
*
* This should be encrypted before returning it to the user.
*
* @returns a promise which resolves to a list of
* session export objects
*/
exportRoomKeys(): Promise<IMegolmSessionData[]>;
}
3 changes: 1 addition & 2 deletions src/crypto/OlmDevice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@ import { IndexedDBCryptoStore } from "./store/indexeddb-crypto-store";
import * as algorithms from "./algorithms";
import { CryptoStore, IProblem, ISessionInfo, IWithheld } from "./store/base";
import { IOlmDevice, IOutboundGroupSessionKey } from "./algorithms/megolm";
import { IMegolmSessionData } from "./index";
import { OlmGroupSessionExtraData } from "../@types/crypto";
import { IMegolmSessionData, OlmGroupSessionExtraData } from "../@types/crypto";
import { IMessage } from "./algorithms/olm";

// The maximum size of an event is 65K, and we base64 the content, so this is a
Expand Down
3 changes: 2 additions & 1 deletion src/crypto/algorithms/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,12 @@ limitations under the License.
* Internal module. Defines the base classes of the encryption implementations
*/

import type { IMegolmSessionData } from "../../@types/crypto";
import { MatrixClient } from "../../client";
import { Room } from "../../models/room";
import { OlmDevice } from "../OlmDevice";
import { IContent, MatrixEvent, RoomMember } from "../../matrix";
import { Crypto, IEncryptedContent, IEventDecryptionResult, IMegolmSessionData, IncomingRoomKeyRequest } from "..";
import { Crypto, IEncryptedContent, IEventDecryptionResult, IncomingRoomKeyRequest } from "..";
import { DeviceInfo } from "../deviceinfo";
import { IRoomEncryption } from "../RoomList";

Expand Down
4 changes: 2 additions & 2 deletions src/crypto/algorithms/megolm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ limitations under the License.

import { v4 as uuidv4 } from "uuid";

import type { IEventDecryptionResult } from "../../@types/crypto";
import type { IEventDecryptionResult, IMegolmSessionData } from "../../@types/crypto";
import { logger } from "../../logger";
import * as olmlib from "../olmlib";
import {
Expand All @@ -39,7 +39,7 @@ import { IOlmSessionResult } from "../olmlib";
import { DeviceInfoMap } from "../DeviceList";
import { IContent, MatrixEvent } from "../../models/event";
import { EventType, MsgType, ToDeviceMessageId } from "../../@types/event";
import { IMegolmEncryptedContent, IMegolmSessionData, IncomingRoomKeyRequest, IEncryptedContent } from "../index";
import { IMegolmEncryptedContent, IncomingRoomKeyRequest, IEncryptedContent } from "../index";
import { RoomKeyRequestState } from "../OutgoingRoomKeyRequestManager";
import { OlmGroupSessionExtraData } from "../../@types/crypto";
import { MatrixError } from "../../http-api";
Expand Down
3 changes: 2 additions & 1 deletion src/crypto/backup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ limitations under the License.
* Classes for dealing with key backup.
*/

import type { IMegolmSessionData } from "../@types/crypto";
import { MatrixClient } from "../client";
import { logger } from "../logger";
import { MEGOLM_ALGORITHM, verifySignature } from "./olmlib";
Expand All @@ -36,7 +37,7 @@ import {
IKeyBackupSession,
} from "./keybackup";
import { UnstableValue } from "../NamespacedValue";
import { CryptoEvent, IMegolmSessionData } from "./index";
import { CryptoEvent } from "./index";
import { crypto } from "./crypto";
import { HTTPError, MatrixError } from "../http-api";

Expand Down
Loading

0 comments on commit dd2feb0

Please sign in to comment.