Page Menu
Home
WickedGov Phorge
Search
Configure Global Search
Log In
Files
F1431342
GlobalRenameUser.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
7 KB
Referenced Files
None
Subscribers
None
GlobalRenameUser.php
View Options
<?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
Details
Attached
Mime Type
text/x-php
Expires
Sat, May 16, 20:21 (23 h, 25 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
bb/71/5450358f034959c0aa4ee5bed4aa
Default Alt Text
GlobalRenameUser.php (7 KB)
Attached To
Mode
rMWPROD MediaWiki Production
Attached
Detach File
Event Timeline
Log In to Comment