Index: includes/DefaultSettings.php =================================================================== --- includes/DefaultSettings.php (revision 23171) +++ includes/DefaultSettings.php (working copy) @@ -1080,6 +1080,21 @@ */ # $wgGroupPermissions['developer']['siteadmin'] = true; +// Limits user groups assignable and removable by every group +$wgAssignableGroups['bureaucrat']['*'] = true; +$wgRemovableGroups['bureaucrat']['*'] = true; + +// Settings suitable for wikimedia wikis +//$wgAssignableGroups['steward' ]['*' ] = true; +//$wgAssignableGroups['bureaucrat']['*' ] = false; +//$wgAssignableGroups['bureaucrat']['sysop' ] = true; +//$wgAssignableGroups['bureaucrat']['bureaucrat'] = true; +//$wgAssignableGroups['bureaucrat']['bot' ] = true; +//$wgRemovableGroups['steward' ]['*' ] = true; +//$wgRemovableGroups['bureaucrat']['*' ] = false; +//$wgRemovableGroups['bureaucrat']['bot' ] = true; + + /** * Set of available actions that can be restricted via action=protect * You probably shouldn't change this. Index: includes/HTMLForm.php =================================================================== --- includes/HTMLForm.php (revision 23171) +++ includes/HTMLForm.php (working copy) @@ -121,6 +121,8 @@ * @todo Document $selectmsg */ function HTMLSelectGroups($selectname, $selectmsg, $selected=array(), $multiple=false, $size=6, $reverse=false) { + global $wgUser, $wgAssignableGroups, $wgRemovableGroups; + $groups = User::getAllGroups(); $out = htmlspecialchars( wfMsg( $selectmsg ) ); $out .= "
"; @@ -148,6 +150,15 @@ $attribs['selected'] = 'selected'; } } + + if( $selectname === 'member' ) { + $lookup = $wgRemovableGroups; + } else { + $lookup = $wgAssignableGroups; + } + if( !$wgUser->canChangeGroup( $lookup, $group ) ) { + $attribs['disabled'] = 'disabled'; + } $out .= wfElement( 'option', $attribs, User::getGroupName( $group ) ) . "\n"; } Index: includes/SpecialUserrights.php =================================================================== --- includes/SpecialUserrights.php (revision 23171) +++ includes/SpecialUserrights.php (working copy) @@ -75,7 +75,7 @@ * */ function saveUserGroups( $username, $removegroup, $addgroup, $reason = '' ) { - global $wgOut; + global $wgOut, $wgAssignableGroups, $wgRemovableGroups; $u = User::newFromName($username); if(is_null($u)) { @@ -90,21 +90,40 @@ $oldGroups = $u->getGroups(); $newGroups = $oldGroups; - // remove then add groups + + // check if user can add or remove particular groups if(isset($removegroup)) { $newGroups = array_diff($newGroups, $removegroup); foreach( $removegroup as $group ) { - $u->removeGroup( $group ); + if( !$u->canChangeGroup( $wgRemovableGroups, $group ) ) { + $wgOut->addWikiText( wfMsg( 'userrights-nopermission', User::getGroupName( $group ) ) ); + return; + } } } if(isset($addgroup)) { $newGroups = array_merge($newGroups, $addgroup); foreach( $addgroup as $group ) { - $u->addGroup( $group ); + if( !$u->canChangeGroup( $wgAssignableGroups, $group ) ) { + $wgOut->addWikiText( wfMsg( 'userrights-nopermission', User::getGroupName( $group ) ) ); + return; + } } } $newGroups = array_unique( $newGroups ); + // remove then add groups + if(isset($removegroup)) { + foreach( $removegroup as $group ) { + $u->removeGroup( $group ); + } + } + if(isset($addgroup)) { + foreach( $addgroup as $group ) { + $u->addGroup( $group ); + } + } + wfDebug( 'oldGroups: ' . print_r( $oldGroups, true ) ); wfDebug( 'newGroups: ' . print_r( $newGroups, true ) ); Index: includes/User.php =================================================================== --- includes/User.php (revision 23171) +++ includes/User.php (working copy) @@ -1745,6 +1745,21 @@ } /** + * Check if user can add or remove a particular group + * @param array $permissions Either $wgAssignableGroups or $wgRemovableGroups + * @param string $group Group to be added or removed + * @return bool True if user is allowed to do so, false otherwise + */ + function canChangeGroup( $permissions, $group ) + { + foreach ( $this->mGroups as $right ) + { + if ( $permissions[$right]['*'] || $permissions[$right][$group] ) return true; + } + return false; + } + + /** * Load a skin if it doesn't exist or return it * @todo FIXME : need to check the old failback system [AV] */ Index: languages/messages/MessagesEn.php =================================================================== --- languages/messages/MessagesEn.php (revision 23171) +++ languages/messages/MessagesEn.php (working copy) @@ -1277,6 +1277,7 @@ 'userrights-groupshelp' => 'Select groups you want the user to be removed from or added to. Unselected groups will not be changed. You can deselect a group with CTRL + Left Click', 'userrights-reason' => 'Reason for change:', +'userrights-nopermission' => 'You don\'t have enough permissions to add or remove group "$1".', # Groups 'group' => 'Group:', Index: languages/messages/MessagesRu.php =================================================================== --- languages/messages/MessagesRu.php (revision 23171) +++ languages/messages/MessagesRu.php (working copy) @@ -1,4 +1,4 @@ - 'Выберите группы, в которые вы хотите включить или из которых хотите исключить участника. Невыбранные группы не изменятся. Снять выделение с группы можно используя CTRL + левую клавишу мыши.', 'userrights-reason' => 'Причина изменения:', +'userrights-nopermission' => 'У вас недостаточно полномочий для присвоения или снятия группы «$1».', # Groups 'group' => 'Группа:', Index: extensions/Makesysop/SpecialMakesysop.php =================================================================== --- SpecialMakesysop.php (revision 23011) +++ SpecialMakesysop.php (working copy) @@ -27,11 +27,21 @@ // * Bureaucrat can only do limited work (makesysop) $wgGroupPermissions['steward' ]['makesysop' ] = true; $wgGroupPermissions['steward' ]['userrights'] = true; -$wgGroupPermissions['bureaucrat']['makesysop' ] = true; -$wgGroupPermissions['bureaucrat']['userrights'] = false; +$wgGroupPermissions['bureaucrat']['makesysop' ] = false; +//$wgGroupPermissions['bureaucrat']['userrights'] = false; $wgAvailableRights[] = 'makesysop'; +$wgAssignableGroups['steward' ]['*' ] = true; +$wgAssignableGroups['bureaucrat']['*' ] = false; +$wgAssignableGroups['bureaucrat']['sysop' ] = true; +$wgAssignableGroups['bureaucrat']['bureaucrat'] = true; +$wgAssignableGroups['bureaucrat']['bot' ] = true; + +$wgRemovableGroups['steward' ]['*' ] = true; +$wgRemovableGroups['bureaucrat']['*' ] = false; +$wgRemovableGroups['bureaucrat']['bot' ] = true; + /** * Quick hack for clusters with multiple master servers; if an alternate * is listed for the requested database, a connection to it will be opened