mirror of
https://github.com/matrix-org/mjolnir.git
synced 2024-06-28 23:52:06 +00:00
Merge branch 'main' into gnuxie/config-bye-bye
This commit is contained in:
commit
b63eb9ecfb
|
@ -103,6 +103,15 @@ export class Mjolnir {
|
||||||
private webapis: WebAPIs;
|
private webapis: WebAPIs;
|
||||||
private protectedRoomActivityTracker: ProtectedRoomActivityTracker;
|
private protectedRoomActivityTracker: ProtectedRoomActivityTracker;
|
||||||
public taskQueue: ThrottlingQueue;
|
public taskQueue: ThrottlingQueue;
|
||||||
|
/**
|
||||||
|
* Used to provide mutual exclusion when synchronizing rooms with the state of a policy list.
|
||||||
|
* This is because requests operating with rules from an older version of the list that are slow
|
||||||
|
* could race & give the room an inconsistent state. An example is if we add multiple m.policy.rule.server rules,
|
||||||
|
* which would cause several requests to a room to send a new m.room.server_acl event.
|
||||||
|
* These requests could finish in any order, which has left rooms with an inconsistent server_acl event
|
||||||
|
* until Mjolnir synchronises the room with its policy lists again, which can be in the region of hours.
|
||||||
|
*/
|
||||||
|
public aclChain: Promise<void> = Promise.resolve();
|
||||||
/*
|
/*
|
||||||
* Config-enabled polling of reports in Synapse, so Mjolnir can react to reports
|
* Config-enabled polling of reports in Synapse, so Mjolnir can react to reports
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -30,6 +30,16 @@ import { ERROR_KIND_FATAL, ERROR_KIND_PERMISSION } from "../ErrorCache";
|
||||||
* @param {Mjolnir} mjolnir The Mjolnir client to apply the ACLs with.
|
* @param {Mjolnir} mjolnir The Mjolnir client to apply the ACLs with.
|
||||||
*/
|
*/
|
||||||
export async function applyServerAcls(lists: PolicyList[], roomIds: string[], mjolnir: Mjolnir): Promise<RoomUpdateError[]> {
|
export async function applyServerAcls(lists: PolicyList[], roomIds: string[], mjolnir: Mjolnir): Promise<RoomUpdateError[]> {
|
||||||
|
// we need to provide mutual exclusion so that we do not have requests updating the m.room.server_acl event
|
||||||
|
// finish out of order and therefore leave the room out of sync with the policy lists.
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
mjolnir.aclChain = mjolnir.aclChain
|
||||||
|
.then(() => _applyServerAcls(lists, roomIds, mjolnir))
|
||||||
|
.then(resolve, reject);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function _applyServerAcls(lists: PolicyList[], roomIds: string[], mjolnir: Mjolnir): Promise<RoomUpdateError[]> {
|
||||||
const serverName: string = new UserID(await mjolnir.client.getUserId()).domain;
|
const serverName: string = new UserID(await mjolnir.client.getUserId()).domain;
|
||||||
|
|
||||||
// Construct a server ACL first
|
// Construct a server ACL first
|
||||||
|
|
|
@ -260,20 +260,23 @@ describe('Test: ACL updates will batch when rules are added in succession.', fun
|
||||||
mjolnir.client.joinRoom(banListId);
|
mjolnir.client.joinRoom(banListId);
|
||||||
mjolnir.watchList(Permalinks.forRoom(banListId));
|
mjolnir.watchList(Permalinks.forRoom(banListId));
|
||||||
const acl = new ServerAcl(serverName).denyIpAddresses().allowServer("*");
|
const acl = new ServerAcl(serverName).denyIpAddresses().allowServer("*");
|
||||||
for (let i = 0; i < 200; i++) {
|
const evilServerCount = 200;
|
||||||
|
for (let i = 0; i < evilServerCount; i++) {
|
||||||
const badServer = `${i}.evil.com`;
|
const badServer = `${i}.evil.com`;
|
||||||
acl.denyServer(badServer);
|
acl.denyServer(badServer);
|
||||||
await createPolicyRule(moderator, banListId, RULE_SERVER, badServer, `Rule #${i}`);
|
await createPolicyRule(moderator, banListId, RULE_SERVER, badServer, `Rule #${i}`);
|
||||||
// Give them a bit of a spread over time.
|
// Give them a bit of a spread over time.
|
||||||
await new Promise(resolve => setTimeout(resolve, 5));
|
await new Promise(resolve => setTimeout(resolve, 5));
|
||||||
}
|
}
|
||||||
// give the events a chance to appear in the response to `/state`, since this is a problem.
|
|
||||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
||||||
|
|
||||||
// We do this because it should force us to wait until all the ACL events have been applied.
|
// We do this because it should force us to wait until all the ACL events have been applied.
|
||||||
// Even if that does mean the last few events will not go through batching...
|
// Even if that does mean the last few events will not go through batching...
|
||||||
await mjolnir.syncLists();
|
await mjolnir.syncLists();
|
||||||
|
|
||||||
|
// At this point we check that the state within Mjolnir is internally consistent, this is just because debugging the following
|
||||||
|
// is a pita.
|
||||||
|
const list: PolicyList = this.mjolnir.policyLists[0]!;
|
||||||
|
assert.equal(list.serverRules.length, evilServerCount, `There should be ${evilServerCount} rules in here`);
|
||||||
|
|
||||||
// Check each of the protected rooms for ACL events and make sure they were batched and are correct.
|
// Check each of the protected rooms for ACL events and make sure they were batched and are correct.
|
||||||
await Promise.all(protectedRooms.map(async room => {
|
await Promise.all(protectedRooms.map(async room => {
|
||||||
const roomAcl = await mjolnir.client.getRoomStateEvent(room, "m.room.server_acl", "");
|
const roomAcl = await mjolnir.client.getRoomStateEvent(room, "m.room.server_acl", "");
|
||||||
|
|
Loading…
Reference in New Issue
Block a user