From d523717540a333ce92ba5106c1d23b6dba3c4aa6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A1ndly=20Gerg=C5=91?= Date: Fri, 11 Feb 2022 14:02:49 +0200 Subject: [PATCH 1/3] Introduced a protection which lets the room bans propagate to a defined banlist --- src/protections/PropagateRoomBan.ts | 111 ++++++++++++++++++++++++++++ src/protections/protections.ts | 4 +- 2 files changed, 114 insertions(+), 1 deletion(-) create mode 100644 src/protections/PropagateRoomBan.ts diff --git a/src/protections/PropagateRoomBan.ts b/src/protections/PropagateRoomBan.ts new file mode 100644 index 00000000..aca1a97a --- /dev/null +++ b/src/protections/PropagateRoomBan.ts @@ -0,0 +1,111 @@ +/* +Copyright 2021 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import { StringProtectionSetting } from './ProtectionSettings'; +import { Mjolnir } from '../Mjolnir'; +import { recommendationToStable, RECOMMENDATION_BAN } from '../models/ListRule'; +import { logMessage } from '../LogProxy'; +import { LogLevel } from 'matrix-bot-sdk'; +import { RULE_USER } from '../models/BanList'; +import { Protection } from './IProtection'; + +export class PropagateRoomBan extends Protection { + settings = { + banlistShortcode: new StringProtectionSetting(), + }; + + public get name(): string { + return 'PropagateRoomBan'; + } + + public get description(): string { + return ( + 'If a user is banned in a protected room by a room administrator then the ban ' + + 'will be published to the banlist defined using the banlistShortcode setting.' + ); + } + + public async handleEvent(mjolnir: Mjolnir, roomId: string, event: any): Promise { + if (!this.isBanEvent(event)) { + // only interested in ban events + return; + } + + const content = event['content'] || {}; + const bannedUser = event['state_key']; + const banReason = content['reason'] || ''; + const sender = event['sender']; + const stateKey = `rule:${bannedUser}`; + + const ruleContent = { + entity: bannedUser, + recommendation: recommendationToStable(RECOMMENDATION_BAN), + reason: banReason, + }; + + if (this.settings.banlistShortcode.value === '') { + await logMessage( + LogLevel.WARN, + 'PropagateRoomBan', + `Can not publish to banlist. User ${bannedUser} was banned in ${roomId}, but protection setting banlistShortcode is missing` + ); + return; + } + + const banlist = mjolnir.lists.find( + (bl) => + bl.listShortcode.toLowerCase() === + this.settings.banlistShortcode.value.toLowerCase() + ); + + if (!banlist) { + await logMessage( + LogLevel.WARN, + 'PropagateRoomBan', + `Can not publish to banlist. User ${bannedUser} was banned in ${roomId}, but banlist ${this.settings.banlistShortcode.value} is not found` + ); + return; + } + + await mjolnir.client.sendStateEvent( + banlist.roomId, + RULE_USER, + stateKey, + ruleContent + ); + await logMessage( + LogLevel.INFO, + 'PropagateRoomBan', + `User ${bannedUser} added to banlist ${banlist.listShortcode}, because ${sender} banned him in ${roomId} for: ${banReason}` + ); + } + + private isBanEvent(event: any): boolean { + if (event['type'] !== 'm.room.member') { + return false; + } + + const membership: string = event['content']['membership']; + let prevMembership = 'join'; + + if (event['unsigned'] && event['unsigned']['prev_content']) { + prevMembership = + event['unsigned']['prev_content']['membership'] || 'join'; + } + + return membership === 'ban' && prevMembership !== 'ban'; + } +} diff --git a/src/protections/protections.ts b/src/protections/protections.ts index 624c6c31..408e52eb 100644 --- a/src/protections/protections.ts +++ b/src/protections/protections.ts @@ -21,6 +21,7 @@ import { WordList } from "./WordList"; import { MessageIsVoice } from "./MessageIsVoice"; import { MessageIsMedia } from "./MessageIsMedia"; import { TrustedReporters } from "./TrustedReporters"; +import { PropagateRoomBan } from './PropagateRoomBan'; export const PROTECTIONS: IProtection[] = [ new FirstMessageIsImage(), @@ -28,5 +29,6 @@ export const PROTECTIONS: IProtection[] = [ new WordList(), new MessageIsVoice(), new MessageIsMedia(), - new TrustedReporters() + new TrustedReporters(), + new PropagateRoomBan() ]; From b5ef4e4264de1fc528af9b0964935f15590ce8ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A1ndly=20Gerg=C5=91?= Date: Thu, 24 Feb 2022 10:02:28 +0200 Subject: [PATCH 2/3] Default to the default banList and use mjolnir.logMessage instead of LogProxy --- src/protections/PropagateRoomBan.ts | 50 +++++++++++++++++++---------- 1 file changed, 33 insertions(+), 17 deletions(-) diff --git a/src/protections/PropagateRoomBan.ts b/src/protections/PropagateRoomBan.ts index aca1a97a..265952f1 100644 --- a/src/protections/PropagateRoomBan.ts +++ b/src/protections/PropagateRoomBan.ts @@ -14,17 +14,17 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { StringProtectionSetting } from './ProtectionSettings'; +import { Protection } from './IProtection'; import { Mjolnir } from '../Mjolnir'; +import { StringProtectionSetting } from './ProtectionSettings'; +import { LogLevel, extractRequestError } from 'matrix-bot-sdk'; import { recommendationToStable, RECOMMENDATION_BAN } from '../models/ListRule'; -import { logMessage } from '../LogProxy'; -import { LogLevel } from 'matrix-bot-sdk'; import { RULE_USER } from '../models/BanList'; -import { Protection } from './IProtection'; +import { DEFAULT_LIST_EVENT_TYPE } from '../commands/SetDefaultBanListCommand'; export class PropagateRoomBan extends Protection { settings = { - banlistShortcode: new StringProtectionSetting(), + banListShortcode: new StringProtectionSetting(), }; public get name(): string { @@ -34,7 +34,8 @@ export class PropagateRoomBan extends Protection { public get description(): string { return ( 'If a user is banned in a protected room by a room administrator then the ban ' + - 'will be published to the banlist defined using the banlistShortcode setting.' + 'will be published to the banlist defined using the banListShortcode setting ' + + '(defaults to the default banlist).' ); } @@ -56,26 +57,41 @@ export class PropagateRoomBan extends Protection { reason: banReason, }; - if (this.settings.banlistShortcode.value === '') { - await logMessage( - LogLevel.WARN, - 'PropagateRoomBan', - `Can not publish to banlist. User ${bannedUser} was banned in ${roomId}, but protection setting banlistShortcode is missing` - ); - return; + let banListShortcode: string = this.settings.banListShortcode.value; + if (banListShortcode === '') { + // try to use default banList + try { + const data: { shortcode: string } = + await mjolnir.client.getAccountData( + DEFAULT_LIST_EVENT_TYPE + ); + banListShortcode = data['shortcode']; + } catch (e) { + await mjolnir.logMessage( + LogLevel.WARN, + 'PropagateRoomBan', + `Can not publish to banlist. User ${bannedUser} was banned in ${roomId}, but protection setting banListShortcode is missing and could not get default banlist` + ); + await mjolnir.logMessage( + LogLevel.WARN, + 'PropagateRoomBan', + extractRequestError(e) + ); + return; + } } const banlist = mjolnir.lists.find( (bl) => bl.listShortcode.toLowerCase() === - this.settings.banlistShortcode.value.toLowerCase() + banListShortcode.toLowerCase() ); if (!banlist) { - await logMessage( + await mjolnir.logMessage( LogLevel.WARN, 'PropagateRoomBan', - `Can not publish to banlist. User ${bannedUser} was banned in ${roomId}, but banlist ${this.settings.banlistShortcode.value} is not found` + `Can not publish to banlist. User ${bannedUser} was banned in ${roomId}, but banlist ${banListShortcode} is not found` ); return; } @@ -86,7 +102,7 @@ export class PropagateRoomBan extends Protection { stateKey, ruleContent ); - await logMessage( + await mjolnir.logMessage( LogLevel.INFO, 'PropagateRoomBan', `User ${bannedUser} added to banlist ${banlist.listShortcode}, because ${sender} banned him in ${roomId} for: ${banReason}` From 6cae0c8997ad213dfbbce0f61bc60d37a9a8b9fe Mon Sep 17 00:00:00 2001 From: Gnuxie <50846879+Gnuxie@users.noreply.github.com> Date: Wed, 15 Jun 2022 12:23:23 +0100 Subject: [PATCH 3/3] oops missing comma --- src/protections/protections.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/protections/protections.ts b/src/protections/protections.ts index f1de2d66..4eb41427 100644 --- a/src/protections/protections.ts +++ b/src/protections/protections.ts @@ -33,7 +33,7 @@ export const PROTECTIONS: Protection[] = [ new MessageIsVoice(), new MessageIsMedia(), new TrustedReporters(), - new PropagateRoomBan() + new PropagateRoomBan(), new DetectFederationLag(), new JoinWaveShortCircuit(), ];