Page MenuHomeWickedGov Phorge

GlobalRenameUser.php
No OneTemporary

Size
7 KB
Referenced Files
None
Subscribers
None

GlobalRenameUser.php

<?php
namespace MediaWiki\Extension\CentralAuth\GlobalRename;
use Job;
use MediaWiki\Extension\CentralAuth\GlobalRename\LocalRenameJob\LocalRenameUserJob;
use MediaWiki\Extension\CentralAuth\User\CentralAuthAntiSpoofManager;
use MediaWiki\Extension\CentralAuth\User\CentralAuthUser;
use MediaWiki\JobQueue\JobQueueGroupFactory;
use MediaWiki\Status\Status;
use MediaWiki\Title\Title;
use MediaWiki\User\UserIdentity;
use Wikimedia\Rdbms\IDBAccessObject;
/**
* Rename a global user
*
* @license GPL-2.0-or-later
* @author Marius Hoch < hoo@online.de >
*/
class GlobalRenameUser {
/**
* @var UserIdentity
*/
private $performingUser;
/**
* @var UserIdentity
*/
private $oldUser;
/**
* @var CentralAuthUser
*/
private $oldCAUser;
/**
* @var UserIdentity
*/
private $newUser;
/**
* @var CentralAuthUser
*/
private $newCAUser;
/**
* @var GlobalRenameUserStatus
*/
private $renameuserStatus;
/** @var JobQueueGroupFactory */
private $jobQueueGroupFactory;
/**
* @var GlobalRenameUserDatabaseUpdates
*/
private $databaseUpdates;
/**
* @var GlobalRenameUserLogger
*/
private $logger;
private CentralAuthAntiSpoofManager $caAntiSpoofManager;
/**
* @var array|null
*/
private ?array $session = null;
/**
* @var UserIdentity|null
*/
private ?UserIdentity $lockPerformingUser;
/**
* @param UserIdentity $performingUser
* @param UserIdentity $oldUser
* @param CentralAuthUser $oldCAUser
* @param UserIdentity $newUser Validated (creatable!) new user
* @param CentralAuthUser $newCAUser
* @param GlobalRenameUserStatus $renameuserStatus
* @param JobQueueGroupFactory $jobQueueGroupFactory
* @param GlobalRenameUserDatabaseUpdates $databaseUpdates
* @param GlobalRenameUserLogger $logger
* @param CentralAuthAntiSpoofManager $caAntiSpoofManager
*/
public function __construct(
UserIdentity $performingUser,
UserIdentity $oldUser,
CentralAuthUser $oldCAUser,
UserIdentity $newUser,
CentralAuthUser $newCAUser,
GlobalRenameUserStatus $renameuserStatus,
JobQueueGroupFactory $jobQueueGroupFactory,
GlobalRenameUserDatabaseUpdates $databaseUpdates,
GlobalRenameUserLogger $logger,
CentralAuthAntiSpoofManager $caAntiSpoofManager
) {
$this->performingUser = $performingUser;
$this->oldUser = $oldUser;
$this->oldCAUser = $oldCAUser;
$this->newUser = $newUser;
$this->newCAUser = $newCAUser;
$this->renameuserStatus = $renameuserStatus;
$this->jobQueueGroupFactory = $jobQueueGroupFactory;
$this->databaseUpdates = $databaseUpdates;
$this->logger = $logger;
$this->caAntiSpoofManager = $caAntiSpoofManager;
}
/**
* Set session data to use with this rename.
*
* @param array $session
* @return GlobalRenameUser
*/
public function withSession( array $session ): GlobalRenameUser {
$this->session = $session;
return $this;
}
/**
* Override the performer to be credited with account locking for vanishes.
*
* @param UserIdentity $lockPerformingUser
* @return GlobalRenameUser
*/
public function withLockPerformingUser( UserIdentity $lockPerformingUser ): GlobalRenameUser {
$this->lockPerformingUser = $lockPerformingUser;
return $this;
}
/**
* Rename a global user (this assumes that the data has been verified before
* and that $newUser is being a creatable user)!
*
* @param array $options
* @return Status
*/
public function rename( array $options ) {
if ( $this->oldUser->getName() === $this->newUser->getName() ) {
return Status::newFatal( 'centralauth-rename-same-name' );
}
static $keepDetails = [ 'attachedMethod' => true, 'attachedTimestamp' => true ];
$wikisAttached = array_map(
static function ( $details ) use ( $keepDetails ) {
return array_intersect_key( $details, $keepDetails );
},
$this->oldCAUser->queryAttached()
);
$status = $this->setRenameStatuses( array_keys( $wikisAttached ) );
if ( !$status->isOK() ) {
return $status;
}
// Rename the user centrally and unattach the old user from all
// attached wikis. Each will be reattached as its LocalRenameUserJob
// runs.
$this->databaseUpdates->update(
$this->oldUser->getName(),
$this->newUser->getName(),
$options['type'] ?? GlobalRenameRequest::RENAME
);
// Update CA's AntiSpoof
$this->caAntiSpoofManager
->getSpoofUser( $this->newUser->getName() )
->update( $this->oldUser->getName() );
if (
isset( $options['type'] ) &&
$options['type'] === GlobalRenameRequest::VANISH &&
!$this->newCAUser->isLocked()
) {
$this->newCAUser->adminLock();
$this->newCAUser->logAction(
'setstatus',
$this->lockPerformingUser ?? $this->performingUser,
// Reason in this context should be the public log entry, not
// the private reason stated by the user.
$options['reason'] ?? '',
[ 'added' => [ 'locked' ], 'removed' => [] ],
false,
false
);
}
// From this point on all code using CentralAuthUser
// needs to use the new username, except for
// the renameInProgress function. Probably.
// Clear some caches...
$this->oldCAUser->quickInvalidateCache();
$this->newCAUser->quickInvalidateCache();
// If job insertion fails, an exception will cause rollback of all DBs.
// The job will block on reading renameuser_status until this commits due to it using
// a locking read and the pending update from setRenameStatuses() above. If we end up
// rolling back, then the job will abort because the status will not be 'queued'.
$this->injectLocalRenameUserJobs( $wikisAttached, $options );
$this->logger->log(
$this->oldUser->getName(),
$this->newUser->getName(),
$options
);
return Status::newGood();
}
/**
* @param array $wikis
*
* @return Status
*/
private function setRenameStatuses( array $wikis ) {
$rows = [];
foreach ( $wikis as $wiki ) {
// @TODO: This shouldn't know about these column names
$rows[] = [
'ru_wiki' => $wiki,
'ru_oldname' => $this->oldUser->getName(),
'ru_newname' => $this->newUser->getName(),
'ru_status' => 'queued'
];
}
$success = $this->renameuserStatus->setStatuses( $rows );
if ( !$success ) {
// Race condition: Another admin already started the rename!
return Status::newFatal( 'centralauth-rename-alreadyinprogress', $this->newUser->getName() );
}
return Status::newGood();
}
/**
* @param array $wikisAttached Attached wiki info
* @param array $options
*/
private function injectLocalRenameUserJobs(
array $wikisAttached, array $options
) {
$job = $this->getJob( $options, $wikisAttached );
$statuses = $this->renameuserStatus->getStatuses( IDBAccessObject::READ_LATEST );
foreach ( $statuses as $wiki => $status ) {
if ( $status === 'queued' ) {
$this->jobQueueGroupFactory->makeJobQueueGroup( $wiki )->push( $job );
break;
}
}
}
/**
* @param array $options
* @param array $wikisAttached Attached wiki info
*
* @return Job
*/
private function getJob( array $options, array $wikisAttached ) {
$params = [
'from' => $this->oldUser->getName(),
'to' => $this->newUser->getName(),
'renamer' => $this->performingUser->getName(),
'reattach' => $wikisAttached,
'movepages' => $options['movepages'],
'suppressredirects' => $options['suppressredirects'],
'promotetoglobal' => false,
'reason' => $options['reason'],
'force' => isset( $options['force'] ) && $options['force'],
];
if ( $this->session !== null ) {
$params['session'] = $this->session;
}
// This isn't used anywhere!
$title = Title::newFromText( 'Global rename job' );
return new LocalRenameUserJob( $title, $params );
}
}

File Metadata

Mime Type
text/x-php
Expires
Sat, May 16, 20:21 (23 h, 43 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
bb/71/5450358f034959c0aa4ee5bed4aa
Default Alt Text
GlobalRenameUser.php (7 KB)

Event Timeline