Index: trunk/phase3/maintenance/archives/patch-external_user.sql |
— | — | @@ -0,0 +1,9 @@ |
| 2 | +CREATE TABLE /*_*/external_user ( |
| 3 | + -- Foreign key to user_id |
| 4 | + eu_wiki_id int unsigned NOT NULL PRIMARY KEY, |
| 5 | + |
| 6 | + -- Some opaque identifier provided by the external database |
| 7 | + eu_external_id varchar(255) binary NOT NULL |
| 8 | +) /*$wgDBTableOptions*/; |
| 9 | + |
| 10 | +CREATE UNIQUE INDEX /*i*/eu_external_id ON /*_*/external_user (eu_external_id); |
Property changes on: trunk/phase3/maintenance/archives/patch-external_user.sql |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 11 | + native |
Index: trunk/phase3/maintenance/updaters.inc |
— | — | @@ -162,6 +162,7 @@ |
163 | 163 | array( 'do_log_search_population' ), |
164 | 164 | array( 'add_field', 'logging', 'log_user_text', 'patch-log_user_text.sql' ), |
165 | 165 | array( 'add_table', 'l10n_cache', 'patch-l10n_cache.sql' ), |
| 166 | + array( 'add_table', 'external_user', 'patch-external_user.sql' ), |
166 | 167 | ), |
167 | 168 | |
168 | 169 | 'sqlite' => array( |
Index: trunk/phase3/maintenance/tables.sql |
— | — | @@ -575,6 +575,20 @@ |
576 | 576 | CREATE INDEX /*i*/el_index ON /*_*/externallinks (el_index(60)); |
577 | 577 | |
578 | 578 | |
| 579 | +-- |
| 580 | +-- Track external user accounts, if ExternalAuth is used |
| 581 | +-- |
| 582 | +CREATE TABLE /*_*/external_user ( |
| 583 | + -- Foreign key to user_id |
| 584 | + eu_wiki_id int unsigned NOT NULL PRIMARY KEY, |
| 585 | + |
| 586 | + -- Some opaque identifier provided by the external database |
| 587 | + eu_external_id varchar(255) binary NOT NULL |
| 588 | +) /*$wgDBTableOptions*/; |
| 589 | + |
| 590 | +CREATE UNIQUE INDEX /*i*/eu_external_id ON /*_*/external_user (eu_external_id); |
| 591 | + |
| 592 | + |
579 | 593 | -- |
580 | 594 | -- Track interlanguage links |
581 | 595 | -- |
Index: trunk/phase3/includes/User.php |
— | — | @@ -3569,6 +3569,10 @@ |
3570 | 3570 | } |
3571 | 3571 | |
3572 | 3572 | protected function saveOptions() { |
| 3573 | + global $wgAllowPrefChange; |
| 3574 | + |
| 3575 | + $extuser = ExternalUser::newFromUser( $this ); |
| 3576 | + |
3573 | 3577 | $this->loadOptions(); |
3574 | 3578 | $dbw = wfGetDB( DB_MASTER ); |
3575 | 3579 | |
— | — | @@ -3582,7 +3586,8 @@ |
3583 | 3587 | return; |
3584 | 3588 | |
3585 | 3589 | foreach( $saveOptions as $key => $value ) { |
3586 | | - if ( ( is_null(self::getDefaultOption($key)) && |
| 3590 | + # Don't bother storing default values |
| 3591 | + if ( ( is_null( self::getDefaultOption( $key ) ) && |
3587 | 3592 | !( $value === false || is_null($value) ) ) || |
3588 | 3593 | $value != self::getDefaultOption( $key ) ) { |
3589 | 3594 | $insert_rows[] = array( |
— | — | @@ -3591,6 +3596,14 @@ |
3592 | 3597 | 'up_value' => $value, |
3593 | 3598 | ); |
3594 | 3599 | } |
| 3600 | + if ( $extuser && isset( $wgAllowPrefChange[$key] ) ) { |
| 3601 | + switch ( $wgAllowPrefChange[$key] ) { |
| 3602 | + case 'local': case 'message': |
| 3603 | + break; |
| 3604 | + case 'semiglobal': case 'global': |
| 3605 | + $extuser->setPref( $key, $value ); |
| 3606 | + } |
| 3607 | + } |
3595 | 3608 | } |
3596 | 3609 | |
3597 | 3610 | $dbw->begin(); |
Index: trunk/phase3/includes/ExternalUser.php |
— | — | @@ -0,0 +1,288 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +# Copyright (C) 2009 Aryeh Gregor |
| 5 | +# |
| 6 | +# This program is free software; you can redistribute it and/or modify |
| 7 | +# it under the terms of the GNU General Public License as published by |
| 8 | +# the Free Software Foundation; either version 2 of the License, or |
| 9 | +# (at your option) any later version. |
| 10 | +# |
| 11 | +# This program is distributed in the hope that it will be useful, |
| 12 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 14 | +# GNU General Public License for more details. |
| 15 | +# |
| 16 | +# You should have received a copy of the GNU General Public License along |
| 17 | +# with this program; if not, write to the Free Software Foundation, Inc., |
| 18 | +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
| 19 | +# http://www.gnu.org/copyleft/gpl.html |
| 20 | + |
| 21 | +/** |
| 22 | + * A class intended to supplement, and perhaps eventually replace, AuthPlugin. |
| 23 | + * See: http://www.mediawiki.org/wiki/ExternalAuth |
| 24 | + * |
| 25 | + * The class represents a user whose data is in a foreign database. The |
| 26 | + * database may have entirely different conventions from MediaWiki, but it's |
| 27 | + * assumed to at least support the concept of a user id (possibly not an |
| 28 | + * integer), a user name (possibly not meeting MediaWiki's username |
| 29 | + * requirements), and a password. |
| 30 | + */ |
| 31 | +abstract class ExternalUser { |
| 32 | + protected function __construct() {} |
| 33 | + |
| 34 | + /** |
| 35 | + * Wrappers around initFrom*(). |
| 36 | + */ |
| 37 | + |
| 38 | + /** |
| 39 | + * @param $name string |
| 40 | + * @return mixed ExternalUser, or false on failure |
| 41 | + */ |
| 42 | + public static function newFromName( $name ) { |
| 43 | + global $wgExternalAuthType; |
| 44 | + if ( is_null( $wgExternalAuthType ) ) { |
| 45 | + return false; |
| 46 | + } |
| 47 | + $class = "ExternalUser_$wgExternalAuthType"; |
| 48 | + $obj = new $class; |
| 49 | + if ( !$obj->initFromName( $name ) ) { |
| 50 | + return false; |
| 51 | + } |
| 52 | + return $obj; |
| 53 | + } |
| 54 | + |
| 55 | + /** |
| 56 | + * @param $id string |
| 57 | + * @return mixed ExternalUser, or false on failure |
| 58 | + */ |
| 59 | + public static function newFromId( $id ) { |
| 60 | + global $wgExternalAuthType; |
| 61 | + if ( is_null( $wgExternalAuthType ) ) { |
| 62 | + return false; |
| 63 | + } |
| 64 | + $class = "ExternalUser_$wgExternalAuthType"; |
| 65 | + $obj = new $class; |
| 66 | + if ( !$obj->initFromId( $id ) ) { |
| 67 | + return false; |
| 68 | + } |
| 69 | + return $obj; |
| 70 | + } |
| 71 | + |
| 72 | + /** |
| 73 | + * @param $cookie string |
| 74 | + * @return mixed ExternalUser, or false on failure |
| 75 | + */ |
| 76 | + public static function newFromCookie( $cookie ) { |
| 77 | + global $wgExternalAuthType; |
| 78 | + if ( is_null( $wgExternalAuthType ) ) { |
| 79 | + return false; |
| 80 | + } |
| 81 | + $class = "ExternalUser_$wgExternalAuthType"; |
| 82 | + $obj = new $class; |
| 83 | + if ( !$obj->initFromCookie( $cookie ) ) { |
| 84 | + return false; |
| 85 | + } |
| 86 | + return $obj; |
| 87 | + } |
| 88 | + |
| 89 | + /** |
| 90 | + * Creates the object corresponding to the given User object, assuming the |
| 91 | + * user exists on the wiki and is linked to an external account. If either |
| 92 | + * of these is false, this will return false. |
| 93 | + * |
| 94 | + * This is a wrapper around newFromId(). |
| 95 | + * |
| 96 | + * @param $user User |
| 97 | + * @return mixed ExternalUser or false |
| 98 | + */ |
| 99 | + public static function newFromUser( $user ) { |
| 100 | + global $wgExternalAuthType; |
| 101 | + if ( is_null( $wgExternalAuthType ) ) { |
| 102 | + # Short-circuit to avoid database query in common case so no one |
| 103 | + # kills me |
| 104 | + return false; |
| 105 | + } |
| 106 | + |
| 107 | + $dbr = wfGetDB( DB_SLAVE ); |
| 108 | + $id = $dbr->selectField( 'external_user', 'eu_external_id', |
| 109 | + array( 'eu_wiki_id' => $user->getId() ), __METHOD__ ); |
| 110 | + if ( $id === false ) { |
| 111 | + return false; |
| 112 | + } |
| 113 | + return self::newFromId( $id ); |
| 114 | + } |
| 115 | + |
| 116 | + /** |
| 117 | + * Given a name, which is a string exactly as input by the user in the |
| 118 | + * login form but with whitespace stripped, initialize this object to be |
| 119 | + * the corresponding ExternalUser. Return true if successful, otherwise |
| 120 | + * false. |
| 121 | + * |
| 122 | + * @param $name string |
| 123 | + * @return bool Success? |
| 124 | + */ |
| 125 | + protected abstract function initFromName( $name ); |
| 126 | + |
| 127 | + /** |
| 128 | + * Given an id, which was at some previous point in history returned by |
| 129 | + * getId(), initialize this object to be the corresponding ExternalUser. |
| 130 | + * Return true if successful, false otherwise. |
| 131 | + * |
| 132 | + * @param $id string |
| 133 | + * @return bool Success? |
| 134 | + */ |
| 135 | + protected abstract function initFromId( $id ); |
| 136 | + |
| 137 | + /** |
| 138 | + * Given the user's cookie, initialize this object to the correct user if |
| 139 | + * the cookie indicates that the user is logged into the external database. |
| 140 | + * If successful, return true. If the external database doesn't support |
| 141 | + * cookie-based authentication, or if the cookies don't belong to a |
| 142 | + * logged-in user, return false. |
| 143 | + * |
| 144 | + * TODO: Actually use this. |
| 145 | + * |
| 146 | + * @param $cookie string |
| 147 | + * @return bool Success? |
| 148 | + */ |
| 149 | + protected function initFromCookie( $cookie ) { |
| 150 | + return false; |
| 151 | + } |
| 152 | + |
| 153 | + /** |
| 154 | + * This must return some identifier that stably, uniquely identifies the |
| 155 | + * user. In a typical web application, this could be an integer |
| 156 | + * representing the "user id". In other cases, it might be a string. In |
| 157 | + * any event, the return value should be a string between 1 and 255 |
| 158 | + * characters in length; must uniquely identify the user in the foreign |
| 159 | + * database; and, if at all possible, should be permanent. |
| 160 | + * |
| 161 | + * This will only ever be used to reconstruct this ExternalUser object via |
| 162 | + * newFromId(). The resulting object in that case should correspond to the |
| 163 | + * same user, even if details have changed in the interim (e.g., renames or |
| 164 | + * preference changes). |
| 165 | + * |
| 166 | + * @return string |
| 167 | + */ |
| 168 | + abstract public function getId(); |
| 169 | + |
| 170 | + /** |
| 171 | + * This must return the name that the user would normally use for login to |
| 172 | + * the external database. It is subject to no particular restrictions |
| 173 | + * beyond rudimentary sanity, and in particular may be invalid as a |
| 174 | + * MediaWiki username. It's used to auto-generate an account name that |
| 175 | + * *is* valid for MediaWiki, either with or without user input, but |
| 176 | + * basically is only a hint. |
| 177 | + * |
| 178 | + * @return string |
| 179 | + */ |
| 180 | + abstract public function getName(); |
| 181 | + |
| 182 | + /** |
| 183 | + * Is the given password valid for the external user? The password is |
| 184 | + * provided in plaintext, with whitespace stripped but not otherwise |
| 185 | + * modified. |
| 186 | + * |
| 187 | + * @param $password string |
| 188 | + * @return bool |
| 189 | + */ |
| 190 | + abstract public function authenticate( $password ); |
| 191 | + |
| 192 | + /** |
| 193 | + * Retrieve the value corresponding to the given preference key. The most |
| 194 | + * important values are: |
| 195 | + * |
| 196 | + * - emailaddress |
| 197 | + * - language |
| 198 | + * |
| 199 | + * The value must meet MediaWiki's requirements for values of this type, |
| 200 | + * and will be checked for validity before use. If the preference makes no |
| 201 | + * sense for the backend, or it makes sense but is unset for this user, or |
| 202 | + * is unrecognized, return null. |
| 203 | + * |
| 204 | + * $pref will never equal 'password', since passwords are usually hashed |
| 205 | + * and cannot be directly retrieved. authenticate() is used for this |
| 206 | + * instead. |
| 207 | + * |
| 208 | + * TODO: Currently this is only called for 'emailaddress'; generalize! Add |
| 209 | + * some config option to decide which values are grabbed on user |
| 210 | + * initialization. |
| 211 | + * |
| 212 | + * @param $pref string |
| 213 | + * @return mixed |
| 214 | + */ |
| 215 | + public function getPref( $pref ) { |
| 216 | + return null; |
| 217 | + } |
| 218 | + |
| 219 | + /** |
| 220 | + * Return an array of identifiers for all the foreign groups that this user |
| 221 | + * has. The identifiers are opaque objects that only need to be |
| 222 | + * specifiable by the administrator in LocalSettings.php when configuring |
| 223 | + * $wgAutopromote. They may be, for instance, strings or integers. |
| 224 | + * |
| 225 | + * TODO: Support this in $wgAutopromote. |
| 226 | + * |
| 227 | + * @return array |
| 228 | + */ |
| 229 | + public function getGroups() { |
| 230 | + return array(); |
| 231 | + } |
| 232 | + |
| 233 | + /** |
| 234 | + * Given a preference key (e.g., 'emailaddress'), provide an HTML message |
| 235 | + * telling the user how to change it in the external database. The |
| 236 | + * administrator has specified that this preference cannot be changed on |
| 237 | + * the wiki, and may only be changed in the foreign database. If no |
| 238 | + * message is available, such as for an unrecognized preference, return |
| 239 | + * false. |
| 240 | + * |
| 241 | + * TODO: Use this somewhere. |
| 242 | + * |
| 243 | + * @param $pref string |
| 244 | + * @return mixed String or false |
| 245 | + */ |
| 246 | + public static function prefMessage( $pref ) { |
| 247 | + return false; |
| 248 | + } |
| 249 | + |
| 250 | + /** |
| 251 | + * Set the given preference key to the given value. Two important |
| 252 | + * preference keys that you might want to implement are 'password' and |
| 253 | + * 'emailaddress'. If the set fails, such as because the preference is |
| 254 | + * unrecognized or because the external database can't be changed right |
| 255 | + * now, return false. If it succeeds, return true. |
| 256 | + * |
| 257 | + * If applicable, you should make sure to validate the new value against |
| 258 | + * any constraints the external database may have, since MediaWiki may have |
| 259 | + * more limited constraints (e.g., on password strength). |
| 260 | + * |
| 261 | + * TODO: Untested. |
| 262 | + * |
| 263 | + * @param $key string |
| 264 | + * @param $value string |
| 265 | + * @return bool Success? |
| 266 | + */ |
| 267 | + public static function setPref( $key, $value ) { |
| 268 | + return false; |
| 269 | + } |
| 270 | + |
| 271 | + /** |
| 272 | + * Create a link for future reference between this object and the provided |
| 273 | + * user_id. If the user was already linked, the old link will be |
| 274 | + * overwritten. |
| 275 | + * |
| 276 | + * This is part of the core code and is not overridable by specific |
| 277 | + * plugins. It's in this class only for convenience. |
| 278 | + * |
| 279 | + * @param $id int user_id |
| 280 | + */ |
| 281 | + public final function link( $id ) { |
| 282 | + $dbw = wfGetDB( DB_MASTER ); |
| 283 | + $dbw->replace( 'external_user', |
| 284 | + array( 'eu_wiki_id', 'eu_external_id' ), |
| 285 | + array( 'eu_wiki_id' => $id, |
| 286 | + 'eu_external_id' => $this->getId() ), |
| 287 | + __METHOD__ ); |
| 288 | + } |
| 289 | +} |
Property changes on: trunk/phase3/includes/ExternalUser.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 290 | + native |
Index: trunk/phase3/includes/AutoLoader.php |
— | — | @@ -74,6 +74,8 @@ |
75 | 75 | 'ExternalStoreDB' => 'includes/ExternalStoreDB.php', |
76 | 76 | 'ExternalStoreHttp' => 'includes/ExternalStoreHttp.php', |
77 | 77 | 'ExternalStore' => 'includes/ExternalStore.php', |
| 78 | + 'ExternalUser' => 'includes/ExternalUser.php', |
| 79 | + 'ExternalUser_vB' => 'includes/extauth/vB.php', |
78 | 80 | 'FatalError' => 'includes/Exception.php', |
79 | 81 | 'FakeTitle' => 'includes/FakeTitle.php', |
80 | 82 | 'FauxRequest' => 'includes/WebRequest.php', |
Index: trunk/phase3/includes/DefaultSettings.php |
— | — | @@ -4028,3 +4028,60 @@ |
4029 | 4029 | * ); |
4030 | 4030 | */ |
4031 | 4031 | $wgPoolCounterConf = null; |
| 4032 | + |
| 4033 | +/** |
| 4034 | + * Use some particular type of external authentication. The specific |
| 4035 | + * authentication module you use will normally require some extra settings to |
| 4036 | + * be specified. |
| 4037 | + * |
| 4038 | + * null indicates no external authentication is to be used. Otherwise, |
| 4039 | + * "ExternalUser_$wgExternalAuthType" must be the name of a non-abstract class |
| 4040 | + * that extends ExternalUser. |
| 4041 | + * |
| 4042 | + * Core authentication modules can be found in includes/extauth/. |
| 4043 | + */ |
| 4044 | +$wgExternalAuthType = null; |
| 4045 | + |
| 4046 | +/** |
| 4047 | + * Configuration for the external authentication. This may include arbitrary |
| 4048 | + * keys that depend on the authentication mechanism. For instance, |
| 4049 | + * authentication against another web app might require that the database login |
| 4050 | + * info be provided. Check the file where your auth mechanism is defined for |
| 4051 | + * info on what to put here. |
| 4052 | + */ |
| 4053 | +$wgExternalAuthConfig = array(); |
| 4054 | + |
| 4055 | +/** |
| 4056 | + * When should we automatically create local accounts when external accounts |
| 4057 | + * already exist, if using ExternalAuth? Can have three values: 'never', |
| 4058 | + * 'login', 'view'. 'view' requires the external database to support cookies, |
| 4059 | + * and implies 'login'. |
| 4060 | + * |
| 4061 | + * TODO: Implement 'view' (currently behaves like 'login'). |
| 4062 | + */ |
| 4063 | +$wgAutocreatePolicy = 'login'; |
| 4064 | + |
| 4065 | +/** |
| 4066 | + * Policies for how each preference is allowed to be changed, in the presence |
| 4067 | + * of external authentication. The keys are preference keys, e.g., 'password' |
| 4068 | + * or 'emailaddress' (see Preferences.php et al.). The value can be one of the |
| 4069 | + * following: |
| 4070 | + * |
| 4071 | + * - local: Allow changes to this pref through the wiki interface but only |
| 4072 | + * apply them locally (default). |
| 4073 | + * - semiglobal: Allow changes through the wiki interface and try to apply them |
| 4074 | + * to the foreign database, but continue on anyway if that fails. |
| 4075 | + * - global: Allow changes through the wiki interface, but only let them go |
| 4076 | + * through if they successfully update the foreign database. |
| 4077 | + * - message: Allow no local changes for linked accounts; replace the change |
| 4078 | + * form with a message provided by the auth plugin, telling the user how to |
| 4079 | + * change the setting externally (maybe providing a link, etc.). If the auth |
| 4080 | + * plugin provides no message for this preference, hide it entirely. |
| 4081 | + * |
| 4082 | + * Accounts that are not linked to an external account are never affected by |
| 4083 | + * this setting. You may want to look at $wgHiddenPrefs instead. |
| 4084 | + * $wgHiddenPrefs supersedes this option. |
| 4085 | + * |
| 4086 | + * TODO: Implement message, global. |
| 4087 | + */ |
| 4088 | +$wgAllowPrefChange = array(); |
Index: trunk/phase3/includes/specials/SpecialUserlogin.php |
— | — | @@ -40,6 +40,8 @@ |
41 | 41 | var $mLoginattempt, $mRemember, $mEmail, $mDomain, $mLanguage; |
42 | 42 | var $mSkipCookieCheck, $mReturnToQuery; |
43 | 43 | |
| 44 | + private $mExtUser = null; |
| 45 | + |
44 | 46 | /** |
45 | 47 | * Constructor |
46 | 48 | * @param WebRequest $request A WebRequest object passed by reference |
— | — | @@ -363,6 +365,14 @@ |
364 | 366 | |
365 | 367 | $wgAuth->initUser( $u, $autocreate ); |
366 | 368 | |
| 369 | + if ( $this->mExtUser ) { |
| 370 | + $this->mExtUser->link( $u->getId() ); |
| 371 | + $email = $this->mExtUser->getPref( 'emailaddress' ); |
| 372 | + if ( $email && !$this->mEmail ) { |
| 373 | + $u->setEmail( $email ); |
| 374 | + } |
| 375 | + } |
| 376 | + |
367 | 377 | $u->setOption( 'rememberpassword', $this->mRemember ? 1 : 0 ); |
368 | 378 | $u->saveSettings(); |
369 | 379 | |
— | — | @@ -417,6 +427,11 @@ |
418 | 428 | wfDebug( __METHOD__.": already logged in as {$this->mName}\n" ); |
419 | 429 | return self::SUCCESS; |
420 | 430 | } |
| 431 | + |
| 432 | + $this->mExtUser = ExternalUser::newFromName( $this->mName ); |
| 433 | + |
| 434 | + # TODO: Allow some magic here for invalid external names, e.g., let the |
| 435 | + # user choose a different wiki name. |
421 | 436 | $u = User::newFromName( $this->mName ); |
422 | 437 | if( is_null( $u ) || !User::isUsableName( $u->getName() ) ) { |
423 | 438 | return self::ILLEGAL; |
— | — | @@ -496,27 +511,41 @@ |
497 | 512 | * @return integer Status code |
498 | 513 | */ |
499 | 514 | function attemptAutoCreate( $user ) { |
500 | | - global $wgAuth, $wgUser; |
| 515 | + global $wgAuth, $wgUser, $wgAutocreatePolicy; |
| 516 | + |
| 517 | + if ( $wgUser->isBlockedFromCreateAccount() ) { |
| 518 | + wfDebug( __METHOD__.": user is blocked from account creation\n" ); |
| 519 | + return self::CREATE_BLOCKED; |
| 520 | + } |
| 521 | + |
501 | 522 | /** |
502 | 523 | * If the external authentication plugin allows it, automatically cre- |
503 | 524 | * ate a new account for users that are externally defined but have not |
504 | 525 | * yet logged in. |
505 | 526 | */ |
506 | | - if ( !$wgAuth->autoCreate() ) { |
507 | | - return self::NOT_EXISTS; |
| 527 | + if ( $this->mExtUser ) { |
| 528 | + # mExtUser is neither null nor false, so use the new ExternalAuth |
| 529 | + # system. |
| 530 | + if ( $wgAutocreatePolicy == 'never' ) { |
| 531 | + return self::NOT_EXISTS; |
| 532 | + } |
| 533 | + if ( !$this->mExtUser->authenticate( $this->mPassword ) ) { |
| 534 | + return self::WRONG_PLUGIN_PASS; |
| 535 | + } |
| 536 | + } else { |
| 537 | + # Old AuthPlugin. |
| 538 | + if ( !$wgAuth->autoCreate() ) { |
| 539 | + return self::NOT_EXISTS; |
| 540 | + } |
| 541 | + if ( !$wgAuth->userExists( $user->getName() ) ) { |
| 542 | + wfDebug( __METHOD__.": user does not exist\n" ); |
| 543 | + return self::NOT_EXISTS; |
| 544 | + } |
| 545 | + if ( !$wgAuth->authenticate( $user->getName(), $this->mPassword ) ) { |
| 546 | + wfDebug( __METHOD__.": \$wgAuth->authenticate() returned false, aborting\n" ); |
| 547 | + return self::WRONG_PLUGIN_PASS; |
| 548 | + } |
508 | 549 | } |
509 | | - if ( !$wgAuth->userExists( $user->getName() ) ) { |
510 | | - wfDebug( __METHOD__.": user does not exist\n" ); |
511 | | - return self::NOT_EXISTS; |
512 | | - } |
513 | | - if ( !$wgAuth->authenticate( $user->getName(), $this->mPassword ) ) { |
514 | | - wfDebug( __METHOD__.": \$wgAuth->authenticate() returned false, aborting\n" ); |
515 | | - return self::WRONG_PLUGIN_PASS; |
516 | | - } |
517 | | - if ( $wgUser->isBlockedFromCreateAccount() ) { |
518 | | - wfDebug( __METHOD__.": user is blocked from account creation\n" ); |
519 | | - return self::CREATE_BLOCKED; |
520 | | - } |
521 | 550 | |
522 | 551 | wfDebug( __METHOD__.": creating account\n" ); |
523 | 552 | $user = $this->initUser( $user, true ); |
— | — | @@ -526,8 +555,7 @@ |
527 | 556 | function processLogin() { |
528 | 557 | global $wgUser, $wgAuth; |
529 | 558 | |
530 | | - switch ($this->authenticateUserData()) |
531 | | - { |
| 559 | + switch ( $this->authenticateUserData() ) { |
532 | 560 | case self::SUCCESS: |
533 | 561 | # We've verified now, update the real record |
534 | 562 | if( (bool)$this->mRemember != (bool)$wgUser->getOption( 'rememberpassword' ) ) { |
Index: trunk/phase3/includes/extauth/vB.php |
— | — | @@ -0,0 +1,97 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +# Copyright (C) 2009 Aryeh Gregor |
| 5 | +# |
| 6 | +# This program is free software; you can redistribute it and/or modify |
| 7 | +# it under the terms of the GNU General Public License as published by |
| 8 | +# the Free Software Foundation; either version 2 of the License, or |
| 9 | +# (at your option) any later version. |
| 10 | +# |
| 11 | +# This program is distributed in the hope that it will be useful, |
| 12 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 14 | +# GNU General Public License for more details. |
| 15 | +# |
| 16 | +# You should have received a copy of the GNU General Public License along |
| 17 | +# with this program; if not, write to the Free Software Foundation, Inc., |
| 18 | +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
| 19 | +# http://www.gnu.org/copyleft/gpl.html |
| 20 | + |
| 21 | +/** |
| 22 | + * This class supports the proprietary vBulletin forum system |
| 23 | + * <http://www.vbulletin.com>, versions 3.5 and up. It calls no functions or |
| 24 | + * code, only reads from the database. Example lines to put in |
| 25 | + * LocalSettings.php: |
| 26 | + * |
| 27 | + * $wgExternalAuthType = 'vB'; |
| 28 | + * $wgExternalAuthConf = array( |
| 29 | + * 'server' => 'localhost', |
| 30 | + * 'username' => 'forum', |
| 31 | + * 'password' => 'udE,jSqDJ<""p=fI.K9', |
| 32 | + * 'dbname' => 'forum', |
| 33 | + * 'tableprefix' => '' |
| 34 | + * ); |
| 35 | + */ |
| 36 | +class ExternalUser_vB extends ExternalUser { |
| 37 | + private $mDb, $mRow; |
| 38 | + |
| 39 | + protected function initFromName( $name ) { |
| 40 | + return $this->initFromCond( array( 'username' => $name ) ); |
| 41 | + } |
| 42 | + |
| 43 | + protected function initFromId( $id ) { |
| 44 | + return $this->initFromCond( array( 'userid' => $id ) ); |
| 45 | + } |
| 46 | + |
| 47 | + # initFromCookie() not yet implemented |
| 48 | + |
| 49 | + private function initFromCond( $cond ) { |
| 50 | + global $wgExternalAuthConf; |
| 51 | + |
| 52 | + $this->mDb = new Database( |
| 53 | + $wgExternalAuthConf['server'], |
| 54 | + $wgExternalAuthConf['username'], |
| 55 | + $wgExternalAuthConf['password'], |
| 56 | + $wgExternalAuthConf['dbname'], |
| 57 | + false, 0, |
| 58 | + $wgExternalAuthConf['tableprefix'] |
| 59 | + ); |
| 60 | + |
| 61 | + $row = $this->mDb->selectRow( |
| 62 | + 'user', |
| 63 | + array( 'userid', 'username', 'password', 'salt', 'email', 'usergroupid', |
| 64 | + 'membergroupids' ), |
| 65 | + $cond, |
| 66 | + __METHOD__ |
| 67 | + ); |
| 68 | + if ( !$row ) { |
| 69 | + return false; |
| 70 | + } |
| 71 | + $this->mRow = $row; |
| 72 | + |
| 73 | + return true; |
| 74 | + } |
| 75 | + |
| 76 | + public function getId() { return $this->mRow->userid; } |
| 77 | + public function getName() { return $this->mRow->username; } |
| 78 | + |
| 79 | + public function authenticate( $password ) { |
| 80 | + return $this->mRow->password == md5( md5( $password ) |
| 81 | + . $this->mRow->salt ); |
| 82 | + } |
| 83 | + |
| 84 | + public function getPref( $pref ) { |
| 85 | + if ( $pref == 'emailaddress' && $this->mRow->email ) { |
| 86 | + # TODO: only return if validated? |
| 87 | + return $this->mRow->email; |
| 88 | + } |
| 89 | + return null; |
| 90 | + } |
| 91 | + |
| 92 | + public function getGroups() { |
| 93 | + $groups = array( $this->mRow->usergroupid ); |
| 94 | + $groups = array_merge( $groups, explode( ',', $this->mRow->membergroupids ) ); |
| 95 | + $groups = array_unique( $groups ); |
| 96 | + return $groups; |
| 97 | + } |
| 98 | +} |
Property changes on: trunk/phase3/includes/extauth/vB.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 99 | + native |
Index: trunk/phase3/RELEASE-NOTES |
— | — | @@ -150,6 +150,7 @@ |
151 | 151 | thumbnails to be stored in a separate location to the source images. |
152 | 152 | * If config/ directory is not executable, the command to make it executable |
153 | 153 | now asks the user to cd to the correct directory |
| 154 | +* Add experimental new external authentication framework, ExternalAuth. |
154 | 155 | |
155 | 156 | === Bug fixes in 1.16 === |
156 | 157 | |