mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/Nuke
synced 2024-11-23 15:57:03 +00:00
Enable temp account lookup by IP address
- Adds a soft dependency on CheckUser - Lists pages created by IP user or temp acccounts associated with IP address when the lookup is available Bug: T342785 Depends-On: I45a18f1fcf1a17bdaeefabebcd2f67a946a2cc2e Change-Id: Idcdd7d787180e8e99fdcbe856e4fc237d9721824
This commit is contained in:
parent
a31ea99a89
commit
98aa8d9942
|
@ -32,4 +32,12 @@ $cfg['exclude_analysis_directory_list'] = array_merge(
|
|||
]
|
||||
);
|
||||
|
||||
// Don't stub CheckUser dependency if present
|
||||
if ( file_exists( '../../extensions/CheckUser/src/Services/CheckUserTemporaryAccountsByIPLookup.php' ) ) {
|
||||
$cfg[ 'exclude_file_list' ] = array_merge(
|
||||
$cfg[ 'exclude_file_list' ],
|
||||
[ '.phan/stubs/CheckUserTemporaryAccountsByIPLookup.php' ]
|
||||
);
|
||||
}
|
||||
|
||||
return $cfg;
|
||||
|
|
30
.phan/stubs/CheckUserTemporaryAccountsByIPLookup.php
Normal file
30
.phan/stubs/CheckUserTemporaryAccountsByIPLookup.php
Normal file
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
namespace MediaWiki\CheckUser\Services;
|
||||
|
||||
class CheckUserTemporaryAccountsByIPLookup {
|
||||
/**
|
||||
* Allows Nuke to pass CI without CheckUser
|
||||
*/
|
||||
public const CONSTRUCTOR_OPTIONS = [];
|
||||
|
||||
/**
|
||||
* @param \MediaWiki\Config\ServiceOptions $serviceOptions
|
||||
* @param \Wikimedia\Rdbms\IConnectionProvider $connectionProvider
|
||||
* @param \JobQueueGroup $jobQueueGroup
|
||||
* @param \MediaWiki\User\TempUser\TempUserConfig $tempUserConfig
|
||||
* @param \MediaWiki\User\UserFactory $userFactory
|
||||
* @param \MediaWiki\Permissions\PermissionManager $permissionManager
|
||||
* @param \MediaWiki\User\UserOptionsLookup $userOptionsLookup
|
||||
*/
|
||||
public function __construct(
|
||||
\MediaWiki\Config\ServiceOptions $serviceOptions,
|
||||
\Wikimedia\Rdbms\IConnectionProvider $connectionProvider,
|
||||
\JobQueueGroup $jobQueueGroup,
|
||||
\MediaWiki\User\TempUser\TempUserConfig $tempUserConfig,
|
||||
\MediaWiki\User\UserFactory $userFactory,
|
||||
\MediaWiki\Permissions\PermissionManager $permissionManager,
|
||||
\MediaWiki\User\UserOptionsLookup $userOptionsLookup
|
||||
) {
|
||||
}
|
||||
}
|
|
@ -72,10 +72,12 @@
|
|||
"PermissionManager",
|
||||
"RepoGroup",
|
||||
"UserFactory",
|
||||
"UserOptionsLookup",
|
||||
"UserNamePrefixSearch",
|
||||
"UserNameUtils",
|
||||
"NamespaceInfo",
|
||||
"ContentLanguage"
|
||||
"ContentLanguage",
|
||||
"NukeIPLookup"
|
||||
],
|
||||
"styles": [
|
||||
"mediawiki.special.special"
|
||||
|
@ -85,5 +87,8 @@
|
|||
"AutoloadNamespaces": {
|
||||
"MediaWiki\\Extension\\Nuke\\": "includes/"
|
||||
},
|
||||
"ServiceWiringFiles": [
|
||||
"includes/ServiceWiring.php"
|
||||
],
|
||||
"manifest_version": 2
|
||||
}
|
||||
|
|
|
@ -10,10 +10,13 @@
|
|||
"nuke-desc": "Gives administrators the ability to [[Special:Nuke|mass delete]] pages",
|
||||
"nuke-nopages": "No new pages by [[Special:Contributions/$1|{{GENDER:$1|$1}}]] in recent changes.",
|
||||
"nuke-list": "The following pages were recently created by [[Special:Contributions/$1|{{GENDER:$1|$1}}]]. Please select which pages to delete, provide an edit summary, and click 'Delete selected' to initiate page deletion.\n\nRedirects are displayed in italics.",
|
||||
"nuke-list-tempaccount": "The following pages were recently created by temporary accounts which were used from the IP address $1. Please select which pages to delete, provide an edit summary, and click 'Delete selected' to initiate page deletion. '''For privacy reasons, please do not write the IP address in the edit summary.'''\n\nRedirects are displayed in italics.",
|
||||
"nuke-list-multiple": "The following pages were recently created. Please select which pages to delete, provide an edit summary, and click 'Delete selected' to initiate page deletion.\n\nRedirects are displayed in italics.",
|
||||
"nuke-defaultreason": "Mass deletion of pages added by [[Special:Contributions/$1|{{GENDER:$1|$1}}]]",
|
||||
"nuke-defaultreason-tempaccount": "Mass deletion of pages added by temporary accounts",
|
||||
"nuke-multiplepeople": "Mass deletion of recently added pages",
|
||||
"nuke-tools": "This tool allows for mass deletions of pages recently added by a given user or an IP address.\nInput the username or IP address to get a list of pages to delete, or leave blank for all users.",
|
||||
"nuke-tools-tempaccount": "This tool allows for mass deletions of pages recently added by a given user or temporary account. Input a username or IP address to get a list of pages to delete, or leave blank for all users. Inputting an IP address will list all pages created by that IP address or any temporary accounts used from that IP address.",
|
||||
"nuke-submit-user": "List pages",
|
||||
"nuke-submit-delete": "Delete selected",
|
||||
"right-nuke": "Mass delete pages",
|
||||
|
|
|
@ -24,9 +24,12 @@
|
|||
"nuke-nopages": "Used if there are no pages to delete and the username is not empty.\n\nParameters:\n* $1 - a username\n\nSee also:\n* {{msg-mw|Nuke-nopages-global}}",
|
||||
"nuke-list": "This message refers to:\n* the comment (reason) field which has the label {{msg-mw|deletecomment}}\n* the button labeled {{msg-mw|nuke-submit-delete}}.\nParameters:\n* $1 - username\nSee also:\n* {{msg-mw|Nuke-list-multiple}}",
|
||||
"nuke-list-multiple": "This message refers to:\n* the comment (reason) field which has the label {{msg-mw|deletecomment}}\n* the button labeled {{msg-mw|nuke-submit-delete}}.\nSee also:\n* {{msg-mw|Nuke-list}}",
|
||||
"nuke-list-tempaccount": "Available when temp accounts and CheckUser are enabled. This message refers to:\n* the comment (reason) field which has the label {{msg-mw|deletecomment}}\n* the button labeled {{msg-mw|nuke-submit-delete}}.\nSee also:\n* {{msg-mw|Nuke-list}}",
|
||||
"nuke-defaultreason": "Reason for deletion in logs. {{msg-mw|nuke-multiplepeople}} is used when pages created by multiple people are deleted.\n\nParameters:\n* $1 - a username or IP address",
|
||||
"nuke-defaultreason-tempaccount": "Reason for deletion in logs, when pages created by one or more temp accounts were deleted; available when temp accounts and CheckUser are enabled.",
|
||||
"nuke-multiplepeople": "Reason for deletion in logs, when pages created by multiple users were deleted.\n\n{{msg-mw|nuke-defaultreason}} is used when pages created by only 1 user are deleted.",
|
||||
"nuke-tools": "Used as intro text for the Nuke (mass deletion) form.",
|
||||
"nuke-tools-tempaccount": "Used as intro text for the Nuke (mass deletion) form; available when temp accounts and CheckUser are enabled.",
|
||||
"nuke-submit-user": "The submit button of a form used to generate a list of pages. \"List\" is a verb here.",
|
||||
"nuke-submit-delete": "Submit button to delete the selected pages.",
|
||||
"right-nuke": "{{doc-right|nuke}}",
|
||||
|
|
24
includes/ServiceWiring.php
Normal file
24
includes/ServiceWiring.php
Normal file
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
|
||||
use MediaWiki\MediaWikiServices;
|
||||
|
||||
/*
|
||||
* CheckUser provides a service for this, but
|
||||
* we define our own nullable here to make CheckUser a soft dependency
|
||||
*/
|
||||
|
||||
return [
|
||||
'NukeIPLookup' => static function (
|
||||
MediaWikiServices $services
|
||||
) {
|
||||
// Allow IP lookups if temp user is known and CheckUser is present
|
||||
if ( !ExtensionRegistry::getInstance()->isLoaded( 'CheckUser' ) ) {
|
||||
return null;
|
||||
}
|
||||
$tempUserIsKnown = $services->getTempUserConfig()->isKnown();
|
||||
if ( !$tempUserIsKnown ) {
|
||||
return null;
|
||||
}
|
||||
return $services->get( 'CheckUserTemporaryAccountsByIPLookup' );
|
||||
}
|
||||
];
|
|
@ -3,7 +3,9 @@
|
|||
namespace MediaWiki\Extension\Nuke;
|
||||
|
||||
use DeletePageJob;
|
||||
use ErrorPageError;
|
||||
use JobQueueGroup;
|
||||
use MediaWiki\CheckUser\Services\CheckUserTemporaryAccountsByIPLookup;
|
||||
use MediaWiki\CommentStore\CommentStore;
|
||||
use MediaWiki\Extension\Nuke\Hooks\NukeHookRunner;
|
||||
use MediaWiki\Html\Html;
|
||||
|
@ -16,6 +18,8 @@ use MediaWiki\Request\WebRequest;
|
|||
use MediaWiki\SpecialPage\SpecialPage;
|
||||
use MediaWiki\Title\NamespaceInfo;
|
||||
use MediaWiki\Title\Title;
|
||||
use MediaWiki\User\Options\UserOptionsLookup;
|
||||
use MediaWiki\User\User;
|
||||
use MediaWiki\User\UserFactory;
|
||||
use MediaWiki\User\UserNamePrefixSearch;
|
||||
use MediaWiki\User\UserNameUtils;
|
||||
|
@ -26,6 +30,7 @@ use OOUI\TextInputWidget;
|
|||
use PermissionsError;
|
||||
use RepoGroup;
|
||||
use UserBlockedError;
|
||||
use Wikimedia\IPUtils;
|
||||
use Wikimedia\Rdbms\IConnectionProvider;
|
||||
use Wikimedia\Rdbms\IExpression;
|
||||
use Wikimedia\Rdbms\LikeMatch;
|
||||
|
@ -42,21 +47,29 @@ class SpecialNuke extends SpecialPage {
|
|||
private PermissionManager $permissionManager;
|
||||
private RepoGroup $repoGroup;
|
||||
private UserFactory $userFactory;
|
||||
private UserOptionsLookup $userOptionsLookup;
|
||||
private UserNamePrefixSearch $userNamePrefixSearch;
|
||||
private UserNameUtils $userNameUtils;
|
||||
private NamespaceInfo $namespaceInfo;
|
||||
private Language $contentLanguage;
|
||||
/** @var CheckUserTemporaryAccountsByIPLookup|null */
|
||||
private $checkUserTemporaryAccountsByIPLookup = null;
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function __construct(
|
||||
JobQueueGroup $jobQueueGroup,
|
||||
IConnectionProvider $dbProvider,
|
||||
PermissionManager $permissionManager,
|
||||
RepoGroup $repoGroup,
|
||||
UserFactory $userFactory,
|
||||
UserOptionsLookup $userOptionsLookup,
|
||||
UserNamePrefixSearch $userNamePrefixSearch,
|
||||
UserNameUtils $userNameUtils,
|
||||
NamespaceInfo $namespaceInfo,
|
||||
Language $contentLanguage
|
||||
Language $contentLanguage,
|
||||
$checkUserTemporaryAccountsByIPLookup = null
|
||||
) {
|
||||
parent::__construct( 'Nuke', 'nuke' );
|
||||
$this->jobQueueGroup = $jobQueueGroup;
|
||||
|
@ -64,10 +77,12 @@ class SpecialNuke extends SpecialPage {
|
|||
$this->permissionManager = $permissionManager;
|
||||
$this->repoGroup = $repoGroup;
|
||||
$this->userFactory = $userFactory;
|
||||
$this->userOptionsLookup = $userOptionsLookup;
|
||||
$this->userNamePrefixSearch = $userNamePrefixSearch;
|
||||
$this->userNameUtils = $userNameUtils;
|
||||
$this->namespaceInfo = $namespaceInfo;
|
||||
$this->contentLanguage = $contentLanguage;
|
||||
$this->checkUserTemporaryAccountsByIPLookup = $checkUserTemporaryAccountsByIPLookup;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -127,7 +142,20 @@ class SpecialNuke extends SpecialPage {
|
|||
return;
|
||||
}
|
||||
} elseif ( $req->getRawVal( 'action' ) === 'submit' ) {
|
||||
$this->listForm( $target, $reason, $limit, $namespace );
|
||||
// if the target is an ip addresss and temp account lookup is available,
|
||||
// list pages created by the ip user or by temp accounts associated with the ip address
|
||||
if (
|
||||
$this->checkUserTemporaryAccountsByIPLookup &&
|
||||
IPUtils::isValid( $target )
|
||||
) {
|
||||
$this->assertUserCanAccessTemporaryAccounts( $currentUser );
|
||||
$tempnames = $this->getTempAccountData( $target );
|
||||
$reason = $this->getDeleteReason( $this->getRequest(), $target, true );
|
||||
$this->listForm( $target, $reason, $limit, $namespace, $tempnames );
|
||||
} else {
|
||||
// otherwise just list pages normally
|
||||
$this->listForm( $target, $reason, $limit, $namespace );
|
||||
}
|
||||
} else {
|
||||
$this->promptForm();
|
||||
}
|
||||
|
@ -138,6 +166,62 @@ class SpecialNuke extends SpecialPage {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the user have the appropriate permissions and have they enabled in preferences?
|
||||
* Adapted from MediaWiki\CheckUser\Api\Rest\Handler\AbstractTemporaryAccountHandler::checkPermissions
|
||||
*
|
||||
* @param User $currentUser
|
||||
*
|
||||
* @throws PermissionsError if the user does not have the 'checkuser-temporary-account' right
|
||||
* @throws ErrorPageError if the user has not enabled the 'checkuser-temporary-account-enabled' preference
|
||||
*/
|
||||
private function assertUserCanAccessTemporaryAccounts( User $currentUser ) {
|
||||
if (
|
||||
!$currentUser->isAllowed( 'checkuser-temporary-account-no-preference' )
|
||||
) {
|
||||
if (
|
||||
!$currentUser->isAllowed( 'checkuser-temporary-account' )
|
||||
) {
|
||||
throw new PermissionsError( 'checkuser-temporary-account' );
|
||||
}
|
||||
if (
|
||||
!$this->userOptionsLookup->getOption(
|
||||
$currentUser,
|
||||
'checkuser-temporary-account-enable'
|
||||
)
|
||||
) {
|
||||
throw new ErrorPageError(
|
||||
$this->msg( 'checkuser-ip-contributions-permission-error-title' ),
|
||||
$this->msg( 'checkuser-ip-contributions-permission-error-description' )
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an IP address, return a list of temporary accounts that are known to have edited from the IP.
|
||||
*
|
||||
* Calls to this method result in a log entry being generated for the logged-in user account making the request.
|
||||
* @param string $ip The IP address used for looking up temporary account names.
|
||||
* The address will be normalized in the IP lookup service.
|
||||
* @return string[] A list of temporary account usernames associated with the IP address
|
||||
*/
|
||||
private function getTempAccountData( string $ip ): array {
|
||||
// Requires CheckUserTemporaryAccountsByIPLookup service
|
||||
if ( !$this->checkUserTemporaryAccountsByIPLookup ) {
|
||||
return [];
|
||||
}
|
||||
$status = $this->checkUserTemporaryAccountsByIPLookup->get(
|
||||
$ip,
|
||||
$this->getAuthority(),
|
||||
true
|
||||
);
|
||||
if ( $status->isGood() ) {
|
||||
return $status->getValue();
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Prompt for a username or IP address.
|
||||
*
|
||||
|
@ -146,7 +230,11 @@ class SpecialNuke extends SpecialPage {
|
|||
protected function promptForm( string $userName = '' ): void {
|
||||
$out = $this->getOutput();
|
||||
|
||||
$out->addWikiMsg( 'nuke-tools' );
|
||||
if ( $this->checkUserTemporaryAccountsByIPLookup ) {
|
||||
$out->addWikiMsg( 'nuke-tools-tempaccount' );
|
||||
} else {
|
||||
$out->addWikiMsg( 'nuke-tools' );
|
||||
}
|
||||
|
||||
$formDescriptor = [
|
||||
'nuke-target' => [
|
||||
|
@ -199,11 +287,12 @@ class SpecialNuke extends SpecialPage {
|
|||
* @param string $reason
|
||||
* @param int $limit
|
||||
* @param int|null $namespace
|
||||
* @param string[] $tempnames
|
||||
*/
|
||||
protected function listForm( $username, $reason, $limit, $namespace = null ): void {
|
||||
protected function listForm( $username, $reason, $limit, $namespace = null, $tempnames = [] ): void {
|
||||
$out = $this->getOutput();
|
||||
|
||||
$pages = $this->getNewPages( $username, $limit, $namespace );
|
||||
$pages = $this->getNewPages( $username, $limit, $namespace, $tempnames );
|
||||
|
||||
if ( !$pages ) {
|
||||
if ( $username === '' ) {
|
||||
|
@ -221,6 +310,8 @@ class SpecialNuke extends SpecialPage {
|
|||
|
||||
if ( $username === '' ) {
|
||||
$out->addWikiMsg( 'nuke-list-multiple' );
|
||||
} elseif ( $tempnames ) {
|
||||
$out->addWikiMsg( 'nuke-list-tempaccount', $username );
|
||||
} else {
|
||||
$out->addWikiMsg( 'nuke-list', $username );
|
||||
}
|
||||
|
@ -340,10 +431,11 @@ class SpecialNuke extends SpecialPage {
|
|||
* @param string $username
|
||||
* @param int $limit
|
||||
* @param int|null $namespace
|
||||
* @param string[] $tempnames
|
||||
*
|
||||
* @return array{0:Title,1:string|false}[]
|
||||
*/
|
||||
protected function getNewPages( $username, $limit, $namespace = null ): array {
|
||||
protected function getNewPages( $username, $limit, $namespace = null, $tempnames = [] ): array {
|
||||
$dbr = $this->dbProvider->getReplicaDatabase();
|
||||
$queryBuilder = $dbr->newSelectQueryBuilder()
|
||||
->select( [ 'page_title', 'page_namespace' ] )
|
||||
|
@ -362,7 +454,8 @@ class SpecialNuke extends SpecialPage {
|
|||
if ( $username === '' ) {
|
||||
$queryBuilder->field( 'actor_name', 'rc_user_text' );
|
||||
} else {
|
||||
$queryBuilder->andWhere( [ 'actor_name' => $username ] );
|
||||
$actornames = [ $username, ...$tempnames ];
|
||||
$queryBuilder->andWhere( [ 'actor_name' => $actornames ] );
|
||||
}
|
||||
|
||||
if ( $namespace !== null ) {
|
||||
|
@ -595,10 +688,14 @@ class SpecialNuke extends SpecialPage {
|
|||
return 'pagetools';
|
||||
}
|
||||
|
||||
private function getDeleteReason( WebRequest $request, string $target ): string {
|
||||
$defaultReason = $target === ''
|
||||
? $this->msg( 'nuke-multiplepeople' )->inContentLanguage()->text()
|
||||
: $this->msg( 'nuke-defaultreason', $target )->inContentLanguage()->text();
|
||||
private function getDeleteReason( WebRequest $request, string $target, bool $tempaccount = false ): string {
|
||||
if ( $tempaccount ) {
|
||||
$defaultReason = $this->msg( 'nuke-defaultreason-tempaccount' );
|
||||
} else {
|
||||
$defaultReason = $target === ''
|
||||
? $this->msg( 'nuke-multiplepeople' )->inContentLanguage()->text()
|
||||
: $this->msg( 'nuke-defaultreason', $target )->inContentLanguage()->text();
|
||||
}
|
||||
|
||||
$dropdownSelection = $request->getText( 'wpDeleteReasonList', 'other' );
|
||||
$reasonInput = $request->getText( 'wpReason', $defaultReason );
|
||||
|
|
30
tests/phpunit/integration/ServiceWiringTest.php
Normal file
30
tests/phpunit/integration/ServiceWiringTest.php
Normal file
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Copy of CentralAuth's CentralAuthServiceWiringTest.php that tests
|
||||
* the ServiceWiring.php file for the Nuke extension.
|
||||
*/
|
||||
|
||||
namespace MediaWiki\Extension\Nuke\Test;
|
||||
|
||||
use MediaWiki\MediaWikiServices;
|
||||
use MediaWikiIntegrationTestCase;
|
||||
|
||||
/**
|
||||
* @coversNothing
|
||||
* @group Database
|
||||
*/
|
||||
class ServiceWiringTest extends MediaWikiIntegrationTestCase {
|
||||
/** @dataProvider provideService */
|
||||
public function testService( string $name ) {
|
||||
MediaWikiServices::getInstance()->get( $name );
|
||||
$this->addToAssertionCount( 1 );
|
||||
}
|
||||
|
||||
public static function provideService() {
|
||||
$wiring = require __DIR__ . '/../../../includes/ServiceWiring.php';
|
||||
foreach ( $wiring as $name => $_ ) {
|
||||
yield $name => [ $name ];
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,9 +2,12 @@
|
|||
|
||||
namespace MediaWiki\Extension\Nuke\Test\Integration;
|
||||
|
||||
use ErrorPageError;
|
||||
use MediaWiki\Context\RequestContext;
|
||||
use MediaWiki\Extension\Nuke\SpecialNuke;
|
||||
use MediaWiki\Permissions\UltimateAuthority;
|
||||
use MediaWiki\Request\FauxRequest;
|
||||
use MediaWiki\Tests\User\TempUser\TempUserTestTrait;
|
||||
use MediaWiki\Title\Title;
|
||||
use PermissionsError;
|
||||
use SpecialPageTestBase;
|
||||
|
@ -17,6 +20,8 @@ use UserBlockedError;
|
|||
*/
|
||||
class SpecialNukeTest extends SpecialPageTestBase {
|
||||
|
||||
use TempUserTestTrait;
|
||||
|
||||
protected function newSpecialPage(): SpecialNuke {
|
||||
$services = $this->getServiceContainer();
|
||||
|
||||
|
@ -26,15 +31,17 @@ class SpecialNukeTest extends SpecialPageTestBase {
|
|||
$services->getPermissionManager(),
|
||||
$services->getRepoGroup(),
|
||||
$services->getUserFactory(),
|
||||
$services->getUserOptionsLookup(),
|
||||
$services->getUserNamePrefixSearch(),
|
||||
$services->getUserNameUtils(),
|
||||
$services->getNamespaceInfo(),
|
||||
$services->getContentLanguage()
|
||||
$services->getContentLanguage(),
|
||||
$services->getService( 'NukeIPLookup' )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that the prompt doesn't allow a user blocked from deleting
|
||||
* Ensure that the prompt prevents a user blocked from deleting
|
||||
* pages from accessing the form.
|
||||
*
|
||||
* @return void
|
||||
|
@ -110,11 +117,92 @@ class SpecialNukeTest extends SpecialPageTestBase {
|
|||
|
||||
public function testPrompt() {
|
||||
$admin = $this->getTestSysop()->getUser();
|
||||
$this->disableAutoCreateTempUser();
|
||||
$performer = new UltimateAuthority( $admin );
|
||||
|
||||
[ $html ] = $this->executeSpecialPage( '', null, 'qqx', $performer );
|
||||
|
||||
$this->assertStringContainsString( '(nuke-summary)', $html );
|
||||
$this->assertStringContainsString( '(nuke-tools)', $html );
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that the prompt prevents a nuke user without the checkuser-temporary-account permission
|
||||
* from performing CheckUser IP lookups
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testPromptCheckUserNoPermission() {
|
||||
$this->expectException( PermissionsError::class );
|
||||
|
||||
$this->markTestSkippedIfExtensionNotLoaded( 'CheckUser' );
|
||||
$this->enableAutoCreateTempUser();
|
||||
$ip = '1.2.3.4';
|
||||
|
||||
$adminUser = $this->getTestSysop()->getUser();
|
||||
$permissionManager = $this->getServiceContainer()->getPermissionManager();
|
||||
$permissions = $permissionManager->getUserPermissions( $adminUser );
|
||||
$permissions = array_diff( $permissions, [ 'checkuser-temporary-account' ] );
|
||||
$permissionManager->overrideUserRightsForTesting( $adminUser,
|
||||
$permissions
|
||||
);
|
||||
$performer = new UltimateAuthority( $adminUser );
|
||||
$request = new FauxRequest( [
|
||||
'target' => $ip,
|
||||
'action' => 'submit',
|
||||
], true );
|
||||
[ $html ] = $this->executeSpecialPage( '', $request, 'qqx', $performer );
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that the prompt prevents a nuke user who hasn't accepted the agreement
|
||||
* from performing CheckUser IP lookups
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testPromptCheckUserNoPreference() {
|
||||
$this->expectException( ErrorPageError::class );
|
||||
$this->expectExceptionMessage(
|
||||
'To view temporary account contributions for an IP, please accept' .
|
||||
' the agreement in [[Special:Preferences|your preferences]].'
|
||||
);
|
||||
$this->markTestSkippedIfExtensionNotLoaded( 'CheckUser' );
|
||||
$this->enableAutoCreateTempUser();
|
||||
$ip = '1.2.3.4';
|
||||
$this->overrideConfigValues( [
|
||||
'GroupPermissions' => [
|
||||
'testgroup' => [
|
||||
'nuke' => true,
|
||||
'checkuser-temporary-account' => true
|
||||
]
|
||||
]
|
||||
] );
|
||||
|
||||
$adminUser = $this->getTestUser( [ 'testgroup' ] )->getUser();
|
||||
$request = new FauxRequest( [
|
||||
'target' => $ip,
|
||||
'action' => 'submit',
|
||||
], true );
|
||||
$adminPerformer = new UltimateAuthority( $adminUser );
|
||||
[ $html ] = $this->executeSpecialPage( '', $request, 'qqx', $adminPerformer );
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that the prompt displays the correct messages when
|
||||
* temp accounts and CheckUser are enabled
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testPromptWithCheckUser() {
|
||||
$this->markTestSkippedIfExtensionNotLoaded( 'CheckUser' );
|
||||
$admin = $this->getTestSysop()->getUser();
|
||||
$this->enableAutoCreateTempUser();
|
||||
$performer = new UltimateAuthority( $admin );
|
||||
|
||||
[ $html ] = $this->executeSpecialPage( '', null, 'qqx', $performer );
|
||||
|
||||
$this->assertStringContainsString( '(nuke-summary)', $html );
|
||||
$this->assertStringContainsString( '(nuke-tools-tempaccount)', $html );
|
||||
}
|
||||
|
||||
public function testPromptTarget() {
|
||||
|
@ -136,6 +224,123 @@ class SpecialNukeTest extends SpecialPageTestBase {
|
|||
$this->assertStringContainsString( 'Target2', $html );
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that the prompt works with anon IP searches when
|
||||
* temp accounts are disabled
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testPromptTargetAnonUser() {
|
||||
$this->disableAutoCreateTempUser( [ 'known' => false ] );
|
||||
$ip = '127.0.0.1';
|
||||
$testUser = $this->getServiceContainer()->getUserFactory()->newAnonymous( $ip );
|
||||
$performer = new UltimateAuthority( $testUser );
|
||||
|
||||
$this->editPage( 'Target1', 'test', "", NS_MAIN, $performer );
|
||||
$this->editPage( 'Target2', 'test', "", NS_MAIN, $performer );
|
||||
|
||||
$adminUser = $this->getTestSysop()->getUser();
|
||||
$request = new FauxRequest( [
|
||||
'target' => $testUser->getUser()->getName()
|
||||
] );
|
||||
$adminPerformer = new UltimateAuthority( $adminUser );
|
||||
|
||||
[ $html ] = $this->executeSpecialPage( '', $request, 'qqx', $adminPerformer );
|
||||
|
||||
$this->assertStringContainsString( '(nuke-list:', $html );
|
||||
$this->assertStringContainsString( 'Target1', $html );
|
||||
$this->assertStringContainsString( 'Target2', $html );
|
||||
|
||||
$usernameCount = substr_count( $html, $ip );
|
||||
$this->assertStringContainsString( 5, $usernameCount );
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that the prompt returns temp accounts from IP lookups when
|
||||
* temp accounts and CheckUser are enabled
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testPromptTargetCheckUser() {
|
||||
$this->markTestSkippedIfExtensionNotLoaded( 'CheckUser' );
|
||||
$this->enableAutoCreateTempUser();
|
||||
$ip = '1.2.3.4';
|
||||
RequestContext::getMain()->getRequest()->setIP( $ip );
|
||||
$testUser = $this->getServiceContainer()->getTempUserCreator()
|
||||
->create( null, new FauxRequest() )->getUser();
|
||||
$this->editPage( 'Target1', 'test', "", NS_MAIN, $testUser );
|
||||
$this->editPage( 'Target2', 'test', "", NS_MAIN, $testUser );
|
||||
|
||||
$adminUser = $this->getTestSysop()->getUser();
|
||||
$permissionManager = $this->getServiceContainer()->getPermissionManager();
|
||||
$permissionManager->overrideUserRightsForTesting( $adminUser,
|
||||
array_merge(
|
||||
$permissionManager->getUserPermissions( $adminUser ),
|
||||
[ 'checkuser-temporary-account-no-preference' ]
|
||||
) );
|
||||
$request = new FauxRequest( [
|
||||
'target' => $ip,
|
||||
'action' => 'submit',
|
||||
], true );
|
||||
$adminPerformer = new UltimateAuthority( $adminUser );
|
||||
[ $html ] = $this->executeSpecialPage( '', $request, 'qqx', $adminPerformer );
|
||||
|
||||
$usernameCount = substr_count( $html, $ip );
|
||||
$this->assertStringContainsString( 1, $usernameCount );
|
||||
|
||||
$this->assertStringContainsString( '(nuke-list-tempaccount:', $html );
|
||||
$this->assertStringContainsString( 'Target1', $html );
|
||||
$this->assertStringContainsString( 'Target2', $html );
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that the prompt returns temp accounts and IP accounts from IP lookups when
|
||||
* temp accounts and CheckUser are enabled and Anonymous IP accounts exist
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testPromptTargetCheckUserMixed() {
|
||||
$this->markTestSkippedIfExtensionNotLoaded( 'CheckUser' );
|
||||
$this->disableAutoCreateTempUser( [ 'known' => false ] );
|
||||
$ip = '1.2.3.4';
|
||||
$testUser = $this->getServiceContainer()->getUserFactory()->newAnonymous( $ip );
|
||||
$performer = new UltimateAuthority( $testUser );
|
||||
|
||||
// create a page as an anonymous IP user
|
||||
$this->editPage( 'Target1', 'test', "", NS_MAIN, $performer );
|
||||
|
||||
$this->enableAutoCreateTempUser();
|
||||
RequestContext::getMain()->getRequest()->setIP( $ip );
|
||||
$testUser = $this->getServiceContainer()->getTempUserCreator()
|
||||
->create( null, new FauxRequest() )->getUser();
|
||||
$performer = new UltimateAuthority( $testUser );
|
||||
|
||||
// create a page as a temp user
|
||||
$this->editPage( 'Target2', 'test', "", NS_MAIN, $performer );
|
||||
|
||||
$adminUser = $this->getTestSysop()->getUser();
|
||||
$permissionManager = $this->getServiceContainer()->getPermissionManager();
|
||||
$permissionManager->overrideUserRightsForTesting( $adminUser,
|
||||
array_merge(
|
||||
$permissionManager->getUserPermissions( $adminUser ),
|
||||
[ 'checkuser-temporary-account-no-preference' ]
|
||||
) );
|
||||
$request = new FauxRequest( [
|
||||
'target' => $ip,
|
||||
'action' => 'submit',
|
||||
], true );
|
||||
$adminPerformer = new UltimateAuthority( $adminUser );
|
||||
[ $html ] = $this->executeSpecialPage( '', $request, 'qqx', $adminPerformer );
|
||||
|
||||
$usernameCount = substr_count( $html, $ip );
|
||||
$this->assertStringContainsString( 1, $usernameCount );
|
||||
|
||||
// They should all show up together
|
||||
$this->assertStringContainsString( '(nuke-list-tempaccount:', $html );
|
||||
$this->assertStringContainsString( 'Target1', $html );
|
||||
$this->assertStringContainsString( 'Target2', $html );
|
||||
}
|
||||
|
||||
public function testListNoPagesGlobal() {
|
||||
$admin = $this->getTestSysop()->getUser();
|
||||
$request = new FauxRequest( [
|
||||
|
|
Loading…
Reference in a new issue