Wikinaut has submitted this change and it was merged. Change subject: Bug 54508: Add "provider only" mode; Bug 46617: allow Sysops to always create account ......................................................................
Bug 54508: Add "provider only" mode; Bug 46617: allow Sysops to always create account * bump to version 4.00 20131122 * depends on 9a362d64c86989837f9a0755abc7c5a78457ca78 MediaWiki core with https://gerrit.wikimedia.org/r/#/c/96029/ merged 2013-11-18 * deprecated: $wgOpenIDConsumerAndAlsoProvider (see CHANGES) replace that with $wgOpenIDMode = array( 'consumer', 'provider' ) * introducing new rights: openid-create-account-with-openid openid-login-with-openid openid-login-without-openid * Bug 46617: allowing sysops to always create accounts In SpecialPages OpenID section, Sysops will always find a link to create a new user account by mail * Bug 54508: introducing $wgOpenIDMode which replaces $wgOpenIDConsumerAndAlsoProvider and can have values 'consumer', 'provider', array( 'consumer', 'provider' ) * Bug 54507: When having a forced provider, disallow adding (converting) further OpenIDs from non-allowed providers: only allow to add the forced provider * hiding OpenID login links if these are not working (consumer mode, or missing or empty list of providers, or no forced provider) * hiding irrelevant sections in the OpenID preferences tab (depending on OpenIDMode) * adding message texts for rights and actions * bug fix: correcting a permission check during account creation: the check was previously (mistakenly) done for the user-to-be-created instead checking the account creation right of account-creating user * adding reset password link in the name picker menu (when attaching an OpenID to an existing account) Bug 46617 Bug 54508 Bug 54507 Change-Id: Ieff71386de02d0c9e428df5131467cc7af75faff --- M CHANGES M OpenID.hooks.php M OpenID.i18n.php M OpenID.php M OpenIDProvider.body.php M SpecialOpenID.body.php M SpecialOpenIDConvert.body.php M SpecialOpenIDDashboard.body.php M SpecialOpenIDIdentifier.body.php M SpecialOpenIDLogin.body.php M SpecialOpenIDServer.body.php M SpecialOpenIDXRDS.body.php 12 files changed, 491 insertions(+), 173 deletions(-) Approvals: Wikinaut: Verified; Looks good to me, approved diff --git a/CHANGES b/CHANGES index 54966ae..da85b54 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,45 @@ CHANGES ======= +4.00 20131121 introducing OpenID::isAllowedMode() + deprecating $wgOpenIDConsumerAndAlsoProvider + + depends on 9a362d64c86989837f9a0755abc7c5a78457ca78 MediaWiki + core https://gerrit.wikimedia.org/r/#/c/96029/ merged 2013-11-18 + + Add "provider only" mode + + introducing new rights: + openid-create-account-with-openid + openid-login-with-openid + openid-login-without-openid + + bug 46617: allowing sysops to always create accounts + In SpecialPages OpenID section, Sysops will always find a link + to create a new user account by mail + + bug 54508: introducing $wgOpenIDMode which replaces + $wgOpenIDConsumerAndAlsoProvider and can have values + 'consumer', 'provider', array( 'consumer', 'provider' ), false + + bug 54507: When having a forced provider, disallow adding + (converting) further OpenIDs from non-allowed providers: + only allow to add the forced provider + + hiding OpenID login links if these are not working + (consumer mode, or missing or empty list of providers, + or no forced provider) + + hiding irrelevant sections in the OpenID preferences tab + (depending on OpenIDMode) + + adding message texts for rights and actions + + bug fix: correcting a permission check during account creation: + the check was previously (mistakenly) done for the user-to-be-created + instead checking the account creation right of account-creating user + + when attaching an OpenID: adding a reset password link under + username/password in the name picker screen 3.44 20131122 bug 54511 Let OpenIDServer show a meaningful error message in case of untrusted trust root diff --git a/OpenID.hooks.php b/OpenID.hooks.php index 8341680..59e4f33 100644 --- a/OpenID.hooks.php +++ b/OpenID.hooks.php @@ -5,42 +5,58 @@ * they're so badly written as to be impossible to extend */ -class SpecialOpenIDCreateAccount extends SpecialRedirectToSpecial { - function __construct() { - parent::__construct( 'SpecialOpenIDCreateAccount', 'OpenIDLogin' ); - } -} -class SpecialOpenIDUserLogin extends SpecialRedirectToSpecial { - function __construct() { - parent::__construct( 'SpecialOpenIDUserLogin', 'OpenIDLogin', false, array( 'returnto', 'returntoquery' ) ); - } -} - class OpenIDHooks { - public static function onSpecialPage_initList( &$list ) { - global $wgOpenIDLoginOnly, $wgOpenIDConsumerAndAlsoProvider, $wgSpecialPageGroups, $wgOpenIDSmallLogoUrl; - $wgOpenIDSmallLogoUrl = self::getOpenIDSmallLogoUrl(); + public static function onSpecialPage_initList( &$specialPagesList ) { + global $wgOpenIDLoginOnly, $wgSpecialPageGroups, $wgUser; - if ( $wgOpenIDLoginOnly ) { - $list['Userlogin'] = 'SpecialOpenIDLogin'; + # redirect all special login pages to our own OpenID login pages + # but only for entitled users - # as Special:CreateAccount is an alias for Special:UserLogin/signup - # we show our own OpenID page here, too - $list['CreateAccount'] = 'SpecialOpenIDLogin'; + $addOpenIDSpecialPagesList = array(); + + if ( OpenID::isAllowedMode( 'consumer' ) ) { + + if ( $wgOpenIDLoginOnly + && !$wgUser->isAllowed( 'openid-create-account-without-openid' ) + && $wgUser->isAllowed( 'openid-login-with-openid' ) ) { + + $specialPagesList['Userlogin'] = 'SpecialOpenIDLogin'; + + # as Special:CreateAccount is an alias for Special:UserLogin/signup + # we show our own OpenID page here, too + + $specialPagesList['CreateAccount'] = 'SpecialOpenIDLogin'; + + } + } - # Special pages are added at global scope; - # remove server-related ones if client-only flag is set - $addList = array( 'Login', 'Convert', 'Dashboard', 'Identifier' ); - if ( $wgOpenIDConsumerAndAlsoProvider ) { - $addList[] = 'Server'; - $addList[] = 'XRDS'; + # Special pages for both modes are added at global scope + + if ( OpenID::isAllowedMode( 'provider' ) || OpenID::isAllowedMode( 'consumer' ) ) { + + if ( !$wgUser->isLoggedIn() + && ( $wgUser->isAllowed( 'openid-login-with-openid' ) + || $wgUser->isAllowed( 'openid-create-account-with-openid' ) ) ) { + $addOpenIDSpecialPagesList[] = 'Login'; + } + + $addOpenIDSpecialPagesList[] = 'Convert'; + $addOpenIDSpecialPagesList[] = 'Dashboard'; } - foreach ( $addList as $sp ) { + # add the server-related Special pages + + if ( OpenID::isAllowedMode( 'provider' ) ) { + $addOpenIDSpecialPagesList[] = 'Identifier'; + $addOpenIDSpecialPagesList[] = 'Server'; + $addOpenIDSpecialPagesList[] = 'XRDS'; + } + + foreach ( $addOpenIDSpecialPagesList as $sp ) { $key = 'OpenID' . $sp; - $list[$key] = 'SpecialOpenID' . $sp; + $specialPagesList[$key] = 'SpecialOpenID' . $sp; $wgSpecialPageGroups[$key] = 'openid'; } @@ -86,7 +102,10 @@ public static function onPersonalUrls( &$personal_urls, &$title ) { global $wgOpenIDHideOpenIDLoginLink, $wgUser, $wgOpenIDLoginOnly; - if ( !$wgOpenIDHideOpenIDLoginLink && $wgUser->getID() == 0 ) { + if ( !$wgOpenIDHideOpenIDLoginLink + && ( $wgUser->getID() == 0 ) + && OpenID::isAllowedMode( 'consumer' ) ) { + $sk = $wgUser->getSkin(); $returnto = $title->isSpecial( 'Userlogout' ) ? '' : ( 'returnto=' . $title->getPrefixedURL() ); @@ -104,6 +123,7 @@ } } } + } return true; @@ -158,7 +178,7 @@ $rows .= Xml::tags( 'tr', array(), Xml::tags( 'td', array(), - self::getOpenIDSmallLogoUrlImageTag() . + OpenID::getOpenIDSmallLogoUrlImageTag() . " " . Xml::element( 'a', array( 'href' => $url_reg->uoi_openid ), $url_reg->uoi_openid ) ) . @@ -190,7 +210,7 @@ $rows ); - if ( !is_string( $wgOpenIDForcedProvider ) ) { + if ( true || !OpenID::isForcedProvider() ) { $info .= Linker::link( SpecialPage::getTitleFor( 'OpenIDConvert' ), wfMessage( 'openid-add-url' )->escaped() @@ -273,9 +293,9 @@ */ public static function onGetPreferences( $user, &$preferences ) { global $wgOpenIDShowUrlOnUserPage, $wgHiddenPrefs, - $wgAuth, $wgUser, $wgLang, $wgOpenIDConsumerAndAlsoProvider; + $wgAuth, $wgUser, $wgLang; - if ( $wgOpenIDConsumerAndAlsoProvider ) { + if ( OpenID::isAllowedMode( 'provider' ) ) { switch ( $wgOpenIDShowUrlOnUserPage ) { @@ -308,7 +328,10 @@ } - } + } /* provider mode */ + + + if ( OpenID::isAllowedMode( 'consumer' ) ) { // setting up user_properties up_property database key names // example 'openid-userinfo-update-on-login-nickname' @@ -345,14 +368,18 @@ 'type' => 'hidden', ); - if ( $wgOpenIDConsumerAndAlsoProvider ) { + } /* consumer mode */ + + + if ( OpenID::isAllowedMode( 'provider' ) ) { $preferences['openid-your-openid'] = array( 'section' => 'openid/openid-local-identity', 'type' => 'info', 'label-message' => 'openid-local-identity', - 'default' => self::getOpenIDSmallLogoUrlImageTag() . " " . SpecialOpenIDServer::getLocalIdentityLink( $user ), + 'default' => OpenID::getOpenIDSmallLogoUrlImageTag() . " " . + SpecialOpenIDServer::getLocalIdentityLink( $user ), 'raw' => true, ); @@ -365,9 +392,11 @@ 'raw' => true, ); - } + } /* provider mode */ + if ( $wgAuth->allowPasswordChange() ) { + $resetlink = Linker::link( SpecialPage::getTitleFor( 'PasswordReset' ), wfMessage( 'passwordreset' )->escaped(), @@ -376,6 +405,7 @@ ); if ( empty( $wgUser->mPassword ) && empty( $wgUser->mNewpassword ) ) { + $preferences['password'] = array( 'section' => 'personal/info', 'type' => 'info', @@ -383,7 +413,9 @@ 'default' => $resetlink, 'label-message' => 'yourpassword', ); + } else { + $preferences['resetpassword'] = array( 'section' => 'personal/info', 'type' => 'info', @@ -391,10 +423,13 @@ 'default' => $resetlink, 'label-message' => null, ); + } global $wgCookieExpiration; + if ( $wgCookieExpiration > 0 ) { + unset( $preferences['rememberpassword'] ); $preferences['rememberpassword'] = array( 'section' => 'personal/info', @@ -404,6 +439,7 @@ $wgLang->formatNum( ceil( $wgCookieExpiration / ( 3600 * 24 ) ) ) )->escaped(), ); + } } @@ -528,30 +564,6 @@ /** * @return string */ - private static function getOpenIDSmallLogoUrl() { - global $wgOpenIDSmallLogoUrl, $wgExtensionAssetsPath; - - if ( !$wgOpenIDSmallLogoUrl ) { - return $wgExtensionAssetsPath . '/OpenID/skin/icons/openid-inputicon.png'; - } else { - return $wgOpenIDSmallLogoUrl; - } - - } - - /** - * @return string - */ - public static function getOpenIDSmallLogoUrlImageTag() { - return Xml::element( 'img', - array( 'src' => self::getOpenIDSmallLogoUrl(), 'alt' => 'OpenID' ), - '' - ); - } - - /** - * @return string - */ private static function providerStyle() { global $wgExtensionAssetsPath; @@ -570,7 +582,7 @@ * @return string */ private static function loginStyle() { - $openIDLogo = self::getOpenIDSmallLogoUrl(); + $openIDLogo = OpenID::getOpenIDSmallLogoUrl(); return <<<EOS <style type='text/css'> li#pt-openidlogin { diff --git a/OpenID.i18n.php b/OpenID.i18n.php index ffde40b..fa0b78f 100644 --- a/OpenID.i18n.php +++ b/OpenID.i18n.php @@ -44,7 +44,8 @@ The page has no other purpose.', 'openidxrds' => 'Yadis file', 'openidconvert' => 'OpenID converter', - 'openiderror' => 'Verification error', + 'openiderror' => 'OpenID error', + 'openid-error-openid-consumer-mode-disabled' => 'You cannot login with OpenID to this wiki, because the OpenID consumer mode has been disabled.', 'openiderrortext' => 'An error occurred during verification of the OpenID URL.', 'openid-error-no-auth' => 'An unspecified authentication response/request error occurred during the verification of the OpenID URL $1.', 'openid-error-server-response' => "An error occurred during the verification of the OpenID URL $1. @@ -176,11 +177,17 @@ 'right-openid-converter-access' => 'Can add or convert their account to use OpenID identities', 'right-openid-dashboard-access' => 'Standard access to the OpenID dashboard', 'right-openid-dashboard-admin' => 'Administrator access to the OpenID dashboard', + 'right-openid-login-with-openid' => 'Can login with OpenID', + 'right-openid-create-account-with-openid' => 'Can create account with OpenID', + 'right-openid-create-account-without-openid' => 'Manual account creation without OpenID', # Associated actions - in the sentence "You do not have permission to X" 'action-openid-converter-access' => 'add or convert your account to use OpenID identities', 'action-openid-dashboard-access' => 'access the OpenID dashboard', 'action-openid-dashboard-admin' => 'access the OpenID administrator dashboard', + 'action-openid-login-with-openid' => 'login with OpenID', + 'action-openid-create-account-with-openid' => 'create an account with OpenID', + 'action-openid-create-account-without-openid' => 'manually create an account i.e. without OpenID', 'openid-dashboard-title' => 'OpenID dashboard', 'openid-dashboard-title-admin' => 'OpenID dashboard (administrator)', diff --git a/OpenID.php b/OpenID.php index 6aa0b08..1d6b8a7 100644 --- a/OpenID.php +++ b/OpenID.php @@ -29,7 +29,7 @@ exit( 1 ); } -define( 'MEDIAWIKI_OPENID_VERSION', '3.44 20131122' ); +define( 'MEDIAWIKI_OPENID_VERSION', '4.00 20131122' ); $path = dirname( __FILE__ ); set_include_path( implode( PATH_SEPARATOR, array( $path ) ) . PATH_SEPARATOR . get_include_path() ); @@ -43,12 +43,20 @@ $wgOpenIDLoginOnly = true; /** - * If true, user accounts on this wiki can be used as OpenIDs on other - * sites. This is called "OpenID Provider" (or "OpenID Server") mode. - * - * @deprecated $wgOpenIDClientOnly since E:OpenID v3.12. Use $wgOpenIDConsumerAndAlsoProvider with inverted logic instead + * @deprecated $wgOpenIDClientOnly since E:OpenID v3.12. Instead set $wgOpenIDMode = 'consumer' + * @deprecated $wgOpenIDConsumerAndAlsoProvider since E:OpenID v3.44. Instead set $wgOpenIDMode = array( 'consumer', 'provider' ) */ -$wgOpenIDConsumerAndAlsoProvider = true; +# if you want to disable the OpenID extension +# $wgOpenIDMode = false; + +# if you want to allow Users of this wiki to use their identity as OpenIDs for logins on other sites +# $wgOpenIDMode = 'provider'; + +# and if you want to allow logins to this wiki with OpenID from elsewhere, or OpenID from a forced provider +# $wgOpenIDMode = 'consumer'; + +# if you want to allow Users of this wiki to use their identity as OpenIDs for logins on other sites +$wgOpenIDMode = array( 'consumer', 'provider' ); /** * If true, users can use their OpenID identity provided by this site A @@ -234,6 +242,7 @@ ) ); + /** * when creating a new account or associating an existing account with OpenID: * @@ -370,18 +379,6 @@ 'descriptionmsg' => 'openid-desc', ); -function OpenIDGetServerPath() { - $rel = 'Auth/OpenID/Server.php'; - - foreach ( explode( PATH_SEPARATOR, get_include_path() ) as $pe ) { - $full = $pe . DIRECTORY_SEPARATOR . $rel; - if ( file_exists( $full ) ) { - return $full; - } - } - return $rel; -} - $dir = $path . '/'; $wgExtensionMessagesFiles['OpenID'] = $dir . 'OpenID.i18n.php'; @@ -404,8 +401,8 @@ # UI class $wgAutoloadClasses['OpenIDProvider'] = $dir . 'OpenIDProvider.body.php'; -# Gets stored in the session, needs to be reified before our setup -$wgAutoloadClasses['Auth_OpenID_CheckIDRequest'] = OpenIDGetServerPath(); +# Gets stored in the session, needs to be verified before our setup +$wgAutoloadClasses['Auth_OpenID_CheckIDRequest'] = OpenID::OpenIDGetServerPath(); $wgAutoloadClasses['MediaWikiOpenIDDatabaseConnection'] = $dir . 'DatabaseConnection.php'; $wgAutoloadClasses['MediaWikiOpenIDMemcachedStore'] = $dir . 'MemcachedStore.php'; @@ -427,10 +424,17 @@ # $wgHooks['UserLoginForm'][] = 'OpenIDHooks::onUserLoginForm'; # new user rights +$wgAvailableRights[] = 'openid-converter-access'; $wgAvailableRights[] = 'openid-dashboard-access'; $wgAvailableRights[] = 'openid-dashboard-admin'; +$wgAvailableRights[] = 'openid-login-with-openid'; +$wgAvailableRights[] = 'openid-create-account-with-openid'; +$wgAvailableRights[] = 'openid-create-account-without-openid'; -# uncomment to allow users to read access the dashboard +# allow everyone to login with OpenID +$wgGroupPermissions['*']['openid-login-with-openid'] = true; + +# uncomment to allow users read access the dashboard # $wgGroupPermissions['user']['openid-dashboard-access'] = true; # allow users to add or convert OpenIDs to their accounts @@ -438,10 +442,17 @@ # if $wgOpenIDForcedProvider is set, the permission is set false $wgGroupPermissions['user']['openid-converter-access'] = true; -# allow sysops to read access the dashboard and -# allow sysops to adminstrate the OpenID settings (feature under construction) +# allow sysops read access the dashboard and +# allow sysops to administrate the OpenID settings (feature under construction) $wgGroupPermissions['sysop']['openid-dashboard-access'] = true; $wgGroupPermissions['sysop']['openid-dashboard-admin'] = true; + +# allow sysops always to create accounts +# i.e. also in case of $wgOpenIDLoginOnly==true +$wgGroupPermissions['*']['openid-login-with-openid'] = true; +$wgGroupPermissions['*']['openid-create-account-with-openid'] = true; +$wgGroupPermissions['*']['openid-create-account-without-openid'] = false; +$wgGroupPermissions['sysop']['openid-create-account-without-openid'] = true; $myResourceTemplate = array( 'localBasePath' => $path . '/skin', @@ -467,3 +478,103 @@ 'ext.openid' ) ); + +class OpenID { + /* + * @param $mode string|array|boolean: mode 'provider'|'consumer'|array('provider','consumer') to be checked if allowed + * @return boolean + */ + static function isAllowedMode( $mode = false ) { + global $wgOpenIDMode, $wgOpenIDProviders, $wgOpenIDForcedProvider; + + if ( !is_string( $mode ) + || is_null( $wgOpenIDMode ) + || ( $wgOpenIDMode === false ) + || !in_array( $mode, array( 'provider', 'consumer' ) ) ) { + return false; + } + + # An empty list of providers _and_ no forced provider implies + # that the wiki cannot act as consumer because it would not accept + # any provider + + if ( $mode === 'consumer' + && !is_array( $wgOpenIDProviders ) + && !self::isForcedProvider() ) { + return false; + } + + if ( is_array( $wgOpenIDMode ) && in_array( $mode, $wgOpenIDMode ) ) { + return true; + } elseif ( is_string( $wgOpenIDMode ) && ( $wgOpenIDMode == $mode ) ) { + return true; + } else { + return false; + } + + } + + /* + * @return boolean + */ + static function isForcedProvider() { + global $wgOpenIDForcedProvider; + return is_string( $wgOpenIDForcedProvider ); + } + + static function getTrustRoot() { + global $wgOpenIDTrustRoot; + + if ( !is_null( $wgOpenIDTrustRoot ) ) { + + $trust_root = $wgOpenIDTrustRoot; + + } else { + + global $wgScriptPath, $wgCanonicalServer; + $trust_root = $wgCanonicalServer . $wgScriptPath; + + } + + return $trust_root; + + } + + static function OpenIDGetServerPath() { + $rel = 'Auth/OpenID/Server.php'; + + foreach ( explode( PATH_SEPARATOR, get_include_path() ) as $pe ) { + $full = $pe . DIRECTORY_SEPARATOR . $rel; + if ( file_exists( $full ) ) { + return $full; + } + } + return $rel; + + } + + /** + * @return string + */ + static function getOpenIDSmallLogoUrl() { + global $wgOpenIDSmallLogoUrl, $wgExtensionAssetsPath; + + if ( !$wgOpenIDSmallLogoUrl ) { + return $wgExtensionAssetsPath . '/OpenID/skin/icons/openid-inputicon.png'; + } else { + return $wgOpenIDSmallLogoUrl; + } + + } + + /** + * @return string + */ + public static function getOpenIDSmallLogoUrlImageTag() { + return Xml::element( 'img', + array( 'src' => self::getOpenIDSmallLogoUrl(), 'alt' => 'OpenID' ), + '' + ); + } + +} /* class OpenID */ diff --git a/OpenIDProvider.body.php b/OpenIDProvider.body.php index 7e534ec..0e7ef47 100644 --- a/OpenIDProvider.body.php +++ b/OpenIDProvider.body.php @@ -139,24 +139,28 @@ $ret = array(); - foreach ( $wgOpenIDProviders as $providerName => $provider ) { - if ( isset( $provider['label'] ) ) { - // fixed, non-localized label string - $label = $provider['label']; - } elseif ( wfMessage( 'openid-provider-label-' . strtolower( $providerName ) )->exists() ) { - $label = wfMessage( 'openid-provider-label-' . strtolower( $providerName ) )->text(); - } else { + if ( is_array( $wgOpenIDProviders ) ) { + + foreach ( $wgOpenIDProviders as $providerName => $provider ) { + if ( isset( $provider['label'] ) ) { + // fixed, non-localized label string + $label = $provider['label']; + } elseif ( wfMessage( 'openid-provider-label-' . strtolower( $providerName ) )->exists() ) { + $label = wfMessage( 'openid-provider-label-' . strtolower( $providerName ) )->text(); + } else { $label = wfMessage( 'openid-provider-label-other-username', array( $providerName ) )->text(); + } + $provider = new self( $providerName, + $provider['large-provider'] ? 'large' : 'small', + $label, + $provider['openid-url'] + ); + if ( $largeOrSmallProvider === null + || $largeOrSmallProvider == $provider->largeOrSmallProvider ) { + $ret[] = $provider; + } } - $provider = new self( $providerName, - $provider['large-provider'] ? 'large' : 'small', - $label, - $provider['openid-url'] - ); - if ( $largeOrSmallProvider === null - || $largeOrSmallProvider == $provider->largeOrSmallProvider ) { - $ret[] = $provider; - } + } return $ret; diff --git a/SpecialOpenID.body.php b/SpecialOpenID.body.php index 2c49437..5298e13 100644 --- a/SpecialOpenID.body.php +++ b/SpecialOpenID.body.php @@ -215,7 +215,7 @@ * @param $finish_page */ function login( $openid_url, $finish_page, $skipTokenTestBecauseForcedProvider = false ) { - global $wgOut, $wgUser, $wgRequest, $wgOpenIDTrustRoot; + global $wgOut, $wgUser, $wgRequest; // Check whether an login or a convert token is present @@ -242,12 +242,7 @@ return; } - if ( !is_null( $wgOpenIDTrustRoot ) ) { - $trust_root = $wgOpenIDTrustRoot; - } else { - global $wgScriptPath, $wgCanonicalServer; - $trust_root = $wgCanonicalServer . $wgScriptPath; - } + $trust_root = OpenID::getTrustRoot(); wfSuppressWarnings(); diff --git a/SpecialOpenIDConvert.body.php b/SpecialOpenIDConvert.body.php index fd8b6a9..39ae655 100644 --- a/SpecialOpenIDConvert.body.php +++ b/SpecialOpenIDConvert.body.php @@ -32,14 +32,25 @@ function __construct() { global $wgOpenIDForcedProvider; - $listed = !is_string( $wgOpenIDForcedProvider ); + $listed = !OpenID::isForcedProvider(); parent::__construct( 'OpenIDConvert', 'openid-converter-access', $listed ); } function execute( $par ) { - global $wgRequest, $wgUser, $wgOut, $wgOpenIDForcedProvider; + global $wgRequest, $wgUser, $wgOut, $wgOpenIDProviders, $wgOpenIDForcedProvider; - if ( is_string( $wgOpenIDForcedProvider ) ) { + if ( !OpenID::isAllowedMode( 'consumer' ) ) { + $wgOut->showErrorPage( + 'openiderror', + 'openid-error-openid-consumer-mode-disabled' + ); + return; + } + +/* use this + if you want to always suppress the convert screen if forced provider + + if ( OpenID::isForcedProvider() ) { $wgOut->showErrorPage( 'openiderror', 'openid-error-openid-convert-not-allowed-forced-provider', @@ -47,6 +58,7 @@ ); return; } +*/ if ( !$this->userCanExecute( $wgUser ) ) { $this->displayRestrictionError(); @@ -68,9 +80,51 @@ break; default: - $openid_url = $wgRequest->getText( 'openid_url' ); + + // if a forced OpenID provider is specified, bypass + // the form and any openid_url in the request. + + $skipTokenTestBecauseForcedProvider = false; + + if ( OpenID::isForcedProvider() ) { + + if ( array_key_exists( $wgOpenIDForcedProvider, $wgOpenIDProviders ) ) { + + $url = $wgOpenIDProviders[$wgOpenIDForcedProvider]['openid-url']; + wfDebug( "OpenID: wgOpenIDForcedProvider $wgOpenIDForcedProvider defined => $url\n" ); + + // make sure that the associated provider Url does not contain {username} placeholder + // and try to use an optional openid-selection-url from the $wgOpenIDProviders array + if ( strpos( $url, '{username}' ) === false ) { + $skipTokenTestBecauseForcedProvider = true; + $openid_url = $url; + } else { + if ( isset ( $wgOpenIDProviders[$wgOpenIDForcedProvider]['openid-selection-url'] ) ) { + $skipTokenTestBecauseForcedProvider = true; + $openid_url = $wgOpenIDProviders[$wgOpenIDForcedProvider]['openid-selection-url']; + } else { + wfDebug( "OpenID: Error: wgOpenIDForcedProvider $wgOpenIDForcedProvider defined, but wgOpenIDProviders array has an invalid provider Url. Must not contain a username placeholder!\n"); + $this->showErrorPage( 'openid-error-wrong-force-provider-setting', array( $wgOpenIDForcedProvider ) ); + return; + } + } + + } else { + + // a fully qualified URL is given + $skipTokenTestBecauseForcedProvider = true; + $openid_url = $wgOpenIDForcedProvider; + + } + + } else { + + $openid_url = $wgRequest->getText( 'openid_url' ); + + } + if ( isset( $openid_url ) && strlen( $openid_url ) > 0 ) { - $this->convert( $openid_url ); + $this->convert( $openid_url, $skipTokenTestBecauseForcedProvider ); } else { $this->form(); } @@ -78,13 +132,17 @@ } } - function convert( $openid_url ) { + function convert( $openid_url, $skipTokenTestBecauseForcedProvider = false ) { global $wgUser, $wgOut, $wgRequest; - if ( !$wgUser->matchEditToken( $wgRequest->getVal( 'openidConvertToken' ), 'openidConvertToken' ) ) { + if ( !$skipTokenTestBecauseForcedProvider + && ( LoginForm::getLoginToken() !== $wgRequest->getVal( 'openidProviderSelectionLoginToken' ) ) + && !( $wgUser->matchEditToken( $wgRequest->getVal( 'openidConvertToken' ), 'openidConvertToken' ) ) ) { + $wgOut->showErrorPage( 'openiderror', 'openid-error-request-forgery' ); return; } + # Expand Interwiki $openid_url = $this->interwikiExpand( $openid_url ); @@ -118,7 +176,8 @@ } // If we're OK to here, let the user go log in - $this->login( $openid_url, SpecialPage::getTitleFor( 'OpenIDConvert', 'Finish' ) ); + $this->login( $openid_url, SpecialPage::getTitleFor( 'OpenIDConvert', 'Finish' ), $skipTokenTestBecauseForcedProvider ); + } public static function renderProviderIcons( &$inputFormHTML, &$largeButtonsHTML, &$smallButtonsHTML ) { diff --git a/SpecialOpenIDDashboard.body.php b/SpecialOpenIDDashboard.body.php index 1295c3b..cd8ca63 100644 --- a/SpecialOpenIDDashboard.body.php +++ b/SpecialOpenIDDashboard.body.php @@ -39,17 +39,27 @@ * @return string */ function show( $string, $value ) { + if ( $value === null ) { $value = 'null'; } elseif ( is_bool( $value ) ) { $value = wfBoolToStr( $value ); } else { - $value = htmlspecialchars( $value ); + $value = htmlspecialchars( $value, ENT_QUOTES ); } - return Html::openElement( 'tr' ) . - Html::openElement( 'td' ) . $string . Html::closeElement( 'td' ) . - Html::openElement( 'td' ) . $value . Html::closeElement( 'td' ) . - Html::closeElement( 'tr' ) . "\n"; + + return Html::rawElement( 'tr', + array(), + Html::rawElement( 'td', + array(), + $string + ) . + Html::rawElement( 'td', + array(), + $value + ) + ) . "\n"; + } /** @@ -59,18 +69,13 @@ */ function execute( $par ) { - global $wgOut, $wgUser; - global $wgOpenIDShowUrlOnUserPage; - global $wgOpenIDTrustEmailAddress; - global $wgOpenIDAllowExistingAccountSelection; - global $wgOpenIDAllowNewAccountname; - global $wgOpenIDUseEmailAsNickname; - global $wgOpenIDProposeUsernameFromSREG; - global $wgOpenIDAllowAutomaticUsername; - global $wgOpenIDLoginOnly; - global $wgOpenIDConsumerAndAlsoProvider; - global $wgOpenIDAllowServingOpenIDUserAccounts; - global $wgOpenIDShowProviderIcons; + global $wgOut, $wgUser, + $wgOpenIDShowUrlOnUserPage, $wgOpenIDTrustEmailAddress, + $wgOpenIDAllowExistingAccountSelection, $wgOpenIDAllowNewAccountname, + $wgOpenIDUseEmailAsNickname, $wgOpenIDProposeUsernameFromSREG, + $wgOpenIDAllowAutomaticUsername, $wgOpenIDLoginOnly, + $wgOpenIDAllowServingOpenIDUserAccounts, $wgOpenIDShowProviderIcons, + $wgOpenIDForcedProvider; if ( !$this->userCanExecute( $wgUser ) ) { $this->displayRestrictionError(); @@ -87,15 +92,36 @@ $wgOut->addWikiMsg( 'openid-dashboard-introduction', 'http://www.mediawiki.org/wiki/Extension:OpenID' ); $wgOut->addHTML( - Html::openElement( 'table', array( 'style' => 'width:50%;', 'class' => 'mw-openiddashboard-table wikitable' ) ) + Html::openElement( 'table', + array( + 'style' => 'width:50%;', + 'class' => 'mw-openiddashboard-table wikitable' + ) + ) ); # Here we show some basic version infos. Retrieval of SVN revision number of OpenID appears to be too difficult $out = $this->show( 'OpenID ' . wfMessage( 'version-software-version' )->text(), MEDIAWIKI_OPENID_VERSION ); $out .= $this->show( 'MediaWiki ' . wfMessage( 'version-software-version' )->text(), SpecialVersion::getVersion() ); $out .= $this->show( '$wgOpenIDLoginOnly', $wgOpenIDLoginOnly ); - $out .= $this->show( '$wgOpenIDConsumerAndAlsoProvider', $wgOpenIDConsumerAndAlsoProvider ); + + $forced = OpenID::isForcedProvider() ? "forced " : ""; + + $mode = "-"; + if ( OpenID::isAllowedMode( 'consumer' ) && OpenID::isAllowedMode( 'provider' ) ) { + $mode = "consumer, {$forced}provider"; + } elseif ( OpenID::isAllowedMode( 'consumer' ) ) { + $mode = "consumer"; + } else { + $mode = "provider"; + } + $out .= $this->show( '$wgOpenIDMode', $mode ); + + $forced = OpenID::isForcedProvider() ? $wgOpenIDForcedProvider : '-'; + $out .= $this->show( '$wgOpenIDForcedProvider', $forced ); + $out .= $this->show( '$wgOpenIDAllowServingOpenIDUserAccounts', $wgOpenIDAllowServingOpenIDUserAccounts ); + $out .= $this->show( '$wgOpenIDTrustRoot', OpenID::getTrustRoot() ); $out .= $this->show( '$wgOpenIDTrustEmailAddress', $wgOpenIDTrustEmailAddress ); $out .= $this->show( '$wgOpenIDAllowExistingAccountSelection', $wgOpenIDAllowExistingAccountSelection ); $out .= $this->show( '$wgOpenIDAllowAutomaticUsername', $wgOpenIDAllowAutomaticUsername ); diff --git a/SpecialOpenIDIdentifier.body.php b/SpecialOpenIDIdentifier.body.php index 60f028a..f44cb67 100644 --- a/SpecialOpenIDIdentifier.body.php +++ b/SpecialOpenIDIdentifier.body.php @@ -29,10 +29,10 @@ } function execute( $par ) { - global $wgOpenIDConsumerAndAlsoProvider, $wgOut; + global $wgOut; $this->setHeaders(); - if ( !$wgOpenIDConsumerAndAlsoProvider ) { + if ( !OpenID::isAllowedMode( 'provider' ) ) { $wgOut->showErrorPage( 'openiderror', 'openidclientonlytext' ); return; } @@ -50,8 +50,7 @@ * @param bool $showSpecialPageText */ public static function showOpenIDIdentifier( $user, $delegate = false, $showSpecialPageText = false ) { - global $wgOut, $wgUser, $wgOpenIDConsumerAndAlsoProvider, $wgOpenIDShowUrlOnUserPage, - $wgOpenIDAllowServingOpenIDUserAccounts; + global $wgOut, $wgUser, $wgOpenIDShowUrlOnUserPage, $wgOpenIDAllowServingOpenIDUserAccounts; // show the own OpenID Url as a subtitle on the user page // but only for the user when visiting their own page @@ -65,7 +64,7 @@ $openid = SpecialOpenID::getUserOpenIDInformation( $user ); # Add OpenID data if its allowed - if ( $wgOpenIDConsumerAndAlsoProvider ) { + if ( OpenID::isAllowedMode( 'provider' ) ) { if ( !( count( $openid ) && ( strlen( $openid[0]->uoi_openid ) != 0 ) && !$wgOpenIDAllowServingOpenIDUserAccounts ) @@ -92,7 +91,7 @@ || ( ( $wgOpenIDShowUrlOnUserPage === 'user' ) && $wgUser->getOption( 'openid-show-openid' ) ) ) ) { $wgOut->setSubtitle( "<span class='subpages'>" . - OpenIDHooks::getOpenIDSmallLogoUrlImageTag() . + OpenID::getOpenIDSmallLogoUrlImageTag() . SpecialOpenIDServer::getLocalIdentityLink( $wgUser ) . "</span>" ); diff --git a/SpecialOpenIDLogin.body.php b/SpecialOpenIDLogin.body.php index d1defab..b368fb0 100644 --- a/SpecialOpenIDLogin.body.php +++ b/SpecialOpenIDLogin.body.php @@ -32,7 +32,9 @@ class SpecialOpenIDLogin extends SpecialOpenID { function __construct() { - parent::__construct( 'OpenIDLogin' ); + global $wgUser; + $listed = !$wgUser->isLoggedIn(); + parent::__construct( 'OpenIDLogin' , 'openid-login-with-openid', $listed ); } /** @@ -41,12 +43,20 @@ * @param $par String or null */ function execute( $par ) { - global $wgRequest, $wgUser, $wgOpenIDForcedProvider, $wgOpenIDProviders; + global $wgRequest, $wgUser, $wgOpenIDForcedProvider, $wgOpenIDProviders, $wgOut; $this->setHeaders(); if ( $wgUser->getID() != 0 ) { $this->alreadyLoggedIn(); + return; + } + + if ( !OpenID::isAllowedMode( 'consumer' ) ) { + $wgOut->showErrorPage( + 'error', + 'openid-error-openid-consumer-mode-disabled' + ); return; } @@ -62,6 +72,7 @@ break; default: # Main entry point + if ( $wgRequest->getText( 'returnto' ) ) { $this->setReturnTo( $wgRequest->getText( 'returnto' ), $wgRequest->getVal( 'returntoquery' ) ); } @@ -71,7 +82,7 @@ $skipTokenTestBecauseForcedProvider = false; - if ( is_string( $wgOpenIDForcedProvider ) ) { + if ( OpenID::isForcedProvider() ) { if ( array_key_exists( $wgOpenIDForcedProvider, $wgOpenIDProviders ) ) { @@ -113,15 +124,9 @@ } else { $this->providerSelectionLoginForm(); } - } - } - /** - * Displays an error message - */ - function showErrorPage( $msg, $params = array() ) { - global $wgUser, $wgOut; - $wgOut->showErrorPage( 'openiderror', $msg, $params ); + } /* switch $par */ + } /** @@ -195,7 +200,7 @@ * @param $messagekey String or null: message name to display at the top */ function chooseNameForm( $openid, $sreg, $ax, $messagekey = null ) { - global $wgOut, $wgOpenIDAllowExistingAccountSelection, $wgHiddenPrefs, + global $wgAuth, $wgOut, $wgOpenIDAllowExistingAccountSelection, $wgHiddenPrefs, $wgUser, $wgOpenIDProposeUsernameFromSREG, $wgOpenIDAllowAutomaticUsername, $wgOpenIDAllowNewAccountname; @@ -303,18 +308,49 @@ array( 'id' => 'wpExistingName' ) - ) . + ) . " " . wfMessage( 'openidchoosepassword' )->text() . Xml::password( 'wpExistingPassword' ) . $oidAttributesUpdate ) . Xml::closeElement( 'tr' ) ); + + if ( $wgAuth->allowPasswordChange() ) { + + $wgOut->addHTML( + Xml::openElement( 'tr' ) . + + Xml::tags( 'td', + array(), + " " + ) . + + Xml::tags( 'td', + array(), + Linker::link( + SpecialPage::getTitleFor( 'PasswordReset' ), + wfMessage( 'passwordreset' )->escaped(), + array(), + array( 'returnto' => SpecialPage::getTitleFor( 'OpenIDLogin' ) ) + ) + ) . + + Xml::closeElement( 'tr' ) + ); + + } + + + $def = true; + } // $wgOpenIDAllowExistingAccountSelection - # These are only available if all visitors are allowed to create accounts - if ( $wgUser->isAllowed( 'createaccount' ) && !$wgUser->isBlockedFromCreateAccount() ) { + # These are only available if the visitor is allowed to create account + if ( $wgUser->isAllowed( 'createaccount' ) + && $wgUser->isAllowed( 'openid-create-account-with-openid' ) + && !$wgUser->isBlockedFromCreateAccount() ) { if ( $wgOpenIDProposeUsernameFromSREG ) { @@ -523,13 +559,16 @@ $nameValue = $wgRequest->getText( 'wpNameValue' ); if ( $choice == 'existing' ) { + $user = $this->attachUser( $openid, $sreg, $wgRequest->getText( 'wpExistingName' ), $wgRequest->getText( 'wpExistingPassword' ) ); - if ( !$user ) { - $this->chooseNameForm( $openid, $sreg, $ax, 'wrongpassword' ); + if ( is_null( $user ) || !$user ) { + + $this->clearValues(); + // $this->chooseNameForm( $openid, $sreg, $ax, 'wrongpassword' ); return; } @@ -543,6 +582,7 @@ $this->updateUser( $user, $sreg, $ax ); } else { + $name = $this->getUserName( $openid, $sreg, $ax, $choice, $nameValue ); if ( !$name || !$this->userNameOK( $name ) ) { @@ -552,13 +592,16 @@ } $user = $this->createUser( $openid, $sreg, $ax, $name ); + } if ( is_null( $user ) ) { + wfDebug( "OpenID: aborting in ChooseName because we could not create user object\n" ); $this->clearValues(); $wgOut->showErrorPage( 'openiderror', 'openiderrortext' ); return; + } $wgUser = $user; @@ -650,6 +693,7 @@ $this->saveValues( $openid, $sreg, $ax ); $this->chooseNameForm( $openid, $sreg, $ax ); + return; } } @@ -795,16 +839,17 @@ function createUser( $openid, $sreg, $ax, $name ) { global $wgUser, $wgAuth; - $user = User::newFromName( $name ); - - # Check permissions - if ( !$user->isAllowed( 'createaccount' ) ) { + # Check permissions of the creating $wgUser + if ( !$wgUser->isAllowed( 'createaccount' ) + || !$wgUser->isAllowed( 'openid-create-account-with-openid' ) ) { wfDebug( "OpenID: User is not allowed to create an account.\n" ); return null; - } elseif ( $user->isBlockedFromCreateAccount() ) { + } elseif ( $wgUser->isBlockedFromCreateAccount() ) { wfDebug( "OpenID: User is blocked.\n" ); return null; } + + $user = User::newFromName( $name ); if ( !$user ) { wfDebug( "OpenID: Error adding new user.\n" ); @@ -844,19 +889,36 @@ * @return bool|null|User */ function attachUser( $openid, $sreg, $name, $password ) { + global $wgAuth; + $user = User::newFromName( $name ); - if ( !$user ) { - return null; + if ( $user->checkPassword( $password ) ) { + + // de-validate the temporary password + // requires MediaWiki core with https://gerrit.wikimedia.org/r/#/c/96029/ merged 2013-11-18 + $user->setNewPassword( null ); + self::addUserUrl( $user, $openid ); + + return $user; + } - if ( !$user->checkPassword( $password ) ) { + if ( $user->checkTemporaryPassword( $password ) ) { + + $wgAuth->updateUser( $user ); + $user->saveSettings(); + + $reset = new SpecialChangePassword(); + $reset->setContext( $this->getContext()->setUser( $user ) ); + $reset->execute( null ); + return null; + } - self::addUserUrl( $user, $openid ); + return null; - return $user; } /** @@ -887,7 +949,10 @@ } # try AX - $fullname = ( ( array_key_exists( 'http://axschema.org/namePerson/first', $ax ) || array_key_exists( 'http://axschema.org/namePerson/last', $ax ) ) ? $ax['http://axschema.org/namePerson/first'][0] . " " . $ax['http://axschema.org/namePerson/last'][0] : null ); + $fullname = ( ( array_key_exists( 'http://axschema.org/namePerson/first', $ax ) + || array_key_exists( 'http://axschema.org/namePerson/last', $ax ) ) ? + $ax['http://axschema.org/namePerson/first'][0] . " " . $ax['http://axschema.org/namePerson/last'][0] : null + ); return $fullname; case 'url': diff --git a/SpecialOpenIDServer.body.php b/SpecialOpenIDServer.body.php index b821b21..aa394d0 100644 --- a/SpecialOpenIDServer.body.php +++ b/SpecialOpenIDServer.body.php @@ -54,7 +54,7 @@ } function execute( $par ) { - global $wgOut, $wgOpenIDConsumerAndAlsoProvider, $wgOpenIDIdentifierSelect, $wgRequest, $wgUser; + global $wgOut, $wgOpenIDIdentifierSelect, $wgRequest, $wgUser; $this->setHeaders(); @@ -62,7 +62,7 @@ # Note: special page is un-registered if this flag is set, # so it'd be unusual to get here. - if ( !$wgOpenIDConsumerAndAlsoProvider ) { + if ( !OpenID::isAllowedMode( 'provider' ) ) { $wgOut->showErrorPage( 'openiderror', 'openidclientonlytext' ); return; } diff --git a/SpecialOpenIDXRDS.body.php b/SpecialOpenIDXRDS.body.php index 37da01d..4b27c80 100644 --- a/SpecialOpenIDXRDS.body.php +++ b/SpecialOpenIDXRDS.body.php @@ -40,13 +40,13 @@ # $par is a user name function execute( $par ) { - global $wgOut, $wgOpenIDConsumerAndAlsoProvider; + global $wgOut; # No server functionality if this site is only a client # Note: special page is un-registered if this flag is set, # so it'd be unusual to get here. - if ( !$wgOpenIDConsumerAndAlsoProvider ) { + if ( !OpenID::isAllowedMode( 'provider' ) ) { wfHttpError( 404, "Not Found", wfMessage( 'openidclientonlytext' )->text() ); return; } -- To view, visit https://gerrit.wikimedia.org/r/94977 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id: Ieff71386de02d0c9e428df5131467cc7af75faff Gerrit-PatchSet: 26 Gerrit-Project: mediawiki/extensions/OpenID Gerrit-Branch: master Gerrit-Owner: Wikinaut <m...@tgries.de> Gerrit-Reviewer: Wikinaut <m...@tgries.de> Gerrit-Reviewer: jenkins-bot _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits