From de8f74aae5996870412899cc3a79e3502d94d790 Mon Sep 17 00:00:00 2001 From: lens0021 Date: Sun, 26 May 2024 03:22:48 +0900 Subject: [PATCH] feat: Block users by blocked emails Cache the result of a query Release 4.1.0 test: Add a dependency --- .github/workflows/dependencies | 1 + CHANGELOG.md | 1 + extension.json | 11 +++- includes/HookHandlers/SpamEmail.php | 99 +++++++++++++++++++++++++++++ 4 files changed, 111 insertions(+), 1 deletion(-) create mode 100644 includes/HookHandlers/SpamEmail.php diff --git a/.github/workflows/dependencies b/.github/workflows/dependencies index f9af29f..c3518bf 100644 --- a/.github/workflows/dependencies +++ b/.github/workflows/dependencies @@ -1,3 +1,4 @@ CategoryTree Disambiguator +SpamBlacklist Wikibase diff --git a/CHANGELOG.md b/CHANGELOG.md index 69de783..238b0dc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ Versions and bullets are arranged chronologically from latest to oldest. - Dropped SpecialOrderedWhatLinksHere because of the hardness of the maintaining. Please upvote https://phabricator.wikimedia.org/T4306 if you still want to the functionality. - Dropped `$UnifiedExtensionForFemiwikiSoftDefaultOptions` configuration variable and the related feature. +- Added `$wgUnifiedExtensionForFemiwikiBlockByEmail` configuration variable (default is true) which provides various email blocking funtionalities. ## Previous Releases diff --git a/extension.json b/extension.json index 793ce6b..03844a8 100644 --- a/extension.json +++ b/extension.json @@ -1,6 +1,6 @@ { "name": "UnifiedExtensionForFemiwiki", - "version": "3.0.1", + "version": "4.1.0", "author": "[https://femiwiki.com/ Femiwiki Team]", "url": "https://github.com/femiwiki/unifiedExtensionForFemiwiki", "descriptionmsg": "unifiedextensionforfemiwiki-desc", @@ -34,10 +34,15 @@ "DefaultOptions": { "class": "MediaWiki\\Extension\\UnifiedExtensionForFemiwiki\\HookHandlers\\DefaultOptions", "services": ["MainConfig", "UserOptionsManager"] + }, + "SpamEmail": { + "class": "MediaWiki\\Extension\\UnifiedExtensionForFemiwiki\\HookHandlers\\SpamEmail", + "services": ["MainConfig", "DBLoadBalancer", "DatabaseBlockStore", "MainWANObjectCache"] } }, "Hooks": { "HtmlPageLinkRendererBegin": "main", + "isValidEmailAddr": "SpamEmail", "LinkerMakeExternalLink": "main", "OutputPageParserOutput": "RelatedArticles", "SidebarBeforeOutput": "main", @@ -63,6 +68,10 @@ "UnifiedExtensionForFemiwikiRelatedArticlesTargetNamespaces": { "value": [], "description": "An array of namespaces which can be a target for RelatedArticles. Empty array means allowing all namespaces." + }, + "UnifiedExtensionForFemiwikiBlockByEmail": { + "value": true, + "description": "Block emails used by block users" } }, "TestAutoloadNamespaces": { diff --git a/includes/HookHandlers/SpamEmail.php b/includes/HookHandlers/SpamEmail.php new file mode 100644 index 0000000..19913f0 --- /dev/null +++ b/includes/HookHandlers/SpamEmail.php @@ -0,0 +1,99 @@ +config = $config; + $this->loadBalancer = $loadBalancer; + $this->databaseBlockStore = $databaseBlockStore; + $this->wanCache = $wanCache; + } + + /** @inheritDoc */ + public function onIsValidEmailAddr( $addr, &$result ) { + if ( !$this->config->get( 'UnifiedExtensionForFemiwikiBlockByEmail' ) ) { + return true; + } + + // Check againt MediaWiki:Email-blacklist + $denylist = BaseBlacklist::getEmailBlacklist()->getBlacklists(); + foreach ( $denylist as $regex ) { + AtEase::suppressWarnings(); + $match = preg_match( $regex, $addr ); + AtEase::restoreWarnings(); + if ( $match ) { + return false; + } + } + + // Check email addresses of block users + if ( version_compare( '1.42', MW_VERSION, '<=' ) ) { + $emails = array_filter( array_unique( array_map( + $this->databaseBlockStore->newListFromConds( [ 'bt_user IS NOT NULL' ] ), + static fn( $block ) => User::newFromIdentity( $block->getBlocker() )->getEmail() + ) ) ); + } else { + $loadBalancer = $this->loadBalancer; + $emails = $this->wanCache->getWithSetCallback( + $this->wanCache->makeKey( 'unified-femiwiki-extension-blocked-email' ), + WANObjectCache::TTL_HOUR, + static function ( $old, &$ttl, array &$setOpts ) use ( $loadBalancer ) { + $dbr = $loadBalancer->getConnectionRef( ILoadBalancer::DB_REPLICA ); + return $dbr->newSelectQueryBuilder() + ->distinct() + ->fields( [ 'user_email' ] ) + ->tables( [ 'ipblocks' ] ) + ->join( 'user', 'user_id = ipb_user' ) + ->conds( [ + 'ipb_user IS NOT NULL', + 'user_email != ' . $dbr->addQuotes( '' ), + 'ipb_expiry > ' . $dbr->addQuotes( $dbr->timestamp() ), + ] ) + ->fetchFieldValues(); + } + ); + if ( !is_array( $emails ) ) { + $emails = []; + } + } + if ( in_array( $addr, $emails ) ) { + return false; + } + } +}