jenkins-bot has submitted this change and it was merged.
Change subject: Replace image-based AutoLogin with iframes
......................................................................
Replace image-based AutoLogin with iframes
The image-based Special:AutoLogin is not secure. Change to an
iframe-based method (using the same code as the js login check) instead.
Change-Id: Id47efec74e2d625bf0d3761ed53e3b6ab6f74c2c
---
M CentralAuth.i18n.php
M CentralAuth.php
M CentralAuthHooks.php
A modules/ext.centralauth.edgeautologin.css
A modules/ext.centralauth.edgeautologin.js
M specials/SpecialCentralAutoLogin.php
M specials/SpecialCentralLogin.php
7 files changed, 246 insertions(+), 145 deletions(-)
Approvals:
Tim Starling: Looks good to me, approved
jenkins-bot: Verified
diff --git a/CentralAuth.i18n.php b/CentralAuth.i18n.php
index 77dc677..01d9657 100644
--- a/CentralAuth.i18n.php
+++ b/CentralAuth.i18n.php
@@ -260,8 +260,6 @@
'centralauth-invalid-wiki' => 'No such wiki database: $1',
'centralauth-account-exists' => 'Cannot create account: the
requested username is already taken in the unified login system.',
'centralauth-account-exists-reset' => 'The username $1 is not
registered on this wiki, but it does exist in the unified login system.',
- 'centralauth-login-progress' => 'Logging you in to wikis of
{{int:Centralauth-groupname}}:', # This message supports {{GENDER}}
- 'centralauth-logout-progress' => 'Logging you out from other wikis
of {{int:Centralauth-groupname}}:',
'centralauth-login-no-others' => 'You have been automatically logged
into other projects of {{int:Centralauth-groupname}}.',
'centralauth-logout-no-others' => 'You have been automatically logged
out of other projects of {{int:Centralauth-groupname}}.',
'centralauth-hidden-blockreason' => 'globally hidden by $1 at $2 with
following reason: $3',
@@ -321,6 +319,8 @@
Please review this site\'s human-readable privacy policy to determine how any
information collected might be used.',
'centralauth-centralautologin-logged-in' => 'You are centrally logged
in as $1. Reload the page to apply your user settings.',
+ 'centralauth-edge-logging-in' => 'Now automatically logging you into
other projects of {{int:Centralauth-groupname}}.',
+ 'centralauth-edge-logged-in' => 'You have been automatically logged
into other projects of {{int:Centralauth-groupname}}.',
// Global group membership
'globalgroupmembership' => 'Membership in global groups',
@@ -497,9 +497,7 @@
$messages['qqq'] = array(
'mergeaccount' => '{{doc-special|MergeAccount}}',
'centralauth-groupname' => 'Used within the following messages:
-* {{msg-mw|centralauth-incomplete-text}}
-* {{msg-mw|centralauth-login-progress}}
-* {{msg-mw|centralauth-logout-progress}}',
+* {{msg-mw|centralauth-incomplete-text}}',
'centralauth-desc' => '{{desc|name=Central
Auth|url=http://www.mediawiki.org/wiki/Extension:CentralAuth}}',
'centralauth-antispoof-desc' => '{{desc}}',
'centralauth-mergeaccount-desc' => 'Description of the special page
[[Special:MergeAccount]]',
@@ -761,8 +759,6 @@
*$1 is wiki name',
'centralauth-account-exists-reset' => "Parameters:
* $1 - global user's name",
- 'centralauth-login-progress' => '{{gender}}
-* (optional) $1 is the user name of the logged in user',
'centralauth-hidden-blockreason' => 'Unused at this time. Parameters:
* $1 - username
* $2 - ...
@@ -860,6 +856,14 @@
'centralauth-centralautologin-logged-in' => 'Message displayed by
JavaScript when the auto-login succeeds.
* $1 - User name
* $2 - User gender code {{gender}}',
+ 'centralauth-edge-logging-in' => 'Message used from JavaScript to tell
the user that they are being logged in to additional sites.
+* $1 - mw.user object {{gender}}
+Used with the following messages:
+* {{msg-mw|centralauth-edge-logged-in}}',
+ 'centralauth-edge-logged-in' => 'Message used from JavaScript to tell
the user that they have been logged in to additional sites.
+* $1 - mw.user object {{gender}}
+Used with the following messages:
+* {{msg-mw|centralauth-edge-logging-in}}',
'globalgroupmembership' => '{{doc-special|GlobalGroupMembership}}',
'globalgrouppermissions' => '{{doc-special|GlobalGroupPermissions}}
See example: [[w:Special:GlobalGroupPermissions]] and
[[w:Special:SpecialPages]]',
diff --git a/CentralAuth.php b/CentralAuth.php
index e451d90..6db45c4 100644
--- a/CentralAuth.php
+++ b/CentralAuth.php
@@ -98,8 +98,8 @@
$wgCentralAuthCookiePrefix = 'centralauth_';
/**
- * List of wiki IDs which should be called on login/logout to set third-party
- * cookies for the global session state.
+ * List of wiki IDs which should be called on login/logout to try to set
+ * third-party cookies for the global session state.
*
* The wiki ID is typically the database name, except when table prefixes are
* used, in which case it is the database name, a hyphen separator, and then
@@ -109,7 +109,7 @@
* session on all of them by hitting one wiki from each domain
* (en.wikipedia.org, en.wikinews.org, etc).
*
- * Done by $wgCentralAuthLoginIcon from Special:AutoLogin on each wiki.
+ * Done by opening hidden iframes to Special:CentralAutoLogin on each wiki.
*
* If empty, no other wikis will be hit.
*
@@ -226,7 +226,6 @@
$wgHooks['UserLoginComplete'][] = 'CentralAuthHooks::onUserLoginComplete';
$wgHooks['UserLoadFromSession'][] = 'CentralAuthHooks::onUserLoadFromSession';
$wgHooks['UserLogout'][] = 'CentralAuthHooks::onUserLogout';
-$wgHooks['UserLogoutComplete'][] = 'CentralAuthHooks::onUserLogoutComplete';
$wgHooks['GetCacheVaryCookies'][] = 'CentralAuthHooks::onGetCacheVaryCookies';
$wgHooks['UserArrayFromResult'][] = 'CentralAuthHooks::onUserArrayFromResult';
$wgHooks['UserGetEmail'][] = 'CentralAuthHooks::onUserGetEmail';
@@ -370,6 +369,24 @@
'centralauth-centralautologin-logged-in',
),
) + $commonModuleInfo;
+$wgResourceModules['ext.centralauth.edgeautologin'] = array(
+ 'scripts' => 'ext.centralauth.edgeautologin.js',
+ 'styles' => 'ext.centralauth.edgeautologin.css',
+ 'position' => 'top',
+ 'dependencies' => array(
+ 'mediawiki.jqueryMsg',
+ 'jquery.ui.progressbar',
+ ),
+ 'messages' => array(
+ 'centralauth-edge-logging-in',
+ 'centralauth-edge-logged-in',
+ 'centralauth-edge-logged-in-list',
+ 'centralauth-groupname',
+ 'and',
+ 'word-separator',
+ 'comma-separator',
+ ),
+) + $commonModuleInfo;
$wgResourceModules['ext.centralauth.noflash'] = array(
'styles' => 'ext.centralauth.noflash.css',
diff --git a/CentralAuthHooks.php b/CentralAuthHooks.php
index 05166e3..0d9bf33 100644
--- a/CentralAuthHooks.php
+++ b/CentralAuthHooks.php
@@ -305,8 +305,8 @@
// Redirect to the central wiki and back to complete
login
self::doCentralLoginRedirect( $user, $centralUser );
} else {
- // Show icons to AutoLogin special page to create
cross-domain cookies
- $inject_html .= self::getDomainAutoLoginIconHtml(
$user, $centralUser );
+ // Show HTML to create cross-domain cookies
+ $inject_html .= self::getDomainAutoLoginHtml( $user,
$centralUser );
}
return true;
@@ -317,50 +317,34 @@
* @param CentralAuthUser $centralUser
* @return String
*/
- public static function getDomainAutoLoginIconHtml( User $user,
CentralAuthUser $centralUser ) {
- global $wgCentralAuthAutoLoginWikis, $wgCentralAuthLoginWiki,
$wgMemc;
+ public static function getDomainAutoLoginHtml( User $user,
CentralAuthUser $centralUser ) {
+ global $wgCentralAuthAutoLoginWikis;
- $wikis = $wgCentralAuthAutoLoginWikis;
- if ( $wgCentralAuthLoginWiki ) {
- // Make sure the user gets any "remember me" token set
on the central login wiki
- $wikis[] = $wgCentralAuthLoginWiki;
- }
-
- // On other domains
- if ( !$wikis ) {
+ // No other domains
+ if ( !$wgCentralAuthAutoLoginWikis ) {
return wfMessage( 'centralauth-login-no-others'
)->text();
}
- $inject_html = '<div class="centralauth-login-box"><p>' .
- wfMessage( 'centralauth-login-progress',
$user->getName() )->text() . "</p>\n<p>";
- foreach ( $wikis as $alt => $wiki ) {
- $data = array(
- 'userName' => $user->getName(),
- 'token' => $centralUser->getAuthToken(),
- 'remember' => $user->getOption(
'rememberpassword' ),
- 'wiki' => $wiki
- );
-
- $loginToken = MWCryptRand::generateHex( 32 );
- $wgMemc->set( CentralAuthUser::memcKey( 'login-token',
$loginToken ), $data, 600 );
-
+ $out = RequestContext::getMain()->getOutput();
+ $out->addInlineStyle( // hide the non-JS text
+ '.client-js #centralauth-edge-login-info { display:
none; }'
+ );
+ $out->addModules( 'ext.centralauth.edgeautologin' );
+ $inject_html = '<div id="centralauth-edge-login-info"
class="centralauth-login-box">' .
+ wfMessage( 'centralauth-login-no-others' )->text() .
+ "</div>\n";
+ foreach ( $wgCentralAuthAutoLoginWikis as $wiki ) {
$wiki = WikiMap::getWiki( $wiki );
// Use WikiReference::getFullUrl(), returns a
protocol-relative URL if needed
- $url = wfAppendQuery( $wiki->getFullUrl(
'Special:AutoLogin' ), "token=$loginToken" );
-
- $inject_html .= Xml::element( 'img',
- array(
- 'src' => $url,
- 'alt' => $alt,
- 'title' => $alt,
- 'width' => 20,
- 'height' => 20,
- 'style' => 'border: 1px solid #ccc;',
- )
+ $url = wfAppendQuery( $wiki->getFullUrl(
'Special:CentralAutoLogin/L0' ), array(
+ 'oncomplete' => 'NW',
+ 'notifywiki' => wfWikiID(),
+ ) );
+ $inject_html .= Xml::element( 'span',
+ array( 'class' => 'centralauth-edge-login-url',
'data-src' => $url ),
+ '', false
);
}
-
- $inject_html .= '</p></div>';
return $inject_html;
}
@@ -556,79 +540,6 @@
$centralUser->resetAuthToken();
}
- return true;
- }
-
- /**
- * @param $user
- * @param $inject_html
- * @param $userName
- * @return bool
- */
- static function onUserLogoutComplete( &$user, &$inject_html, $userName
) {
- global $wgCentralAuthCookies, $wgCentralAuthAutoLoginWikis,
$wgCentralAuthLoginWiki;
-
- if ( !$wgCentralAuthCookies ) {
- // Nothing to do.
- return true;
- }
-
- $wikis = $wgCentralAuthAutoLoginWikis;
- if ( $wgCentralAuthLoginWiki ) {
- // Make sure the user gets logged out on the central
login wiki
- $wikis[] = $wgCentralAuthLoginWiki;
- }
-
- if ( !$wikis ) {
- $inject_html .= wfMessage(
'centralauth-logout-no-others' )->parseAsBlock();
- return true;
- }
-
- $centralUser = CentralAuthUser::getInstance( $user );
- if ( !$centralUser->exists() || !$centralUser->isAttached() ) {
- return true;
- }
-
- // Generate the images
- $inject_html .= '<div class="centralauth-logout-box"><p>' .
- wfMessage( 'centralauth-logout-progress' )->escaped() .
"</p>\n<p>";
- $centralUser = new CentralAuthUser( $userName );
-
- foreach ( $wikis as $alt => $wiki ) {
- $data = array(
- 'userName' => $userName,
- 'token' => $centralUser->getAuthToken(),
- 'remember' => false,
- 'wiki' => $wiki,
- 'action' => 'logout'
- );
- $loginToken = MWCryptRand::generateHex( 32 );
- global $wgMemc;
- $wgMemc->set( CentralAuthUser::memcKey( 'login-token',
$loginToken ), $data, 600 );
-
- $wiki = WikiMap::getWiki( $wiki );
- // Use WikiReference::getFullUrl(), returns a
protocol-relative URL if needed
- $url = $wiki->getFullUrl( 'Special:AutoLogin' );
-
- if ( strpos( $url, '?' ) > 0 ) {
- $url .= "&logout=1&token=$loginToken";
- } else {
- $url .= "?logout=1&token=$loginToken";
- }
-
- $inject_html .= Xml::element( 'img',
- array(
- 'src' => $url,
- 'alt' => $alt,
- 'title' => $alt,
- 'width' => 20,
- 'height' => 20,
- 'style' => 'border: 1px solid #ccc;',
- )
- );
- }
-
- $inject_html .= '</p></div>';
return true;
}
diff --git a/modules/ext.centralauth.edgeautologin.css
b/modules/ext.centralauth.edgeautologin.css
new file mode 100644
index 0000000..cd9928c
--- /dev/null
+++ b/modules/ext.centralauth.edgeautologin.css
@@ -0,0 +1,18 @@
+#centralauth-edge-progressbar {
+ text-align: center;
+ white-space: nowrap;
+}
+
+#centralauth-edge-progressbar > * {
+ vertical-align: middle;
+}
+
+#centralauth-edge-progressbar .ui-progressbar {
+ display: inline-block;
+ width: 400px;
+}
+
+#centralauth-edge-progressbar .ui-progressbar-value {
+ background: #dfeffa; /* default white is ugly */
+}
+
diff --git a/modules/ext.centralauth.edgeautologin.js
b/modules/ext.centralauth.edgeautologin.js
new file mode 100644
index 0000000..02d9fe4
--- /dev/null
+++ b/modules/ext.centralauth.edgeautologin.js
@@ -0,0 +1,88 @@
+( function ( mw, $ ) {
+ var max = 0, count = 0, $progressbar, $tick;
+
+ function edgeLoginDone() {
+ $( '#centralauth-edge-login-info' )
+ .text( mw.message( 'centralauth-edge-logged-in',
mw.user ) )
+ .css( 'display', 'block' );
+ $tick.css( 'visibility', 'visible' );
+ }
+
+ mw.CentralAuth = {
+ edgeLoginComplete: function ( frame ) {
+ if ( frame ) {
+ $( frame ).trigger( 'ca-done' );
+ }
+ $progressbar.progressbar( 'value', ++count );
+ if ( count >= max ) {
+ edgeLoginDone();
+ }
+ }
+ };
+
+ $( function () {
+ var $urlSpans, $progressbarcontainer;
+
+ $urlSpans = $( '.centralauth-edge-login-url' );
+ if ( $urlSpans.length <= 0 ) {
+ edgeLoginDone();
+ return;
+ }
+
+ max = $urlSpans.length;
+
+ $progressbarcontainer = $( '<div>' )
+ .attr( 'id', 'centralauth-edge-progressbar' );
+
+ $progressbar = $( '<div>' )
+ .appendTo( $progressbarcontainer )
+ .progressbar( { max: max, value: count } );
+ $tick = $( '<img>' )
+ .attr( {
+ src: mw.config.get( 'stylepath' ) +
'/common/images/tick-32.png',
+ width: 32,
+ height: 32
+ } )
+ .css( 'visibility', 'hidden' )
+ .appendTo( $progressbarcontainer );
+
+ $( '#centralauth-edge-login-info' )
+ .text( mw.message( 'centralauth-edge-logging-in',
mw.user ) )
+ .after( $progressbarcontainer )
+ .css( 'display', 'block' );
+
+ $urlSpans.each( function () {
+ var timer, $iframe;
+
+ function giveUp() {
+ timer = null;
+ mw.CentralAuth.edgeLoginComplete( $iframe,
null, [ 'timed-out' ] );
+ }
+ timer = setTimeout( giveUp, 10000 );
+
+ $iframe = $( '<iframe>' )
+ .css( {
+ position: 'absolute',
+ top: 0,
+ left: '-10px',
+ width: '1px',
+ height: '1px'
+ } )
+ .on( 'load', function () {
+ // Reset timeout
+ if ( timer ) {
+ clearTimeout( timer );
+ timer = setTimeout( giveUp,
10000 );
+ }
+ } )
+ .on( 'ca-done', function () {
+ if ( timer ) {
+ clearTimeout( timer );
+ timer = null;
+ }
+ } )
+ .attr( 'src', $( this ).data( 'src' ) )
+ .appendTo( document.body );
+ } );
+ } );
+}( mediaWiki, jQuery ) );
diff --git a/specials/SpecialCentralAutoLogin.php
b/specials/SpecialCentralAutoLogin.php
index e59d1d1..da1a6b6 100644
--- a/specials/SpecialCentralAutoLogin.php
+++ b/specials/SpecialCentralAutoLogin.php
@@ -7,13 +7,26 @@
*/
class SpecialCentralAutoLogin extends UnlistedSpecialPage {
private $isForm = false;
+ private $loginWiki;
function __construct() {
parent::__construct( 'CentralAutoLogin' );
}
function execute( $par ) {
- global $wgMemc, $wgUser;
+ global $wgMemc, $wgUser, $wgCentralAuthLoginWiki;
+
+ $this->loginWiki = $wgCentralAuthLoginWiki;
+ if ( !$this->loginWiki ) {
+ // Ugh, no central wiki. If we're coming from the
iframes generated
+ // by CentralAuthHooks::getDomainAutoLoginHtml, make the
+ // logged-into wiki the de-facto central wiki for this
request so
+ // auto-login still works.
+ $notifywiki = $this->getRequest()->getVal( 'notifywiki'
);
+ if ( $notifywiki !== null && WikiMap::getWiki(
$notifywiki ) ) {
+ $this->loginWiki = $notifywiki;
+ }
+ }
switch ( strval( $par ) ) {
case '': // also null and false
@@ -282,8 +295,32 @@
'returntoquery' => $request->getVal(
'returntoquery' ),
) );
$data['script'] = 'top.location.href = ' .
Xml::encodeJsVar( $url ) . ';';
+
+ case 'NW':
+ // To avoid cross-domain restrictions, we have
+ // to redirect to the original domain now. But
+ // don't actually redirect, to make sure
+ // cookies get set first.
+ $data['params']['domain'] =
CentralAuthUser::getCookieDomain();
+ $data['nextState'] = 'NW';
break;
}
+ break;
+
+ case 'NW':
+ $this->isForm = true;
+ $domain = $this->getRequest()->getVal( 'domain' );
+ $msg = FormatJson::decode( $this->getRequest()->getVal(
'msg', 'null' ) );
+ $data = array(
+ 'status' => 'ok',
+ 'script' => XML::encodeJsCall(
+ 'top.mw.CentralAuth.edgeLoginComplete',
array(
+ new XmlJsCode(
'window.frameElement' ),
+ $domain, $msg
+ )
+ ),
+ 'params' => array(),
+ );
break;
default:
@@ -294,12 +331,28 @@
break;
}
+ // Send notification to the login progress bar
+ if ( $this->isForm && $data['status'] === 'error'
+ && $this->getRequest()->getVal( 'oncomplete',
'mw.notify' ) === 'NW' ) {
+ if ( $data['msg'][0] ==
'centralauth-centralautologin-alreadyloggedinlocally' ) {
+ $domain = CentralAuthUser::getCookieDomain();
+ } else {
+ $domain = null;
+ }
+ $data = array(
+ 'status' => 'ok',
+ 'nextState' => 'NW',
+ 'params' => array(
+ 'domain' => $domain,
+ 'msg' => FormatJson::encode(
$data['msg'] ),
+ ),
+ );
+ }
+
$this->outputData( $data );
}
private function checkInputState( $par, $central ) {
- global $wgCentralAuthLoginWiki;
-
$request = $this->getRequest();
$this->isForm = $request->getBool( 'form' );
@@ -313,7 +366,7 @@
// Validate the state for this wiki
if ( $central ) {
- if ( wfWikiID() !== $wgCentralAuthLoginWiki ) {
+ if ( wfWikiID() !== $this->loginWiki ) {
return array(
'status' => 'error',
'msg' => array(
'centralauth-centralautologin-badstate-central', $par ),
@@ -321,7 +374,7 @@
}
$wikiId = $request->getVal( 'wikiid' );
- if ( $wikiId === $wgCentralAuthLoginWiki ) {
+ if ( $wikiId === $this->loginWiki ) {
return array(
'status' => 'error',
'msg' => array(
'centralauth-centralautologin-badwiki', $wikiId ),
@@ -369,7 +422,7 @@
$this->getOutput()->addVaryHeader( 'Origin' );
}
} else {
- if ( wfWikiID() === $wgCentralAuthLoginWiki ) {
+ if ( wfWikiID() === $this->loginWiki ) {
return array(
'status' => 'error',
'msg' => array(
'centralauth-centralautologin-badstate-local', $par ),
@@ -425,28 +478,38 @@
}
if ( isset( $data['nextState'] ) ) {
+ switch ( substr( $data['nextState'], 0,
1 ) ) {
+ case 'C':
+ $target = $this->loginWiki;
+ break;
+
+ case 'N':
+ $target =
$this->getRequest()->getVal( 'notifywiki', wfWikiID() );
+ break;
+
+ default:
+ $target =
$this->getRequest()->getVal( 'wikiid', wfWikiID() );
+ break;
+ }
+ $action = WikiMap::getForeignURL(
$target, 'Special:CentralAutoLogin/' . $data['nextState'] );
+ if ( $action === false ) {
+ $script = '';
+ $body = wfMessage(
'centralauth-centralautologin-badwiki', $target )->escaped();
+ break;
+ }
+
$script .= "\n\nfunction doSubmit()
{\n" .
"\tif ( document.forms[0] )
{\n" .
"\t\tdocument.forms[0].submit();\n" .
"\t}\n" .
"}";
$bodyParams['onload'] = 'doSubmit()';
-
- switch ( substr( $data['nextState'], 0,
1 ) ) {
- case 'C':
- global $wgCentralAuthLoginWiki;
- $target =
$wgCentralAuthLoginWiki;
-
- default:
- $target =
$this->getRequest()->getVal( 'wikiid', wfWikiID() );
- break;
- }
$body .= "\n" . Html::openElement(
'form', array(
'method' => 'POST',
- 'action' =>
WikiMap::getForeignURL( $target, 'Special:CentralAutoLogin/' .
$data['nextState'] ),
+ 'action' => $action,
) ) . "\n";
$body .= Html::hidden( 'form', '1' ) .
"\n";
- foreach ( array( 'oncomplete',
'returnto', 'returntoquery' ) as $k ) {
+ foreach ( array( 'oncomplete',
'returnto', 'returntoquery', 'notifywiki' ) as $k ) {
$v =
$this->getRequest()->getVal( $k );
if ( $v !== null ) {
$body .= Html::hidden(
$k, $v ) . "\n";
@@ -462,7 +525,7 @@
case 'error':
$params = $data['msg'];
$key = array_shift( $params );
- $body = wfMessage( $key, $params )->escaped();
+ $body = wfMessage( $key, $params )->escaped();
break;
}
diff --git a/specials/SpecialCentralLogin.php b/specials/SpecialCentralLogin.php
index 087ccf6..8c0dc5d 100644
--- a/specials/SpecialCentralLogin.php
+++ b/specials/SpecialCentralLogin.php
@@ -191,11 +191,11 @@
$url = $this->getFullTitle()->getFullUrl( $query,
false, PROTO_HTTP );
$this->getOutput()->redirect( $url );
} else {
- // Show any icons that trigger cross-domain cookies.
+ // Show HTML to trigger cross-domain cookies.
// This will trigger filling in the "remember me" token
cookie on the
// central wiki, which can only be done once
authorization is completed.
$this->getOutput()->addHtml(
- CentralAuthHooks::getDomainAutoLoginIconHtml(
$user, $centralUser ) );
+ CentralAuthHooks::getDomainAutoLoginHtml(
$user, $centralUser ) );
}
}
@@ -216,9 +216,9 @@
$this->getRequest()->getVal( 'returntoquery', '' )
);
$this->getOutput()->setPageTitle( $this->msg(
'centralloginsuccesful' ) );
- // Show any icons that trigger cross-domain cookies
+ // Show HTML to trigger cross-domain cookies
$this->getOutput()->addHtml(
- CentralAuthHooks::getDomainAutoLoginIconHtml(
$this->getUser(), $centralUser ) );
+ CentralAuthHooks::getDomainAutoLoginHtml(
$this->getUser(), $centralUser ) );
}
protected function showError( /* varargs */ ) {
--
To view, visit https://gerrit.wikimedia.org/r/62194
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: Id47efec74e2d625bf0d3761ed53e3b6ab6f74c2c
Gerrit-PatchSet: 13
Gerrit-Project: mediawiki/extensions/CentralAuth
Gerrit-Branch: master
Gerrit-Owner: Anomie <[email protected]>
Gerrit-Reviewer: Anomie <[email protected]>
Gerrit-Reviewer: CSteipp <[email protected]>
Gerrit-Reviewer: Daniel Friesen <[email protected]>
Gerrit-Reviewer: Peachey88 <[email protected]>
Gerrit-Reviewer: Siebrand <[email protected]>
Gerrit-Reviewer: Tim Starling <[email protected]>
Gerrit-Reviewer: jenkins-bot
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits