jenkins-bot has submitted this change and it was merged.

Change subject: Consistently handle anonymous users on logged-in-only special 
pages
......................................................................


Consistently handle anonymous users on logged-in-only special pages

Added new helper function SpecialPage#requireLogin() to check if the
current user is logged in and, if not, format an error message linking
to Special:Userlogin and throw UserNotLoggedIn exception, to be
handled by OutputPage later.

Reused old error messages. Not all use the new parameter and they're
very inconsistent, but this is a matter for another patch.

Used it on 7 special pages. I don't think there are any other ones
which specifically require having an account, instead of just some
rights usually associated with logged-in users.

* SpecialChangeEmail
* SpecialChangePassword: It allows anonymous users under specific
  circumstances, but is logged-in-only in general.
* SpecialConfirmemail
* SpecialEditWatchlist
* SpecialPreferences
* SpecialResetTokens: It was missing the check, added it.
* SpecialWatchlist

Change-Id: I43ceaddb370d09784021b3fc2d5d1ff6616fef1f
---
M includes/SpecialPage.php
M includes/specials/SpecialChangeEmail.php
M includes/specials/SpecialChangePassword.php
M includes/specials/SpecialConfirmemail.php
M includes/specials/SpecialEditWatchlist.php
M includes/specials/SpecialPreferences.php
M includes/specials/SpecialResetTokens.php
M includes/specials/SpecialWatchlist.php
M languages/messages/MessagesEn.php
M languages/messages/MessagesQqq.php
M maintenance/dictionary/mediawiki.dic
M maintenance/language/messages.inc
12 files changed, 73 insertions(+), 66 deletions(-)

Approvals:
  Aude: Looks good to me, but someone else must approve
  Parent5446: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/includes/SpecialPage.php b/includes/SpecialPage.php
index a6195fc..3aea4d9 100644
--- a/includes/SpecialPage.php
+++ b/includes/SpecialPage.php
@@ -600,6 +600,49 @@
        }
 
        /**
+        * If the user is not logged in, throws UserNotLoggedIn error.
+        *
+        * Default error message includes a link to Special:Userlogin with 
properly set 'returnto' query
+        * parameter.
+        *
+        * @since 1.23
+        * @param string|Message $reasonMsg [optional] Passed on to 
UserNotLoggedIn constructor. Strings
+        *     will be used as message keys. If a string is given, the message 
will also receive a
+        *     formatted login link (generated using the 'loginreqlink' 
message) as first parameter. If a
+        *     Message is given, it will be passed on verbatim.
+        * @param string|Message $titleMsg [optional] Passed on to 
UserNotLoggedIn constructor. Strings
+        *     will be used as message keys.
+        * @throws UserNotLoggedIn
+        */
+       public function requireLogin( $reasonMsg = null, $titleMsg = null ) {
+               if ( $this->getUser()->isAnon() ) {
+                       // Use default messages if not given or explicit null 
passed
+                       if ( !$reasonMsg ) {
+                               $reasonMsg = 'exception-nologin-text-manual';
+                       }
+                       if ( !$titleMsg ) {
+                               $titleMsg = 'exception-nologin';
+                       }
+
+                       // Convert to Messages with current context
+                       if ( is_string( $reasonMsg ) ) {
+                               $loginreqlink = Linker::linkKnown(
+                                       SpecialPage::getTitleFor( 'Userlogin' ),
+                                       $this->msg( 'loginreqlink' )->escaped(),
+                                       array(),
+                                       array( 'returnto' => 
$this->getTitle()->getPrefixedText() )
+                               );
+                               $reasonMsg = $this->msg( $reasonMsg 
)->rawParams( $loginreqlink );
+                       }
+                       if ( is_string( $titleMsg ) ) {
+                               $titleMsg = $this->msg( $titleMsg );
+                       }
+
+                       throw new UserNotLoggedIn( $reasonMsg, $titleMsg );
+               }
+       }
+
+       /**
         * Sets headers - this should be called from the execute() method of 
all derived classes!
         */
        function setHeaders() {
diff --git a/includes/specials/SpecialChangeEmail.php 
b/includes/specials/SpecialChangeEmail.php
index d02886f..e1531cc 100644
--- a/includes/specials/SpecialChangeEmail.php
+++ b/includes/specials/SpecialChangeEmail.php
@@ -75,11 +75,7 @@
                $user = $this->getUser();
                $request = $this->getRequest();
 
-               if ( !$user->isLoggedIn() ) {
-                       $this->error( 'changeemail-no-info' );
-
-                       return;
-               }
+               $this->requireLogin( 'changeemail-no-info' );
 
                if ( $request->wasPosted() && $request->getBool( 'wpCancel' ) ) 
{
                        $this->doReturnTo();
@@ -92,7 +88,7 @@
 
                // This could also let someone check the current email address, 
so
                // require both permissions.
-               if ( !$this->getUser()->isAllowed( 'viewmyprivateinfo' ) ) {
+               if ( !$user->isAllowed( 'viewmyprivateinfo' ) ) {
                        throw new PermissionsError( 'viewmyprivateinfo' );
                }
 
diff --git a/includes/specials/SpecialChangePassword.php 
b/includes/specials/SpecialChangePassword.php
index 7fcab19..8b96e6c 100644
--- a/includes/specials/SpecialChangePassword.php
+++ b/includes/specials/SpecialChangePassword.php
@@ -45,6 +45,11 @@
                $this->getOutput()->disallowUserJs();
 
                $request = $this->getRequest();
+
+               if ( !$request->wasPosted() ) {
+                       $this->requireLogin( 'resetpass-no-info' );
+               }
+
                $this->mUserName = trim( $request->getVal( 'wpName' ) );
                $this->mOldpass = $request->getVal( 'wpPassword' );
                $this->mNewpass = $request->getVal( 'wpNewPassword' );
@@ -52,11 +57,6 @@
                $this->mDomain = $request->getVal( 'wpDomain' );
 
                $user = $this->getUser();
-               if ( !$request->wasPosted() && !$user->isLoggedIn() ) {
-                       $this->error( $this->msg( 'resetpass-no-info' )->text() 
);
-
-                       return;
-               }
 
                if ( $request->wasPosted() && $request->getBool( 'wpCancel' ) ) 
{
                        $titleObj = Title::newFromText( $request->getVal( 
'returnto' ) );
diff --git a/includes/specials/SpecialConfirmemail.php 
b/includes/specials/SpecialConfirmemail.php
index 6757990..bef155c 100644
--- a/includes/specials/SpecialConfirmemail.php
+++ b/includes/specials/SpecialConfirmemail.php
@@ -45,6 +45,8 @@
                $this->checkReadOnly();
                $this->checkPermissions();
 
+               $this->requireLogin( 'confirmemail_needlogin' );
+
                // This could also let someone check the current email address, 
so
                // require both permissions.
                if ( !$this->getUser()->isAllowed( 'viewmyprivateinfo' ) ) {
@@ -52,22 +54,10 @@
                }
 
                if ( $code === null || $code === '' ) {
-                       if ( $this->getUser()->isLoggedIn() ) {
-                               if ( Sanitizer::validateEmail( 
$this->getUser()->getEmail() ) ) {
-                                       $this->showRequestForm();
-                               } else {
-                                       $this->getOutput()->addWikiMsg( 
'confirmemail_noemail' );
-                               }
+                       if ( Sanitizer::validateEmail( 
$this->getUser()->getEmail() ) ) {
+                               $this->showRequestForm();
                        } else {
-                               $llink = Linker::linkKnown(
-                                       SpecialPage::getTitleFor( 'Userlogin' ),
-                                       $this->msg( 'loginreqlink' )->escaped(),
-                                       array(),
-                                       array( 'returnto' => 
$this->getTitle()->getPrefixedText() )
-                               );
-                               $this->getOutput()->addHTML(
-                                       $this->msg( 'confirmemail_needlogin' 
)->rawParams( $llink )->parse()
-                               );
+                               $this->getOutput()->addWikiMsg( 
'confirmemail_noemail' );
                        }
                } else {
                        $this->attemptConfirm( $code );
diff --git a/includes/specials/SpecialEditWatchlist.php 
b/includes/specials/SpecialEditWatchlist.php
index ca2daaf..e085240 100644
--- a/includes/specials/SpecialEditWatchlist.php
+++ b/includes/specials/SpecialEditWatchlist.php
@@ -61,21 +61,10 @@
        public function execute( $mode ) {
                $this->setHeaders();
 
-               $out = $this->getOutput();
-
                # Anons don't get a watchlist
-               if ( $this->getUser()->isAnon() ) {
-                       $out->setPageTitle( $this->msg( 'watchnologin' ) );
-                       $llink = Linker::linkKnown(
-                               SpecialPage::getTitleFor( 'Userlogin' ),
-                               $this->msg( 'loginreqlink' )->escaped(),
-                               array(),
-                               array( 'returnto' => 
$this->getTitle()->getPrefixedText() )
-                       );
-                       $out->addHTML( $this->msg( 'watchlistanontext' 
)->rawParams( $llink )->parse() );
+               $this->requireLogin( 'watchlistanontext', 'watchnologin' );
 
-                       return;
-               }
+               $out = $this->getOutput();
 
                $this->checkPermissions();
                $this->checkReadOnly();
diff --git a/includes/specials/SpecialPreferences.php 
b/includes/specials/SpecialPreferences.php
index ecee0bb..5f4b208 100644
--- a/includes/specials/SpecialPreferences.php
+++ b/includes/specials/SpecialPreferences.php
@@ -37,14 +37,7 @@
                $out = $this->getOutput();
                $out->disallowUserJs(); # Prevent hijacked user scripts from 
sniffing passwords etc.
 
-               $user = $this->getUser();
-               if ( $user->isAnon() ) {
-                       throw new ErrorPageError(
-                               'prefsnologin',
-                               'prefsnologintext',
-                               array( $this->getTitle()->getPrefixedDBkey() )
-                       );
-               }
+               $this->requireLogin( 'prefsnologintext2', 'prefsnologin' );
                $this->checkReadOnly();
 
                if ( $par == 'reset' ) {
@@ -62,7 +55,7 @@
                        );
                }
 
-               $htmlForm = Preferences::getFormObject( $user, 
$this->getContext() );
+               $htmlForm = Preferences::getFormObject( $this->getUser(), 
$this->getContext() );
                $htmlForm->setSubmitCallback( array( 'Preferences', 
'tryUISubmit' ) );
 
                $htmlForm->show();
diff --git a/includes/specials/SpecialResetTokens.php 
b/includes/specials/SpecialResetTokens.php
index ef2a45d..db98bea 100644
--- a/includes/specials/SpecialResetTokens.php
+++ b/includes/specials/SpecialResetTokens.php
@@ -61,6 +61,7 @@
        public function execute( $par ) {
                // This is a preferences page, so no user JS for y'all.
                $this->getOutput()->disallowUserJs();
+               $this->requireLogin();
 
                parent::execute( $par );
 
diff --git a/includes/specials/SpecialWatchlist.php 
b/includes/specials/SpecialWatchlist.php
index 336b05b..78216ca 100644
--- a/includes/specials/SpecialWatchlist.php
+++ b/includes/specials/SpecialWatchlist.php
@@ -41,18 +41,7 @@
                $output = $this->getOutput();
 
                # Anons don't get a watchlist
-               if ( $user->isAnon() ) {
-                       $output->setPageTitle( $this->msg( 'watchnologin' ) );
-                       $output->setRobotPolicy( 'noindex,nofollow' );
-                       $llink = Linker::linkKnown(
-                               SpecialPage::getTitleFor( 'Userlogin' ),
-                               $this->msg( 'loginreqlink' )->escaped(),
-                               array(),
-                               array( 'returnto' => 
$this->getTitle()->getPrefixedText() )
-                       );
-                       $output->addHTML( $this->msg( 'watchlistanontext' 
)->rawParams( $llink )->parse() );
-                       return;
-               }
+               $this->requireLogin( 'watchlistanontext', 'watchnologin' );
 
                // Check permissions
                $this->checkPermissions();
diff --git a/languages/messages/MessagesEn.php 
b/languages/messages/MessagesEn.php
index 39f0b8a..1ef2d5b 100644
--- a/languages/messages/MessagesEn.php
+++ b/languages/messages/MessagesEn.php
@@ -1085,7 +1085,8 @@
 'invalidtitle-knownnamespace'   => 'Invalid title with namespace "$2" and text 
"$3"',
 'invalidtitle-unknownnamespace' => 'Invalid title with unknown namespace 
number $1 and text "$2"',
 'exception-nologin'             => 'Not logged in',
-'exception-nologin-text'        => 'This page or action requires you to be 
logged in on this wiki.',
+'exception-nologin-text'        => 'Please [[Special:Userlogin|log in]] to be 
able to access this page or action.',
+'exception-nologin-text-manual' => 'Please $1 to be able to access this page 
or action.',
 
 # Virus scanner
 'virus-badscanner'     => "Bad configuration: Unknown virus scanner: ''$1''",
@@ -1899,7 +1900,7 @@
 'mypreferences'                 => 'Preferences',
 'prefs-edits'                   => 'Number of edits:',
 'prefsnologin'                  => 'Not logged in',
-'prefsnologintext'              => 'You must be <span 
class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} logged 
in]</span> to set user preferences.',
+'prefsnologintext2'             => 'Please $1 to set user preferences.',
 'changepassword'                => 'Change password',
 'changepassword-summary'        => '', # do not translate or duplicate this 
message to other languages
 'prefs-skin'                    => 'Skin',
diff --git a/languages/messages/MessagesQqq.php 
b/languages/messages/MessagesQqq.php
index 14a9d3b..032fff2 100644
--- a/languages/messages/MessagesQqq.php
+++ b/languages/messages/MessagesQqq.php
@@ -1222,6 +1222,10 @@
 'exception-nologin' => 'Generic page title used on error page when a user is 
not logged in. Message used by the UserNotLoggedIn exception.
 {{Identical|Not logged in}}',
 'exception-nologin-text' => 'Generic reason displayed on error page when a 
user is not logged in. Message used by the UserNotLoggedIn exception.',
+'exception-nologin-text-manual' => 'Generic reason displayed on error page 
when a user is not logged in.
+
+Parameters:
+* $1 - a link to [[Special:UserLogin]] with {{msg-mw|loginreqlink}} as link 
description',
 
 # Virus scanner
 'virus-badscanner' => 'Used as error message. Parameters:
@@ -2963,8 +2967,8 @@
 {{Identical|Preferences}}',
 'prefs-edits' => 'In user preferences.',
 'prefsnologin' => '{{Identical|Not logged in}}',
-'prefsnologintext' => 'Parameters:
-* $1 - URI for "returnto" argument',
+'prefsnologintext2' => 'Parameters:
+* $1 - a link to [[Special:UserLogin]] with {{msg-mw|loginreqlink}} as link 
description',
 'changepassword' => "Section heading on [[Special:Preferences]], tab 'User 
profile'.
 {{Identical|Change password}}",
 'prefs-skin' => 'Used in user preferences.
diff --git a/maintenance/dictionary/mediawiki.dic 
b/maintenance/dictionary/mediawiki.dic
index 164b5b0..b6ca281 100644
--- a/maintenance/dictionary/mediawiki.dic
+++ b/maintenance/dictionary/mediawiki.dic
@@ -3127,7 +3127,7 @@
 prefs
 prefsection
 prefsnologin
-prefsnologintext
+prefsnologintext2
 prefsubmit
 preload
 preloads
diff --git a/maintenance/language/messages.inc 
b/maintenance/language/messages.inc
index 1ac9500..c149ec6 100644
--- a/maintenance/language/messages.inc
+++ b/maintenance/language/messages.inc
@@ -434,6 +434,7 @@
                'invalidtitle-unknownnamespace',
                'exception-nologin',
                'exception-nologin-text',
+               'exception-nologin-text-manual',
        ),
        'virus' => array(
                'virus-badscanner',
@@ -1028,7 +1029,7 @@
                'mypreferences',
                'prefs-edits',
                'prefsnologin',
-               'prefsnologintext',
+               'prefsnologintext2',
                'changepassword',
                'changepassword-summary',
                'prefs-skin',

-- 
To view, visit https://gerrit.wikimedia.org/r/94406
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I43ceaddb370d09784021b3fc2d5d1ff6616fef1f
Gerrit-PatchSet: 3
Gerrit-Project: mediawiki/core
Gerrit-Branch: master
Gerrit-Owner: Bartosz Dziewoński <[email protected]>
Gerrit-Reviewer: Aaron Schulz <[email protected]>
Gerrit-Reviewer: Alex Monk <[email protected]>
Gerrit-Reviewer: Aude <[email protected]>
Gerrit-Reviewer: Bartosz Dziewoński <[email protected]>
Gerrit-Reviewer: Brian Wolff <[email protected]>
Gerrit-Reviewer: Brion VIBBER <[email protected]>
Gerrit-Reviewer: Chad <[email protected]>
Gerrit-Reviewer: Parent5446 <[email protected]>
Gerrit-Reviewer: jenkins-bot

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to