From 0770beef04d033b33cb75c721f57af795068aadc Mon Sep 17 00:00:00 2001 From: lens0021 Date: Sun, 26 May 2024 03:22:48 +0900 Subject: [PATCH 1/4] feat: Block users by blocked emails --- extension.json | 9 ++++ includes/HookHandlers/SpamEmail.php | 80 +++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+) create mode 100644 includes/HookHandlers/SpamEmail.php diff --git a/extension.json b/extension.json index 793ce6b..6c34a64 100644 --- a/extension.json +++ b/extension.json @@ -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"] } }, "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..549a04d --- /dev/null +++ b/includes/HookHandlers/SpamEmail.php @@ -0,0 +1,80 @@ +config = $config; + $this->loadBalancer = $loadBalancer; + $this->databaseBlockStore = $databaseBlockStore; + } + + /** @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 { + $dbr = $this->loadBalancer->getConnectionRef( ILoadBalancer::DB_REPLICA ); + $emails = $dbr->newSelectQueryBuilder() + ->fields( [ 'user_email' ] ) + ->tables( [ 'ipblocks' ] ) + ->join( 'user', 'user_id = ipb_user' ) + ->conds( [ + 'ipb_user IS NOT NULL', + "ipb_expiry > " . $dbr->addQuotes( $dbr->timestamp() ), + ] ) + ->fetchFieldValues(); + $emails = array_filter(array_unique($emails)); + } + if ( in_array( $addr, $emails ) ) { + return false; + } + } +} From f7e630497ff4422a5b963976523d15c3af804948 Mon Sep 17 00:00:00 2001 From: lens0021 Date: Sun, 26 May 2024 04:35:14 +0900 Subject: [PATCH 2/4] Cache the result of a query --- extension.json | 2 +- includes/HookHandlers/SpamEmail.php | 43 +++++++++++++++++++++-------- 2 files changed, 32 insertions(+), 13 deletions(-) diff --git a/extension.json b/extension.json index 6c34a64..3f908da 100644 --- a/extension.json +++ b/extension.json @@ -37,7 +37,7 @@ }, "SpamEmail": { "class": "MediaWiki\\Extension\\UnifiedExtensionForFemiwiki\\HookHandlers\\SpamEmail", - "services": ["MainConfig", "DBLoadBalancer", "DatabaseBlockStore"] + "services": ["MainConfig", "DBLoadBalancer", "DatabaseBlockStore", "MainWANObjectCache"] } }, "Hooks": { diff --git a/includes/HookHandlers/SpamEmail.php b/includes/HookHandlers/SpamEmail.php index 549a04d..19913f0 100644 --- a/includes/HookHandlers/SpamEmail.php +++ b/includes/HookHandlers/SpamEmail.php @@ -6,6 +6,7 @@ use MediaWiki\Block\DatabaseBlockStore; use MediaWiki\Extension\SpamBlacklist\BaseBlacklist; use MediaWiki\User\User; +use WANObjectCache; use Wikimedia\AtEase\AtEase; use Wikimedia\Rdbms\ILoadBalancer; @@ -22,19 +23,26 @@ class SpamEmail implements /** @var DatabaseBlockStore */ private $databaseBlockStore; + /** @var WANObjectCache */ + private $wanCache; + /** * @param Config $config * @param ILoadBalancer $loadBalancer * @param DatabaseBlockStore $databaseBlockStore + * @param WANObjectCache $wanCache + * */ public function __construct( Config $config, ILoadBalancer $loadBalancer, - DatabaseBlockStore $databaseBlockStore + DatabaseBlockStore $databaseBlockStore, + WANObjectCache $wanCache ) { $this->config = $config; $this->loadBalancer = $loadBalancer; $this->databaseBlockStore = $databaseBlockStore; + $this->wanCache = $wanCache; } /** @inheritDoc */ @@ -61,17 +69,28 @@ public function onIsValidEmailAddr( $addr, &$result ) { static fn( $block ) => User::newFromIdentity( $block->getBlocker() )->getEmail() ) ) ); } else { - $dbr = $this->loadBalancer->getConnectionRef( ILoadBalancer::DB_REPLICA ); - $emails = $dbr->newSelectQueryBuilder() - ->fields( [ 'user_email' ] ) - ->tables( [ 'ipblocks' ] ) - ->join( 'user', 'user_id = ipb_user' ) - ->conds( [ - 'ipb_user IS NOT NULL', - "ipb_expiry > " . $dbr->addQuotes( $dbr->timestamp() ), - ] ) - ->fetchFieldValues(); - $emails = array_filter(array_unique($emails)); + $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; From 58f227efe0e775cfbed5d69031921d63fb494521 Mon Sep 17 00:00:00 2001 From: lens0021 Date: Sun, 26 May 2024 04:38:48 +0900 Subject: [PATCH 3/4] Release 4.1.0 --- CHANGELOG.md | 1 + extension.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) 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 3f908da..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", From e16a67cbf1bcf9b21902df0edd93cbdf7a44f9b2 Mon Sep 17 00:00:00 2001 From: lens0021 Date: Sun, 26 May 2024 04:40:12 +0900 Subject: [PATCH 4/4] test: Add a dependency --- .github/workflows/dependencies | 1 + 1 file changed, 1 insertion(+) 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