You've already forked matrix-js-sdk
mirror of
https://github.com/matrix-org/matrix-js-sdk.git
synced 2025-08-06 12:02:40 +03:00
Allow knocking rooms (#3647)
Signed-off-by: Charly Nguyen <charly.nguyen@nordeck.net>
This commit is contained in:
@@ -19,7 +19,7 @@ import { Mocked } from "jest-mock";
|
|||||||
import * as utils from "../test-utils/test-utils";
|
import * as utils from "../test-utils/test-utils";
|
||||||
import { CRYPTO_ENABLED, IStoredClientOpts, MatrixClient } from "../../src/client";
|
import { CRYPTO_ENABLED, IStoredClientOpts, MatrixClient } from "../../src/client";
|
||||||
import { MatrixEvent } from "../../src/models/event";
|
import { MatrixEvent } from "../../src/models/event";
|
||||||
import { Filter, MemoryStore, Method, Room, SERVICE_TYPES } from "../../src/matrix";
|
import { Filter, KnockRoomOpts, MemoryStore, Method, Room, SERVICE_TYPES } from "../../src/matrix";
|
||||||
import { TestClient } from "../TestClient";
|
import { TestClient } from "../TestClient";
|
||||||
import { THREAD_RELATION_TYPE } from "../../src/models/thread";
|
import { THREAD_RELATION_TYPE } from "../../src/models/thread";
|
||||||
import { IFilterDefinition } from "../../src/filter";
|
import { IFilterDefinition } from "../../src/filter";
|
||||||
@@ -205,6 +205,84 @@ describe("MatrixClient", function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("knockRoom", function () {
|
||||||
|
const roomId = "!some-room-id:example.org";
|
||||||
|
const reason = "some reason";
|
||||||
|
const viaServers = "example.com";
|
||||||
|
|
||||||
|
type TestCase = [string, KnockRoomOpts];
|
||||||
|
const testCases: TestCase[] = [
|
||||||
|
["should knock a room", {}],
|
||||||
|
["should knock a room for a reason", { reason }],
|
||||||
|
["should knock a room via given servers", { viaServers }],
|
||||||
|
["should knock a room for a reason via given servers", { reason, viaServers }],
|
||||||
|
];
|
||||||
|
|
||||||
|
it.each(testCases)("%s", async (_, opts) => {
|
||||||
|
httpBackend
|
||||||
|
.when("POST", "/knock/" + encodeURIComponent(roomId))
|
||||||
|
.check((request) => {
|
||||||
|
expect(request.data).toEqual({ reason: opts.reason });
|
||||||
|
expect(request.queryParams).toEqual({ server_name: opts.viaServers });
|
||||||
|
})
|
||||||
|
.respond(200, { room_id: roomId });
|
||||||
|
|
||||||
|
const prom = client.knockRoom(roomId, opts);
|
||||||
|
await httpBackend.flushAllExpected();
|
||||||
|
expect((await prom).room_id).toBe(roomId);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should no-op if you've already knocked a room", function () {
|
||||||
|
const room = new Room(roomId, client, userId);
|
||||||
|
|
||||||
|
client.fetchRoomEvent = () =>
|
||||||
|
Promise.resolve({
|
||||||
|
type: "test",
|
||||||
|
content: {},
|
||||||
|
});
|
||||||
|
|
||||||
|
room.addLiveEvents([
|
||||||
|
utils.mkMembership({
|
||||||
|
user: userId,
|
||||||
|
room: roomId,
|
||||||
|
mship: "knock",
|
||||||
|
event: true,
|
||||||
|
}),
|
||||||
|
]);
|
||||||
|
|
||||||
|
httpBackend.verifyNoOutstandingRequests();
|
||||||
|
store.storeRoom(room);
|
||||||
|
client.knockRoom(roomId);
|
||||||
|
httpBackend.verifyNoOutstandingRequests();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("errors", function () {
|
||||||
|
type TestCase = [number, { errcode: string; error?: string }, string];
|
||||||
|
const testCases: TestCase[] = [
|
||||||
|
[
|
||||||
|
403,
|
||||||
|
{ errcode: "M_FORBIDDEN", error: "You don't have permission to knock" },
|
||||||
|
"[M_FORBIDDEN: MatrixError: [403] You don't have permission to knock]",
|
||||||
|
],
|
||||||
|
[
|
||||||
|
500,
|
||||||
|
{ errcode: "INTERNAL_SERVER_ERROR" },
|
||||||
|
"[INTERNAL_SERVER_ERROR: MatrixError: [500] Unknown message]",
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
it.each(testCases)("should handle %s error", async (code, { errcode, error }, snapshot) => {
|
||||||
|
httpBackend.when("POST", "/knock/" + encodeURIComponent(roomId)).respond(code, { errcode, error });
|
||||||
|
|
||||||
|
const prom = client.knockRoom(roomId);
|
||||||
|
await Promise.all([
|
||||||
|
httpBackend.flushAllExpected(),
|
||||||
|
expect(prom).rejects.toMatchInlineSnapshot(snapshot),
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe("getFilter", function () {
|
describe("getFilter", function () {
|
||||||
const filterId = "f1lt3r1d";
|
const filterId = "f1lt3r1d";
|
||||||
|
|
||||||
|
@@ -45,6 +45,18 @@ export interface IJoinRoomOpts {
|
|||||||
viaServers?: string[];
|
viaServers?: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface KnockRoomOpts {
|
||||||
|
/**
|
||||||
|
* The reason for the knock.
|
||||||
|
*/
|
||||||
|
reason?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The server names to try and knock through in addition to those that are automatically chosen.
|
||||||
|
*/
|
||||||
|
viaServers?: string | string[];
|
||||||
|
}
|
||||||
|
|
||||||
export interface IRedactOpts {
|
export interface IRedactOpts {
|
||||||
reason?: string;
|
reason?: string;
|
||||||
/**
|
/**
|
||||||
|
@@ -134,6 +134,7 @@ import {
|
|||||||
ITagsResponse,
|
ITagsResponse,
|
||||||
IStatusResponse,
|
IStatusResponse,
|
||||||
IAddThreePidBody,
|
IAddThreePidBody,
|
||||||
|
KnockRoomOpts,
|
||||||
} from "./@types/requests";
|
} from "./@types/requests";
|
||||||
import {
|
import {
|
||||||
EventType,
|
EventType,
|
||||||
@@ -4158,6 +4159,34 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|||||||
return syncRoom;
|
return syncRoom;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Knock a room. If you have already knocked the room, this will no-op.
|
||||||
|
* @param roomIdOrAlias - The room ID or room alias to knock.
|
||||||
|
* @param opts - Options when knocking the room.
|
||||||
|
* @returns Promise which resolves: `{room_id: {string}}`
|
||||||
|
* @returns Rejects: with an error response.
|
||||||
|
*/
|
||||||
|
public knockRoom(roomIdOrAlias: string, opts: KnockRoomOpts = {}): Promise<{ room_id: string }> {
|
||||||
|
const room = this.getRoom(roomIdOrAlias);
|
||||||
|
if (room?.hasMembershipState(this.credentials.userId!, "knock")) {
|
||||||
|
return Promise.resolve({ room_id: room.roomId });
|
||||||
|
}
|
||||||
|
|
||||||
|
const path = utils.encodeUri("/knock/$roomIdOrAlias", { $roomIdOrAlias: roomIdOrAlias });
|
||||||
|
|
||||||
|
const queryParams: Record<string, string | string[]> = {};
|
||||||
|
if (opts.viaServers) {
|
||||||
|
queryParams.server_name = opts.viaServers;
|
||||||
|
}
|
||||||
|
|
||||||
|
const body: Record<string, string> = {};
|
||||||
|
if (opts.reason) {
|
||||||
|
body.reason = opts.reason;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.http.authedRequest(Method.Post, path, queryParams, body);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resend an event. Will also retry any to-device messages waiting to be sent.
|
* Resend an event. Will also retry any to-device messages waiting to be sent.
|
||||||
* @param event - The event to resend.
|
* @param event - The event to resend.
|
||||||
|
Reference in New Issue
Block a user