1
0
mirror of https://github.com/matrix-org/matrix-js-sdk.git synced 2025-12-17 21:42:17 +03:00

Merge commit from fork

* Validate room upgrade relationships in MatrixClient::getJoinedRooms

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Tests

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

---------

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
This commit is contained in:
Michael Telatynski
2025-09-16 12:36:14 +01:00
committed by GitHub
parent ff89c9ec42
commit 43c72d5bf5
2 changed files with 30 additions and 14 deletions

View File

@@ -2998,6 +2998,8 @@ describe("MatrixClient", function () {
replacedByDynamicPredecessor2,
room2,
];
client.store.getRoom = (roomId: string) =>
client.store.getRooms().find((r) => r.roomId === roomId) || null;
room1.addLiveEvents(
[
roomCreateEvent(room1.roomId, replacedByCreate1.roomId),
@@ -3036,6 +3038,7 @@ describe("MatrixClient", function () {
replacedByDynamicPredecessor2,
};
}
it("Returns an empty list if there are no rooms", () => {
client.store = new StubStore();
client.store.getRooms = () => [];
@@ -3062,6 +3065,8 @@ describe("MatrixClient", function () {
const room2 = new Room("room2", client, "@daryl:alexandria.example.com");
client.store = new StubStore();
client.store.getRooms = () => [room1, replacedRoom1, replacedRoom2, room2];
client.store.getRoom = (roomId: string) =>
client.store.getRooms().find((r) => r.roomId === roomId) || null;
room1.addLiveEvents([roomCreateEvent(room1.roomId, replacedRoom1.roomId)], { addToState: true });
room2.addLiveEvents([roomCreateEvent(room2.roomId, replacedRoom2.roomId)], { addToState: true });
replacedRoom1.addLiveEvents([tombstoneEvent(room1.roomId, replacedRoom1.roomId)], { addToState: true });
@@ -3127,6 +3132,24 @@ describe("MatrixClient", function () {
expect(rooms).toContain(room1);
expect(rooms).toContain(room2);
});
it("should ignore room replacements which are not reciprocated by the predecessor", () => {
const room1 = new Room("room1", client, "@carol:alexandria.example.com");
// Room 2 claims to replace room 1 but room 1 does not agree
const room2 = new Room("replacedRoom1", client, "@daryl:alexandria.example.com");
client.store = new StubStore();
client.store.getRooms = () => [room1, room2];
client.store.getRoom = (roomId: string) =>
client.store.getRooms().find((r) => r.roomId === roomId) || null;
room2.addLiveEvents([roomCreateEvent(room2.roomId, room1.roomId)], { addToState: true });
// When we ask for the visible rooms
const rooms = client.getVisibleRooms();
expect(rooms).toContain(room1);
expect(rooms).toContain(room2);
});
});
describe("getRoomUpgradeHistory", () => {

View File

@@ -2141,21 +2141,14 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
public getVisibleRooms(msc3946ProcessDynamicPredecessor = false): Room[] {
const allRooms = this.store.getRooms();
const replacedRooms = new Set();
for (const r of allRooms) {
const predecessor = r.findPredecessor(msc3946ProcessDynamicPredecessor)?.roomId;
if (predecessor) {
replacedRooms.add(predecessor);
const visibleRooms = new Set(allRooms);
for (const room of visibleRooms) {
const predecessors = this.findPredecessorRooms(room, true, msc3946ProcessDynamicPredecessor);
for (const predecessor of predecessors) {
visibleRooms.delete(predecessor);
}
}
return allRooms.filter((r) => {
const tombstone = r.currentState.getStateEvents(EventType.RoomTombstone, "");
if (tombstone && replacedRooms.has(r.roomId)) {
return false;
}
return true;
});
return Array.from(visibleRooms);
}
/**
@@ -3852,7 +3845,7 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
roomId: string,
includeFuture = true,
): Promise<{ [roomId: string]: Error | MatrixError | null }> {
const upgradeHistory = this.getRoomUpgradeHistory(roomId);
const upgradeHistory = this.getRoomUpgradeHistory(roomId, true);
let eligibleToLeave = upgradeHistory;
if (!includeFuture) {