Files
Draupnir/test/integration/commands/redactCommandTest.ts
Gnuxie 337a6a3b76 Add reuse.software (#486)
We have a lot of verbose headers, and i think now is the best opportunity we have to become reuse compliant given that we just did two other similar maintenance changes (prettier, typescirpt5 & eslint9 & typescript-eslint).

* synapse_antispam resuse headers.

* delete old unused tslint.json.

* Add REUSE to pre-commit config.

* reuse info for config directory.
2024-07-25 10:58:40 +01:00

296 lines
9.7 KiB
TypeScript

// Copyright 2022 - 2024 Gnuxie <Gnuxie@protonmail.com>
// Copyright 2021 The Matrix.org Foundation C.I.C.
//
// SPDX-License-Identifier: AFL-3.0 AND Apache-2.0
//
// SPDX-FileAttributionText: <text>
// This modified file incorporates work from mjolnir
// https://github.com/matrix-org/mjolnir
// </text>
import { strict as assert } from "assert";
import { newTestUser } from "../clientHelper";
import { getMessagesByUserIn } from "../../../src/utils";
import { LogService } from "matrix-bot-sdk";
import { getFirstReaction } from "./commandUtils";
import {
draupnirClient,
draupnirSafeEmitter,
DraupnirTestContext,
} from "../mjolnirSetupUtils";
import { MatrixClient } from "matrix-bot-sdk";
interface RedactionTestContext extends DraupnirTestContext {
moderator?: MatrixClient;
}
describe("Test: The redaction command", function () {
// If a test has a timeout while awaitng on a promise then we never get given control back.
afterEach(function () {
this.moderator?.stop();
});
it(
"Mjölnir redacts all of the events sent by a spammer when instructed to by giving their id and a room id.",
async function (this: RedactionTestContext) {
this.timeout(60000);
// Create a few users and a room.
const badUser = await newTestUser(this.config.homeserverUrl, {
name: { contains: "spammer-needs-redacting" },
});
const badUserId = await badUser.getUserId();
const draupnirMatrixClient = draupnirClient();
const draupnir = this.draupnir;
if (draupnirMatrixClient === null || draupnir === undefined) {
throw new TypeError(`Test isn't setup correctly`);
}
const mjolnirUserId = await draupnirMatrixClient.getUserId();
const moderator = await newTestUser(this.config.homeserverUrl, {
name: { contains: "moderator" },
});
this.moderator = moderator;
await moderator.joinRoom(this.config.managementRoom);
const targetRoom = await moderator.createRoom({
invite: [await badUser.getUserId(), mjolnirUserId],
});
await moderator.setUserPowerLevel(mjolnirUserId, targetRoom, 100);
await badUser.joinRoom(targetRoom);
await getFirstReaction(
draupnirSafeEmitter(),
draupnir.managementRoomID,
"✅",
async () => {
return moderator.sendMessage(draupnir.managementRoomID, {
msgtype: "m.text",
body: `!draupnir rooms add ${targetRoom}`,
});
}
);
LogService.debug(
"redactionTest",
`targetRoom: ${targetRoom}, managementRoom: ${this.config.managementRoom}`
);
// Sandwich irrelevant messages in bad messages.
await badUser.sendMessage(targetRoom, {
msgtype: "m.text",
body: "Very Bad Stuff",
});
await Promise.all(
[...Array(50).keys()].map((i) =>
moderator.sendMessage(targetRoom, {
msgtype: "m.text",
body: `Irrelevant Message #${i}`,
})
)
);
for (let i = 0; i < 5; i++) {
await badUser.sendMessage(targetRoom, {
msgtype: "m.text",
body: "Very Bad Stuff",
});
}
await Promise.all(
[...Array(50).keys()].map((i) =>
moderator.sendMessage(targetRoom, {
msgtype: "m.text",
body: `Irrelevant Message #${i}`,
})
)
);
await badUser.sendMessage(targetRoom, {
msgtype: "m.text",
body: "Very Bad Stuff",
});
await getFirstReaction(
draupnirSafeEmitter(),
draupnir.managementRoomID,
"✅",
async () => {
return await moderator.sendMessage(draupnir.managementRoomID, {
msgtype: "m.text",
body: `!draupnir redact ${badUserId} --room ${targetRoom}`,
});
}
);
await getMessagesByUserIn(
moderator,
badUserId,
targetRoom,
1000,
function (events) {
events.map((e) => {
if (e.type === "m.room.member") {
assert.equal(
Object.keys(e.content).length,
1,
"Only membership should be left on the membership even when it has been redacted."
);
} else if (Object.keys(e.content).length !== 0) {
throw new Error(
`This event should have been redacted: ${JSON.stringify(e, null, 2)}`
);
}
});
}
);
} as unknown as Mocha.AsyncFunc
);
it(
"Mjölnir redacts all of the events sent by a spammer when instructed to by giving their id in multiple rooms.",
async function (this: RedactionTestContext) {
this.timeout(60000);
// Create a few users and a room.
const badUser = await newTestUser(this.config.homeserverUrl, {
name: { contains: "spammer-needs-redacting" },
});
const badUserId = await badUser.getUserId();
const draupnir = this.draupnir;
if (draupnir === undefined) {
throw new TypeError(`Test isn't setup correctly`);
}
const mjolnirUserId = await draupnir.client.getUserId();
const moderator = await newTestUser(this.config.homeserverUrl, {
name: { contains: "moderator" },
});
this.moderator = moderator;
await moderator.joinRoom(this.config.managementRoom);
const targetRooms: string[] = [];
for (let i = 0; i < 5; i++) {
const targetRoom = await moderator.createRoom({
invite: [await badUser.getUserId(), mjolnirUserId],
});
await moderator.setUserPowerLevel(mjolnirUserId, targetRoom, 100);
await badUser.joinRoom(targetRoom);
await moderator.sendMessage(draupnir.managementRoomID, {
msgtype: "m.text",
body: `!draupnir rooms add ${targetRoom}`,
});
targetRooms.push(targetRoom);
// Sandwich irrelevant messages in bad messages.
await badUser.sendMessage(targetRoom, {
msgtype: "m.text",
body: "Very Bad Stuff",
});
await Promise.all(
[...Array(50).keys()].map((j) =>
moderator.sendMessage(targetRoom, {
msgtype: "m.text",
body: `Irrelevant Message #${j}`,
})
)
);
for (let j = 0; j < 5; j++) {
await badUser.sendMessage(targetRoom, {
msgtype: "m.text",
body: "Very Bad Stuff",
});
}
await Promise.all(
[...Array(50).keys()].map((j) =>
moderator.sendMessage(targetRoom, {
msgtype: "m.text",
body: `Irrelevant Message #${j}`,
})
)
);
await badUser.sendMessage(targetRoom, {
msgtype: "m.text",
body: "Very Bad Stuff",
});
}
await getFirstReaction(
draupnirSafeEmitter(),
draupnir.managementRoomID,
"✅",
async () => {
return await moderator.sendMessage(draupnir.managementRoomID, {
msgtype: "m.text",
body: `!draupnir redact ${badUserId}`,
});
}
);
await Promise.all(
targetRooms.map(async (targetRoom) => {
await getMessagesByUserIn(
moderator,
badUserId,
targetRoom,
1000,
function (events) {
events.map((e) => {
if (e.type === "m.room.member") {
assert.equal(
Object.keys(e.content).length,
1,
"Only membership should be left on the membership even when it has been redacted."
);
} else if (Object.keys(e.content).length !== 0) {
throw new Error(
`This event should have been redacted: ${JSON.stringify(e, null, 2)}`
);
}
});
}
);
})
);
} as unknown as Mocha.AsyncFunc
);
it("Redacts a single event when instructed to.", async function (
this: RedactionTestContext
) {
this.timeout(60000);
// Create a few users and a room.
const badUser = await newTestUser(this.config.homeserverUrl, {
name: { contains: "spammer-needs-redacting" },
});
const draupnir = this.draupnir;
if (draupnir === undefined) {
throw new TypeError(`Test isn't setup correctly`);
}
const moderator = await newTestUser(this.config.homeserverUrl, {
name: { contains: "moderator" },
});
this.moderator = moderator;
await moderator.joinRoom(this.config.managementRoom);
const targetRoom = await moderator.createRoom({
invite: [await badUser.getUserId(), draupnir.clientUserID],
});
await moderator.setUserPowerLevel(draupnir.clientUserID, targetRoom, 100);
await badUser.joinRoom(targetRoom);
await moderator.sendMessage(draupnir.managementRoomID, {
msgtype: "m.text",
body: `!draupnir rooms add ${targetRoom}`,
});
const eventToRedact = await badUser.sendMessage(targetRoom, {
msgtype: "m.text",
body: "Very Bad Stuff",
});
await getFirstReaction(
draupnirSafeEmitter(),
draupnir.managementRoomID,
"✅",
async () => {
return await moderator.sendMessage(draupnir.managementRoomID, {
msgtype: "m.text",
body: `!draupnir redact https://matrix.to/#/${encodeURIComponent(targetRoom)}/${encodeURIComponent(eventToRedact)}`,
});
}
);
const redactedEvent = await moderator.getEvent(targetRoom, eventToRedact);
assert.equal(
Object.keys(redactedEvent.content).length,
0,
"This event should have been redacted"
);
} as unknown as Mocha.AsyncFunc);
});