Blocked domains: Add support for "added by" field

This field gets added automatically when using the special page form but
is only shown to admins and other people who have access. It's not private
information (users can find it in history) but this is to avoid making
these admins an easy target for harassment (Talking to PM of moderation
team he agreed this is a good compromise).

Bug: T341626
Change-Id: I8410f39db54b96981b05de8e064fed65df30ef2f
This commit is contained in:
Amir Sarabadani 2023-12-25 21:07:38 +01:00
parent bc9fa2bb64
commit d628a99442
5 changed files with 46 additions and 8 deletions

View file

@ -581,6 +581,7 @@
"abusefilter-blocked-domains-domain-header": "Domain",
"abusefilter-blocked-domains-notes-header": "Notes",
"abusefilter-blocked-domains-actions-header": "Actions",
"abusefilter-blocked-domains-addedby-header": "Added by",
"abusefilter-blocked-domains-remove": "remove",
"abusefilter-blocked-domains-remove-title": "Remove a blocked domain",
"abusefilter-blocked-domains-remove-explanation-initial": "On this page you can remove a blocked domain",

View file

@ -625,6 +625,7 @@
"abusefilter-blocked-domains-domain-header": "Domain header in the table",
"abusefilter-blocked-domains-notes-header": "Notes header in the table",
"abusefilter-blocked-domains-actions-header": "Actions header in the table",
"abusefilter-blocked-domains-addedby-header": "Header for added by username in the table",
"abusefilter-blocked-domains-remove": "Link to remove a domain from blocked list",
"abusefilter-blocked-domains-remove-title": "Title of the special page on removing the domain from blocked list",
"abusefilter-blocked-domains-remove-explanation-initial": "Explanation of the special page on removing the domain from blocked list",

View file

@ -199,7 +199,7 @@ class BlockedDomainStorage implements IDBAccessObject {
if ( $content === null ) {
return null;
}
$content[] = [ 'domain' => $domain, 'notes' => $notes ];
$content[] = [ 'domain' => $domain, 'notes' => $notes, 'addedBy' => $user->getName() ];
$comment = Message::newFromSpecifier( 'abusefilter-blocked-domains-domain-added-comment' )
->params( $domain, $notes )
->plain();

View file

@ -27,6 +27,8 @@ class EditPermissionHandler implements GetUserPermissionsErrorsHook, JsonValidat
'notes'
];
private const JSON_OPTIONAL_FIELDS = [ 'addedBy' ];
/**
* @see https://www.mediawiki.org/wiki/Manual:Hooks/getUserPermissionsErrors
*
@ -92,14 +94,29 @@ class EditPermissionHandler implements GetUserPermissionsErrorsHook, JsonValidat
$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 ) ) {
// Check if each element is an object with all known fields, allow optional fields but 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;
}
}
foreach ( self::JSON_OPTIONAL_FIELDS as $field ) {
if ( property_exists( $element, $field ) && !is_string( $element->{$field} ) ) {
$isValid = false;
break 2;
}
}
foreach ( $element as $field => $value ) {
if (
!in_array( $field, array_merge( self::JSON_OPTIONAL_FIELDS, self::JSON_OBJECT_FIELDS ) )
) {
$isValid = false;
break;
}
}
} else {
$isValid = false;
break;

View file

@ -25,6 +25,7 @@ use IDBAccessObject;
use MediaWiki\Extension\AbuseFilter\BlockedDomainStorage;
use MediaWiki\Html\Html;
use MediaWiki\SpecialPage\SpecialPage;
use MediaWiki\Title\TitleValue;
use PermissionsError;
use WANObjectCache;
@ -112,11 +113,19 @@ class BlockedExternalDomains extends SpecialPage {
}
$content = Html::element( 'th', [], $this->msg( 'abusefilter-blocked-domains-domain-header' )->text() ) .
Html::element( 'th', [], $this->msg( 'abusefilter-blocked-domains-notes-header' )->text() ) .
( $userCanManage ?
Html::element( 'th', [ 'class' => 'unsortable' ],
$this->msg( 'abusefilter-blocked-domains-actions-header' )->text() ) :
'' );
Html::element( 'th', [], $this->msg( 'abusefilter-blocked-domains-notes-header' )->text() );
if ( $userCanManage ) {
$content .= Html::element(
'th',
[],
$this->msg( 'abusefilter-blocked-domains-addedby-header' )->text()
);
$content .= Html::element(
'th',
[ 'class' => 'unsortable' ],
$this->msg( 'abusefilter-blocked-domains-actions-header' )->text()
);
}
$thead = Html::rawElement( 'tr', [], $content );
// Parsing each row is expensive, put it behind WAN cache
@ -163,6 +172,16 @@ class BlockedExternalDomains extends SpecialPage {
$newRow .= Html::rawElement( 'td', [], $this->getOutput()->parseInlineAsInterface( $domain['notes'] ) );
if ( $showManageActions ) {
if ( isset( $domain['addedBy'] ) ) {
$addedBy = $this->getLinkRenderer()->makeLink(
new TitleValue( 3, $domain['addedBy'] ),
$domain['addedBy']
);
} else {
$addedBy = '';
}
$newRow .= Html::rawElement( 'td', [], $addedBy );
$actionLink = $this->getLinkRenderer()->makeKnownLink(
$this->getPageTitle( 'remove' ),
$this->msg( 'abusefilter-blocked-domains-remove' )->text(),