Use UndeletePage from ApiUndelete

UndeletePage is responsible for checking permissions. As a user-facing
change, if the user cannot undelete pages, the module will error with
the "permissiondenied" code and the "badaccess-groups" message. This is
consistent with other API modules (e.g. ApiDelete), and replaces the
previous behaviour of failing with code "permdenied-undelete" and no
message explaining the failure (which seems to be a bug). For everything
else, backwards compatibility is preserved; in particular, we still die
with "apierror-cantundelete" if nothing was deleted (which UndeletePage
considers a successful operation).

Bug: T290021
Change-Id: I89f5e9e4a1e120e6ca6dd52987059baefbcb84d5
This commit is contained in:
Daimona Eaytoy 2021-09-28 00:10:29 +02:00
parent dcd793203b
commit 027efc625e
2 changed files with 39 additions and 26 deletions

View file

@ -255,6 +255,8 @@ class ApiMain extends ApiBase {
'services' => [
'WatchlistManager',
'UserOptionsLookup',
'UndeletePageFactory',
'WikiPageFactory',
]
],
'protect' => [

View file

@ -20,6 +20,9 @@
* @file
*/
use MediaWiki\Page\UndeletePage;
use MediaWiki\Page\UndeletePageFactory;
use MediaWiki\Page\WikiPageFactory;
use MediaWiki\Permissions\Authority;
use MediaWiki\User\UserOptionsLookup;
use MediaWiki\Watchlist\WatchlistManager;
@ -31,17 +34,27 @@ class ApiUndelete extends ApiBase {
use ApiWatchlistTrait;
/** @var UndeletePageFactory */
private $undeletePageFactory;
/** @var WikiPageFactory */
private $wikiPageFactory;
/**
* @param ApiMain $mainModule
* @param string $moduleName
* @param WatchlistManager $watchlistManager
* @param UserOptionsLookup $userOptionsLookup
* @param UndeletePageFactory $undeletePageFactory
* @param WikiPageFactory $wikiPageFactory
*/
public function __construct(
ApiMain $mainModule,
$moduleName,
WatchlistManager $watchlistManager,
UserOptionsLookup $userOptionsLookup
UserOptionsLookup $userOptionsLookup,
UndeletePageFactory $undeletePageFactory,
WikiPageFactory $wikiPageFactory
) {
parent::__construct( $mainModule, $moduleName );
@ -50,6 +63,8 @@ class ApiUndelete extends ApiBase {
$this->watchlistMaxDuration = $this->getConfig()->get( 'WatchlistExpiryMaxDuration' );
$this->watchlistManager = $watchlistManager;
$this->userOptionsLookup = $userOptionsLookup;
$this->undeletePageFactory = $undeletePageFactory;
$this->wikiPageFactory = $wikiPageFactory;
}
public function execute() {
@ -68,18 +83,6 @@ class ApiUndelete extends ApiBase {
$this->dieWithError( [ 'apierror-invalidtitle', wfEscapeWikiText( $params['title'] ) ] );
}
if ( !$this->getAuthority()->authorizeWrite( 'undelete', $titleObj ) ) {
$this->dieWithError( 'permdenied-undelete' );
}
// Check if user can add tags
if ( $params['tags'] !== null ) {
$ableToTag = ChangeTags::canAddTagsAccompanyingChange( $params['tags'], $this->getAuthority() );
if ( !$ableToTag->isOK() ) {
$this->dieStatus( $ableToTag );
}
}
// Convert timestamps
if ( !isset( $params['timestamps'] ) ) {
$params['timestamps'] = [];
@ -91,20 +94,28 @@ class ApiUndelete extends ApiBase {
$params['timestamps'][$i] = wfTimestamp( TS_MW, $ts );
}
$pa = new PageArchive( $titleObj );
$retval = $pa->undeleteAsUser(
( $params['timestamps'] ?? [] ),
$user,
$params['reason'],
$params['fileids'] ?: [],
false,
$params['tags'] ?: []
$undeletePage = $this->undeletePageFactory->newUndeletePage(
$this->wikiPageFactory->newFromTitle( $titleObj ),
$this->getAuthority()
);
if ( !is_array( $retval ) ) {
$status = $undeletePage
->setUndeleteOnlyTimestamps( $params['timestamps'] ?? [] )
->setUndeleteOnlyFileVersions( $params['fileids'] ?: [] )
->setTags( $params['tags'] ?: [] )
->undeleteIfAllowed( $params['reason'] );
if ( !$status->isGood() ) {
$this->dieStatus( $status );
}
$restoredRevs = $status->getValue()[UndeletePage::REVISIONS_RESTORED];
$restoredFiles = $status->getValue()[UndeletePage::FILES_RESTORED];
if ( $restoredRevs === 0 && $restoredFiles === 0 ) {
// BC for code that predates UndeletePage
$this->dieWithError( 'apierror-cantundelete' );
}
if ( $retval[1] ) {
if ( $restoredFiles ) {
$this->getHookRunner()->onFileUndeleteComplete(
$titleObj, $params['fileids'],
$this->getUser(), $params['reason'] );
@ -115,9 +126,9 @@ class ApiUndelete extends ApiBase {
$info = [
'title' => $titleObj->getPrefixedText(),
'revisions' => (int)$retval[0],
'fileversions' => (int)$retval[1],
'reason' => $retval[2]
'revisions' => $restoredRevs,
'fileversions' => $restoredFiles,
'reason' => $params['reason']
];
$this->getResult()->addValue( null, $this->getModuleName(), $info );
}