use MediaWiki\Block\AbstractBlock;
use MediaWiki\Block\DatabaseBlock;
+use MediaWiki\Linker\LinkTarget;
use MediaWiki\MediaWikiServices;
+use MediaWiki\Permissions\PermissionManager;
use Wikimedia\Rdbms\IDatabase;
/**
$this->getMain()->setContinuationManager( $manager );
}
+ /**
+ * Obtain a PermissionManager instance that subclasses may use in their authorization checks.
+ *
+ * @since 1.34
+ * @return PermissionManager
+ */
+ protected function getPermissionManager(): PermissionManager {
+ return MediaWikiServices::getInstance()->getPermissionManager();
+ }
+
/**@}*/
/************************************************************************//**
/**
* Helper function for permission-denied errors
- * @since 1.29
- * @since 1.33 Changed the third parameter from $user to $options.
- * @param Title $title
+ *
+ * @param LinkTarget $linkTarget
* @param string|string[] $actions
* @param array $options Additional options
* - user: (User) User to use rather than $this->getUser()
* - autoblock: (bool, default false) Whether to spread autoblocks
* For compatibility, passing a User object is treated as the value for the 'user' option.
* @throws ApiUsageException if the user doesn't have all of the rights.
+ *
+ * @since 1.29
+ * @since 1.33 Changed the third parameter from $user to $options.
*/
- public function checkTitleUserPermissions( Title $title, $actions, $options = [] ) {
+ public function checkTitleUserPermissions( LinkTarget $linkTarget, $actions, $options = [] ) {
if ( !is_array( $options ) ) {
wfDeprecated( '$user as the third parameter to ' . __METHOD__, '1.33' );
$options = [ 'user' => $options ];
$errors = [];
foreach ( (array)$actions as $action ) {
- $errors = array_merge( $errors, $title->getUserPermissionsErrors( $action, $user ) );
+ $errors = array_merge(
+ $errors,
+ $this->getPermissionManager()->getPermissionErrors( $action, $user, $linkTarget )
+ );
}
if ( $errors ) {
// Hook completed and did not return a valid feed item
$title = Title::makeTitle( (int)$row->page_namespace, $row->page_title );
- if ( $title && $title->userCan( 'read', $this->getUser() ) ) {
+ $user = $this->getUser();
+
+ if ( $title && $this->getPermissionManager()->userCan( 'read', $user, $title ) ) {
$date = $row->rev_timestamp;
$comments = $title->getTalkPage()->getFullURL();
$revision = $this->revisionStore->newRevisionFromRow( $row );
$exportTitles = [];
$titles = $pageSet->getGoodTitles();
if ( count( $titles ) ) {
- $user = $this->getUser();
/** @var Title $title */
foreach ( $titles as $title ) {
- if ( $title->userCan( 'read', $user ) ) {
+ if ( $this->getPermissionManager()->userCan( 'read', $this->getUser(), $title ) ) {
$exportTitles[] = $title;
}
}
$pageInfo['pagelanguagehtmlcode'] = $pageLanguage->getHtmlCode();
$pageInfo['pagelanguagedir'] = $pageLanguage->getDir();
+ $user = $this->getUser();
+
if ( $titleExists ) {
$pageInfo['touched'] = wfTimestamp( TS_ISO_8601, $this->pageTouched[$pageid] );
$pageInfo['lastrevid'] = (int)$this->pageLatest[$pageid];
$pageInfo['canonicalurl'] = wfExpandUrl( $title->getFullURL(), PROTO_CANONICAL );
}
if ( $this->fld_readable ) {
- $pageInfo['readable'] = $title->userCan( 'read', $this->getUser() );
+ $pageInfo['readable'] = $this->getPermissionManager()->userCan(
+ 'read', $user, $title
+ );
}
if ( $this->fld_preload ) {
$this->countTestedActions++;
if ( $detailLevel === 'boolean' ) {
- $pageInfo['actions'][$action] = $title->userCan( $action, $user );
+ $pageInfo['actions'][$action] = $this->getPermissionManager()->userCan(
+ $action, $user, $title
+ );
} else {
$pageInfo['actions'][$action] = $errorFormatter->arrayFromStatus( $this->errorArrayToStatus(
- $title->getUserPermissionsErrors( $action, $user, $rigor ),
+ $this->getPermissionManager()->getPermissionErrors(
+ $action, $user, $title, $rigor
+ ),
$user
) );
}
if ( $resultPageSet === null && $this->fetchContent ) {
// For each page we will request, the user must have read rights for that page
- $user = $this->getUser();
$status = Status::newGood();
+ $user = $this->getUser();
+
/** @var Title $title */
foreach ( $pageSet->getGoodTitles() as $title ) {
- if ( !$title->userCan( 'read', $user ) ) {
+ if ( !$this->getPermissionManager()->userCan( 'read', $user, $title ) ) {
$status->fatal( ApiMessage::create(
[ 'apierror-cannotviewtitle', wfEscapeWikiText( $title->getPrefixedText() ) ],
'accessdenied'
$this->dieWithError( [ 'apierror-invalidtitle', wfEscapeWikiText( $params['title'] ) ] );
}
- if ( !$titleObj->userCan( 'undelete', $user, 'secure' ) ) {
+ if ( !$this->getPermissionManager()->userCan( 'undelete', $this->getUser(), $titleObj ) ) {
$this->dieWithError( 'permdenied-undelete' );
}
);
}
}
+
+ public function testShouldNotExportPagesThatUserCanNotRead() {
+ $title = Title::makeTitle( NS_MAIN, 'Test article' );
+ $this->insertPage( $title );
+
+ $this->setTemporaryHook( 'getUserPermissionsErrors',
+ function ( Title $page, &$user, $action, &$result ) use ( $title ) {
+ if ( $page->equals( $title ) && $action === 'read' ) {
+ $result = false;
+ return false;
+ }
+ } );
+
+ $data = $this->doApiRequest( [
+ 'action' => 'query',
+ 'titles' => $title->getPrefixedText(),
+ 'export' => 1,
+ ] );
+
+ $this->assertArrayHasKey( 'query', $data[0] );
+ $this->assertArrayHasKey( 'export', $data[0]['query'] );
+ // This response field contains an XML document even if no pages were exported
+ $this->assertNotContains( $title->getPrefixedText(), $data[0]['query']['export'] );
+ }
}