Allow setting a allowList for rooms

- prevents from joining & showing not allowed rooms if enabled
- prevents from listing such rooms in room directory as well (with bad UX for now)
This commit is contained in:
felix.stupp@banananet.work 2023-07-27 17:08:50 +00:00
parent f91b8f07f3
commit c6c22a78f3
No known key found for this signature in database
GPG Key ID: 93E1BD26F6B02FB7
5 changed files with 91 additions and 0 deletions

View File

@ -21,4 +21,9 @@
// Secrets
//"matrixAccessToken": "xxx"
// Restrict to rooms listed below
//"enableAllowList": true,
// use room ids starting with a `!`, not aliases
//"roomAllowList": ["!ypQyNeReyEPUCKYjPU:matrix.org"], // e.g. room about Matrix Reputation
}

View File

@ -0,0 +1,27 @@
'use strict';
const assert = require('assert');
const fetchRoomId = require('./fetch-room-id');
const config = require('../config');
const basePath = config.get('basePath');
assert(basePath);
const matrixServerUrl = config.get('matrixServerUrl');
assert(matrixServerUrl);
config.defaults({
"enableAllowList": false,
"roomAllowList": [],
});
async function checkIfAllowed(roomIdOrAlias) {
if (!config.get("enableAllowList")) {
return true;
}
const roomId = await fetchRoomId(roomIdOrAlias);
const result = config.get("roomAllowList").includes(roomId)
return result;
}
module.exports = checkIfAllowed;

View File

@ -5,6 +5,7 @@ const urlJoin = require('url-join');
const StatusError = require('../errors/status-error');
const { fetchEndpointAsJson } = require('../fetch-endpoint');
const checkIfAllowed = require('./check-room-allowed');
const getServerNameFromMatrixRoomIdOrAlias = require('./get-server-name-from-matrix-room-id-or-alias');
const MatrixViewerURLCreator = require('matrix-viewer-shared/lib/url-creator');
@ -21,6 +22,11 @@ async function ensureRoomJoined(
roomIdOrAlias,
{ viaServers = new Set(), abortSignal } = {}
) {
const result = await checkIfAllowed(roomIdOrAlias);
if (!result) {
throw new StatusError(403, `Bot is not allowed to view room, room is not listed in explicit allow list.`);
}
// We use a `Set` to ensure that we don't have duplicate servers in the list
assert(viaServers instanceof Set);

View File

@ -0,0 +1,45 @@
'use strict';
const assert = require('assert');
const urlJoin = require('url-join');
const StatusError = require('../errors/status-error');
const { fetchEndpointAsJson } = require('../fetch-endpoint');
const config = require('../config');
const basePath = config.get('basePath');
assert(basePath);
const matrixServerUrl = config.get('matrixServerUrl');
assert(matrixServerUrl);
config.defaults({
"enableAllowlist": false,
"roomAllowlist": [],
});
async function fetchRoomId(
roomIdOrAlias,
) {
if (roomIdOrAlias.startsWith("!")) {
return roomIdOrAlias;
}
const resolveEndpoint = urlJoin(
matrixServerUrl,
`_matrix/client/v3/directory/room/${encodeURIComponent(roomIdOrAlias)}`
);
try {
const { data: roomData } = await fetchEndpointAsJson(resolveEndpoint, {
method: 'GET',
});
assert(
roomData.room_id,
`Alias resolve endpoint (${resolveEndpoint}) did not return \`room_id\` as expected. This is probably a problem with that homeserver.`
);
return roomData.room_id;
} catch (err) {
throw new StatusError(403, `Bot is unable to resolve alias of room: ${err.message}`);
}
}
module.exports = fetchRoomId;

View File

@ -10,6 +10,7 @@ const { DIRECTION } = require('matrix-viewer-shared/lib/reference-values');
const RouteTimeoutAbortError = require('../lib/errors/route-timeout-abort-error');
const UserClosedConnectionAbortError = require('../lib/errors/user-closed-connection-abort-error');
const identifyRoute = require('../middleware/identify-route-middleware');
const checkIfAllowed = require('../lib/matrix-utils/check-room-allowed');
const fetchAccessibleRooms = require('../lib/matrix-utils/fetch-accessible-rooms');
const renderHydrogenVmRenderScriptToPageHtml = require('../hydrogen-render/render-hydrogen-vm-render-script-to-page-html');
const setHeadersToPreloadAssets = require('../lib/set-headers-to-preload-assets');
@ -81,6 +82,13 @@ router.get(
}
}
// limit to allow list
// Because filtering happens after checking the directory this may lead into a bad UX.
if (config.get("enableAllowList")) {
const checkResults = await Promise.all(rooms.map((r) => r.room_id).map(checkIfAllowed));
rooms = rooms.filter((_v, index) => checkResults[index]);
}
// We index the room directory unless the config says we shouldn't index anything
const stopSearchEngineIndexingFromConfig = config.get('stopSearchEngineIndexing');
const shouldIndex = !stopSearchEngineIndexingFromConfig;