From 2ea047f64e159db93f5935514d450abeb47837f9 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 14 Oct 2021 10:57:16 +0100 Subject: [PATCH 1/2] Fix removing a room from a Space and interaction with `m.space.parent` --- src/components/structures/SpaceHierarchy.tsx | 10 ++++++++ src/stores/SpaceStore.ts | 24 ++++++++++++-------- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/src/components/structures/SpaceHierarchy.tsx b/src/components/structures/SpaceHierarchy.tsx index c97c984d59f..2a9b88cbe61 100644 --- a/src/components/structures/SpaceHierarchy.tsx +++ b/src/components/structures/SpaceHierarchy.tsx @@ -537,9 +537,19 @@ const ManageButtons = ({ hierarchy, selected, setSelected, setError }: IManageBu onClick={async () => { setRemoving(true); try { + const userId = cli.getUserId(); for (const [parentId, childId] of selectedRelations) { await cli.sendStateEvent(parentId, EventType.SpaceChild, {}, childId); + // remove the child->parent relation too, if we have permission to. + const childRoom = cli.getRoom(childId); + const parentRelation = childRoom?.currentState.getStateEvents(EventType.SpaceParent, parentId); + if (childRoom?.currentState.maySendStateEvent(EventType.SpaceParent, userId) && + Array.isArray(parentRelation?.getContent().via) + ) { + await cli.sendStateEvent(childId, EventType.SpaceParent, {}, parentId); + } + hierarchy.removeRelation(parentId, childId); } } catch (e) { diff --git a/src/stores/SpaceStore.ts b/src/stores/SpaceStore.ts index b4a1889d3e0..264b9f020c2 100644 --- a/src/stores/SpaceStore.ts +++ b/src/stores/SpaceStore.ts @@ -305,16 +305,22 @@ export class SpaceStoreClass extends AsyncStoreWithClient { return room?.currentState.getStateEvents(EventType.SpaceParent) .map(ev => { const content = ev.getContent(); - if (Array.isArray(content?.via) && (!canonicalOnly || content?.canonical)) { - const parent = this.matrixClient.getRoom(ev.getStateKey()); - // only respect the relationship if the sender has sufficient permissions in the parent to set - // 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; - } + if (!Array.isArray(content.via) || (canonicalOnly && !content.canonical)) { + return; // skip } - // else implicit undefined which causes this element to be filtered out + + // only respect the relationship if the sender has sufficient permissions in the parent to set + // 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 + const parent = this.matrixClient.getRoom(ev.getStateKey()); + if (!parent?.currentState.maySendStateEvent(EventType.SpaceChild, userId) || + // also skip this relation if the parent had this child added but then since removed it + !Array.isArray(parent.currentState.getStateEvents(EventType.SpaceChild, roomId)?.getContent().via) + ) { + return; // skip + } + + return parent; }) .filter(Boolean) || []; } From d0892ce10116cbe8ad6d9ba9d79c6860996705b5 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Mon, 18 Oct 2021 16:08:01 +0100 Subject: [PATCH 2/2] Fix implementation edge case --- src/stores/SpaceStore.ts | 3 ++- test/stores/SpaceStore-test.ts | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/stores/SpaceStore.ts b/src/stores/SpaceStore.ts index 264b9f020c2..0ebbbd0c33b 100644 --- a/src/stores/SpaceStore.ts +++ b/src/stores/SpaceStore.ts @@ -313,9 +313,10 @@ export class SpaceStoreClass extends AsyncStoreWithClient { // 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 const parent = this.matrixClient.getRoom(ev.getStateKey()); + const relation = parent.currentState.getStateEvents(EventType.SpaceChild, roomId); if (!parent?.currentState.maySendStateEvent(EventType.SpaceChild, userId) || // also skip this relation if the parent had this child added but then since removed it - !Array.isArray(parent.currentState.getStateEvents(EventType.SpaceChild, roomId)?.getContent().via) + (relation && !Array.isArray(relation.getContent().via)) ) { return; // skip } diff --git a/test/stores/SpaceStore-test.ts b/test/stores/SpaceStore-test.ts index cdc3e58a4fd..ccbf0af4024 100644 --- a/test/stores/SpaceStore-test.ts +++ b/test/stores/SpaceStore-test.ts @@ -281,7 +281,7 @@ describe("SpaceStore", () => { mkSpace(space1, [fav1, room1]); mkSpace(space2, [fav1, fav2, fav3, room1]); mkSpace(space3, [invite2]); - // client.getRoom.mockImplementation(roomId => rooms.find(room => room.roomId === roomId)); + client.getRoom.mockImplementation(roomId => rooms.find(room => room.roomId === roomId)); [fav1, fav2, fav3].forEach(roomId => { client.getRoom(roomId).tags = {