mirror of
https://github.com/matrix-org/mjolnir.git
synced 2024-10-01 01:36:06 -04:00
Merge branch 'main' into gnuxie/rule-limit
This commit is contained in:
commit
49ae58d27d
@ -39,6 +39,7 @@ export class ProtectedRoomActivityTracker {
|
|||||||
*/
|
*/
|
||||||
public addProtectedRoom(roomId: string): void {
|
public addProtectedRoom(roomId: string): void {
|
||||||
this.protectedRoomActivities.set(roomId, /* epoch */ 0);
|
this.protectedRoomActivities.set(roomId, /* epoch */ 0);
|
||||||
|
this.activeRoomsCache = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -47,6 +48,7 @@ export class ProtectedRoomActivityTracker {
|
|||||||
*/
|
*/
|
||||||
public removeProtectedRoom(roomId: string): void {
|
public removeProtectedRoom(roomId: string): void {
|
||||||
this.protectedRoomActivities.delete(roomId);
|
this.protectedRoomActivities.delete(roomId);
|
||||||
|
this.activeRoomsCache = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -68,7 +68,11 @@ export class ReportPoller {
|
|||||||
response_ = await this.mjolnir.client.doRequest(
|
response_ = await this.mjolnir.client.doRequest(
|
||||||
"GET",
|
"GET",
|
||||||
"/_synapse/admin/v1/event_reports",
|
"/_synapse/admin/v1/event_reports",
|
||||||
{ from: this.from.toString() }
|
{
|
||||||
|
// short for direction: forward; i.e. show newest last
|
||||||
|
dir: "f",
|
||||||
|
from: this.from.toString()
|
||||||
|
}
|
||||||
);
|
);
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
await this.mjolnir.logMessage(LogLevel.ERROR, "getAbuseReports", `failed to poll events: ${ex}`);
|
await this.mjolnir.logMessage(LogLevel.ERROR, "getAbuseReports", `failed to poll events: ${ex}`);
|
||||||
|
@ -141,7 +141,6 @@ describe("Test: Updating the PolicyList", function() {
|
|||||||
assert.equal(banList.userRules.filter(rule => rule.entity === entity).length, 0, 'The rule should no longer be stored.');
|
assert.equal(banList.userRules.filter(rule => rule.entity === entity).length, 0, 'The rule should no longer be stored.');
|
||||||
})
|
})
|
||||||
it("A rule of the most recent type won't be deleted when an old rule is deleted for the same entity.", async function() {
|
it("A rule of the most recent type won't be deleted when an old rule is deleted for the same entity.", async function() {
|
||||||
this.timeout(3000);
|
|
||||||
const mjolnir: Mjolnir = this.mjolnir!
|
const mjolnir: Mjolnir = this.mjolnir!
|
||||||
const moderator = await newTestUser({ name: { contains: "moderator" } });
|
const moderator = await newTestUser({ name: { contains: "moderator" } });
|
||||||
const banListId = await mjolnir.client.createRoom({ invite: [await moderator.getUserId()] });
|
const banListId = await mjolnir.client.createRoom({ invite: [await moderator.getUserId()] });
|
||||||
@ -239,7 +238,7 @@ describe('Test: ACL updates will batch when rules are added in succession.', fun
|
|||||||
|
|
||||||
// Setup some protected rooms so we can check their ACL state later.
|
// Setup some protected rooms so we can check their ACL state later.
|
||||||
const protectedRooms: string[] = [];
|
const protectedRooms: string[] = [];
|
||||||
for (let i = 0; i < 10; i++) {
|
for (let i = 0; i < 5; i++) {
|
||||||
const room = await moderator.createRoom({ invite: [mjolnirId] });
|
const room = await moderator.createRoom({ invite: [mjolnirId] });
|
||||||
await mjolnir.client.joinRoom(room);
|
await mjolnir.client.joinRoom(room);
|
||||||
await moderator.setUserPowerLevel(mjolnirId, room, 100);
|
await moderator.setUserPowerLevel(mjolnirId, room, 100);
|
||||||
@ -299,12 +298,11 @@ describe('Test: ACL updates will batch when rules are added in succession.', fun
|
|||||||
describe('Test: unbaning entities via the PolicyList.', function() {
|
describe('Test: unbaning entities via the PolicyList.', function() {
|
||||||
afterEach(function() { this.moderator?.stop(); });
|
afterEach(function() { this.moderator?.stop(); });
|
||||||
it('Will remove rules that have legacy types', async function() {
|
it('Will remove rules that have legacy types', async function() {
|
||||||
this.timeout(20000)
|
|
||||||
const mjolnir: Mjolnir = this.mjolnir!
|
const mjolnir: Mjolnir = this.mjolnir!
|
||||||
const serverName: string = new UserID(await mjolnir.client.getUserId()).domain
|
const serverName: string = new UserID(await mjolnir.client.getUserId()).domain
|
||||||
const moderator = await newTestUser({ name: { contains: "moderator" } });
|
const moderator = await newTestUser({ name: { contains: "moderator" } });
|
||||||
this.moderator = moderator;
|
this.moderator = moderator;
|
||||||
moderator.joinRoom(mjolnir.managementRoomId);
|
await moderator.joinRoom(mjolnir.managementRoomId);
|
||||||
const mjolnirId = await mjolnir.client.getUserId();
|
const mjolnirId = await mjolnir.client.getUserId();
|
||||||
|
|
||||||
// We'll make 1 protected room to test ACLs in.
|
// We'll make 1 protected room to test ACLs in.
|
||||||
@ -315,6 +313,7 @@ describe('Test: unbaning entities via the PolicyList.', function() {
|
|||||||
|
|
||||||
// If a previous test hasn't cleaned up properly, these rooms will be populated by bogus ACLs at this point.
|
// If a previous test hasn't cleaned up properly, these rooms will be populated by bogus ACLs at this point.
|
||||||
await mjolnir.syncLists();
|
await mjolnir.syncLists();
|
||||||
|
// If this is not present, then it means the room isn't being protected, which is really bad.
|
||||||
const roomAcl = await mjolnir.client.getRoomStateEvent(protectedRoom, "m.room.server_acl", "");
|
const roomAcl = await mjolnir.client.getRoomStateEvent(protectedRoom, "m.room.server_acl", "");
|
||||||
assert.equal(roomAcl?.deny?.length ?? 0, 0, 'There should be no entries in the deny ACL.');
|
assert.equal(roomAcl?.deny?.length ?? 0, 0, 'There should be no entries in the deny ACL.');
|
||||||
|
|
||||||
@ -323,7 +322,7 @@ describe('Test: unbaning entities via the PolicyList.', function() {
|
|||||||
await moderator.setUserPowerLevel(await mjolnir.client.getUserId(), banListId, 100);
|
await moderator.setUserPowerLevel(await mjolnir.client.getUserId(), banListId, 100);
|
||||||
await moderator.sendStateEvent(banListId, 'org.matrix.mjolnir.shortcode', '', { shortcode: "unban-test" });
|
await moderator.sendStateEvent(banListId, 'org.matrix.mjolnir.shortcode', '', { shortcode: "unban-test" });
|
||||||
await mjolnir.client.joinRoom(banListId);
|
await mjolnir.client.joinRoom(banListId);
|
||||||
this.mjolnir!.watchList(Permalinks.forRoom(banListId));
|
await mjolnir.watchList(Permalinks.forRoom(banListId));
|
||||||
// we use this to compare changes.
|
// we use this to compare changes.
|
||||||
const banList = new PolicyList(banListId, banListId, moderator);
|
const banList = new PolicyList(banListId, banListId, moderator);
|
||||||
// we need two because we need to test the case where an entity has all rule types in the list
|
// we need two because we need to test the case where an entity has all rule types in the list
|
||||||
@ -351,8 +350,8 @@ describe('Test: unbaning entities via the PolicyList.', function() {
|
|||||||
try {
|
try {
|
||||||
await moderator.start();
|
await moderator.start();
|
||||||
for (const server of [olderBadServer, newerBadServer]) {
|
for (const server of [olderBadServer, newerBadServer]) {
|
||||||
await getFirstReaction(moderator, this.mjolnir.managementRoomId, '✅', async () => {
|
await getFirstReaction(moderator, mjolnir.managementRoomId, '✅', async () => {
|
||||||
return await moderator.sendMessage(this.mjolnir.managementRoomId, { msgtype: 'm.text', body: `!mjolnir unban unban-test server ${server}` });
|
return await moderator.sendMessage(mjolnir.managementRoomId, { msgtype: 'm.text', body: `!mjolnir unban unban-test server ${server}` });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
@ -360,7 +359,7 @@ describe('Test: unbaning entities via the PolicyList.', function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Wait for mjolnir to sync protected rooms to update ACL.
|
// Wait for mjolnir to sync protected rooms to update ACL.
|
||||||
await this.mjolnir!.syncLists();
|
await mjolnir.syncLists();
|
||||||
// Confirm that the server is unbanned.
|
// Confirm that the server is unbanned.
|
||||||
await banList.updateList();
|
await banList.updateList();
|
||||||
assert.equal(banList.allRules.length, 0);
|
assert.equal(banList.allRules.length, 0);
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { strict as assert } from "assert";
|
import { strict as assert } from "assert";
|
||||||
import { newTestUser, overrideRatelimitForUser, resetRatelimitForUser } from "./clientHelper";
|
import { newTestUser } from "./clientHelper";
|
||||||
import { getMessagesByUserIn } from "../../src/utils";
|
import { getMessagesByUserIn } from "../../src/utils";
|
||||||
import { getFirstReaction } from "./commands/commandUtils";
|
|
||||||
|
|
||||||
describe("Test: throttled users can function with Mjolnir.", function () {
|
describe("Test: throttled users can function with Mjolnir.", function () {
|
||||||
it('throttled users survive being throttled by synapse', async function() {
|
it('throttled users survive being throttled by synapse', async function() {
|
||||||
@ -18,58 +17,17 @@ describe("Test: throttled users can function with Mjolnir.", function () {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("Test: Mjolnir can still sync and respond to commands while throttled", function () {
|
/**
|
||||||
beforeEach(async function() {
|
* We used to have a test here that tested whether Mjolnir was going to carry out a redact order the default limits in a reasonable time scale.
|
||||||
await resetRatelimitForUser(await this.mjolnir.client.getUserId())
|
* Now I think that's never going to happen without writing a new algorithm for respecting rate limiting.
|
||||||
})
|
* Which is not something there is time for.
|
||||||
afterEach(async function() {
|
*
|
||||||
// If a test has a timeout while awaitng on a promise then we never get given control back.
|
* https://github.com/matrix-org/synapse/pull/13018
|
||||||
this.moderator?.stop();
|
*
|
||||||
|
* Synapse rate limits were broken and very permitting so that's why the current hack worked so well.
|
||||||
await overrideRatelimitForUser(await this.mjolnir.client.getUserId());
|
* Now it is not broken, so our rate limit handling is.
|
||||||
})
|
*
|
||||||
|
* https://github.com/matrix-org/mjolnir/commit/b850e4554c6cbc9456e23ab1a92ede547d044241
|
||||||
it('Can still perform and respond to a redaction command', async function () {
|
*
|
||||||
// Create a few users and a room.
|
* Honestly I don't think we can expect anyone to be able to use Mjolnir under default rate limits.
|
||||||
let badUser = await newTestUser({ name: { contains: "spammer-needs-redacting" } });
|
*/
|
||||||
let badUserId = await badUser.getUserId();
|
|
||||||
const mjolnir = this.mjolnir.client;
|
|
||||||
let mjolnirUserId = await mjolnir.getUserId();
|
|
||||||
let moderator = await newTestUser({ name: { contains: "moderator" } });
|
|
||||||
this.moderator = moderator;
|
|
||||||
await moderator.joinRoom(this.mjolnir.managementRoomId);
|
|
||||||
let targetRoom = await moderator.createRoom({ invite: [await badUser.getUserId(), mjolnirUserId]});
|
|
||||||
await moderator.setUserPowerLevel(mjolnirUserId, targetRoom, 100);
|
|
||||||
await badUser.joinRoom(targetRoom);
|
|
||||||
|
|
||||||
// Give Mjolnir some work to do and some messages to sync through.
|
|
||||||
await Promise.all([...Array(25).keys()].map((i) => moderator.sendMessage(this.mjolnir.managementRoomId, {msgtype: 'm.text.', body: `Irrelevant Message #${i}`})));
|
|
||||||
await Promise.all([...Array(25).keys()].map(_ => moderator.sendMessage(this.mjolnir.managementRoomId, {msgtype: 'm.text', body: '!mjolnir status'})));
|
|
||||||
|
|
||||||
await moderator.sendMessage(this.mjolnir.managementRoomId, {msgtype: 'm.text', body: `!mjolnir rooms add ${targetRoom}`});
|
|
||||||
|
|
||||||
await Promise.all([...Array(25).keys()].map((i) => badUser.sendMessage(targetRoom, {msgtype: 'm.text.', body: `Bad Message #${i}`})));
|
|
||||||
|
|
||||||
try {
|
|
||||||
await moderator.start();
|
|
||||||
await getFirstReaction(moderator, this.mjolnir.managementRoomId, '✅', async () => {
|
|
||||||
return await moderator.sendMessage(this.mjolnir.managementRoomId, { msgtype: 'm.text', body: `!mjolnir redact ${badUserId} ${targetRoom}` });
|
|
||||||
});
|
|
||||||
} finally {
|
|
||||||
moderator.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
let count = 0;
|
|
||||||
await getMessagesByUserIn(moderator, badUserId, targetRoom, 1000, function(events) {
|
|
||||||
count += events.length
|
|
||||||
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 event 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)}`)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
});
|
|
||||||
assert.equal(count, 26, "There should be exactly 26 events from the spammer in this room.");
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
Loading…
Reference in New Issue
Block a user