You've already forked matrix-react-sdk
							
							
				mirror of
				https://github.com/matrix-org/matrix-react-sdk.git
				synced 2025-11-03 00:33:22 +03:00 
			
		
		
		
	Merge pull request #6746 from matrix-org/t3chguy/fix/10935
This commit is contained in:
		@@ -366,16 +366,22 @@ export class SpaceStoreClass extends AsyncStoreWithClient<IState> {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public getParents(roomId: string, canonicalOnly = false): Room[] {
 | 
					    public getParents(roomId: string, canonicalOnly = false): Room[] {
 | 
				
			||||||
 | 
					        const userId = this.matrixClient?.getUserId();
 | 
				
			||||||
        const room = this.matrixClient?.getRoom(roomId);
 | 
					        const room = this.matrixClient?.getRoom(roomId);
 | 
				
			||||||
        return room?.currentState.getStateEvents(EventType.SpaceParent)
 | 
					        return room?.currentState.getStateEvents(EventType.SpaceParent)
 | 
				
			||||||
            .filter(ev => {
 | 
					            .map(ev => {
 | 
				
			||||||
                const content = ev.getContent();
 | 
					                const content = ev.getContent();
 | 
				
			||||||
                if (!content?.via?.length) return false;
 | 
					                if (Array.isArray(content?.via) && (!canonicalOnly || content?.canonical)) {
 | 
				
			||||||
                // TODO apply permissions check to verify that the parent mapping is valid
 | 
					                    const parent = this.matrixClient.getRoom(ev.getStateKey());
 | 
				
			||||||
                if (canonicalOnly && !content?.canonical) return false;
 | 
					                    // only respect the relationship if the sender has sufficient permissions in the parent to set
 | 
				
			||||||
                return true;
 | 
					                    // child relations, as per MSC1772.
 | 
				
			||||||
 | 
					                    // https://github.com/matrix-org/matrix-doc/blob/main/proposals/1772-groups-as-rooms.md#relationship-between-rooms-and-spaces
 | 
				
			||||||
 | 
					                    if (parent?.currentState.maySendStateEvent(EventType.SpaceChild, userId)) {
 | 
				
			||||||
 | 
					                        return parent;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                // else implicit undefined which causes this element to be filtered out
 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
            .map(ev => this.matrixClient.getRoom(ev.getStateKey()))
 | 
					 | 
				
			||||||
            .filter(Boolean) || [];
 | 
					            .filter(Boolean) || [];
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -530,6 +536,14 @@ export class SpaceStoreClass extends AsyncStoreWithClient<IState> {
 | 
				
			|||||||
            });
 | 
					            });
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const hiddenChildren = new EnhancedMap<string, Set<string>>();
 | 
				
			||||||
 | 
					        visibleRooms.forEach(room => {
 | 
				
			||||||
 | 
					            if (room.getMyMembership() !== "join") return;
 | 
				
			||||||
 | 
					            this.getParents(room.roomId).forEach(parent => {
 | 
				
			||||||
 | 
					                hiddenChildren.getOrCreate(parent.roomId, new Set()).add(room.roomId);
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.rootSpaces.forEach(s => {
 | 
					        this.rootSpaces.forEach(s => {
 | 
				
			||||||
            // traverse each space tree in DFS to build up the supersets as you go up,
 | 
					            // traverse each space tree in DFS to build up the supersets as you go up,
 | 
				
			||||||
            // reusing results from like subtrees.
 | 
					            // reusing results from like subtrees.
 | 
				
			||||||
@@ -559,6 +573,9 @@ export class SpaceStoreClass extends AsyncStoreWithClient<IState> {
 | 
				
			|||||||
                        roomIds.add(roomId);
 | 
					                        roomIds.add(roomId);
 | 
				
			||||||
                    });
 | 
					                    });
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
 | 
					                hiddenChildren.get(spaceId)?.forEach(roomId => {
 | 
				
			||||||
 | 
					                    roomIds.add(roomId);
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
                this.spaceFilteredRooms.set(spaceId, roomIds);
 | 
					                this.spaceFilteredRooms.set(spaceId, roomIds);
 | 
				
			||||||
                return roomIds;
 | 
					                return roomIds;
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
@@ -690,6 +707,12 @@ export class SpaceStoreClass extends AsyncStoreWithClient<IState> {
 | 
				
			|||||||
                }
 | 
					                }
 | 
				
			||||||
                this.emit(room.roomId);
 | 
					                this.emit(room.roomId);
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            case EventType.RoomPowerLevels:
 | 
				
			||||||
 | 
					                if (room.isSpaceRoom()) {
 | 
				
			||||||
 | 
					                    this.onRoomsUpdate();
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -276,10 +276,12 @@ describe("SpaceStore", () => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        describe("test fixture 1", () => {
 | 
					        describe("test fixture 1", () => {
 | 
				
			||||||
            beforeEach(async () => {
 | 
					            beforeEach(async () => {
 | 
				
			||||||
                [fav1, fav2, fav3, dm1, dm2, dm3, orphan1, orphan2, invite1, invite2, room1].forEach(mkRoom);
 | 
					                [fav1, fav2, fav3, dm1, dm2, dm3, orphan1, orphan2, invite1, invite2, room1, room2, room3]
 | 
				
			||||||
 | 
					                    .forEach(mkRoom);
 | 
				
			||||||
                mkSpace(space1, [fav1, room1]);
 | 
					                mkSpace(space1, [fav1, room1]);
 | 
				
			||||||
                mkSpace(space2, [fav1, fav2, fav3, room1]);
 | 
					                mkSpace(space2, [fav1, fav2, fav3, room1]);
 | 
				
			||||||
                mkSpace(space3, [invite2]);
 | 
					                mkSpace(space3, [invite2]);
 | 
				
			||||||
 | 
					                // client.getRoom.mockImplementation(roomId => rooms.find(room => room.roomId === roomId));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                [fav1, fav2, fav3].forEach(roomId => {
 | 
					                [fav1, fav2, fav3].forEach(roomId => {
 | 
				
			||||||
                    client.getRoom(roomId).tags = {
 | 
					                    client.getRoom(roomId).tags = {
 | 
				
			||||||
@@ -329,6 +331,48 @@ describe("SpaceStore", () => {
 | 
				
			|||||||
                ]);
 | 
					                ]);
 | 
				
			||||||
                // dmPartner3 is not in any common spaces with you
 | 
					                // dmPartner3 is not in any common spaces with you
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                // room 2 claims to be a child of space2 and is so via a valid m.space.parent
 | 
				
			||||||
 | 
					                const cliRoom2 = client.getRoom(room2);
 | 
				
			||||||
 | 
					                cliRoom2.currentState.getStateEvents.mockImplementation(testUtils.mockStateEventImplementation([
 | 
				
			||||||
 | 
					                    mkEvent({
 | 
				
			||||||
 | 
					                        event: true,
 | 
				
			||||||
 | 
					                        type: EventType.SpaceParent,
 | 
				
			||||||
 | 
					                        room: room2,
 | 
				
			||||||
 | 
					                        user: client.getUserId(),
 | 
				
			||||||
 | 
					                        skey: space2,
 | 
				
			||||||
 | 
					                        content: { via: [], canonical: true },
 | 
				
			||||||
 | 
					                        ts: Date.now(),
 | 
				
			||||||
 | 
					                    }),
 | 
				
			||||||
 | 
					                ]));
 | 
				
			||||||
 | 
					                const cliSpace2 = client.getRoom(space2);
 | 
				
			||||||
 | 
					                cliSpace2.currentState.maySendStateEvent.mockImplementation((evType: string, userId: string) => {
 | 
				
			||||||
 | 
					                    if (evType === EventType.SpaceChild) {
 | 
				
			||||||
 | 
					                        return userId === client.getUserId();
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    return true;
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                // room 3 claims to be a child of space3 but is not due to invalid m.space.parent (permissions)
 | 
				
			||||||
 | 
					                const cliRoom3 = client.getRoom(room3);
 | 
				
			||||||
 | 
					                cliRoom3.currentState.getStateEvents.mockImplementation(testUtils.mockStateEventImplementation([
 | 
				
			||||||
 | 
					                    mkEvent({
 | 
				
			||||||
 | 
					                        event: true,
 | 
				
			||||||
 | 
					                        type: EventType.SpaceParent,
 | 
				
			||||||
 | 
					                        room: room3,
 | 
				
			||||||
 | 
					                        user: client.getUserId(),
 | 
				
			||||||
 | 
					                        skey: space3,
 | 
				
			||||||
 | 
					                        content: { via: [], canonical: true },
 | 
				
			||||||
 | 
					                        ts: Date.now(),
 | 
				
			||||||
 | 
					                    }),
 | 
				
			||||||
 | 
					                ]));
 | 
				
			||||||
 | 
					                const cliSpace3 = client.getRoom(space3);
 | 
				
			||||||
 | 
					                cliSpace3.currentState.maySendStateEvent.mockImplementation((evType: string, userId: string) => {
 | 
				
			||||||
 | 
					                    if (evType === EventType.SpaceChild) {
 | 
				
			||||||
 | 
					                        return false;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    return true;
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                await run();
 | 
					                await run();
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -445,6 +489,14 @@ describe("SpaceStore", () => {
 | 
				
			|||||||
                expect(store.getNotificationState(space2).rooms.map(r => r.roomId).includes(room1)).toBeTruthy();
 | 
					                expect(store.getNotificationState(space2).rooms.map(r => r.roomId).includes(room1)).toBeTruthy();
 | 
				
			||||||
                expect(store.getNotificationState(space3).rooms.map(r => r.roomId).includes(room1)).toBeFalsy();
 | 
					                expect(store.getNotificationState(space3).rooms.map(r => r.roomId).includes(room1)).toBeFalsy();
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            it("honours m.space.parent if sender has permission in parent space", () => {
 | 
				
			||||||
 | 
					                expect(store.getSpaceFilteredRoomIds(client.getRoom(space2)).has(room2)).toBeTruthy();
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            it("does not honour m.space.parent if sender does not have permission in parent space", () => {
 | 
				
			||||||
 | 
					                expect(store.getSpaceFilteredRoomIds(client.getRoom(space3)).has(room3)).toBeFalsy();
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user