* PermissionsError now calls OutputPage::showPermissionsErrorPage() to display the error (this is needed to make the item above work correctly)
* Removed the override of the HTML title in OutputPage::showPermissionsErrorPage() so that it shows "Permission errors - Sitename" instead of simply "Permission errors" for consistency with the other things
* Pass the error array returned by Title::getUserPermissionsErrors() to PermissionsError where available
* Converted direct calls to OutputPage::showPermissionsErrorPage() to throw an PermissionsError error instead
* Added 'action-rollback' message that will be displayed when accessing action=rollback without sufficient rights
* Changed getRestriction() in subclasses of Action to return null when they previously returned 'read' so that user rights can be check with Title::getUserPermissionsErrors()
* Reordered checks to do first user rights, then block (if needed) and finally read only (also if needed) so that users don't think the error is temporary when they both don't have right and the database is locked
* @throws ErrorPageError
*/
protected function checkCanExecute( User $user ) {
- if ( $this->requiresWrite() && wfReadOnly() ) {
- throw new ReadOnlyError();
- }
-
- if ( $this->getRestriction() !== null && !$user->isAllowed( $this->getRestriction() ) ) {
- throw new PermissionsError( $this->getRestriction() );
+ $right = $this->getRestriction();
+ if ( $right !== null ) {
+ $errors = $this->getTitle()->getUserPermissionsErrors( $right, $user );
+ if ( count( $errors ) ) {
+ throw new PermissionsError( $right, $errors );
+ }
}
if ( $this->requiresUnblock() && $user->isBlocked() ) {
$block = $user->mBlock;
throw new UserBlockedError( $block );
}
+
+ // This should be checked at the end so that the user won't think the
+ // error is only temporary when he also don't have the rights to execute
+ // this action
+ if ( $this->requiresWrite() && wfReadOnly() ) {
+ throw new ReadOnlyError();
+ }
}
/**
public function delete() {
global $wgOut, $wgRequest;
+ # This code desperately needs to be totally rewritten
+
+ # Check permissions
+ $permission_errors = $this->mTitle->getUserPermissionsErrors( 'delete', $this->getContext()->getUser() );
+ if ( count( $permission_errors ) ) {
+ throw new PermissionsError( 'delete', $permission_errors );
+ }
+
+ # Read-only check...
+ if ( wfReadOnly() ) {
+ throw new ReadOnlyError;
+ }
+
$confirm = $wgRequest->wasPosted() &&
$this->getContext()->getUser()->matchEditToken( $wgRequest->getVal( 'wpEditToken' ) );
# Flag to hide all contents of the archived revisions
$suppress = $wgRequest->getVal( 'wpSuppress' ) && $this->getContext()->getUser()->isAllowed( 'suppressrevision' );
- # This code desperately needs to be totally rewritten
-
- # Read-only check...
- if ( wfReadOnly() ) {
- $wgOut->readOnlyPage();
-
- return;
- }
-
- # Check permissions
- $permission_errors = $this->getTitle()->getUserPermissionsErrors( 'delete', $this->getContext()->getUser() );
-
- if ( count( $permission_errors ) > 0 ) {
- $wgOut->showPermissionsErrorPage( $permission_errors );
-
- return;
- }
-
$wgOut->setPageTitle( wfMessage( 'delete-confirm', $this->getTitle()->getPrefixedText() ) );
# Better double-check that it hasn't been deleted yet!
* @ingroup Exception
*/
class PermissionsError extends ErrorPageError {
- public $permission;
+ public $permission, $errors;
- function __construct( $permission ) {
+ function __construct( $permission, $errors = array() ) {
global $wgLang;
$this->permission = $permission;
- $groups = array_map(
- array( 'User', 'makeGroupLinkWiki' ),
- User::getGroupsWithPermission( $this->permission )
- );
-
- if( $groups ) {
- parent::__construct(
- 'badaccess',
- 'badaccess-groups',
- array(
- $wgLang->commaList( $groups ),
- count( $groups )
- )
- );
- } else {
- parent::__construct(
- 'badaccess',
- 'badaccess-group0'
+ if ( !count( $errors ) ) {
+ $groups = array_map(
+ array( 'User', 'makeGroupLinkWiki' ),
+ User::getGroupsWithPermission( $this->permission )
);
+
+ if ( $groups ) {
+ $errors[] = array( 'badaccess-groups', $wgLang->commaList( $groups ), count( $groups ) );
+ } else {
+ $errors[] = array( 'badaccess-group0' );
+ }
}
+
+ $this->errors = $errors;
+ }
+
+ function report() {
+ global $wgOut;
+
+ $wgOut->showPermissionsErrorPage( $this->errors, $this->permission );
+ $wgOut->output();
}
}
*/
public function execute() {
global $wgOut, $wgRequest, $wgUser;
- $this->setHeaders();
- $permission_errors = $this->title->getUserPermissionsErrors('delete', $wgUser);
- if ( count( $permission_errors ) > 0 ) {
- $wgOut->showPermissionsErrorPage( $permission_errors );
- return;
+ $permissionErrors = $this->title->getUserPermissionsErrors( 'delete', $wgUser );
+ if ( count( $permissionErrors ) ) {
+ throw new PermissionsError( 'delete', $permissionErrors );
}
if ( wfReadOnly() ) {
throw new ReadOnlyError;
}
+ $this->setHeaders();
+
$this->oldimage = $wgRequest->getText( 'oldimage', false );
$token = $wgRequest->getText( 'wpEditToken' );
# Flag to hide all contents of the archived revisions
* @param $action String: action that was denied or null if unknown
*/
public function showPermissionsErrorPage( $errors, $action = null ) {
- $this->prepareErrorPage( $this->msg( 'permissionserrors' ), $this->msg( 'permissionserrors' ) );
+ $this->prepareErrorPage( $this->msg( 'permissionserrors' ) );
$this->addWikiText( $this->formatPermissionsErrorMessage( $errors, $action ) );
}
}
public function getRestriction() {
- return 'read';
+ return null;
}
public function requiresWrite() {
}
public function getRestriction() {
- return 'read';
+ return null;
}
protected function getDescription() {
}
public function getRestriction() {
- return 'read';
+ return null;
}
protected function getDescription() {
return;
}
- if ( !empty( $errors ) ) {
- $this->getOutput()->showPermissionsErrorPage( $errors );
- return;
+ if ( count( $errors ) ) {
+ throw new PermissionsErrorPage( 'patrol', $errors );
}
# Inform the user
}
public function getRestriction() {
- return 'read';
+ return null;
}
public function requiresWrite() {
}
public function getRestriction() {
- return 'read';
+ return null;
}
public function show() {
$out [] = $error;
}
}
- $this->getOutput()->showPermissionsErrorPage( $out );
-
- return;
+ throw new PermissionsError( 'rollback', $out );
}
if ( $result == array( array( 'readonlytext' ) ) ) {
}
public function getRestriction() {
- return 'read';
+ return null;
}
public function requiresUnblock() {
throw new PermissionsError( 'import' );
}
- if ( wfReadOnly() ) {
- throw new ReadOnlyError;
- }
-
# @todo Allow Title::getUserPermissionsErrors() to take an array
# @todo FIXME: Title::checkSpecialsAndNSPermissions() has a very wierd expectation of what
# getUserPermissionsErrors() might actually be used for, hence the 'ns-specialprotected'
)
);
- if( $errors ){
- $this->getOutput()->showPermissionsErrorPage( $errors );
- return;
+ if ( $errors ) {
+ throw new PermissionsError( 'import', $errors );
+ }
+
+ if ( wfReadOnly() ) {
+ throw new ReadOnlyError;
}
$request = $this->getRequest();
if( !empty( $permErrors ) ) {
// Auto-block user's IP if the account was "hard" blocked
$user->spreadAnyEditBlock();
- $this->getOutput()->showPermissionsErrorPage( $permErrors );
- return;
+ throw new PermissionsError( 'move', $permErrors );
}
$def = !$request->wasPosted();
// Block signup here if in readonly. Keeps user from
// going through the process (filling out data, etc)
// and being informed later.
- if ( wfReadOnly() ) {
- throw new ReadOnlyError;
+ $permErrors = $titleObj->getUserPermissionsErrors( 'createaccount', $user, true );
+ if ( count( $permErrors ) ) {
+ throw new PermissionsError( 'createaccount', $permErrors );
} elseif ( $user->isBlockedFromCreateAccount() ) {
$this->userBlockedMessage( $user->isBlockedFromCreateAccount() );
return;
- } elseif ( count( $permErrors = $titleObj->getUserPermissionsErrors( 'createaccount', $user, true ) )>0 ) {
- $this->getOutput()->showPermissionsErrorPage( $permErrors, 'createaccount' );
- return;
+ } elseif ( wfReadOnly() ) {
+ throw new ReadOnlyError;
}
}
$this->isself = true;
}
- $out = $this->getOutput();
-
if( !$this->userCanChangeRights( $user, true ) ) {
// @todo FIXME: There may be intermediate groups we can mention.
- $out->showPermissionsErrorPage( array( array(
- $user->isAnon()
- ? 'userrights-nologin'
- : 'userrights-notallowed' ) ) );
- return;
+ $msg = $user->isAnon() ? 'userrights-nologin' : 'userrights-notallowed';
+ throw new PermissionsError( null, array( array( $msg ) ) );
}
if ( wfReadOnly() ) {
throw new ReadOnlyError;
}
+ $this->setHeaders();
$this->outputHeader();
+
+ $out = $this->getOutput();
$out->addModuleStyles( 'mediawiki.special' );
- $this->setHeaders();
// show the general form
if ( count( $available['add'] ) || count( $available['remove'] ) ) {
'action-suppressionlog' => 'view this private log',
'action-block' => 'block this user from editing',
'action-protect' => 'change protection levels for this page',
+'action-rollback' => 'quickly rollback the edits of the last user who edited a particular page',
'action-import' => 'import this page from another wiki',
'action-importupload' => 'import this page from a file upload',
'action-patrol' => "mark others' edit as patrolled",
'action-suppressionlog' => '{{Doc-action|suppressionlog}}',
'action-block' => '{{Doc-action|block}}',
'action-protect' => '{{Doc-action|protect}}',
+'action-rollback' => '{{Doc-action|rollback}}',
'action-import' => '{{Doc-action|import}}',
'action-importupload' => '{{Doc-action|importupload}}',
'action-patrol' => '{{Doc-action|patrol}}',
'action-suppressionlog',
'action-block',
'action-protect',
+ 'action-rollback',
'action-import',
'action-importupload',
'action-patrol',