Skip to content

Commit

Permalink
Set minimum supported Matrix 1.1 version (drop legacy r0 versions) (#…
Browse files Browse the repository at this point in the history
…3007)

Co-authored-by: Germain <germains@element.io>
Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>
  • Loading branch information
3 people authored Aug 14, 2023
1 parent 55b9116 commit 8c16d69
Show file tree
Hide file tree
Showing 27 changed files with 229 additions and 287 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
This is the [Matrix](https://matrix.org) Client-Server SDK for JavaScript and TypeScript. This SDK can be run in a
browser or in Node.js.

#### Minimum Matrix server version: v1.1

The Matrix specification is constantly evolving - while this SDK aims for maximum backwards compatibility, it only
guarantees that a feature will be supported for at least 4 spec releases. For example, if a feature the js-sdk supports
is removed in v1.4 then the feature is _eligible_ for removal from the SDK when v1.8 is released. This SDK has no
Expand Down
2 changes: 1 addition & 1 deletion spec/TestClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ export class TestClient implements IE2EKeyReceiver, ISyncResponder {
logger.log(this + ": starting");
this.httpBackend.when("GET", "/versions").respond(200, {
// we have tests that rely on support for lazy-loading members
versions: ["r0.5.0"],
versions: ["v1.1"],
});
this.httpBackend.when("GET", "/pushrules").respond(200, {});
this.httpBackend.when("POST", "/filter").respond(200, { filter_id: "fid" });
Expand Down
17 changes: 9 additions & 8 deletions spec/integ/crypto/crypto.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1945,7 +1945,7 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("crypto (%s)", (backend: string,
};
};

for (const path of ["/_matrix/client/r0/keys/upload", "/_matrix/client/v3/keys/upload"]) {
for (const path of ["/_matrix/client/v3/keys/upload", "/_matrix/client/v3/keys/upload"]) {
fetchMock.post(new URL(path, aliceClient.getHomeserverUrl()).toString(), listener, {
// These routes are already defined in the E2EKeyReceiver
// We want to overwrite the behaviour of the E2EKeyReceiver
Expand Down Expand Up @@ -2082,9 +2082,10 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("crypto (%s)", (backend: string,
return queryResponseBody;
};

for (const path of ["/_matrix/client/r0/keys/query", "/_matrix/client/v3/keys/query"]) {
fetchMock.post(new URL(path, aliceClient.getHomeserverUrl()).toString(), listener);
}
fetchMock.post(
new URL("/_matrix/client/v3/keys/query", aliceClient.getHomeserverUrl()).toString(),
listener,
);
});
}

Expand Down Expand Up @@ -2175,7 +2176,7 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("crypto (%s)", (backend: string,
});

/**
* Create a mock to respond to the PUT request `/_matrix/client/r0/user/:userId/account_data/:type(m.secret_storage.*)`
* Create a mock to respond to the PUT request `/_matrix/client/v3/user/:userId/account_data/:type(m.secret_storage.*)`
* Resolved when a key is uploaded (ie in `body.content.key`)
* https://spec.matrix.org/v1.6/client-server-api/#put_matrixclientv3useruseridaccount_datatype
*/
Expand All @@ -2184,7 +2185,7 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("crypto (%s)", (backend: string,
// This url is called multiple times during the secret storage bootstrap process
// When we received the newly generated key, we return it
fetchMock.put(
"express:/_matrix/client/r0/user/:userId/account_data/:type(m.secret_storage.*)",
"express:/_matrix/client/v3/user/:userId/account_data/:type(m.secret_storage.*)",
(url: string, options: RequestInit) => {
const content = JSON.parse(options.body as string);

Expand All @@ -2200,15 +2201,15 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("crypto (%s)", (backend: string,
}

/**
* Create a mock to respond to the PUT request `/_matrix/client/r0/user/:userId/account_data/m.cross_signing.${key}`
* Create a mock to respond to the PUT request `/_matrix/client/v3/user/:userId/account_data/m.cross_signing.${key}`
* Resolved when the cross signing key is uploaded
* https://spec.matrix.org/v1.6/client-server-api/#put_matrixclientv3useruseridaccount_datatype
*/
function awaitCrossSigningKeyUpload(key: string): Promise<Record<string, {}>> {
return new Promise((resolve) => {
// Called when the cross signing key is uploaded
fetchMock.put(
`express:/_matrix/client/r0/user/:userId/account_data/m.cross_signing.${key}`,
`express:/_matrix/client/v3/user/:userId/account_data/m.cross_signing.${key}`,
(url: string, options: RequestInit) => {
const content = JSON.parse(options.body as string);
resolve(content.encrypted);
Expand Down
6 changes: 3 additions & 3 deletions spec/integ/matrix-client-event-timeline.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1342,7 +1342,7 @@ describe("MatrixClient event timelines", function () {
function respondToContext(event: Partial<IEvent> = THREAD_ROOT): ExpectedHttpRequest {
const request = httpBackend.when(
"GET",
encodeUri("/_matrix/client/r0/rooms/$roomId/context/$eventId", {
encodeUri("/_matrix/client/v3/rooms/$roomId/context/$eventId", {
$roomId: roomId,
$eventId: event.event_id!,
}),
Expand All @@ -1360,7 +1360,7 @@ describe("MatrixClient event timelines", function () {
function respondToEvent(event: Partial<IEvent> = THREAD_ROOT): ExpectedHttpRequest {
const request = httpBackend.when(
"GET",
encodeUri("/_matrix/client/r0/rooms/$roomId/event/$eventId", {
encodeUri("/_matrix/client/v3/rooms/$roomId/event/$eventId", {
$roomId: roomId,
$eventId: event.event_id!,
}),
Expand All @@ -1371,7 +1371,7 @@ describe("MatrixClient event timelines", function () {
function respondToMessagesRequest(): ExpectedHttpRequest {
const request = httpBackend.when(
"GET",
encodeUri("/_matrix/client/r0/rooms/$roomId/messages", {
encodeUri("/_matrix/client/v3/rooms/$roomId/messages", {
$roomId: roomId,
}),
);
Expand Down
94 changes: 79 additions & 15 deletions spec/integ/matrix-client-methods.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ describe("MatrixClient", function () {

it("should upload the file", function () {
httpBackend
.when("POST", "/_matrix/media/r0/upload")
.when("POST", "/_matrix/media/v3/upload")
.check(function (req) {
expect(req.rawData).toEqual(buf);
expect(req.queryParams?.filename).toEqual("hi.txt");
Expand Down Expand Up @@ -108,7 +108,7 @@ describe("MatrixClient", function () {

it("should parse errors into a MatrixError", function () {
httpBackend
.when("POST", "/_matrix/media/r0/upload")
.when("POST", "/_matrix/media/v3/upload")
.check(function (req) {
expect(req.rawData).toEqual(buf);
// @ts-ignore private property
Expand Down Expand Up @@ -708,7 +708,7 @@ describe("MatrixClient", function () {
const auth = { identifier: 1 };
it("should pass through an auth dict", function () {
httpBackend
.when("DELETE", "/_matrix/client/r0/devices/my_device")
.when("DELETE", "/_matrix/client/v3/devices/my_device")
.check(function (req) {
expect(req.data).toEqual({ auth: auth });
})
Expand Down Expand Up @@ -1102,10 +1102,6 @@ describe("MatrixClient", function () {
submit_url: "https://foobar.matrix/_matrix/matrix",
};

httpBackend.when("GET", "/_matrix/client/versions").respond(200, {
versions: ["r0.6.0"],
});

const prom = client.requestRegisterEmailToken("bob@email", "secret", 1);
httpBackend
.when("POST", "/register/email/requestToken")
Expand All @@ -1126,10 +1122,6 @@ describe("MatrixClient", function () {
it("should supply an id_access_token", async () => {
const targetEmail = "gerald@example.org";

httpBackend.when("GET", "/_matrix/client/versions").respond(200, {
versions: ["r0.6.0"],
});

httpBackend
.when("POST", "/invite")
.check((req) => {
Expand Down Expand Up @@ -1165,10 +1157,6 @@ describe("MatrixClient", function () {
],
};

httpBackend.when("GET", "/_matrix/client/versions").respond(200, {
versions: ["r0.6.0"],
});

httpBackend
.when("POST", "/createRoom")
.check((req) => {
Expand Down Expand Up @@ -1652,6 +1640,82 @@ describe("MatrixClient", function () {
]);
});
});

describe("getFallbackAuthUrl", () => {
it("should return fallback url", () => {
expect(client.getFallbackAuthUrl("loginType", "authSessionId")).toMatchInlineSnapshot(
`"http://alice.localhost.test.server/_matrix/client/v3/auth/loginType/fallback/web?session=authSessionId"`,
);
});
});

describe("addThreePidOnly", () => {
it("should make expected POST request", async () => {
httpBackend
.when("POST", "/_matrix/client/v3/account/3pid/add")
.check(function (req) {
expect(req.data).toEqual({
client_secret: "secret",
sid: "sid",
});
expect(req.headers["Authorization"]).toBe("Bearer " + accessToken);
})
.respond(200, {});

await Promise.all([
client.addThreePidOnly({
client_secret: "secret",
sid: "sid",
}),
httpBackend.flushAllExpected(),
]);
});
});

describe("bindThreePid", () => {
it("should make expected POST request", async () => {
httpBackend
.when("POST", "/_matrix/client/v3/account/3pid/bind")
.check(function (req) {
expect(req.data).toEqual({
client_secret: "secret",
id_server: "server",
id_access_token: "token",
sid: "sid",
});
expect(req.headers["Authorization"]).toBe("Bearer " + accessToken);
})
.respond(200, {});

await Promise.all([
client.bindThreePid({
client_secret: "secret",
id_server: "server",
id_access_token: "token",
sid: "sid",
}),
httpBackend.flushAllExpected(),
]);
});
});

describe("unbindThreePid", () => {
it("should make expected POST request", async () => {
httpBackend
.when("POST", "/_matrix/client/v3/account/3pid/unbind")
.check(function (req) {
expect(req.data).toEqual({
medium: "email",
address: "alice@server.com",
id_server: "identity.localhost",
});
expect(req.headers["Authorization"]).toBe("Bearer " + accessToken);
})
.respond(200, {});

await Promise.all([client.unbindThreePid("email", "alice@server.com"), httpBackend.flushAllExpected()]);
});
});
});

function withThreadId(event: MatrixEvent, newThreadId: string): MatrixEvent {
Expand Down
4 changes: 0 additions & 4 deletions spec/integ/matrix-client-syncing.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -224,8 +224,6 @@ describe("MatrixClient syncing", () => {
});

it("should honour lazyLoadMembers if user is not a guest", () => {
client!.doesServerSupportLazyLoading = jest.fn().mockResolvedValue(true);

httpBackend!
.when("GET", "/sync")
.check((req) => {
Expand All @@ -242,8 +240,6 @@ describe("MatrixClient syncing", () => {
it("should not honour lazyLoadMembers if user is a guest", () => {
httpBackend!.expectedRequests = [];
httpBackend!.when("GET", "/versions").respond(200, {});
client!.doesServerSupportLazyLoading = jest.fn().mockResolvedValue(true);

httpBackend!
.when("GET", "/sync")
.check((req) => {
Expand Down
2 changes: 1 addition & 1 deletion spec/integ/sliding-sync-sdk.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ describe("SlidingSyncSdk", () => {
await client!.initCrypto();
syncOpts.cryptoCallbacks = syncOpts.crypto = client!.crypto;
}
httpBackend!.when("GET", "/_matrix/client/r0/pushrules").respond(200, {});
httpBackend!.when("GET", "/_matrix/client/v3/pushrules").respond(200, {});
sdk = new SlidingSyncSdk(mockSlidingSync, client, testOpts, syncOpts);
};

Expand Down
2 changes: 0 additions & 2 deletions spec/test-utils/E2EKeyReceiver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,6 @@ export class E2EKeyReceiver implements IE2EKeyReceiver {
const listener = (url: string, options: RequestInit) =>
this.onKeyUploadRequest(resolveOneTimeKeys, options);

// catch both r0 and v3 variants
fetchMock.post(new URL("/_matrix/client/r0/keys/upload", homeserverUrl).toString(), listener);
fetchMock.post(new URL("/_matrix/client/v3/keys/upload", homeserverUrl).toString(), listener);
});
}
Expand Down
2 changes: 0 additions & 2 deletions spec/test-utils/E2EKeyResponder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,6 @@ export class E2EKeyResponder {
public constructor(homeserverUrl: string) {
// set up a listener for /keys/query.
const listener = (url: string, options: RequestInit) => this.onKeyQueryRequest(options);
// catch both r0 and v3 variants
fetchMock.post(new URL("/_matrix/client/r0/keys/query", homeserverUrl).toString(), listener);
fetchMock.post(new URL("/_matrix/client/v3/keys/query", homeserverUrl).toString(), listener);
}

Expand Down
2 changes: 1 addition & 1 deletion spec/test-utils/SyncResponder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ export class SyncResponder implements ISyncResponder {
*/
public constructor(homeserverUrl: string) {
this.debug = debugFunc(`sync-responder:[${homeserverUrl}]`);
fetchMock.get("begin:" + new URL("/_matrix/client/r0/sync?", homeserverUrl).toString(), (_url, _options) =>
fetchMock.get("begin:" + new URL("/_matrix/client/v3/sync?", homeserverUrl).toString(), (_url, _options) =>
this.onSyncRequest(),
);
}
Expand Down
1 change: 0 additions & 1 deletion spec/test-utils/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,6 @@ export const mockClientMethodsEvents = () => ({
* Returns basic mocked client methods related to server support
*/
export const mockClientMethodsServer = (): Partial<Record<MethodLikeKeys<MatrixClient>, unknown>> => ({
doesServerSupportSeparateAddAndBind: jest.fn(),
getIdentityServerUrl: jest.fn(),
getHomeserverUrl: jest.fn(),
getCapabilities: jest.fn().mockReturnValue({}),
Expand Down
10 changes: 5 additions & 5 deletions spec/test-utils/mockEndpoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,23 +22,23 @@ import fetchMock from "fetch-mock-jest";
* @param homeserverUrl - the homeserver url for the client under test
*/
export function mockInitialApiRequests(homeserverUrl: string) {
fetchMock.getOnce(new URL("/_matrix/client/versions", homeserverUrl).toString(), { versions: ["r0.5.0"] });
fetchMock.getOnce(new URL("/_matrix/client/r0/pushrules/", homeserverUrl).toString(), {});
fetchMock.postOnce(new URL("/_matrix/client/r0/user/%40alice%3Alocalhost/filter", homeserverUrl).toString(), {
fetchMock.getOnce(new URL("/_matrix/client/versions", homeserverUrl).toString(), { versions: ["v1.1"] });
fetchMock.getOnce(new URL("/_matrix/client/v3/pushrules/", homeserverUrl).toString(), {});
fetchMock.postOnce(new URL("/_matrix/client/v3/user/%40alice%3Alocalhost/filter", homeserverUrl).toString(), {
filter_id: "fid",
});
}

/**
* Mock the requests needed to set up cross signing
*
* Return 404 error for `GET _matrix/client/r0/user/:userId/account_data/:type` request
* Return 404 error for `GET _matrix/client/v3/user/:userId/account_data/:type` request
* Return `{}` for `POST _matrix/client/v3/keys/signatures/upload` request (named `upload-sigs` for fetchMock check)
* Return `{}` for `POST /_matrix/client/(unstable|v3)/keys/device_signing/upload` request (named `upload-keys` for fetchMock check)
*/
export function mockSetupCrossSigningRequests(): void {
// have account_data requests return an empty object
fetchMock.get("express:/_matrix/client/r0/user/:userId/account_data/:type", {
fetchMock.get("express:/_matrix/client/v3/user/:userId/account_data/:type", {
status: 404,
body: { errcode: "M_NOT_FOUND", error: "Account data not found." },
});
Expand Down
Loading

0 comments on commit 8c16d69

Please sign in to comment.