mjolnir/test/integration/protectionSettingsTest.ts
Gnuxie 77ad40e27a
Refactor protected rooms. (#371)
* 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.
2022-09-29 14:49:09 +01:00

162 lines
6.8 KiB
TypeScript

import { strict as assert } from "assert";
import { Mjolnir } from "../../src/Mjolnir";
import { IProtection } from "../../src/protections/IProtection";
import { ProtectionSettingValidationError } from "../../src/protections/ProtectionSettings";
import { NumberProtectionSetting, StringProtectionSetting, StringListProtectionSetting } from "../../src/protections/ProtectionSettings";
import { newTestUser, noticeListener } from "./clientHelper";
import { matrixClient, mjolnir } from "./mjolnirSetupUtils";
describe("Test: Protection settings", function() {
let client;
this.beforeEach(async function () {
client = await newTestUser(this.config.homeserverUrl, { name: { contains: "protection-settings" }});
await client.start();
})
this.afterEach(async function () {
await client.stop();
})
it("Mjolnir refuses to save invalid protection setting values", async function() {
this.timeout(20000);
await assert.rejects(
async () => await this.mjolnir.protectionManager.setProtectionSettings("BasicFloodingProtection", {"maxPerMinute": "soup"}),
ProtectionSettingValidationError
);
});
it("Mjolnir successfully saves valid protection setting values", async function() {
this.timeout(20000);
await this.mjolnir.protectionManager.registerProtection(new class implements IProtection {
name = "05OVMS";
description = "A test protection";
settings = { test: new NumberProtectionSetting(3) };
});
await this.mjolnir.protectionManager.setProtectionSettings("05OVMS", { test: 123 });
assert.equal(
(await this.mjolnir.protectionManager.getProtectionSettings("05OVMS"))["test"],
123
);
});
it("Mjolnir should accumulate changed settings", async function() {
this.timeout(20000);
await this.mjolnir.protectionManager.registerProtection(new class implements IProtection {
name = "HPUjKN";
settings = {
test1: new NumberProtectionSetting(3),
test2: new NumberProtectionSetting(4)
};
});
await this.mjolnir.protectionManager.setProtectionSettings("HPUjKN", { test1: 1 });
await this.mjolnir.protectionManager.setProtectionSettings("HPUjKN", { test2: 2 });
const settings = await this.mjolnir.protectionManager.getProtectionSettings("HPUjKN");
assert.equal(settings["test1"], 1);
assert.equal(settings["test2"], 2);
});
it("Mjolnir responds to !set correctly", async function() {
this.timeout(20000);
await client.joinRoom(this.config.managementRoom);
await this.mjolnir.protectionManager.registerProtection(new class implements IProtection {
name = "JY2TPN";
description = "A test protection";
settings = { test: new StringProtectionSetting() };
});
let reply = new Promise((resolve, reject) => {
client.on('room.message', noticeListener(this.mjolnir.managementRoomId, (event) => {
if (event.content.body.includes("Changed JY2TPN.test ")) {
resolve(event);
}
}))
});
await client.sendMessage(this.mjolnir.managementRoomId, {msgtype: "m.text", body: "!mjolnir config set JY2TPN.test asd"})
await reply
const settings = await this.mjolnir.protectionManager.getProtectionSettings("JY2TPN");
assert.equal(settings["test"], "asd");
});
it("Mjolnir adds a value to a list setting", async function() {
this.timeout(20000);
await client.joinRoom(this.config.managementRoom);
await this.mjolnir.protectionManager.registerProtection(new class implements IProtection {
name = "r33XyT";
description = "A test protection";
settings = { test: new StringListProtectionSetting() };
});
let reply = new Promise((resolve, reject) => {
client.on('room.message', noticeListener(this.mjolnir.managementRoomId, (event) => {
if (event.content.body.includes("Changed r33XyT.test ")) {
resolve(event);
}
}))
});
await client.sendMessage(this.mjolnir.managementRoomId, {msgtype: "m.text", body: "!mjolnir config add r33XyT.test asd"})
await reply
assert.deepEqual(await this.mjolnir.protectionManager.getProtectionSettings("r33XyT"), { "test": ["asd"] });
});
it("Mjolnir removes a value from a list setting", async function() {
this.timeout(20000);
await client.joinRoom(this.config.managementRoom);
await this.mjolnir.protectionManager.registerProtection(new class implements IProtection {
name = "oXzT0E";
description = "A test protection";
settings = { test: new StringListProtectionSetting() };
});
let reply = () => new Promise((resolve, reject) => {
client.on('room.message', noticeListener(this.mjolnir.managementRoomId, (event) => {
if (event.content.body.includes("Changed oXzT0E.test ")) {
resolve(event);
}
}))
});
await client.sendMessage(this.mjolnir.managementRoomId, {msgtype: "m.text", body: "!mjolnir config add oXzT0E.test asd"})
await reply();
await client.sendMessage(this.mjolnir.managementRoomId, {msgtype: "m.text", body: "!mjolnir config remove oXzT0E.test asd"})
await reply();
assert.deepEqual(await this.mjolnir.protectionManager.getProtectionSettings("oXzT0E"), { "test": [] });
});
it("Mjolnir will change a protection setting in-place", async function() {
this.timeout(20000);
await client.joinRoom(this.config.managementRoom);
await this.mjolnir.protectionManager.registerProtection(new class implements IProtection {
name = "d0sNrt";
description = "A test protection";
settings = { test: new StringProtectionSetting() };
});
let replyPromise = new Promise((resolve, reject) => {
let i = 0;
client.on('room.message', noticeListener(this.mjolnir.managementRoomId, (event) => {
if (event.content.body.includes("Changed d0sNrt.test ")) {
if (++i == 2) {
resolve(event);
}
}
}))
});
await client.sendMessage(this.mjolnir.managementRoomId, {msgtype: "m.text", body: "!mjolnir config set d0sNrt.test asd1"})
await client.sendMessage(this.mjolnir.managementRoomId, {msgtype: "m.text", body: "!mjolnir config set d0sNrt.test asd2"})
assert.equal(
(await replyPromise).content.body.split("\n", 3)[2],
"Changed d0sNrt.test to asd2 (was asd1)"
)
});
});