Allow showing a CAPTCHA in response to AbuseFilter consequence

Why:

- We want to allow administrators to invoke a CAPTCHA
  if an AbuseFilter is configured to do so.

What:

- Implement the AbuseFilterCustomActions hook and define
  CaptchaConsequence, which will inform AbuseFilter's implementation
  of onConfirmEditTriggersCaptcha that it should show a CAPTCHA
- Deliberately do not register the "showcaptcha" action as a "dangerous
  action", because filters that use this action are aimed at bot
  traffic, and we don't want a bot to be able to get past the
  "showcaptcha" action just by making repeat requests

Soft depends on I110a5f5321649dcf85993a0c209ab70b9886057c

Bug: T20110
Change-Id: Ie87e3d850541c7dc44aaeb6b30489a32a0c8cc60
This commit is contained in:
Kosta Harlan 2024-05-04 23:28:51 +03:00
parent 41fbcb2963
commit 10b9276855
No known key found for this signature in database
GPG key ID: BC3D8915606A5ED9
7 changed files with 99 additions and 3 deletions

View file

@ -94,6 +94,9 @@
"services": [
"MainWANObjectCache"
]
},
"AbuseFilterHooks": {
"class": "MediaWiki\\Extension\\ConfirmEdit\\AbuseFilterHooks"
}
},
"Hooks": {
@ -107,7 +110,8 @@
"EditPage::showEditForm:fields": "ConfirmEditHooks",
"EditFilterMergedContent": "ConfirmEditHooks",
"APIGetAllowedParams": "ConfirmEditHooks",
"AuthChangeFormFields": "ConfirmEditHooks"
"AuthChangeFormFields": "ConfirmEditHooks",
"AbuseFilterCustomActions": "AbuseFilterHooks"
},
"AuthManagerAutoConfig": {
"preauth": {

View file

@ -31,5 +31,6 @@
"confirmedit-preview-validity": "Validity",
"confirmedit-preview-valid": "valid",
"confirmedit-preview-invalid": "invalid",
"confirmedit-preview-description": "The following table shows the list of lines on this page and whether it's a valid IP address or IP address range. If the line is a valid IP address or IP address range, it will be excluded from CAPTCHA checks but invalid lines will be ignored. An example of a valid IP address range would be: 69.208.0.0/16 which goes from 69.208.0.0 to 69.208.255.255. [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Range_blocks#Calculating_the_CIDR_suffix More information] about calculating an IP address range."
"confirmedit-preview-description": "The following table shows the list of lines on this page and whether it's a valid IP address or IP address range. If the line is a valid IP address or IP address range, it will be excluded from CAPTCHA checks but invalid lines will be ignored. An example of a valid IP address range would be: 69.208.0.0/16 which goes from 69.208.0.0 to 69.208.255.255. [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Range_blocks#Calculating_the_CIDR_suffix More information] about calculating an IP address range.",
"abusefilter-edit-action-showcaptcha": "Require the user to complete a CAPTCHA in order to proceed with the action. Users with permission to skip a CAPTCHA are exempt."
}

View file

@ -47,5 +47,6 @@
"confirmedit-preview-validity": "Used as a table heading for the edit preview of [[MediaWiki:Captcha-ip-whitelist]] to indicate the validity of a content of a line (if it's an IP address or not).\n{{Identical|Validity}}",
"confirmedit-preview-valid": "Used to indicate a valid IP address in the edit preview of [[MediaWiki:Captcha-ip-whitelist]].\n{{Identical|Valid}}",
"confirmedit-preview-invalid": "Used to indicate an invalid IP address in the edit preview of [[MediaWiki:Captcha-ip-whitelist]].\n{{Identical|Invalid}}",
"confirmedit-preview-description": "Explains the edit preview of [[MediaWiki:Captcha-ip-whitelist]]."
"confirmedit-preview-description": "Explains the edit preview of [[MediaWiki:Captcha-ip-whitelist]].",
"abusefilter-edit-action-showcaptcha": "Label shown in [[Special:AbuseFilter]] for the show CAPTCHA consequence."
}

View file

@ -0,0 +1,22 @@
<?php
namespace MediaWiki\Extension\ConfirmEdit\AbuseFilter;
use MediaWiki\Context\RequestContext;
use MediaWiki\Extension\AbuseFilter\Consequences\Consequence\Consequence;
/**
* Will inform ConfirmEdit extension to show a CAPTCHA.
*/
class CaptchaConsequence extends Consequence {
public const FLAG = 'wgAbuseFilterCaptchaConsequence';
public function execute(): bool {
// This consequence was triggered, so we need to set a global flag
// which Extension:ConfirmEdit will read in order to decide if a
// CAPTCHA should be shown to the user in onConfirmEditTriggersCaptcha
RequestContext::getMain()->getRequest()->setVal( self::FLAG, true );
return true;
}
}

View file

@ -0,0 +1,18 @@
<?php
namespace MediaWiki\Extension\ConfirmEdit;
use MediaWiki\Extension\AbuseFilter\Consequences\Parameters;
use MediaWiki\Extension\AbuseFilter\Hooks\AbuseFilterCustomActionsHook;
use MediaWiki\Extension\ConfirmEdit\AbuseFilter\CaptchaConsequence;
class AbuseFilterHooks implements AbuseFilterCustomActionsHook {
/** @inheritDoc */
public function onAbuseFilterCustomActions( array &$actions ): void {
$actions['showcaptcha'] = static function ( Parameters $params ): CaptchaConsequence {
return new CaptchaConsequence( $params );
};
}
}

View file

@ -0,0 +1,31 @@
<?php
namespace MediaWiki\Extension\ConfirmEdit\Test\Integration\AbuseFilter;
use MediaWiki\Context\RequestContext;
use MediaWiki\Extension\AbuseFilter\Consequences\Parameters;
use MediaWiki\Extension\ConfirmEdit\AbuseFilter\CaptchaConsequence;
use MediaWikiIntegrationTestCase;
/**
* @covers \MediaWiki\Extension\ConfirmEdit\AbuseFilter\CaptchaConsequence
*/
class CaptchaConsequenceTest extends MediaWikiIntegrationTestCase {
public function testExecute() {
$parameters = $this->createMock( Parameters::class );
$parameters->method( 'getAction' )->willReturn( 'edit' );
$captchaConsequence = new CaptchaConsequence( $parameters );
$request = RequestContext::getMain();
$this->assertNull( $request->getRequest()->getVal(
CaptchaConsequence::FLAG
) );
$captchaConsequence->execute();
$this->assertTrue(
$request->getRequest()->getBool(
CaptchaConsequence::FLAG
)
);
}
}

View file

@ -0,0 +1,19 @@
<?php
namespace MediaWiki\Extension\ConfirmEdit\Test\Unit\AbuseFilter;
use MediaWiki\Extension\ConfirmEdit\AbuseFilterHooks;
use MediaWikiUnitTestCase;
/**
* @covers \MediaWiki\Extension\ConfirmEdit\AbuseFilterHooks
*/
class AbuseFilterHooksTest extends MediaWikiUnitTestCase {
public function testOnAbuseFilterCustomActions() {
$abuseFilterHooks = new AbuseFilterHooks();
$actions = [];
$abuseFilterHooks->onAbuseFilterCustomActions( $actions );
$this->assertArrayHasKey( 'showcaptcha', $actions );
}
}