mirror of
https://github.com/matrix-org/mjolnir.git
synced 2024-10-01 01:36:06 -04:00
77ad40e27a
* Attempt to factor out protected rooms from Mjolnir. This is useful to the appservice because it means we don't have to wrap a Mjolnir that is designed to sync. It's also useful if we later on want to have specific settings per space. It's also just a nice seperation between Mjolnir's needs while syncing via client-server and the behaviour of syncing policy rooms. ### Things that have changed - `ErrorCache` no longer a static class (phew), gets used by `ProtectedRooms`. - `ManagementRoomOutput` class gets created to handle logging back to the management room. - Responsibilities for syncing member bans and server ACL are handled by `ProtectedRooms`. - Responsibilities for watched lists should be moved to `ProtectedRooms` if they haven't been. - `EventRedactionQueue` is moved to `ProtectedRooms` since this needs to happen after member bans. - ApplyServerAcls moved to `ProtectedRooms` - ApplyMemberBans move to `ProtectedRooms` - `logMessage` and `replaceRoomIdsWithPills` moved to `ManagementRoomOutput`. - `resyncJoinedRooms` has been made a little more clear, though I am concerned about how often it does run because it does seem expensive. * ProtectedRooms is not supposed to track joined rooms. The reason is because it is supposed to represent a specific set of rooms to protect, not do horrible logic for working out what rooms mjolnir is supposed to protect.
160 lines
6.5 KiB
TypeScript
160 lines
6.5 KiB
TypeScript
import { strict as assert } from "assert";
|
|
|
|
import { Mjolnir } from "../../src/Mjolnir";
|
|
import { IProtection } from "../../src/protections/IProtection";
|
|
import { newTestUser, noticeListener } from "./clientHelper";
|
|
import { matrixClient, mjolnir } from "./mjolnirSetupUtils";
|
|
import { ConsequenceBan, ConsequenceRedact } from "../../src/protections/consequence";
|
|
|
|
describe("Test: standard consequences", function() {
|
|
let badUser;
|
|
let goodUser;
|
|
this.beforeEach(async function () {
|
|
badUser = await newTestUser(this.config.homeserverUrl, { name: { contains: "standard-consequences" }});
|
|
goodUser = await newTestUser(this.config.homeserverUrl, { name: { contains: "standard-consequences" }});
|
|
await badUser.start();
|
|
await goodUser.start();
|
|
})
|
|
this.afterEach(async function () {
|
|
await badUser.stop();
|
|
await goodUser.stop();
|
|
})
|
|
it("Mjolnir applies a standard consequence redaction", async function() {
|
|
this.timeout(20000);
|
|
|
|
let protectedRoomId = await this.mjolnir.client.createRoom({ invite: [await badUser.getUserId()] });
|
|
await badUser.joinRoom(this.mjolnir.managementRoomId);
|
|
await badUser.joinRoom(protectedRoomId);
|
|
await this.mjolnir.addProtectedRoom(protectedRoomId);
|
|
|
|
await this.mjolnir.protectionManager.registerProtection(new class implements IProtection {
|
|
name = "JY2TPN";
|
|
description = "A test protection";
|
|
settings = { };
|
|
handleEvent = async (mjolnir: Mjolnir, roomId: string, event: any) => {
|
|
if (event.content.body === "ngmWkF") {
|
|
return [new ConsequenceRedact("asd")];
|
|
}
|
|
};
|
|
});
|
|
await this.mjolnir.protectionManager.enableProtection("JY2TPN");
|
|
|
|
let reply = new Promise(async (resolve, reject) => {
|
|
const messageId = await badUser.sendMessage(protectedRoomId, {msgtype: "m.text", body: "ngmWkF"});
|
|
let redaction;
|
|
badUser.on('room.event', (roomId, event) => {
|
|
if (
|
|
roomId === protectedRoomId
|
|
&& event?.type === "m.room.redaction"
|
|
&& event.redacts === messageId
|
|
) {
|
|
redaction = event
|
|
}
|
|
if (
|
|
roomId === this.mjolnir.managementRoomId
|
|
&& event?.type === "m.room.message"
|
|
&& event?.content?.body?.startsWith("protection JY2TPN enacting redact against ")
|
|
&& redaction !== undefined
|
|
) {
|
|
resolve([redaction, event])
|
|
}
|
|
});
|
|
});
|
|
|
|
const [eventRedact, eventMessage] = await reply
|
|
});
|
|
it("Mjolnir applies a standard consequence ban", async function() {
|
|
this.timeout(20000);
|
|
|
|
let protectedRoomId = await this.mjolnir.client.createRoom({ invite: [await badUser.getUserId()] });
|
|
await badUser.joinRoom(this.mjolnir.managementRoomId);
|
|
await badUser.joinRoom(protectedRoomId);
|
|
await this.mjolnir.addProtectedRoom(protectedRoomId);
|
|
|
|
await this.mjolnir.protectionManager.registerProtection(new class implements IProtection {
|
|
name = "0LxMTy";
|
|
description = "A test protection";
|
|
settings = { };
|
|
handleEvent = async (mjolnir: Mjolnir, roomId: string, event: any) => {
|
|
if (event.content.body === "7Uga3d") {
|
|
return [new ConsequenceBan("asd")];
|
|
}
|
|
};
|
|
});
|
|
await this.mjolnir.protectionManager.enableProtection("0LxMTy");
|
|
|
|
let reply = new Promise(async (resolve, reject) => {
|
|
const messageId = await badUser.sendMessage(protectedRoomId, {msgtype: "m.text", body: "7Uga3d"});
|
|
let ban;
|
|
badUser.on('room.leave', (roomId, event) => {
|
|
if (
|
|
roomId === protectedRoomId
|
|
&& event?.type === "m.room.member"
|
|
&& event.content?.membership === "ban"
|
|
&& event.state_key === badUser.userId
|
|
) {
|
|
ban = event;
|
|
}
|
|
});
|
|
badUser.on('room.event', (roomId, event) => {
|
|
if (
|
|
roomId === this.mjolnir.managementRoomId
|
|
&& event?.type === "m.room.message"
|
|
&& event?.content?.body?.startsWith("protection 0LxMTy enacting ban against ")
|
|
&& ban !== undefined
|
|
) {
|
|
resolve([ban, event])
|
|
}
|
|
});
|
|
});
|
|
|
|
const [eventBan, eventMessage] = await reply
|
|
});
|
|
it("Mjolnir doesn't ban a good user", async function() {
|
|
this.timeout(20000);
|
|
|
|
let protectedRoomId = await this.mjolnir.client.createRoom({ invite: [await goodUser.getUserId(), await badUser.getUserId()] });
|
|
await badUser.joinRoom(protectedRoomId);
|
|
await goodUser.joinRoom(protectedRoomId);
|
|
await this.mjolnir.addProtectedRoom(protectedRoomId);
|
|
|
|
await this.mjolnir.protectionManager.registerProtection(new class implements IProtection {
|
|
name = "95B1Cr";
|
|
description = "A test protection";
|
|
settings = { };
|
|
handleEvent = async (mjolnir: Mjolnir, roomId: string, event: any) => {
|
|
if (event.content.body === "8HUnwb") {
|
|
return [new ConsequenceBan("asd")];
|
|
}
|
|
};
|
|
});
|
|
await this.mjolnir.protectionManager.enableProtection("95B1Cr");
|
|
|
|
let reply = new Promise(async (resolve, reject) => {
|
|
this.mjolnir.client.on('room.message', async (roomId, event) => {
|
|
if (event?.content?.body === "SUwvFT") {
|
|
await badUser.sendMessage(protectedRoomId, {msgtype: "m.text", body: "8HUnwb"});
|
|
}
|
|
});
|
|
|
|
this.mjolnir.client.on('room.event', (roomId, event) => {
|
|
if (
|
|
roomId === protectedRoomId
|
|
&& event?.type === "m.room.member"
|
|
&& event.content?.membership === "ban"
|
|
) {
|
|
if (event.state_key === goodUser.userId) {
|
|
reject("good user has been banned");
|
|
} else if (event.state_key === badUser.userId) {
|
|
resolve(null);
|
|
}
|
|
}
|
|
});
|
|
});
|
|
await goodUser.sendMessage(protectedRoomId, {msgtype: "m.text", body: "SUwvFT"});
|
|
|
|
await reply
|
|
});
|
|
});
|
|
|