mirror of
https://github.com/the-draupnir-project/Draupnir.git
synced 2026-05-13 02:54:48 +00:00
d73d0fc4c2
Cat ran into this funny leftover when validating if abuse reporting still works after Cats reworks in mdad. Turns out they do and as it was my first time using these flows Cat discovered this.
296 lines
9.7 KiB
TypeScript
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(
|
|
"Draupnir 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(
|
|
"Draupnir 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);
|
|
});
|