mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/AbuseFilter.git
synced 2024-11-23 21:53:35 +00:00
BlockedExternalDomains: validate JSON structure before save
This makes raw page editing safer, and potentially enables opening up access to less restricted user groups. Bug: T337431 Change-Id: I14f21003a551f34b6e524e9b229613e79b0e5a70
This commit is contained in:
parent
1298c9243b
commit
8a22007034
|
@ -411,7 +411,8 @@
|
|||
"BeforeCreateEchoEvent": "MediaWiki\\Extension\\AbuseFilter\\Hooks\\Handlers\\EchoHandler::onBeforeCreateEchoEvent",
|
||||
"ParserOutputStashForEdit": "FilteredActions",
|
||||
"UnitTestsAfterDatabaseSetup": "Tests",
|
||||
"UnitTestsBeforeDatabaseTeardown": "Tests"
|
||||
"UnitTestsBeforeDatabaseTeardown": "Tests",
|
||||
"JsonValidateSave": "EditPermission"
|
||||
},
|
||||
"ServiceWiringFiles": [
|
||||
"includes/ServiceWiring.php"
|
||||
|
|
|
@ -583,6 +583,8 @@
|
|||
"abusefilter-blocked-domains-remove-reason": "Reason",
|
||||
"abusefilter-blocked-domains-remove-submit": "Remove",
|
||||
"abusefilter-blocked-domains-attempted": "The text you wanted to publish was blocked by our filter. The following domain is blocked from being added: $1",
|
||||
"abusefilter-blocked-domains-json-error": "JSON should be an array",
|
||||
"abusefilter-blocked-domains-invalid-entry": "Entry $1 in JSON is invalid - it should be an object with 'domain' and 'notes' fields only, both being strings",
|
||||
"log-description-abusefilterprivatedetails": "This log shows a list of times when a user accessed the private details of an abuse log.",
|
||||
"abusefilter-noreason": "Warning: To see the private details of this log, you must provide a reason.",
|
||||
"abusefilter-log-ip-not-available": "Not Available",
|
||||
|
|
|
@ -625,6 +625,8 @@
|
|||
"abusefilter-blocked-domains-remove-reason": "Reason given for removal",
|
||||
"abusefilter-blocked-domains-remove-submit": "Submit button",
|
||||
"abusefilter-blocked-domains-attempted": "The error message when adding a blocked domain has been attempted.",
|
||||
"abusefilter-blocked-domains-json-error": "The error message when editing the JSON page to no longer be an array",
|
||||
"abusefilter-blocked-domains-invalid-entry": "The error message when adding an invalid entry to the JSON array. Parameters:\n* $1 - the serial number of the entry which is invalid.",
|
||||
"log-description-abusefilterprivatedetails": "The description of the abuse filter private details access log.",
|
||||
"abusefilter-noreason": "Warning message shown when no reasons is given to access the private details of an abuse log.",
|
||||
"abusefilter-log-ip-not-available": "Text shown when IP address is not available.\n{{Identical|Not available}}",
|
||||
|
|
|
@ -3,18 +3,29 @@
|
|||
|
||||
namespace MediaWiki\Extension\AbuseFilter\Hooks\Handlers;
|
||||
|
||||
use JsonContent;
|
||||
use MediaWiki\Content\Hook\JsonValidateSaveHook;
|
||||
use MediaWiki\Extension\AbuseFilter\BlockedDomainStorage;
|
||||
use MediaWiki\MediaWikiServices;
|
||||
use MediaWiki\Page\PageIdentity;
|
||||
use MediaWiki\Permissions\Hook\GetUserPermissionsErrorsHook;
|
||||
use MessageSpecifier;
|
||||
use StatusValue;
|
||||
use Title;
|
||||
use TitleValue;
|
||||
use User;
|
||||
|
||||
/**
|
||||
* This hook handler is for very simple checks, rather than the much more advanced ones
|
||||
* undertaken by the FilteredActionsHandler.
|
||||
*/
|
||||
class EditPermissionHandler implements GetUserPermissionsErrorsHook {
|
||||
class EditPermissionHandler implements GetUserPermissionsErrorsHook, JsonValidateSaveHook {
|
||||
|
||||
/** @var string[] */
|
||||
private const JSON_OBJECT_FIELDS = [
|
||||
'domain',
|
||||
'notes'
|
||||
];
|
||||
|
||||
/**
|
||||
* @see https://www.mediawiki.org/wiki/Manual:Hooks/getUserPermissionsErrors
|
||||
|
@ -48,4 +59,52 @@ class EditPermissionHandler implements GetUserPermissionsErrorsHook {
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param JsonContent $content
|
||||
* @param PageIdentity $pageIdentity
|
||||
* @param StatusValue $status
|
||||
* @return bool|void
|
||||
*/
|
||||
public function onJsonValidateSave( JsonContent $content, PageIdentity $pageIdentity, StatusValue $status ) {
|
||||
$services = MediaWikiServices::getInstance();
|
||||
|
||||
// Only do anything if we're enabled on this wiki.
|
||||
if ( !$services->getMainConfig()->get( 'AbuseFilterEnableBlockedExternalDomain' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$title = TitleValue::newFromPage( $pageIdentity );
|
||||
if ( !$title->inNamespace( NS_MEDIAWIKI ) || $title->getText() !== BlockedDomainStorage::TARGET_PAGE ) {
|
||||
return;
|
||||
}
|
||||
$data = $content->getData()->getValue();
|
||||
|
||||
if ( !is_array( $data ) ) {
|
||||
$status->fatal( 'abusefilter-blocked-domains-json-error' );
|
||||
return;
|
||||
}
|
||||
|
||||
$isValid = true;
|
||||
$entryNumber = 0;
|
||||
foreach ( $data as $element ) {
|
||||
$entryNumber++;
|
||||
// Check if each element is an object with all known fields, and no other fields
|
||||
if ( is_object( $element ) && count( get_object_vars( $element ) ) === count( self::JSON_OBJECT_FIELDS ) ) {
|
||||
foreach ( self::JSON_OBJECT_FIELDS as $field ) {
|
||||
if ( !property_exists( $element, $field ) || !is_string( $element->{$field} ) ) {
|
||||
$isValid = false;
|
||||
break 2;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$isValid = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !$isValid ) {
|
||||
$status->fatal( 'abusefilter-blocked-domains-invalid-entry', $entryNumber );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue