r48970 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r48969‎ | r48970 | r48971 >
Date:19:08, 28 March 2009
Author:catrope
Status:ok (Comments)
Tags:
Comment:
Redo r48746 (API userrights, reverted in r48909 and r48910) in a way that doesn't break CentralAuth. Basically, this works around PHP's inability (at least in < 5.3) to override static methods by adding a hook. Changes to CentralAuth in next commit.
Modified paths:
  • /trunk/phase3/RELEASE-NOTES (modified) (history)
  • /trunk/phase3/docs/hooks.txt (modified) (history)
  • /trunk/phase3/includes/AutoLoader.php (modified) (history)
  • /trunk/phase3/includes/User.php (modified) (history)
  • /trunk/phase3/includes/api/ApiMain.php (modified) (history)
  • /trunk/phase3/includes/api/ApiQueryRecentChanges.php (modified) (history)
  • /trunk/phase3/includes/api/ApiQueryUsers.php (modified) (history)
  • /trunk/phase3/includes/api/ApiUserrights.php (added) (history)
  • /trunk/phase3/includes/specials/SpecialUserrights.php (modified) (history)

Diff [purge]

Index: trunk/phase3/docs/hooks.txt
@@ -1439,6 +1439,13 @@
14401440 'add-self' => array( addablegroups to self ),
14411441 'remove-self' => array( removable groups from self )
14421442 )
 1443+
 1444+'UserRightsLogEntry': before a log entry is added by UserrightsPage::addLogEntry(). If you use this hook to add your own log entries, you can return false to prevent the usual log entry from being added
 1445+$user: User or UserrightsProxy object
 1446+$oldGroups: Array of groups the user was a member of before the change
 1447+$newGroups: Array of groups the user is a member of after the change
 1448+$reason: User-provided summary
 1449+
14431450 'UserRetrieveNewTalks': called when retrieving "You have new messages!" message(s)
14441451 $user: user retrieving new talks messages
14451452 $talks: array of new talks page(s)
Index: trunk/phase3/includes/User.php
@@ -3231,8 +3231,116 @@
32323232 return $text;
32333233 }
32343234 }
 3235+
 3236+ /**
 3237+ * Returns an array of the groups that a particular group can add/remove.
 3238+ *
 3239+ * @param $group String: the group to check for whether it can add/remove
 3240+ * @return Array array( 'add' => array( addablegroups ),
 3241+ * 'remove' => array( removablegroups ),
 3242+ * 'add-self' => array( addablegroups to self),
 3243+ * 'remove-self' => array( removable groups from self) )
 3244+ */
 3245+ static function changeableByGroup( $group ) {
 3246+ global $wgAddGroups, $wgRemoveGroups, $wgGroupsAddToSelf, $wgGroupsRemoveFromSelf;
32353247
 3248+ $groups = array( 'add' => array(), 'remove' => array(), 'add-self' => array(), 'remove-self' => array() );
 3249+ if( empty($wgAddGroups[$group]) ) {
 3250+ // Don't add anything to $groups
 3251+ } elseif( $wgAddGroups[$group] === true ) {
 3252+ // You get everything
 3253+ $groups['add'] = self::getAllGroups();
 3254+ } elseif( is_array($wgAddGroups[$group]) ) {
 3255+ $groups['add'] = $wgAddGroups[$group];
 3256+ }
 3257+
 3258+ // Same thing for remove
 3259+ if( empty($wgRemoveGroups[$group]) ) {
 3260+ } elseif($wgRemoveGroups[$group] === true ) {
 3261+ $groups['remove'] = self::getAllGroups();
 3262+ } elseif( is_array($wgRemoveGroups[$group]) ) {
 3263+ $groups['remove'] = $wgRemoveGroups[$group];
 3264+ }
 3265+
 3266+ // Re-map numeric keys of AddToSelf/RemoveFromSelf to the 'user' key for backwards compatibility
 3267+ if( empty($wgGroupsAddToSelf['user']) || $wgGroupsAddToSelf['user'] !== true ) {
 3268+ foreach($wgGroupsAddToSelf as $key => $value) {
 3269+ if( is_int($key) ) {
 3270+ $wgGroupsAddToSelf['user'][] = $value;
 3271+ }
 3272+ }
 3273+ }
 3274+
 3275+ if( empty($wgGroupsRemoveFromSelf['user']) || $wgGroupsRemoveFromSelf['user'] !== true ) {
 3276+ foreach($wgGroupsRemoveFromSelf as $key => $value) {
 3277+ if( is_int($key) ) {
 3278+ $wgGroupsRemoveFromSelf['user'][] = $value;
 3279+ }
 3280+ }
 3281+ }
 3282+
 3283+ // Now figure out what groups the user can add to him/herself
 3284+ if( empty($wgGroupsAddToSelf[$group]) ) {
 3285+ } elseif( $wgGroupsAddToSelf[$group] === true ) {
 3286+ // No idea WHY this would be used, but it's there
 3287+ $groups['add-self'] = User::getAllGroups();
 3288+ } elseif( is_array($wgGroupsAddToSelf[$group]) ) {
 3289+ $groups['add-self'] = $wgGroupsAddToSelf[$group];
 3290+ }
 3291+
 3292+ if( empty($wgGroupsRemoveFromSelf[$group]) ) {
 3293+ } elseif( $wgGroupsRemoveFromSelf[$group] === true ) {
 3294+ $groups['remove-self'] = User::getAllGroups();
 3295+ } elseif( is_array($wgGroupsRemoveFromSelf[$group]) ) {
 3296+ $groups['remove-self'] = $wgGroupsRemoveFromSelf[$group];
 3297+ }
 3298+
 3299+ return $groups;
 3300+ }
 3301+
32363302 /**
 3303+ * Returns an array of groups that this user can add and remove
 3304+ * @return Array array( 'add' => array( addablegroups ),
 3305+ * 'remove' => array( removablegroups ),
 3306+ * 'add-self' => array( addablegroups to self),
 3307+ * 'remove-self' => array( removable groups from self) )
 3308+ */
 3309+ function changeableGroups() {
 3310+ if( $this->isAllowed( 'userrights' ) ) {
 3311+ // This group gives the right to modify everything (reverse-
 3312+ // compatibility with old "userrights lets you change
 3313+ // everything")
 3314+ // Using array_merge to make the groups reindexed
 3315+ $all = array_merge( User::getAllGroups() );
 3316+ return array(
 3317+ 'add' => $all,
 3318+ 'remove' => $all,
 3319+ 'add-self' => array(),
 3320+ 'remove-self' => array()
 3321+ );
 3322+ }
 3323+
 3324+ // Okay, it's not so simple, we will have to go through the arrays
 3325+ $groups = array(
 3326+ 'add' => array(),
 3327+ 'remove' => array(),
 3328+ 'add-self' => array(),
 3329+ 'remove-self' => array() );
 3330+ $addergroups = $this->getEffectiveGroups();
 3331+
 3332+ foreach ($addergroups as $addergroup) {
 3333+ $groups = array_merge_recursive(
 3334+ $groups, $this->changeableByGroup($addergroup)
 3335+ );
 3336+ $groups['add'] = array_unique( $groups['add'] );
 3337+ $groups['remove'] = array_unique( $groups['remove'] );
 3338+ $groups['add-self'] = array_unique( $groups['add-self'] );
 3339+ $groups['remove-self'] = array_unique( $groups['remove-self'] );
 3340+ }
 3341+ return $groups;
 3342+ }
 3343+
 3344+ /**
32373345 * Increment the user's edit-count field.
32383346 * Will have no effect for anonymous users.
32393347 */
Index: trunk/phase3/includes/api/ApiQueryRecentChanges.php
@@ -43,12 +43,13 @@
4444 private $fld_comment = false, $fld_user = false, $fld_flags = false,
4545 $fld_timestamp = false, $fld_title = false, $fld_ids = false,
4646 $fld_sizes = false;
47 -
 47+ /**
 48+ * Get an array mapping token names to their handler functions.
 49+ * The prototype for a token function is func($pageid, $title, $rc)
 50+ * it should return a token or false (permission denied)
 51+ * @return array(tokenname => function)
 52+ */
4853 protected function getTokenFunctions() {
49 - // tokenname => function
50 - // function prototype is func($pageid, $title, $rev)
51 - // should return token or false
52 -
5354 // Don't call the hooks twice
5455 if(isset($this->tokenFunctions))
5556 return $this->tokenFunctions;
Index: trunk/phase3/includes/api/ApiUserrights.php
@@ -0,0 +1,117 @@
 2+<?php
 3+
 4+/*
 5+ * Created on Mar 24, 2009
 6+ * API for MediaWiki 1.8+
 7+ *
 8+ * Copyright (C) 2009 Roan Kattouw <Firstname>.<Lastname>@home.nl
 9+ *
 10+ * This program is free software; you can redistribute it and/or modify
 11+ * it under the terms of the GNU General Public License as published by
 12+ * the Free Software Foundation; either version 2 of the License, or
 13+ * (at your option) any later version.
 14+ *
 15+ * This program is distributed in the hope that it will be useful,
 16+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 17+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 18+ * GNU General Public License for more details.
 19+ *
 20+ * You should have received a copy of the GNU General Public License along
 21+ * with this program; if not, write to the Free Software Foundation, Inc.,
 22+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 23+ * http://www.gnu.org/copyleft/gpl.html
 24+ */
 25+
 26+if (!defined('MEDIAWIKI')) {
 27+ // Eclipse helper - will be ignored in production
 28+ require_once ("ApiBase.php");
 29+}
 30+
 31+
 32+/**
 33+ * @ingroup API
 34+ */
 35+class ApiUserrights extends ApiBase {
 36+
 37+ public function __construct($main, $action) {
 38+ parent :: __construct($main, $action);
 39+ }
 40+
 41+ public function execute() {
 42+ global $wgUser;
 43+ $params = $this->extractRequestParams();
 44+ if(is_null($params['user']))
 45+ $this->dieUsageMsg(array('missingparam', 'user'));
 46+ $user = User::newFromName($params['user']);
 47+ if($user->isAnon())
 48+ $this->dieUsageMsg(array('nosuchuser', $params['user']));
 49+ if(is_null($params['token']))
 50+ $this->dieUsageMsg(array('missingparam', 'token'));
 51+ if(!$wgUser->matchEditToken($params['token'], $user->getName()))
 52+ $this->dieUsageMsg(array('sessionfailure'));
 53+
 54+ $r['user'] = $user->getName();
 55+ list($r['added'], $r['removed']) =
 56+ UserrightsPage::doSaveUserGroups(
 57+ $user, (array)$params['add'],
 58+ (array)$params['remove'], $params['reason']);
 59+
 60+ $this->getResult()->setIndexedTagName($r['added'], 'group');
 61+ $this->getResult()->setIndexedTagName($r['removed'], 'group');
 62+ $this->getResult()->addValue(null, $this->getModuleName(), $r);
 63+ }
 64+
 65+ public function mustBePosted() {
 66+ return true;
 67+ }
 68+
 69+ public function isWriteMode() {
 70+ return true;
 71+ }
 72+
 73+ public function getAllowedParams() {
 74+ return array (
 75+ 'user' => array(
 76+ ApiBase :: PARAM_TYPE => 'user'
 77+ ),
 78+ 'add' => array(
 79+ ApiBase :: PARAM_TYPE => User::getAllGroups(),
 80+ ApiBase :: PARAM_ISMULTI => true
 81+ ),
 82+ 'remove' => array(
 83+ ApiBase :: PARAM_TYPE => User::getAllGroups(),
 84+ ApiBase :: PARAM_ISMULTI => true
 85+ ),
 86+ 'token' => null,
 87+ 'reason' => array(
 88+ ApiBase :: PARAM_DFLT => ''
 89+ )
 90+ );
 91+ }
 92+
 93+ public function getParamDescription() {
 94+ return array (
 95+ 'user' => 'User name',
 96+ 'add' => 'Add the user to these groups',
 97+ 'remove' => 'Remove the user from these groups',
 98+ 'token' => 'A userrights token previously retrieved through list=users',
 99+ 'reason' => 'Reason for the change',
 100+ );
 101+ }
 102+
 103+ public function getDescription() {
 104+ return array(
 105+ 'Add/remove a user to/from groups',
 106+ );
 107+ }
 108+
 109+ protected function getExamples() {
 110+ return array (
 111+ 'api.php?action=userrights&user=FooBot&add=bot&remove=sysop|bureaucrat&token=123ABC'
 112+ );
 113+ }
 114+
 115+ public function getVersion() {
 116+ return __CLASS__ . ': $Id$';
 117+ }
 118+}
Property changes on: trunk/phase3/includes/api/ApiUserrights.php
___________________________________________________________________
Name: svn:eol-style
1119 + native
Name: svn:keywords
2120 + Id
Index: trunk/phase3/includes/api/ApiMain.php
@@ -80,6 +80,7 @@
8181 'watch' => 'ApiWatch',
8282 'patrol' => 'ApiPatrol',
8383 'import' => 'ApiImport',
 84+ 'userrights' => 'ApiUserrights',
8485 );
8586
8687 /**
Index: trunk/phase3/includes/api/ApiQueryUsers.php
@@ -39,7 +39,37 @@
4040 public function __construct($query, $moduleName) {
4141 parent :: __construct($query, $moduleName, 'us');
4242 }
 43+
 44+ /**
 45+ * Get an array mapping token names to their handler functions.
 46+ * The prototype for a token function is func($user)
 47+ * it should return a token or false (permission denied)
 48+ * @return array(tokenname => function)
 49+ */
 50+ protected function getTokenFunctions() {
 51+ // Don't call the hooks twice
 52+ if(isset($this->tokenFunctions))
 53+ return $this->tokenFunctions;
4354
 55+ // If we're in JSON callback mode, no tokens can be obtained
 56+ if(!is_null($this->getMain()->getRequest()->getVal('callback')))
 57+ return array();
 58+
 59+ $this->tokenFunctions = array(
 60+ 'userrights' => array( 'ApiQueryUsers', 'getUserrightsToken' ),
 61+ );
 62+ wfRunHooks('APIQueryUsersTokens', array(&$this->tokenFunctions));
 63+ return $this->tokenFunctions;
 64+ }
 65+
 66+ public static function getUserrightsToken($user)
 67+ {
 68+ global $wgUser;
 69+ // Since the permissions check for userrights is non-trivial,
 70+ // don't bother with it here
 71+ return $wgUser->editToken($user->getName());
 72+ }
 73+
4474 public function execute() {
4575 $params = $this->extractRequestParams();
4676 $result = $this->getResult();
@@ -115,6 +145,18 @@
116146 }
117147 if(isset($this->prop['emailable']) && $user->canReceiveEmail())
118148 $data[$name]['emailable'] = '';
 149+ if(!is_null($params['token']))
 150+ {
 151+ $tokenFunctions = $this->getTokenFunctions();
 152+ foreach($params['token'] as $t)
 153+ {
 154+ $val = call_user_func($tokenFunctions[$t], $user);
 155+ if($val === false)
 156+ $this->setWarning("Action '$t' is not allowed for the current user");
 157+ else
 158+ $data[$name][$t . 'token'] = $val;
 159+ }
 160+ }
119161 }
120162 }
121163 // Second pass: add result data to $retval
@@ -153,7 +195,11 @@
154196 ),
155197 'users' => array(
156198 ApiBase :: PARAM_ISMULTI => true
157 - )
 199+ ),
 200+ 'token' => array(
 201+ ApiBase :: PARAM_TYPE => array_keys($this->getTokenFunctions()),
 202+ ApiBase :: PARAM_ISMULTI => true
 203+ ),
158204 );
159205 }
160206
@@ -167,7 +213,8 @@
168214 ' registration - adds the user\'s registration timestamp',
169215 ' emailable - tags if the user can and wants to receive e-mail through [[Special:Emailuser]]',
170216 ),
171 - 'users' => 'A list of users to obtain the same information for'
 217+ 'users' => 'A list of users to obtain the same information for',
 218+ 'token' => 'Which tokens to obtain for each user',
172219 );
173220 }
174221
Index: trunk/phase3/includes/AutoLoader.php
@@ -292,6 +292,7 @@
293293 'ApiRollback' => 'includes/api/ApiRollback.php',
294294 'ApiUnblock' => 'includes/api/ApiUnblock.php',
295295 'ApiUndelete' => 'includes/api/ApiUndelete.php',
 296+ 'ApiUserrights' => 'includes/api/ApiUserrights.php',
296297 'ApiWatch' => 'includes/api/ApiWatch.php',
297298 'Services_JSON' => 'includes/api/ApiFormatJson_json.php',
298299 'Services_JSON_Error' => 'includes/api/ApiFormatJson_json.php',
Index: trunk/phase3/includes/specials/SpecialUserrights.php
@@ -149,29 +149,46 @@
150150 $removegroup[] = $group;
151151 }
152152 }
 153+ self::doSaveUserGroups( $user, $addgroup, $removegroup, $reason );
 154+ }
 155+
 156+ /**
 157+ * Save user groups changes in the database.
 158+ *
 159+ * @param $user User object
 160+ * @param $add Array of groups to add
 161+ * @param $remove Array of groups to remove
 162+ * @param $reason String: reason for group change
 163+ * @return Array: Tuple of added, then removed groups
 164+ */
 165+ static function doSaveUserGroups( $user, $add, $remove, $reason = '' ) {
 166+ global $wgUser;
153167
154168 // Validate input set...
155 - $changeable = $this->changeableGroups();
156 - $addable = array_merge( $changeable['add'], $this->isself ? $changeable['add-self'] : array() );
157 - $removable = array_merge( $changeable['remove'], $this->isself ? $changeable['remove-self'] : array() );
 169+ $isself = ($user->getName() == $wgUser->getName());
 170+ $groups = $user->getGroups();
 171+ $changeable = $wgUser->changeableGroups();
 172+ $addable = array_merge( $changeable['add'], $isself ? $changeable['add-self'] : array() );
 173+ $removable = array_merge( $changeable['remove'], $isself ? $changeable['remove-self'] : array() );
158174
159 - $removegroup = array_unique(
160 - array_intersect( (array)$removegroup, $removable ) );
161 - $addgroup = array_unique(
162 - array_intersect( (array)$addgroup, $addable ) );
 175+ $remove = array_unique(
 176+ array_intersect( (array)$remove, $removable, $groups ) );
 177+ $add = array_unique( array_diff(
 178+ array_intersect( (array)$add, $addable ),
 179+ $groups ) );
163180
164181 $oldGroups = $user->getGroups();
165182 $newGroups = $oldGroups;
166183 // remove then add groups
167 - if( $removegroup ) {
168 - $newGroups = array_diff($newGroups, $removegroup);
169 - foreach( $removegroup as $group ) {
 184+ if( $remove ) {
 185+ $newGroups = array_diff($newGroups, $remove);
 186+ foreach( $remove as $group ) {
170187 $user->removeGroup( $group );
171188 }
172189 }
173 - if( $addgroup ) {
174 - $newGroups = array_merge($newGroups, $addgroup);
175 - foreach( $addgroup as $group ) {
 190+ if( $add ) {
 191+ $newGroups = array_merge($newGroups, $add);
 192+ foreach( $add as $group ) {
176193 $user->addGroup( $group );
177194 }
178195 }
@@ -182,29 +199,34 @@
183200
184201 wfDebug( 'oldGroups: ' . print_r( $oldGroups, true ) );
185202 wfDebug( 'newGroups: ' . print_r( $newGroups, true ) );
186 - if( $user instanceof User ) {
187 - // hmmm
188 - wfRunHooks( 'UserRights', array( &$user, $addgroup, $removegroup ) );
189 - }
 203+ wfRunHooks( 'UserRights', array( &$user, $add, $remove ) );
190204
191205 if( $newGroups != $oldGroups ) {
192 - $this->addLogEntry( $user, $oldGroups, $newGroups );
 206+ self::addLogEntry( $user, $oldGroups, $newGroups, $reason );
193207 }
 208+ return array( $add, $remove );
194209 }
 210+
195211
196212 /**
197213 * Add a rights log entry for an action.
198214 */
199 - function addLogEntry( $user, $oldGroups, $newGroups ) {
200 - global $wgRequest;
 215+ static function addLogEntry( $user, $oldGroups, $newGroups, $reason ) {
 216+ // Just overriding addLogEntry in a subclass would be cleaner,
 217+ // but that requires PHP 5.3 (late static bindings)
 218+ if( !wfRunHooks( 'UserRightsLogEntry', array( $user, $oldGroups,
 219+ $newGroups, $reason ) ) ) {
 220+ return;
 221+ }
 222+
201223 $log = new LogPage( 'rights' );
202224
203225 $log->addEntry( 'rights',
204226 $user->getUserPage(),
205 - $wgRequest->getText( 'user-reason' ),
 227+ $reason,
206228 array(
207 - $this->makeGroupNameListForLog( $oldGroups ),
208 - $this->makeGroupNameListForLog( $newGroups )
 229+ self::makeGroupNameListForLog( $oldGroups ),
 230+ self::makeGroupNameListForLog( $newGroups )
209231 )
210232 );
211233 }
@@ -293,7 +315,7 @@
294316 return $user;
295317 }
296318
297 - function makeGroupNameList( $ids ) {
 319+ static function makeGroupNameList( $ids ) {
298320 if( empty( $ids ) ) {
299321 return wfMsgForContent( 'rightsnone' );
300322 } else {
@@ -301,11 +323,11 @@
302324 }
303325 }
304326
305 - function makeGroupNameListForLog( $ids ) {
 327+ static function makeGroupNameListForLog( $ids ) {
306328 if( empty( $ids ) ) {
307329 return '';
308330 } else {
309 - return $this->makeGroupNameList( $ids );
 331+ return self::makeGroupNameList( $ids );
310332 }
311333 }
312334
@@ -511,115 +533,20 @@
512534 }
513535
514536 /**
515 - * Returns an array of the groups that the user can add/remove.
 537+ * Returns $wgUser->changeableGroups()
516538 *
517539 * @return Array array( 'add' => array( addablegroups ), 'remove' => array( removablegroups ) , 'add-self' => array( addablegroups to self), 'remove-self' => array( removable groups from self) )
518540 */
519541 function changeableGroups() {
520542 global $wgUser;
521 -
522 - if( $wgUser->isAllowed( 'userrights' ) ) {
523 - // This group gives the right to modify everything (reverse-
524 - // compatibility with old "userrights lets you change
525 - // everything")
526 - // Using array_merge to make the groups reindexed
527 - $all = array_merge( User::getAllGroups() );
528 - return array(
529 - 'add' => $all,
530 - 'remove' => $all,
531 - 'add-self' => array(),
532 - 'remove-self' => array()
533 - );
534 - }
535 -
536 - // Okay, it's not so simple, we will have to go through the arrays
537 - $groups = array(
538 - 'add' => array(),
539 - 'remove' => array(),
540 - 'add-self' => array(),
541 - 'remove-self' => array() );
542 - $addergroups = $wgUser->getEffectiveGroups();
543 -
544 - foreach ($addergroups as $addergroup) {
545 - $groups = array_merge_recursive(
546 - $groups, $this->changeableByGroup($addergroup)
547 - );
548 - $groups['add'] = array_unique( $groups['add'] );
549 - $groups['remove'] = array_unique( $groups['remove'] );
550 - $groups['add-self'] = array_unique( $groups['add-self'] );
551 - $groups['remove-self'] = array_unique( $groups['remove-self'] );
552 - }
553 -
 543+ $groups = $wgUser->changeableGroups();
554544 // Run a hook because we can
555 - wfRunHooks( 'UserrightsChangeableGroups', array( $this, $wgUser, $addergroups, &$groups ) );
556 -
 545+ wfRunHooks( 'UserrightsChangeableGroups', array( $this,
 546+ $wgUser, $wgUser->getEffectiveGroups(), &$groups ) );
557547 return $groups;
558548 }
559549
560550 /**
561 - * Returns an array of the groups that a particular group can add/remove.
562 - *
563 - * @param $group String: the group to check for whether it can add/remove
564 - * @return Array array( 'add' => array( addablegroups ), 'remove' => array( removablegroups ) , 'add-self' => array( addablegroups to self), 'remove-self' => array( removable groups from self) )
565 - */
566 - private function changeableByGroup( $group ) {
567 - global $wgAddGroups, $wgRemoveGroups, $wgGroupsAddToSelf, $wgGroupsRemoveFromSelf;
568 -
569 - $groups = array( 'add' => array(), 'remove' => array(), 'add-self' => array(), 'remove-self' => array() );
570 - if( empty($wgAddGroups[$group]) ) {
571 - // Don't add anything to $groups
572 - } elseif( $wgAddGroups[$group] === true ) {
573 - // You get everything
574 - $groups['add'] = User::getAllGroups();
575 - } elseif( is_array($wgAddGroups[$group]) ) {
576 - $groups['add'] = $wgAddGroups[$group];
577 - }
578 -
579 - // Same thing for remove
580 - if( empty($wgRemoveGroups[$group]) ) {
581 - } elseif($wgRemoveGroups[$group] === true ) {
582 - $groups['remove'] = User::getAllGroups();
583 - } elseif( is_array($wgRemoveGroups[$group]) ) {
584 - $groups['remove'] = $wgRemoveGroups[$group];
585 - }
586 -
587 - // Re-map numeric keys of AddToSelf/RemoveFromSelf to the 'user' key for backwards compatibility
588 - if( empty($wgGroupsAddToSelf['user']) || $wgGroupsAddToSelf['user'] !== true ) {
589 - foreach($wgGroupsAddToSelf as $key => $value) {
590 - if( is_int($key) ) {
591 - $wgGroupsAddToSelf['user'][] = $value;
592 - }
593 - }
594 - }
595 -
596 - if( empty($wgGroupsRemoveFromSelf['user']) || $wgGroupsRemoveFromSelf['user'] !== true ) {
597 - foreach($wgGroupsRemoveFromSelf as $key => $value) {
598 - if( is_int($key) ) {
599 - $wgGroupsRemoveFromSelf['user'][] = $value;
600 - }
601 - }
602 - }
603 -
604 - // Now figure out what groups the user can add to him/herself
605 - if( empty($wgGroupsAddToSelf[$group]) ) {
606 - } elseif( $wgGroupsAddToSelf[$group] === true ) {
607 - // No idea WHY this would be used, but it's there
608 - $groups['add-self'] = User::getAllGroups();
609 - } elseif( is_array($wgGroupsAddToSelf[$group]) ) {
610 - $groups['add-self'] = $wgGroupsAddToSelf[$group];
611 - }
612 -
613 - if( empty($wgGroupsRemoveFromSelf[$group]) ) {
614 - } elseif( $wgGroupsRemoveFromSelf[$group] === true ) {
615 - $groups['remove-self'] = User::getAllGroups();
616 - } elseif( is_array($wgGroupsRemoveFromSelf[$group]) ) {
617 - $groups['remove-self'] = $wgGroupsRemoveFromSelf[$group];
618 - }
619 -
620 - return $groups;
621 - }
622 -
623 - /**
624551 * Show a rights log fragment for the specified user
625552 *
626553 * @param $user User to show log for
Index: trunk/phase3/RELEASE-NOTES
@@ -345,6 +345,7 @@
346346 when someone tries to use them
347347 * BREAKING CHANGE: action=purge requires write rights and, for anonymous users,
348348 a POST request
 349+* (bug 15935) Added action=userrights to add/remove users to/from groups
349350 * (bug 18099) Using appendtext to edit a non-existent page causes an interface
350351 message to be included in the page text
351352 * Added uiprop=changeablegroups to meta=userinfo

Follow-up revisions

RevisionCommit summaryAuthorDate
r48971Followup to r48970: apply userrights changes to CentralAuthcatrope19:15, 28 March 2009
r49013Remove ugly userrights-CentralAuth hack introduced in r48970 and friends:...catrope16:39, 29 March 2009
r51952Fix bug in global auth caused by r48970 (I think). You need to call this->cha...werdna09:40, 16 June 2009

Past revisions this follows-up on

RevisionCommit summaryAuthorDate
r48746* API: (bug 15935) Add action=userrights to the API...catrope16:04, 24 March 2009
r48909Revert r48746 (API userrights). Breaks Special:GlobalGroupMembership by chang...werdna05:59, 27 March 2009
r48910properly revert r48775 r48778werdna06:01, 27 March 2009

Comments

#Comment by Werdna (talk | contribs)   04:27, 29 March 2009

Has this been tested? It looks like having CentralAuth installed would break *local* userrights -- remember that CentralAuth adds ONE subclass to userrights, and both SpecialUserrights and SpecialGlobalGroupPermissions need to work correctly.

Maybe a better approach is to ditch the awful strategy of calling static methods on SpecialPage objects and actually moving the business logic further into MediaWiki. See how it's done in GlobalBlocking for an example. The only logic in the SpecialPage object, ideally, should be the interface with an HTML form, any business logic should be in a utility class. We are, of course, all guilty of not following this ideal.

#Comment by Catrope (talk | contribs)   10:35, 29 March 2009

That may be right, I've only tested this with the CentralAuth userrights, not with MW's one. Will fix this shortly

#Comment by Catrope (talk | contribs)   11:05, 29 March 2009

Done in r48988

Status & tagging log