From 417ed8d742c68cd505c7b8c26fa194e150ccf7d0 Mon Sep 17 00:00:00 2001 From: Will Hunt Date: Mon, 1 Mar 2021 14:10:15 +0000 Subject: [PATCH 1/2] Remove admin/pm rooms when the matrix-side user leaves to allow server to GC --- src/bridge/MatrixHandler.ts | 27 ++++++++++++++++++++++++++- src/datastore/DataStore.ts | 4 ++++ src/datastore/NedbDataStore.ts | 18 ++++++++++++++++++ src/datastore/postgres/PgDataStore.ts | 16 ++++++++++++++++ 4 files changed, 64 insertions(+), 1 deletion(-) diff --git a/src/bridge/MatrixHandler.ts b/src/bridge/MatrixHandler.ts index 06af2b80e..582b0067e 100644 --- a/src/bridge/MatrixHandler.ts +++ b/src/bridge/MatrixHandler.ts @@ -719,9 +719,34 @@ export class MatrixHandler { serverLookup[ircClient.server.domain] = ircClient; }); + const store = this.ircBridge.getStore(); // which channels should the connected client leave? - const ircRooms = await this.ircBridge.getStore().getIrcChannelsForRoomId(event.room_id); + const ircRooms = await store.getIrcChannelsForRoomId(event.room_id); + + if (!ircRooms) { + const adminRoom = await store.getAdminRoomById(event.room_id); + if (adminRoom) { + await store.removeAdminRoom(adminRoom); + // The user left the admin room, let's also leave. + // XXX: The typing of .leave is wrong, it should + // allow undefined. + await this.membershipQueue.leave(event.room_id, "", req); + return null; + } + + const pmRoom = await store.getMatrixPmRoomById(event.room_id); + if (pmRoom) { + await store.removePmRoom(pmRoom.roomId); + // The user left the pm room, let's also leave. + const members = await this.ircBridge.getAppServiceBridge().getBot().getJoinedMembers(pmRoom.roomId); + await Promise.all(Object.keys(members).map((u) => { + this.membershipQueue.leave(event.room_id, u, req); + })); + return null; + } + + } // ========== Client Parting ========== // for each room, if we're connected to it, leave the channel. diff --git a/src/datastore/DataStore.ts b/src/datastore/DataStore.ts index 5dcca2693..bc0bb20c5 100644 --- a/src/datastore/DataStore.ts +++ b/src/datastore/DataStore.ts @@ -124,6 +124,8 @@ export interface DataStore { getMatrixPmRoom(realUserId: string, virtualUserId: string): Promise; + getMatrixPmRoomById(roomId: string): Promise; + getTrackedChannelsForServer(domain: string): Promise; getRoomIdsFromConfig(): Promise; @@ -138,6 +140,8 @@ export interface DataStore { storeAdminRoom(room: MatrixRoom, userId: string): Promise; + removeAdminRoom(room: MatrixRoom): Promise; + upsertMatrixRoom(room: MatrixRoom): Promise; getAdminRoomByUserId(userId: string): Promise; diff --git a/src/datastore/NedbDataStore.ts b/src/datastore/NedbDataStore.ts index f83f083f7..3c4d07a09 100644 --- a/src/datastore/NedbDataStore.ts +++ b/src/datastore/NedbDataStore.ts @@ -384,6 +384,18 @@ export class NeDBDataStore implements DataStore { return entry.matrix || null; } + public async getMatrixPmRoomById(roomId: string) { + const entry = await this.roomStore.getEntriesByMatrixId(roomId); + if (!entry) { + return null; + } + if (entry.length > 1) { + log.warn(`More than one PM room assigned to Matrix room ${roomId}, returning first`); + } + return entry[0].matrix || null; + } + + public async getTrackedChannelsForServer(domain: string) { const entries: Entry[] = await this.roomStore.getEntriesByRemoteRoomData({ domain }); const channels = new Set(); @@ -480,6 +492,12 @@ export class NeDBDataStore implements DataStore { }); } + public async removeAdminRoom(room: MatrixRoom): Promise { + await this.roomStore.delete({ + matrix: room, + }); + } + public async upsertMatrixRoom(room: MatrixRoom): Promise { await this.roomStore.setMatrixRoom(room); } diff --git a/src/datastore/postgres/PgDataStore.ts b/src/datastore/postgres/PgDataStore.ts index 7a0e22210..e05dc3573 100644 --- a/src/datastore/postgres/PgDataStore.ts +++ b/src/datastore/postgres/PgDataStore.ts @@ -348,6 +348,18 @@ export class PgDataStore implements DataStore { return new MatrixRoom(res.rows[0].room_id); } + public async getMatrixPmRoomById(roomId: string): Promise { + log.debug(`getMatrixPmRoom (roomId=${roomId})`); + const res = await this.pgPool.query( + "SELECT room_id, matrix_user_id, virtual_user_id FROM pm_rooms WHERE room_id = $1", [ + roomId, + ]); + if (res.rowCount === 0) { + return null; + } + return new MatrixRoom(res.rows[0].room_id); + } + public async getTrackedChannelsForServer(domain: string): Promise { if (!this.serverMappings[domain]) { // Return empty if we don't know the server. @@ -410,6 +422,10 @@ export class PgDataStore implements DataStore { return new MatrixRoom(res.rows[0].room_id); } + public async removeAdminRoom(room: MatrixRoom): Promise { + await this.pgPool.query("DELETE FROM admin_rooms WHERE room_id = $1", [room.roomId]); + } + public async storeMatrixUser(matrixUser: MatrixUser): Promise { const parameters = { user_id: matrixUser.getId(), From 0b70b95b23a1fadecee1d1a636f0f4533efcd4f2 Mon Sep 17 00:00:00 2001 From: Will Hunt Date: Mon, 1 Mar 2021 14:13:25 +0000 Subject: [PATCH 2/2] changelog --- changelog.d/1258.misc | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/1258.misc diff --git a/changelog.d/1258.misc b/changelog.d/1258.misc new file mode 100644 index 000000000..0a1b01132 --- /dev/null +++ b/changelog.d/1258.misc @@ -0,0 +1 @@ +Leave DM rooms and admin rooms if the Matrix user leaves so that a homeserver may clear them up later. \ No newline at end of file