Index: branches/group_rights/maintenance/archives/patch-group_rights.sql |
— | — | @@ -0,0 +1,19 @@ |
| 2 | +--- Add table for group rights assignable on-wiki |
| 3 | + |
| 4 | +CREATE TABLE /*$wgDBprefix*/group_rights ( |
| 5 | + gr_group varbinary(16) NOT NULL default '', |
| 6 | + gr_right varbinary(16) NOT NULL default '', |
| 7 | + gr_enabled tinyint(1) NOT NULL default 1, |
| 8 | + PRIMARY KEY (gr_group,gr_right), |
| 9 | + KEY gr_right (gr_right) |
| 10 | +) /*$wgDBoptions*/; |
| 11 | +--- Add table for group rights assignable on-wiki |
| 12 | + |
| 13 | +CREATE TABLE /*$wgDBprefix*/changeable_groups ( |
| 14 | + cg_changer varbinary(16) NOT NULL, |
| 15 | + cg_group varbinary(16) NOT NULL, |
| 16 | + cg_action varbinary(16) default NULL, |
| 17 | + UNIQUE KEY cg_changer (cg_changer,cg_group,cg_action), |
| 18 | + KEY cg_group (cg_group) |
| 19 | +) /*$wgDBoptions*/; |
| 20 | +--- Add table for group rights assignable on-wiki |
\ No newline at end of file |
Property changes on: branches/group_rights/maintenance/archives/patch-group_rights.sql |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 21 | + native |
Index: branches/group_rights/maintenance/updaters.inc |
— | — | @@ -145,6 +145,8 @@ |
146 | 146 | array( 'update_password_format' ), |
147 | 147 | |
148 | 148 | // 1.14 |
| 149 | + array( 'add_table', 'group_rights', 'patch-group_rights.sql' ), |
| 150 | + array( 'add_table', 'changeable_groups', 'patch-group_rights.sql' ), |
149 | 151 | array( 'add_field', 'site_stats', 'ss_active_users', 'patch-ss_active_users.sql' ), |
150 | 152 | array( 'do_active_users_init' ), |
151 | 153 | array( 'add_field', 'ipblocks', 'ipb_allow_usertalk', 'patch-ipb_allow_usertalk.sql' ) |
Index: branches/group_rights/maintenance/tables.sql |
— | — | @@ -1243,4 +1243,23 @@ |
1244 | 1244 | PRIMARY KEY (ul_key) |
1245 | 1245 | ) /*$wgDBTableOptions*/; |
1246 | 1246 | |
| 1247 | +--- Add table for group rights assignable on-wiki |
| 1248 | + |
| 1249 | +CREATE TABLE /*$wgDBprefix*/group_rights ( |
| 1250 | + gr_group varbinary(16) NOT NULL default '', |
| 1251 | + gr_right varbinary(16) NOT NULL default '', |
| 1252 | + gr_enabled tinyint(1) NOT NULL default 1, |
| 1253 | + PRIMARY KEY (gr_group,gr_right), |
| 1254 | + KEY gr_right (gr_right) |
| 1255 | +) /*$wgDBoptions*/; |
| 1256 | + |
| 1257 | +CREATE TABLE /*$wgDBprefix*/changeable_groups ( |
| 1258 | + cg_changer varbinary(16) NOT NULL, |
| 1259 | + cg_group varbinary(16) NOT NULL, |
| 1260 | + cg_action varbinary(16) default NULL, |
| 1261 | + UNIQUE KEY cg_changer (cg_changer,cg_group,cg_action), |
| 1262 | + KEY cg_group (cg_group) |
| 1263 | +) /*$wgDBoptions*/; |
| 1264 | + |
| 1265 | + |
1247 | 1266 | -- vim: sw=2 sts=2 et |
Index: branches/group_rights/includes/ProtectionForm.php |
— | — | @@ -254,12 +254,12 @@ |
255 | 255 | |
256 | 256 | # They shouldn't be able to do this anyway, but just to make sure, ensure that cascading restrictions aren't being applied |
257 | 257 | # to a semi-protected page. |
258 | | - global $wgGroupPermissions; |
| 258 | + $groupPerms = User::getAllGroupPermissions(); |
259 | 259 | |
260 | 260 | $edit_restriction = $this->mRestrictions['edit']; |
261 | 261 | $this->mCascade = $wgRequest->getBool( 'mwProtect-cascade' ); |
262 | 262 | if ($this->mCascade && ($edit_restriction != 'protect') && |
263 | | - !(isset($wgGroupPermissions[$edit_restriction]['protect']) && $wgGroupPermissions[$edit_restriction]['protect'] ) ) |
| 263 | + !(isset($groupPerms[$edit_restriction]['protect']) && $groupPerms[$edit_restriction]['protect'] ) ) |
264 | 264 | $this->mCascade = false; |
265 | 265 | |
266 | 266 | if ($this->mTitle->exists()) { |
— | — | @@ -513,11 +513,12 @@ |
514 | 514 | } |
515 | 515 | |
516 | 516 | function buildCleanupScript() { |
517 | | - global $wgRestrictionLevels, $wgGroupPermissions; |
| 517 | + global $wgRestrictionLevels; |
518 | 518 | $script = 'var wgCascadeableLevels='; |
519 | 519 | $CascadeableLevels = array(); |
| 520 | + $groupPerms = User::getAllGroupPermissions(); |
520 | 521 | foreach( $wgRestrictionLevels as $key ) { |
521 | | - if ( (isset($wgGroupPermissions[$key]['protect']) && $wgGroupPermissions[$key]['protect']) || $key == 'protect' ) { |
| 522 | + if ( (isset($groupPerms[$key]['protect']) && $groupPerms[$key]['protect']) || $key == 'protect' ) { |
522 | 523 | $CascadeableLevels[] = "'" . Xml::escapeJsString( $key ) . "'"; |
523 | 524 | } |
524 | 525 | } |
Index: branches/group_rights/includes/User.php |
— | — | @@ -1936,7 +1936,7 @@ |
1937 | 1937 | function getRights() { |
1938 | 1938 | if ( is_null( $this->mRights ) ) { |
1939 | 1939 | $this->mRights = self::getGroupPermissions( $this->getEffectiveGroups() ); |
1940 | | - wfRunHooks( 'UserGetRights', array( $this, &$this->mRights ) ); |
| 1940 | + #wfRunHooks( 'UserGetRights', array( $this, &$this->mRights ) ); |
1941 | 1941 | // Force reindexation of rights when a hook has unset one of them |
1942 | 1942 | $this->mRights = array_values( $this->mRights ); |
1943 | 1943 | } |
— | — | @@ -2987,32 +2987,30 @@ |
2988 | 2988 | * @return \type{\arrayof{\string}} List of permission key names for given groups combined |
2989 | 2989 | */ |
2990 | 2990 | static function getGroupPermissions( $groups ) { |
2991 | | - global $wgGroupPermissions; |
2992 | | - $rights = array(); |
2993 | | - foreach( $groups as $group ) { |
2994 | | - if( isset( $wgGroupPermissions[$group] ) ) { |
2995 | | - $rights = array_merge( $rights, |
2996 | | - array_keys( array_filter( $wgGroupPermissions[$group] ) ) ); |
2997 | | - } |
2998 | | - } |
2999 | | - return $rights; |
| 2991 | + $rm = new RightsManagerMulti; |
| 2992 | + |
| 2993 | + return $rm->getGroupPermissions($groups); |
3000 | 2994 | } |
3001 | 2995 | |
3002 | 2996 | /** |
| 2997 | + * Get a list of all group permissions. |
| 2998 | + */ |
| 2999 | + static function getAllGroupPermissions() { |
| 3000 | + $rm = new RightsManagerMulti; |
| 3001 | + |
| 3002 | + return $rm->getAllGroupPermissions(); |
| 3003 | + } |
| 3004 | + |
| 3005 | + /** |
3003 | 3006 | * Get all the groups who have a given permission |
3004 | 3007 | * |
3005 | 3008 | * @param $role \type{\string} Role to check |
3006 | 3009 | * @return \type{\arrayof{\string}} List of internal group names with the given permission |
3007 | 3010 | */ |
3008 | 3011 | static function getGroupsWithPermission( $role ) { |
3009 | | - global $wgGroupPermissions; |
3010 | | - $allowedGroups = array(); |
3011 | | - foreach ( $wgGroupPermissions as $group => $rights ) { |
3012 | | - if ( isset( $rights[$role] ) && $rights[$role] ) { |
3013 | | - $allowedGroups[] = $group; |
3014 | | - } |
3015 | | - } |
3016 | | - return $allowedGroups; |
| 3012 | + $rm = new RightsManagerMulti; |
| 3013 | + |
| 3014 | + return $rm->getGroupsWithPermission( $role ); |
3017 | 3015 | } |
3018 | 3016 | |
3019 | 3017 | /** |
— | — | @@ -3054,9 +3052,12 @@ |
3055 | 3053 | * @return \type{\arrayof{\string}} Array of internal group names |
3056 | 3054 | */ |
3057 | 3055 | static function getAllGroups() { |
3058 | | - global $wgGroupPermissions; |
| 3056 | + $rm = new RightsManagerMulti; |
| 3057 | + |
| 3058 | + $groups = $rm->getAllGroups(); |
| 3059 | + |
3059 | 3060 | return array_diff( |
3060 | | - array_keys( $wgGroupPermissions ), |
| 3061 | + $groups, |
3061 | 3062 | self::getImplicitGroups() |
3062 | 3063 | ); |
3063 | 3064 | } |
Index: branches/group_rights/includes/GlobalFunctions.php |
— | — | @@ -1377,6 +1377,9 @@ |
1378 | 1378 | if (strpos( $diff_lines[1], '+++' ) === 0) { |
1379 | 1379 | unset($diff_lines[1]); |
1380 | 1380 | } |
| 1381 | + if (strpos( $diff_lines[count($diff_lines)-1], "\\" ) == 0) { |
| 1382 | + unset( $diff_lines[count($diff_lines-1] ); |
| 1383 | + } |
1381 | 1384 | |
1382 | 1385 | $diff = implode( "\n", $diff_lines ); |
1383 | 1386 | |
Index: branches/group_rights/includes/api/ApiQuerySiteinfo.php |
— | — | @@ -245,9 +245,9 @@ |
246 | 246 | } |
247 | 247 | |
248 | 248 | protected function appendUserGroups( $property ) { |
249 | | - global $wgGroupPermissions; |
| 249 | + $groupPerms = User::getAllGroupPermissions(); |
250 | 250 | $data = array(); |
251 | | - foreach( $wgGroupPermissions as $group => $permissions ) { |
| 251 | + foreach( $groupPerms as $group => $permissions ) { |
252 | 252 | $arr = array( 'name' => $group, 'rights' => array_keys( $permissions, true ) ); |
253 | 253 | $this->getResult()->setIndexedTagName( $arr['rights'], 'permission' ); |
254 | 254 | $data[] = $arr; |
Index: branches/group_rights/includes/AutoLoader.php |
— | — | @@ -153,6 +153,11 @@ |
154 | 154 | 'Replacer' => 'includes/StringUtils.php', |
155 | 155 | 'ReverseChronologicalPager' => 'includes/Pager.php', |
156 | 156 | 'Revision' => 'includes/Revision.php', |
| 157 | + 'RightsManager' => 'includes/RightsManager.php', |
| 158 | + 'RightsManagerConfigDB' => 'includes/RightsManager.php', |
| 159 | + 'RightsManagerForeignConfigDB' => 'includes/RightsManager.php', |
| 160 | + 'RightsManagerMulti' => 'includes/RightsManager.php', |
| 161 | + 'RightsManagerReadOnly' => 'includes/RightsManager.php', |
157 | 162 | 'RSSFeed' => 'includes/Feed.php', |
158 | 163 | 'Sanitizer' => 'includes/Sanitizer.php', |
159 | 164 | 'SearchEngineDummy' => 'includes/SearchEngine.php', |
— | — | @@ -474,6 +479,7 @@ |
475 | 480 | 'ShortPagesPage' => 'includes/specials/SpecialShortpages.php', |
476 | 481 | 'SpecialAllpages' => 'includes/specials/SpecialAllpages.php', |
477 | 482 | 'SpecialBookSources' => 'includes/specials/SpecialBooksources.php', |
| 483 | + 'SpecialGroupRights' => 'includes/specials/SpecialGroupRights.php', |
478 | 484 | 'SpecialListGroupRights' => 'includes/specials/SpecialListgrouprights.php', |
479 | 485 | 'SpecialMostlinkedtemplates' => 'includes/specials/SpecialMostlinkedtemplates.php', |
480 | 486 | 'SpecialPrefixindex' => 'includes/specials/SpecialPrefixindex.php', |
Index: branches/group_rights/includes/DefaultSettings.php |
— | — | @@ -2736,6 +2736,8 @@ |
2737 | 2737 | 'protect/unprotect' => 'unprotectedarticle', |
2738 | 2738 | 'protect/move_prot' => 'movedarticleprotection', |
2739 | 2739 | 'rights/rights' => 'rightslogentry', |
| 2740 | + 'rights/rights2' => 'rightslogentry2', |
| 2741 | + 'rights/grprights' => 'grouprightslog', |
2740 | 2742 | 'delete/delete' => 'deletedarticle', |
2741 | 2743 | 'delete/restore' => 'undeletedarticle', |
2742 | 2744 | 'delete/revision' => 'revdelete-logentry', |
— | — | @@ -2813,6 +2815,7 @@ |
2814 | 2816 | |
2815 | 2817 | 'Listusers' => 'users', |
2816 | 2818 | 'Listgrouprights' => 'users', |
| 2819 | + 'GroupRights' => 'users', |
2817 | 2820 | 'Ipblocklist' => 'users', |
2818 | 2821 | 'Contributions' => 'users', |
2819 | 2822 | 'Emailuser' => 'users', |
— | — | @@ -3449,3 +3452,16 @@ |
3450 | 3453 | * Requires memcached. |
3451 | 3454 | */ |
3452 | 3455 | $wgPasswordAttemptThrottle = array( 'count' => 5, 'seconds' => 300 ); |
| 3456 | + |
| 3457 | +/** |
| 3458 | + * Whether or not to allow rights changes made through Special:GroupRights to revoke |
| 3459 | + * rights issued in the site configuration |
| 3460 | + */ |
| 3461 | +$wgAllowDBRightSubtraction = true; |
| 3462 | + |
| 3463 | +/** |
| 3464 | + * The rights managers which are allowed to give users groups and permissions. |
| 3465 | + * An array of class names. Generally not modified by users, but by extensions |
| 3466 | + * and the like. |
| 3467 | + */ |
| 3468 | +$wgRightsManagers = array( 'RightsManagerConfigDB' ); |
\ No newline at end of file |
Index: branches/group_rights/includes/specials/SpecialUserrights.php |
— | — | @@ -26,13 +26,54 @@ |
27 | 27 | } |
28 | 28 | |
29 | 29 | public function userCanExecute( $user ) { |
30 | | - $available = $this->changeableGroups(); |
31 | | - return !empty( $available['add'] ) |
32 | | - or !empty( $available['remove'] ) |
33 | | - or ($this->isself and |
34 | | - (!empty( $available['add-self'] ) |
35 | | - or !empty( $available['remove-self'] ))); |
| 30 | + return (bool)count( $this->getAvailableBackends( $user ) ); |
36 | 31 | } |
| 32 | + |
| 33 | + function getAvailableBackends( $user ) { |
| 34 | + global $wgRightsManagers; |
| 35 | + |
| 36 | + $availableBackends = array(); |
| 37 | + |
| 38 | + foreach( $wgRightsManagers as $rmClass ) { |
| 39 | + $rm = new $rmClass; |
| 40 | + |
| 41 | + $changeableGroups = $rm->getChangeableGroupsForUser( $user ); |
| 42 | + |
| 43 | + $counts = array_map( 'count', $changeableGroups ); |
| 44 | + $enabled = array_filter( $counts ); |
| 45 | + |
| 46 | + if ( count( $enabled ) ) { |
| 47 | + $availableBackends[] = $rmClass; |
| 48 | + } |
| 49 | + } |
| 50 | + |
| 51 | + return $availableBackends; |
| 52 | + } |
| 53 | + |
| 54 | + function showBackendSelector() { |
| 55 | + global $wgUser, $wgOut; |
| 56 | + |
| 57 | + $wgOut->setSubTitle( wfMsg( 'userrights-backendselect-subtitle' ) ); |
| 58 | + $wgOut->addWikiMsg( 'userrights-backendselect-text' ); |
| 59 | + |
| 60 | + // Produce list. |
| 61 | + $sk = $wgUser->getSkin(); |
| 62 | + $availableBackends = $this->getAvailableBackends( $wgUser ); |
| 63 | + $list = ''; |
| 64 | + foreach( $availableBackends as $backend ) { |
| 65 | + $text = wfMsg( "rights-backend-$backend" ); |
| 66 | + $link = $sk->link( $this->getTitle(), $text, array(), array( 'backend' => $backend ) ); |
| 67 | + $list .= Xml::tags( 'li', null, $link ); |
| 68 | + } |
| 69 | + |
| 70 | + $list = Xml::tags( 'ul', null, $list ); |
| 71 | + |
| 72 | + $wgOut->addHTML( $list ); |
| 73 | + } |
| 74 | + |
| 75 | + function getBackend() { |
| 76 | + return new $this->mBackend; |
| 77 | + } |
37 | 78 | |
38 | 79 | /** |
39 | 80 | * Manage forms to be shown according to posted data. |
— | — | @@ -41,15 +82,39 @@ |
42 | 83 | * @param $par Mixed: string if any subpage provided, else null |
43 | 84 | */ |
44 | 85 | function execute( $par ) { |
45 | | - // If the visitor doesn't have permissions to assign or remove |
46 | | - // any groups, it's a bit silly to give them the user search prompt. |
47 | | - global $wgUser, $wgRequest; |
| 86 | + global $wgUser, $wgRequest, $wgOut; |
| 87 | + |
| 88 | + $wgOut->setPageTitle( wfMsg('userrights') ); |
48 | 89 | |
49 | 90 | if( $par ) { |
50 | 91 | $this->mTarget = $par; |
51 | 92 | } else { |
52 | 93 | $this->mTarget = $wgRequest->getVal( 'user' ); |
53 | 94 | } |
| 95 | + |
| 96 | + if( !$this->userCanExecute( $wgUser ) ) { |
| 97 | + // fixme... there may be intermediate groups we can mention. |
| 98 | + global $wgOut; |
| 99 | + $wgOut->showPermissionsErrorPage( array( |
| 100 | + $wgUser->isAnon() |
| 101 | + ? 'userrights-nologin' |
| 102 | + : 'userrights-notallowed' ) ); |
| 103 | + return; |
| 104 | + } |
| 105 | + |
| 106 | + $specifiedBackend = $this->mBackend = $wgRequest->getVal( 'backend' ); |
| 107 | + |
| 108 | + $availableBackends = $this->getAvailableBackends( $wgUser ); |
| 109 | + |
| 110 | + // Check backend. |
| 111 | + if ( count($availableBackends) == 1 ) { |
| 112 | + $this->mBackend = $availableBackends[0]; |
| 113 | + } elseif ( in_array( $specifiedBackend, $availableBackends ) ) { |
| 114 | + $this->mBackend = $specifiedBackend; |
| 115 | + } else { |
| 116 | + $this->showBackendSelector(); |
| 117 | + return; |
| 118 | + } |
54 | 119 | |
55 | 120 | if (!$this->mTarget) { |
56 | 121 | /* |
— | — | @@ -65,16 +130,6 @@ |
66 | 131 | if ($this->mTarget == $wgUser->getName()) |
67 | 132 | $this->isself = true; |
68 | 133 | |
69 | | - if( !$this->userCanExecute( $wgUser ) ) { |
70 | | - // fixme... there may be intermediate groups we can mention. |
71 | | - global $wgOut; |
72 | | - $wgOut->showPermissionsErrorPage( array( |
73 | | - $wgUser->isAnon() |
74 | | - ? 'userrights-nologin' |
75 | | - : 'userrights-notallowed' ) ); |
76 | | - return; |
77 | | - } |
78 | | - |
79 | 134 | if ( wfReadOnly() ) { |
80 | 135 | global $wgOut; |
81 | 136 | $wgOut->readOnlyPage(); |
— | — | @@ -140,64 +195,12 @@ |
141 | 196 | } |
142 | 197 | |
143 | 198 | // Validate input set... |
144 | | - $changeable = $this->changeableGroups(); |
145 | | - $addable = array_merge( $changeable['add'], $this->isself ? $changeable['add-self'] : array() ); |
146 | | - $removable = array_merge( $changeable['remove'], $this->isself ? $changeable['remove-self'] : array() ); |
147 | | - |
148 | | - $removegroup = array_unique( |
149 | | - array_intersect( (array)$removegroup, $removable ) ); |
150 | | - $addgroup = array_unique( |
151 | | - array_intersect( (array)$addgroup, $addable ) ); |
152 | | - |
153 | | - $oldGroups = $user->getGroups(); |
154 | | - $newGroups = $oldGroups; |
155 | | - // remove then add groups |
156 | | - if( $removegroup ) { |
157 | | - $newGroups = array_diff($newGroups, $removegroup); |
158 | | - foreach( $removegroup as $group ) { |
159 | | - $user->removeGroup( $group ); |
160 | | - } |
161 | | - } |
162 | | - if( $addgroup ) { |
163 | | - $newGroups = array_merge($newGroups, $addgroup); |
164 | | - foreach( $addgroup as $group ) { |
165 | | - $user->addGroup( $group ); |
166 | | - } |
167 | | - } |
168 | | - $newGroups = array_unique( $newGroups ); |
169 | | - |
170 | | - // Ensure that caches are cleared |
171 | | - $user->invalidateCache(); |
172 | | - |
173 | | - wfDebug( 'oldGroups: ' . print_r( $oldGroups, true ) ); |
174 | | - wfDebug( 'newGroups: ' . print_r( $newGroups, true ) ); |
175 | | - if( $user instanceof User ) { |
176 | | - // hmmm |
177 | | - wfRunHooks( 'UserRights', array( &$user, $addgroup, $removegroup ) ); |
178 | | - } |
179 | | - |
180 | | - if( $newGroups != $oldGroups ) { |
181 | | - $this->addLogEntry( $user, $oldGroups, $newGroups ); |
182 | | - } |
| 199 | + $rm = $this->getBackend(); |
| 200 | + $reason = $wgRequest->getText( 'user-reason' ); |
| 201 | + |
| 202 | + $rm->changeUserGroups( $user, $addgroup, $removegroup, $reason, $wgUser ); |
183 | 203 | } |
184 | | - |
185 | | - /** |
186 | | - * Add a rights log entry for an action. |
187 | | - */ |
188 | | - function addLogEntry( $user, $oldGroups, $newGroups ) { |
189 | | - global $wgRequest; |
190 | | - $log = new LogPage( 'rights' ); |
191 | 204 | |
192 | | - $log->addEntry( 'rights', |
193 | | - $user->getUserPage(), |
194 | | - $wgRequest->getText( 'user-reason' ), |
195 | | - array( |
196 | | - $this->makeGroupNameListForLog( $oldGroups ), |
197 | | - $this->makeGroupNameListForLog( $newGroups ) |
198 | | - ) |
199 | | - ); |
200 | | - } |
201 | | - |
202 | 205 | /** |
203 | 206 | * Edit user groups membership |
204 | 207 | * @param $username String: name of the user. |
— | — | @@ -210,7 +213,7 @@ |
211 | 214 | return; |
212 | 215 | } |
213 | 216 | |
214 | | - $groups = $user->getGroups(); |
| 217 | + $groups = $this->getBackend()->getUserGroups( $user ); |
215 | 218 | |
216 | 219 | $this->showEditUserGroupsForm( $user, $groups ); |
217 | 220 | |
— | — | @@ -229,52 +232,9 @@ |
230 | 233 | function fetchUser( $username ) { |
231 | 234 | global $wgOut, $wgUser; |
232 | 235 | |
233 | | - $parts = explode( '@', $username ); |
234 | | - if( count( $parts ) < 2 ) { |
235 | | - $name = trim( $username ); |
236 | | - $database = ''; |
237 | | - } else { |
238 | | - list( $name, $database ) = array_map( 'trim', $parts ); |
| 236 | + $user = $this->getBackend()->fetchUser( $username ); |
239 | 237 | |
240 | | - if( !$wgUser->isAllowed( 'userrights-interwiki' ) ) { |
241 | | - $wgOut->addWikiMsg( 'userrights-no-interwiki' ); |
242 | | - return null; |
243 | | - } |
244 | | - if( !UserRightsProxy::validDatabase( $database ) ) { |
245 | | - $wgOut->addWikiMsg( 'userrights-nodatabase', $database ); |
246 | | - return null; |
247 | | - } |
248 | | - } |
249 | | - |
250 | | - if( $name == '' ) { |
251 | | - $wgOut->addWikiMsg( 'nouserspecified' ); |
252 | | - return false; |
253 | | - } |
254 | | - |
255 | | - if( $name{0} == '#' ) { |
256 | | - // Numeric ID can be specified... |
257 | | - // We'll do a lookup for the name internally. |
258 | | - $id = intval( substr( $name, 1 ) ); |
259 | | - |
260 | | - if( $database == '' ) { |
261 | | - $name = User::whoIs( $id ); |
262 | | - } else { |
263 | | - $name = UserRightsProxy::whoIs( $database, $id ); |
264 | | - } |
265 | | - |
266 | | - if( !$name ) { |
267 | | - $wgOut->addWikiMsg( 'noname' ); |
268 | | - return null; |
269 | | - } |
270 | | - } |
271 | | - |
272 | | - if( $database == '' ) { |
273 | | - $user = User::newFromName( $name ); |
274 | | - } else { |
275 | | - $user = UserRightsProxy::newFromName( $database, $name ); |
276 | | - } |
277 | | - |
278 | | - if( !$user || $user->isAnon() ) { |
| 238 | + if( $user == null ) { |
279 | 239 | $wgOut->addWikiMsg( 'nosuchusershort', $username ); |
280 | 240 | return null; |
281 | 241 | } |
— | — | @@ -290,14 +250,6 @@ |
291 | 251 | } |
292 | 252 | } |
293 | 253 | |
294 | | - function makeGroupNameListForLog( $ids ) { |
295 | | - if( empty( $ids ) ) { |
296 | | - return ''; |
297 | | - } else { |
298 | | - return $this->makeGroupNameList( $ids ); |
299 | | - } |
300 | | - } |
301 | | - |
302 | 254 | /** |
303 | 255 | * Output a form to allow searching for a user |
304 | 256 | */ |
— | — | @@ -306,6 +258,7 @@ |
307 | 259 | $wgOut->addHTML( |
308 | 260 | Xml::openElement( 'form', array( 'method' => 'get', 'action' => $wgScript, 'name' => 'uluser', 'id' => 'mw-userrights-form1' ) ) . |
309 | 261 | Xml::hidden( 'title', $this->getTitle()->getPrefixedText() ) . |
| 262 | + Xml::hidden( 'backend', $this->mBackend ) . |
310 | 263 | Xml::openElement( 'fieldset' ) . |
311 | 264 | Xml::element( 'legend', array(), wfMsg( 'userrights-lookup-user' ) ) . |
312 | 265 | Xml::inputLabel( wfMsg( 'userrights-user-editname' ), 'user', 'username', 30, $this->mTarget ) . ' ' . |
— | — | @@ -324,7 +277,12 @@ |
325 | 278 | * @return Array: Tuple of addable, then removable groups |
326 | 279 | */ |
327 | 280 | protected function splitGroups( $groups ) { |
328 | | - list($addable, $removable, $addself, $removeself) = array_values( $this->changeableGroups() ); |
| 281 | + $changeableGroups = $this->getBackend()->getChangeableGroups( $groups ); |
| 282 | + |
| 283 | + $addable = $changeableGroups['add']; |
| 284 | + $removable = $changeableGroups['remove']; |
| 285 | + $addself = $changeableGroups['add-self']; |
| 286 | + $removeself = $changeableGroups['remove-self']; |
329 | 287 | |
330 | 288 | $removable = array_intersect( |
331 | 289 | array_merge( $this->isself ? $removeself : array(), $removable ), |
— | — | @@ -348,7 +306,7 @@ |
349 | 307 | list( $addable, $removable ) = $this->splitGroups( $groups ); |
350 | 308 | |
351 | 309 | $list = array(); |
352 | | - foreach( $user->getGroups() as $group ) |
| 310 | + foreach( $groups as $group ) |
353 | 311 | $list[] = self::buildGroupLink( $group ); |
354 | 312 | |
355 | 313 | $grouplist = ''; |
— | — | @@ -359,6 +317,7 @@ |
360 | 318 | $wgOut->addHTML( |
361 | 319 | Xml::openElement( 'form', array( 'method' => 'post', 'action' => $this->getTitle()->getLocalURL(), 'name' => 'editGroup', 'id' => 'mw-userrights-form2' ) ) . |
362 | 320 | Xml::hidden( 'user', $this->mTarget ) . |
| 321 | + Xml::hidden( 'backend', $this->mBackend ) . |
363 | 322 | Xml::hidden( 'wpEditToken', $wgUser->editToken( $this->mTarget ) ) . |
364 | 323 | Xml::openElement( 'fieldset' ) . |
365 | 324 | Xml::element( 'legend', array(), wfMsg( 'userrights-editusergroup' ) ) . |
— | — | @@ -404,8 +363,8 @@ |
405 | 364 | * Returns an array of all groups that may be edited |
406 | 365 | * @return array Array of groups that may be edited. |
407 | 366 | */ |
408 | | - protected static function getAllGroups() { |
409 | | - return User::getAllGroups(); |
| 367 | + protected function getAllGroups() { |
| 368 | + return array_diff( $this->getBackend()->getAllGroups(), User::getImplicitGroups() ); |
410 | 369 | } |
411 | 370 | |
412 | 371 | /** |
— | — | @@ -509,40 +468,13 @@ |
510 | 469 | function changeableGroups() { |
511 | 470 | global $wgUser; |
512 | 471 | |
513 | | - if( $wgUser->isAllowed( 'userrights' ) ) { |
514 | | - // This group gives the right to modify everything (reverse- |
515 | | - // compatibility with old "userrights lets you change |
516 | | - // everything") |
517 | | - // Using array_merge to make the groups reindexed |
518 | | - $all = array_merge( User::getAllGroups() ); |
519 | | - return array( |
520 | | - 'add' => $all, |
521 | | - 'remove' => $all, |
522 | | - 'add-self' => array(), |
523 | | - 'remove-self' => array() |
524 | | - ); |
525 | | - } |
526 | | - |
527 | | - // Okay, it's not so simple, we will have to go through the arrays |
528 | | - $groups = array( |
529 | | - 'add' => array(), |
530 | | - 'remove' => array(), |
531 | | - 'add-self' => array(), |
532 | | - 'remove-self' => array() ); |
533 | | - $addergroups = $wgUser->getEffectiveGroups(); |
534 | | - |
535 | | - foreach ($addergroups as $addergroup) { |
536 | | - $groups = array_merge_recursive( |
537 | | - $groups, $this->changeableByGroup($addergroup) |
538 | | - ); |
539 | | - $groups['add'] = array_unique( $groups['add'] ); |
540 | | - $groups['remove'] = array_unique( $groups['remove'] ); |
541 | | - $groups['add-self'] = array_unique( $groups['add-self'] ); |
542 | | - $groups['remove-self'] = array_unique( $groups['remove-self'] ); |
543 | | - } |
| 472 | + $groups = $this->getBackend()->getChangeableGroupsForUser( $wgUser ); |
544 | 473 | |
| 474 | + // Load data for hooks |
| 475 | + $addergroups = $this->getBackend()->getUserGroups( $wgUser ); |
| 476 | + |
545 | 477 | // Run a hook because we can |
546 | | - wfRunHooks( 'UserrightsChangeableGroups', array( $this, $wgUser, $addergroups, &$groups ) ); |
| 478 | + wfRunHooks( 'UserrightsChangeableGroups', array( $this, $wgUser, $addergroups, &$groups, $this->mBackend ) ); |
547 | 479 | |
548 | 480 | return $groups; |
549 | 481 | } |
— | — | @@ -553,61 +485,8 @@ |
554 | 486 | * @param $group String: the group to check for whether it can add/remove |
555 | 487 | * @return Array array( 'add' => array( addablegroups ), 'remove' => array( removablegroups ) , 'add-self' => array( addablegroups to self), 'remove-self' => array( removable groups from self) ) |
556 | 488 | */ |
557 | | - private function changeableByGroup( $group ) { |
558 | | - global $wgAddGroups, $wgRemoveGroups, $wgGroupsAddToSelf, $wgGroupsRemoveFromSelf; |
559 | | - |
560 | | - $groups = array( 'add' => array(), 'remove' => array(), 'add-self' => array(), 'remove-self' => array() ); |
561 | | - if( empty($wgAddGroups[$group]) ) { |
562 | | - // Don't add anything to $groups |
563 | | - } elseif( $wgAddGroups[$group] === true ) { |
564 | | - // You get everything |
565 | | - $groups['add'] = User::getAllGroups(); |
566 | | - } elseif( is_array($wgAddGroups[$group]) ) { |
567 | | - $groups['add'] = $wgAddGroups[$group]; |
568 | | - } |
569 | | - |
570 | | - // Same thing for remove |
571 | | - if( empty($wgRemoveGroups[$group]) ) { |
572 | | - } elseif($wgRemoveGroups[$group] === true ) { |
573 | | - $groups['remove'] = User::getAllGroups(); |
574 | | - } elseif( is_array($wgRemoveGroups[$group]) ) { |
575 | | - $groups['remove'] = $wgRemoveGroups[$group]; |
576 | | - } |
577 | | - |
578 | | - // Re-map numeric keys of AddToSelf/RemoveFromSelf to the 'user' key for backwards compatibility |
579 | | - if( empty($wgGroupsAddToSelf['user']) || $wgGroupsAddToSelf['user'] !== true ) { |
580 | | - foreach($wgGroupsAddToSelf as $key => $value) { |
581 | | - if( is_int($key) ) { |
582 | | - $wgGroupsAddToSelf['user'][] = $value; |
583 | | - } |
584 | | - } |
585 | | - } |
586 | | - |
587 | | - if( empty($wgGroupsRemoveFromSelf['user']) || $wgGroupsRemoveFromSelf['user'] !== true ) { |
588 | | - foreach($wgGroupsRemoveFromSelf as $key => $value) { |
589 | | - if( is_int($key) ) { |
590 | | - $wgGroupsRemoveFromSelf['user'][] = $value; |
591 | | - } |
592 | | - } |
593 | | - } |
594 | | - |
595 | | - // Now figure out what groups the user can add to him/herself |
596 | | - if( empty($wgGroupsAddToSelf[$group]) ) { |
597 | | - } elseif( $wgGroupsAddToSelf[$group] === true ) { |
598 | | - // No idea WHY this would be used, but it's there |
599 | | - $groups['add-self'] = User::getAllGroups(); |
600 | | - } elseif( is_array($wgGroupsAddToSelf[$group]) ) { |
601 | | - $groups['add-self'] = $wgGroupsAddToSelf[$group]; |
602 | | - } |
603 | | - |
604 | | - if( empty($wgGroupsRemoveFromSelf[$group]) ) { |
605 | | - } elseif( $wgGroupsRemoveFromSelf[$group] === true ) { |
606 | | - $groups['remove-self'] = User::getAllGroups(); |
607 | | - } elseif( is_array($wgGroupsRemoveFromSelf[$group]) ) { |
608 | | - $groups['remove-self'] = $wgGroupsRemoveFromSelf[$group]; |
609 | | - } |
610 | | - |
611 | | - return $groups; |
| 489 | + private function changeableByGroup( $group ) { |
| 490 | + return $this->getBackend()->getChangeableGroups( array( $group ) ); |
612 | 491 | } |
613 | 492 | |
614 | 493 | /** |
— | — | @@ -617,7 +496,6 @@ |
618 | 497 | * @param $output OutputPage to use |
619 | 498 | */ |
620 | 499 | protected function showLogFragment( $user, $output ) { |
621 | | - $output->addHtml( Xml::element( 'h2', null, LogPage::logName( 'rights' ) . "\n" ) ); |
622 | | - LogEventsList::showLogExtract( $output, 'rights', $user->getUserPage()->getPrefixedText() ); |
| 500 | + $this->getBackend()->showUserLogFragment( $user, $output ); |
623 | 501 | } |
624 | 502 | } |
Index: branches/group_rights/includes/specials/SpecialListgrouprights.php |
— | — | @@ -25,8 +25,11 @@ |
26 | 26 | */ |
27 | 27 | public function execute( $par ) { |
28 | 28 | global $wgOut, $wgImplicitGroups, $wgMessageCache; |
29 | | - global $wgGroupPermissions, $wgAddGroups, $wgRemoveGroups; |
| 29 | + global $wgAddGroups, $wgRemoveGroups; |
30 | 30 | $wgMessageCache->loadAllMessages(); |
| 31 | + |
| 32 | + $rm = new RightsManagerMulti; |
| 33 | + $groupPerms = $rm->getAllGroupPermissions(); |
31 | 34 | |
32 | 35 | $this->setHeaders(); |
33 | 36 | $this->outputHeader(); |
— | — | @@ -39,8 +42,8 @@ |
40 | 43 | '</tr>' |
41 | 44 | ); |
42 | 45 | |
43 | | - foreach( $wgGroupPermissions as $group => $permissions ) { |
44 | | - $groupname = ( $group == '*' ) ? 'all' : htmlspecialchars( $group ); // Replace * with a more descriptive groupname |
| 46 | + foreach( $groupPerms as $group => $permissions ) { |
| 47 | + $groupname = ( $group == '*' ) ? 'all' : htmlspecialchars( $group ); // TODO: Replace * with a more descriptive groupname |
45 | 48 | |
46 | 49 | $msg = wfMsg( 'group-' . $groupname ); |
47 | 50 | if ( wfEmptyMsg( 'group-' . $groupname, $msg ) || $msg == '' ) { |
— | — | @@ -70,16 +73,21 @@ |
71 | 74 | $grouplink = ''; |
72 | 75 | } |
73 | 76 | |
74 | | - $addgroups = isset( $wgAddGroups[$group] ) ? $wgAddGroups[$group] : array(); |
75 | | - $removegroups = isset( $wgRemoveGroups[$group] ) ? $wgRemoveGroups[$group] : array(); |
| 77 | + $changeableGroups = array(); |
76 | 78 | |
| 79 | + global $wgRightsManagers; |
| 80 | + foreach( $wgRightsManagers as $rmClass ) { |
| 81 | + $rm = new $rmClass; |
| 82 | + $changeableGroups = array_merge_recursive( $rm->getChangeableGroups( array( $group ) ), $changeableGroups ); |
| 83 | + } |
| 84 | + |
77 | 85 | $wgOut->addHTML( |
78 | 86 | '<tr> |
79 | 87 | <td>' . |
80 | 88 | $grouppage . $grouplink . |
81 | 89 | '</td> |
82 | 90 | <td>' . |
83 | | - self::formatPermissions( $permissions, $addgroups, $removegroups ) . |
| 91 | + self::formatPermissions( $permissions, $changeableGroups ) . |
84 | 92 | '</td> |
85 | 93 | </tr>' |
86 | 94 | ); |
— | — | @@ -93,9 +101,10 @@ |
94 | 102 | * Create a user-readable list of permissions from the given array. |
95 | 103 | * |
96 | 104 | * @param $permissions Array of permission => bool (from $wgGroupPermissions items) |
| 105 | + * @param $changeableGroups Array of action => list of groups (from RightsManager::getChangeableGroups) |
97 | 106 | * @return string List of all granted permissions, separated by comma separator |
98 | 107 | */ |
99 | | - private static function formatPermissions( $permissions, $add, $remove ) { |
| 108 | + private static function formatPermissions( $permissions, $changeableGroups ) { |
100 | 109 | global $wgLang; |
101 | 110 | $r = array(); |
102 | 111 | foreach( $permissions as $permission => $granted ) { |
— | — | @@ -108,16 +117,21 @@ |
109 | 118 | } |
110 | 119 | } |
111 | 120 | sort( $r ); |
112 | | - if( $add === true ){ |
113 | | - $r[] = wfMsgExt( 'listgrouprights-addgroup-all', array( 'escape' ) ); |
114 | | - } else if( is_array( $add ) && count( $add ) ) { |
115 | | - $r[] = wfMsgExt( 'listgrouprights-addgroup', array( 'parseinline' ), $wgLang->listToText( array_map( array( 'User', 'makeGroupLinkWiki' ), $add ) ), count( $add ) ); |
| 121 | + |
| 122 | + // Get addable/removable groups. |
| 123 | + $groupActions = array( 'add-self' => 'addself', 'remove-self' => 'removeself', 'add' => 'add', 'remove' => 'remove' ); |
| 124 | + |
| 125 | + foreach( $groupActions as $key => $value ) { |
| 126 | + if ( !isset($changeableGroups[$key]) || !is_array($changeableGroups[$key]) || !count($changeableGroups[$key]) ) { |
| 127 | + // Do nothing. |
| 128 | + } elseif ( !count( array_diff( $changeableGroups[$key], array_diff( User::getAllGroups(), User::getImplicitGroups() ) ) ) ) { |
| 129 | + // i.e. User can change *all* groups. |
| 130 | + $r[] = wfMsgExt( "listgrouprights-{$value}group-all", array( 'escape' ) ); |
| 131 | + } elseif ( count( $changeableGroups[$key] ) ) { |
| 132 | + $r[] = wfMsgExt( "listgrouprights-{$value}group", array( 'parseinline' ), $wgLang->listToText( array_map( array( 'User', 'makeGroupLinkWiki' ), $changeableGroups[$key] ) ), count( $changeableGroups[$key] ) ); |
| 133 | + } |
116 | 134 | } |
117 | | - if( $remove === true ){ |
118 | | - $r[] = wfMsgExt( 'listgrouprights-removegroup-all', array( 'escape' ) ); |
119 | | - } else if( is_array( $remove ) && count( $remove ) ) { |
120 | | - $r[] = wfMsgExt( 'listgrouprights-removegroup', array( 'parseinline' ), $wgLang->listToText( array_map( array( 'User', 'makeGroupLinkWiki' ), $remove ) ), count( $remove ) ); |
121 | | - } |
| 135 | + |
122 | 136 | if( empty( $r ) ) { |
123 | 137 | return ''; |
124 | 138 | } else { |
Index: branches/group_rights/includes/specials/SpecialGroupRights.php |
— | — | @@ -0,0 +1,340 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +#This file is part of MediaWiki. |
| 5 | + |
| 6 | +#MediaWiki is free software: you can redistribute it and/or modify |
| 7 | +#it under the terms of version 2 of the GNU General Public License |
| 8 | +#as published by the Free Software Foundation. |
| 9 | + |
| 10 | +#MediaWiki is distributed in the hope that it will be useful, |
| 11 | +#but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 12 | +#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 13 | +#GNU General Public License for more details. |
| 14 | + |
| 15 | +/** |
| 16 | + * Special page to allow managing groups |
| 17 | + */ |
| 18 | + |
| 19 | +if ( !defined( 'MEDIAWIKI' ) ) { |
| 20 | + die(); |
| 21 | +} |
| 22 | + |
| 23 | + |
| 24 | +class SpecialGroupRights extends SpecialPage |
| 25 | +{ |
| 26 | + function __construct() { |
| 27 | + parent::__construct('GroupRights', 'grouprights'); |
| 28 | + } |
| 29 | + |
| 30 | + function getAvailableBackends( $user ) { |
| 31 | + global $wgRightsManagers; |
| 32 | + |
| 33 | + $availableBackends = array(); |
| 34 | + |
| 35 | + foreach( $wgRightsManagers as $rmClass ) { |
| 36 | + $rm = new $rmClass; |
| 37 | + |
| 38 | + if ( $rm->canEditRights( $user ) ) { |
| 39 | + $availableBackends[] = $rmClass; |
| 40 | + } |
| 41 | + } |
| 42 | + |
| 43 | + return $availableBackends; |
| 44 | + } |
| 45 | + |
| 46 | + function userCanExecute( $user ) { |
| 47 | + return (bool) count($this->getAvailableBackends( $user )); |
| 48 | + } |
| 49 | + |
| 50 | + function getBackend() { |
| 51 | + static $backend = null; |
| 52 | + |
| 53 | + if ( !is_null($backend) ) |
| 54 | + return $backend; |
| 55 | + |
| 56 | + return $backend = new $this->mBackend; |
| 57 | + } |
| 58 | + |
| 59 | + function execute( $subpage ) { |
| 60 | + global $wgRequest,$wgOut,$wgUser; |
| 61 | + |
| 62 | + if (!$this->userCanExecute($wgUser)) { |
| 63 | + $this->displayRestrictionError(); |
| 64 | + return; |
| 65 | + } |
| 66 | + |
| 67 | + $wgOut->setPageTitle( wfMsg( 'grouprights' ) ); |
| 68 | + $wgOut->setRobotPolicy( "noindex,nofollow" ); |
| 69 | + $wgOut->setArticleRelated( false ); |
| 70 | + $wgOut->enableClientCache( false ); |
| 71 | + |
| 72 | + $availableBackends = $this->getAvailableBackends( $wgUser ); |
| 73 | + $specifiedBackend = $wgRequest->getVal( 'backend' ); |
| 74 | + |
| 75 | + if ( count($availableBackends) == 1 ) { |
| 76 | + $this->mBackend = $availableBackends[0]; |
| 77 | + } elseif ( in_array( $specifiedBackend, $availableBackends ) ) { |
| 78 | + $this->mBackend = $specifiedBackend; |
| 79 | + } else { |
| 80 | + $this->showBackendSelector(); |
| 81 | + return; |
| 82 | + } |
| 83 | + |
| 84 | + if ($subpage == '' ) { |
| 85 | + $subpage = $wgRequest->getVal( 'wpGroup' ); |
| 86 | + } |
| 87 | + |
| 88 | + if ($subpage != '' && $wgUser->matchEditToken( $wgRequest->getVal( 'wpEditToken' ) )) { |
| 89 | + $this->doSubmit($subpage); |
| 90 | + } else if ($subpage != '') { |
| 91 | + $this->buildGroupView($subpage); |
| 92 | + } else { |
| 93 | + $this->buildMainView(); |
| 94 | + } |
| 95 | + } |
| 96 | + |
| 97 | + function showBackendSelector() { |
| 98 | + global $wgUser, $wgOut; |
| 99 | + |
| 100 | + $wgOut->setSubTitle( wfMsg( 'grouprights-backendselect-subtitle' ) ); |
| 101 | + $wgOut->addWikiMsg( 'grouprights-backendselect-text' ); |
| 102 | + |
| 103 | + // Produce list. |
| 104 | + $sk = $wgUser->getSkin(); |
| 105 | + $availableBackends = $this->getAvailableBackends( $wgUser ); |
| 106 | + $list = ''; |
| 107 | + foreach( $availableBackends as $backend ) { |
| 108 | + $text = wfMsg( "rights-backend-$backend" ); |
| 109 | + $link = $sk->link( $this->getTitle(), $text, array(), array( 'backend' => $backend ) ); |
| 110 | + $list .= Xml::tags( 'li', null, $link ); |
| 111 | + } |
| 112 | + |
| 113 | + $list = Xml::tags( 'ul', null, $list ); |
| 114 | + |
| 115 | + $wgOut->addHTML( $list ); |
| 116 | + } |
| 117 | + |
| 118 | + function getAllGroups() { |
| 119 | + return $this->getBackend()->getAllGroups(); |
| 120 | + } |
| 121 | + |
| 122 | + function buildMainView() { |
| 123 | + global $wgOut,$wgUser,$wgScript; |
| 124 | + $sk = $wgUser->getSkin(); |
| 125 | + |
| 126 | + $groups = $this->getAllGroups(); |
| 127 | + |
| 128 | + // Existing groups |
| 129 | + $html = Xml::openElement( 'fieldset' ); |
| 130 | + $html .= Xml::element( 'legend', null, wfMsg( 'grouprights-existinggroup-legend' ) ); |
| 131 | + |
| 132 | + $wgOut->addHTML( $html ); |
| 133 | + |
| 134 | + if (count($groups)) { |
| 135 | + $wgOut->addWikiMsg( 'grouprights-grouplist' ); |
| 136 | + $wgOut->addHTML( '<ul>' ); |
| 137 | + |
| 138 | + foreach ($groups as $group) { |
| 139 | + $editLink = $sk->link( $this->getTitle( $group ), wfMsg( 'grouprights-editlink'), array(), array( 'backend' => $this->mBackend ) ); |
| 140 | + $text = htmlspecialchars($group) ." ($editLink)"; |
| 141 | + |
| 142 | + $wgOut->addHTML( "<li> $text </li>" ); |
| 143 | + } |
| 144 | + } else { |
| 145 | + $wgOut->addWikiMsg( 'grouprights-nogroups' ); |
| 146 | + } |
| 147 | + |
| 148 | + $wgOut->addHTML( Xml::closeElement( 'ul' ) . Xml::closeElement( 'fieldset' ) ); |
| 149 | + |
| 150 | + // "Create a group" prompt |
| 151 | + $html = Xml::openElement( 'fieldset' ) . Xml::element( 'legend', null, wfMsg( 'grouprights-newgroup-legend' ) ); |
| 152 | + $html .= wfMsgExt( 'grouprights-newgroup-intro', array( 'parse' ) ); |
| 153 | + $html .= Xml::openElement( 'form', array( 'method' => 'post', 'action' => $wgScript, 'name' => 'grouprights-newgroup' ) ); |
| 154 | + $html .= Xml::hidden( 'title', $this->getTitle()->getPrefixedText() ); |
| 155 | + $html .= Xml::hidden( 'backend', $this->mBackend ); |
| 156 | + |
| 157 | + $fields = array( 'grouprights-newgroupname' => wfInput( 'wpGroup', 45 ) ); |
| 158 | + |
| 159 | + $html .= wfBuildForm( $fields, 'grouprights-creategroup-submit' ); |
| 160 | + $html .= Xml::closeElement( 'form' ); |
| 161 | + $html .= Xml::closeElement( 'fieldset' ); |
| 162 | + |
| 163 | + $wgOut->addHTML( $html ); |
| 164 | + } |
| 165 | + |
| 166 | + function buildGroupView( $group ) { |
| 167 | + global $wgOut, $wgUser, $wgScript; |
| 168 | + |
| 169 | + $backend = $this->getBackend(); |
| 170 | + |
| 171 | + $wgOut->setSubtitle( wfMsg( 'grouprights-subtitle', $group ) ); |
| 172 | + |
| 173 | + $html = Xml::openElement( 'fieldset' ) . Xml::element( 'legend', null, wfMsg( 'grouprights-fieldset', $group ) ); |
| 174 | + $html .= Xml::openElement( 'form', array( 'method' => 'post', 'action' => $this->getTitle( $group)->getLocalUrl(), 'name' => 'grouprights-newgroup' ) ); |
| 175 | + $html .= Xml::hidden( 'wpGroup', $group ); |
| 176 | + $html .= Xml::hidden( 'wpEditToken', $wgUser->editToken() ); |
| 177 | + $html .= Xml::hidden( 'backend', $this->mBackend ); |
| 178 | + |
| 179 | + $fields = array(); |
| 180 | + |
| 181 | + $fields['grouprights-editgroup-name'] = $group; |
| 182 | + $fields['grouprights-editgroup-display'] = wfMsgExt( 'grouprights-editgroup-display-edit', array( 'parseinline' ), $group, User::getGroupName( $group ) ); |
| 183 | + $fields['grouprights-editgroup-member'] = wfMsgExt( 'grouprights-editgroup-member-edit', array( 'parseinline' ), $group, User::getGroupMember( $group ) ); |
| 184 | + $fields['grouprights-editgroup-members'] = wfMsgExt( 'grouprights-editgroup-members-link', array( 'parseinline' ), $group, User::getGroupMember( $group ) ); |
| 185 | + |
| 186 | + // Allow backends to add extras here |
| 187 | + $backend->doExtraGroupForm( $fields, $group ); |
| 188 | + |
| 189 | + $fields['grouprights-editgroup-perms'] = $this->buildCheckboxes($group); |
| 190 | + |
| 191 | + $changeable = $backend->getChangeableGroups( array($group) ); |
| 192 | + |
| 193 | + foreach( $changeable as $type => $groups ) { |
| 194 | + $changeable[$type] = implode( ', ', $groups ); |
| 195 | + } |
| 196 | + |
| 197 | + $fields['grouprights-editgroup'] = ''; |
| 198 | + |
| 199 | + $editTypes = array( 'add', 'remove', 'add-self', 'remove-self' ); |
| 200 | + foreach( $editTypes as $type ) { |
| 201 | + $fields["grouprights-editgroup-$type"] = wfInput( "wpGroupChange-$type", 45, $changeable[$type] ); |
| 202 | + } |
| 203 | + |
| 204 | + $fields['grouprights-editgroup-reason'] = wfInput( 'wpReason', 45 ); |
| 205 | + |
| 206 | + $html .= wfBuildForm( $fields, 'grouprights-editgroup-submit' ); |
| 207 | + |
| 208 | + $html .= Xml::closeElement( 'form' ); |
| 209 | + $html .= Xml::closeElement( 'fieldset' ); |
| 210 | + |
| 211 | + $wgOut->addHTML( $html ); |
| 212 | + |
| 213 | + $backend->showGroupLogFragment( $group, $wgOut ); |
| 214 | + } |
| 215 | + |
| 216 | + function rightEditable( $group, $right ) { |
| 217 | + return $this->getBackend()->rightEditable( $group, $right ); |
| 218 | + } |
| 219 | + |
| 220 | + function buildCheckboxes( $group ) { |
| 221 | + |
| 222 | + $rights = User::getAllRights(); |
| 223 | + $assignedRights = $this->getAssignedRights( $group ); |
| 224 | + |
| 225 | + sort($rights); |
| 226 | + |
| 227 | + $checkboxes = array(); |
| 228 | + |
| 229 | + foreach( $rights as $right ) { |
| 230 | + # Build a checkbox. |
| 231 | + $checked = in_array( $right, $assignedRights ); |
| 232 | + $attribs = array(); |
| 233 | + if ( !$this->rightEditable( $group, $right ) ) { |
| 234 | + $attribs['disabled'] = 'disabled'; |
| 235 | + } |
| 236 | + |
| 237 | + $checkbox = Xml::checkLabel( User::getRightDescription( $right ), |
| 238 | + "wpRightAssigned-$right", "wpRightAssigned-$right", $checked, $attribs ); |
| 239 | + |
| 240 | + $checkboxes[] = "<li>$checkbox</li>"; |
| 241 | + } |
| 242 | + |
| 243 | + $count = count($checkboxes); |
| 244 | + |
| 245 | + $firstCol = round($count/2); |
| 246 | + |
| 247 | + $checkboxes1 = array_slice($checkboxes, 0, $firstCol); |
| 248 | + $checkboxes2 = array_slice($checkboxes, $firstCol ); |
| 249 | + |
| 250 | + $html = '<table><tbody><tr><td><ul>'; |
| 251 | + |
| 252 | + foreach( $checkboxes1 as $cb ) { |
| 253 | + $html .= $cb; |
| 254 | + } |
| 255 | + |
| 256 | + $html .= '</ul></td><td><ul>'; |
| 257 | + |
| 258 | + foreach( $checkboxes2 as $cb ) { |
| 259 | + $html .= $cb; |
| 260 | + } |
| 261 | + |
| 262 | + $html .= '</ul></td></tr></tbody></table>'; |
| 263 | + |
| 264 | + return $html; |
| 265 | + } |
| 266 | + |
| 267 | + function getAssignedRights( $group ) { |
| 268 | + return $this->getBackend()->getGroupPermissions( array($group) ); |
| 269 | + } |
| 270 | + |
| 271 | + function beginTransaction() { |
| 272 | + $dbw = wfGetDB( DB_MASTER ); |
| 273 | + $dbw->begin(); |
| 274 | + } |
| 275 | + |
| 276 | + function endTransaction() { |
| 277 | + $dbw = wfGetDB( DB_MASTER ); |
| 278 | + $dbw->commit(); |
| 279 | + } |
| 280 | + |
| 281 | + function doSubmit( $group ) { |
| 282 | + global $wgRequest,$wgOut,$wgScript,$wgUser; |
| 283 | + |
| 284 | + $newRights = array(); |
| 285 | + $addRights = array(); |
| 286 | + $removeRights = array(); |
| 287 | + $oldRights = $this->getAssignedRights( $group ); |
| 288 | + $allRights = User::getAllRights(); |
| 289 | + |
| 290 | + $reason = $wgRequest->getVal( 'wpReason', '' ); |
| 291 | + |
| 292 | + foreach ($allRights as $right) { |
| 293 | + $alreadyAssigned = in_array( $right, $oldRights ); |
| 294 | + |
| 295 | + if ($wgRequest->getCheck( "wpRightAssigned-$right" )) { |
| 296 | + $newRights[] = $right; |
| 297 | + } |
| 298 | + |
| 299 | + if (!$alreadyAssigned && $wgRequest->getCheck( "wpRightAssigned-$right" )) { |
| 300 | + $addRights[] = $right; |
| 301 | + } else if ($alreadyAssigned && !$wgRequest->getCheck( "wpRightAssigned-$right" ) ) { |
| 302 | + $removeRights[] = $right; |
| 303 | + } # Otherwise, do nothing. |
| 304 | + } |
| 305 | + |
| 306 | + $backend = $this->getBackend(); |
| 307 | + |
| 308 | + // Assign the rights. |
| 309 | + if (count($addRights)>0) |
| 310 | + $backend->assignRights( $group, $addRights ); |
| 311 | + if (count($removeRights)>0) |
| 312 | + $backend->revokeRights( $group, $removeRights ); |
| 313 | + |
| 314 | + // Log it |
| 315 | + if (!(count($addRights)==0 && count($removeRights)==0)) |
| 316 | + $backend->addGroupLogEntry( $group, $addRights, $removeRights, $reason, $wgUser ); |
| 317 | + |
| 318 | + // Changeable groups |
| 319 | + $changeableGroups = $backend->getChangeableGroups( array( $group ) ); |
| 320 | + $newChangeableGroups = array(); |
| 321 | + |
| 322 | + $editTypes = array( 'add' => 'addable', 'remove' => 'removable', 'add-self' => 'addself', 'remove-self' => 'removeself' ); |
| 323 | + foreach( $editTypes as $type => $var ) { |
| 324 | + $newChangeableGroups[$var] = array_map( 'trim', explode( ',', $wgRequest->getVal( "wpGroupChange-$type" ) ) ); |
| 325 | + } |
| 326 | + extract($newChangeableGroups); |
| 327 | + $backend->setChangeableGroups( $group, $addable, $removable, $addself, $removeself ); |
| 328 | + |
| 329 | + // Clear the cache |
| 330 | + $backend->invalidateGroupCache( $group ); |
| 331 | + |
| 332 | + // Do extra stuff. |
| 333 | + $backend->doExtraGroupSubmit( $group, $reason, $wgRequest); |
| 334 | + |
| 335 | + // Display success |
| 336 | + $sk = $wgUser->getSkin(); |
| 337 | + $wgOut->setSubTitle( wfMsg( 'grouprights-editgroup-success' ) ); |
| 338 | + $wgOut->addWikiMsg( 'grouprights-editgroup-success-text', $group ); |
| 339 | + $wgOut->addHTML( $sk->link( $this->getTitle( ), wfMsg( 'grouprights-return' ), array(), array( 'backend' => $this->mBackend ) ) ); |
| 340 | + } |
| 341 | +} |
Property changes on: branches/group_rights/includes/specials/SpecialGroupRights.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 342 | + native |
Index: branches/group_rights/includes/RightsManager.php |
— | — | @@ -0,0 +1,723 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +if ( !defined( 'MEDIAWIKI' ) ) |
| 5 | + die(); |
| 6 | + |
| 7 | +abstract class RightsManager { |
| 8 | + |
| 9 | + /** |
| 10 | + * Assign a set of rights to a group. |
| 11 | + * @param $group \type{\string} The group to assign rights to. |
| 12 | + * @param $rights \type{\arrayof{\string}} The rights to assign. |
| 13 | + */ |
| 14 | + function assignRights( $group, $rights ) { |
| 15 | + $this->setRightsStatus( $group, array_fill_keys( $rights, true ) ); |
| 16 | + } |
| 17 | + |
| 18 | + /** |
| 19 | + * Invalidate the cache of rights for a group. |
| 20 | + * @param $group \type{\string} The group to invalidate the cache for. |
| 21 | + */ |
| 22 | + function invalidateGroupCache( $group ) {} |
| 23 | + |
| 24 | + /** |
| 25 | + * Invalidate the cache of rights for a user. |
| 26 | + * @param $user \type{\object{User}} The user to invalidate the cache for. |
| 27 | + */ |
| 28 | + function invalidateUserCache( $user ) {} |
| 29 | + |
| 30 | + /** |
| 31 | + * Revoke a set of rights from a group. |
| 32 | + * @param $group \type{\string} The group to revoke rights from. |
| 33 | + * @param $rights \type{\arrayof{\string}} The rights to revoke. |
| 34 | + */ |
| 35 | + function revokeRights( $group, $rights ) { |
| 36 | + $this->setRightsStatus( $group, array_fill_keys( $rights, false ) ); |
| 37 | + } |
| 38 | + |
| 39 | + /** |
| 40 | + * Set the status of rights. |
| 41 | + * @param $group \type{\string} The group to set rights status for |
| 42 | + * @param $rights \type{\array} An array with key=right, value=whether or not the right is assigned. |
| 43 | + */ |
| 44 | + abstract function setRightsStatus( $group, $rights ); |
| 45 | + |
| 46 | + /** |
| 47 | + * Modify the changeable groups for a group. |
| 48 | + * @param $group \type{\string} The group to assign edit changeable groups for. |
| 49 | + * @param $addable \type{\arrayof{\string}} The groups to be addable. |
| 50 | + * @param $removable \type{\arrayof{\string}} The groups to be removable. |
| 51 | + * @param $addtoself \type{\arrayof{\string}} The groups to be addable by the user in question only. |
| 52 | + * @param $removefromself \type{\arrayof{\string}} The groups to be removable by the user in question only. |
| 53 | + */ |
| 54 | + abstract function setChangeableGroups( $group, $addable, $removable, $addtoself, $removefromself ); |
| 55 | + |
| 56 | + /** |
| 57 | + * Get a list of all group permissions. |
| 58 | + * @return \type{\array} Array of group => (permission => allowed, ...), ... |
| 59 | + */ |
| 60 | + abstract function getAllGroupPermissions(); |
| 61 | + |
| 62 | + /** |
| 63 | + * Determine whether a given user is allowed to change group rights. |
| 64 | + * @param $user \type{\object{User}} The user to check. |
| 65 | + * @return \type{\bool} Whether or not the user is allowed to change group rights. |
| 66 | + */ |
| 67 | + abstract function canEditRights( $user ); |
| 68 | + |
| 69 | + /** |
| 70 | + * Add a user to a group or groups. |
| 71 | + * @param $user \type{\object{User}} |
| 72 | + * @param $groups \type{\arrayof{\string}} |
| 73 | + */ |
| 74 | + abstract function addUserGroups( $user, $groups ); |
| 75 | + |
| 76 | + /** |
| 77 | + * Remove a user from a group or groups. |
| 78 | + * @param $user \type{\object{User}} |
| 79 | + * @param $groups \type{\arrayof{\string}} |
| 80 | + */ |
| 81 | + abstract function removeUserGroups( $user, $groups ); |
| 82 | + |
| 83 | + /** |
| 84 | + * Make a list of group names, for the log. |
| 85 | + */ |
| 86 | + function makeGroupNameListForLog( $ids ) { |
| 87 | + if( empty( $ids ) ) { |
| 88 | + return wfMsgForContent( 'rightsnone' ); |
| 89 | + } else { |
| 90 | + return implode( ', ', $ids ); |
| 91 | + } |
| 92 | + } |
| 93 | + |
| 94 | + /** |
| 95 | + * Make a list of rights, for the log. |
| 96 | + */ |
| 97 | + function makeRightsList( $ids ) { |
| 98 | + return (bool)count($ids) ? implode( ', ', $ids ) : wfMsgForContent( 'rightsnone' ); |
| 99 | + } |
| 100 | + |
| 101 | + function changeUserGroups( $user, $addgroups, $removegroups, $reason, $doer ) { |
| 102 | + // Validate input set... |
| 103 | + $changeable = $this->getChangeableGroupsForUser( $user ); |
| 104 | + $isself = $this->userEquals( $user, $doer ); |
| 105 | + |
| 106 | + // Allow adding to self |
| 107 | + $addable = array_merge( $changeable['add'], $isself ? $changeable['add-self'] : array() ); |
| 108 | + $removable = array_merge( $changeable['remove'], $isself ? $changeable['remove-self'] : array() ); |
| 109 | + |
| 110 | + // Filter for what we can actually change |
| 111 | + $removegroups = array_unique( |
| 112 | + array_intersect( (array)$removegroups, $removable ) ); |
| 113 | + $addgroups = array_unique( |
| 114 | + array_intersect( (array)$addgroups, $addable ) ); |
| 115 | + |
| 116 | + if (!count(array_merge( $removegroups, $addgroups ) ) ) |
| 117 | + return; |
| 118 | + |
| 119 | + // Only add groups user doesn't have, remove groups user does have. |
| 120 | + $oldGroups = $this->getUserGroups( $user ); |
| 121 | + $removegroups = array_intersect( $removegroups, $oldGroups ); |
| 122 | + $addgroups = array_diff( $addgroups, array_intersect( $addgroups, $oldGroups ) ); |
| 123 | + |
| 124 | + // The actual business end. |
| 125 | + $this->addUserGroups( $user, $addgroups ); |
| 126 | + $this->removeUserGroups( $user, $removegroups ); |
| 127 | + |
| 128 | + // Ensure that caches are cleared |
| 129 | + $this->invalidateUserCache( $user ); |
| 130 | + |
| 131 | + // Log it |
| 132 | + $this->addUserGroupsLogEntry( $user, $addgroups, $removegroups, $reason, $doer ); |
| 133 | + } |
| 134 | + |
| 135 | + /** |
| 136 | + * Get a list of changeable groups. |
| 137 | + * @return \type{\array} Array of group => array( group1, group2, ... ) |
| 138 | + */ |
| 139 | + abstract function getAllChangeableGroups(); |
| 140 | + |
| 141 | + /** |
| 142 | + * Checks if two user objects are equal |
| 143 | + */ |
| 144 | + function userEquals( $a, $b ) { |
| 145 | + return $a->getId() == $b->getId(); |
| 146 | + } |
| 147 | + |
| 148 | + abstract function fetchUser( $username ); |
| 149 | + |
| 150 | + /** |
| 151 | + * Get a list of groups changeable by a particular group. |
| 152 | + * @param $groups \type{string} Group or array of groups to check. |
| 153 | + * @return \type{\arrayof{\string}} Array of action => groups changeable by this group/groups |
| 154 | + */ |
| 155 | + function getChangeableGroups( $groups ) { |
| 156 | + $changeable = $this->getAllChangeableGroups(); |
| 157 | + $result = array('add' => array(), 'remove' => array(), 'addself' => array(), 'removeself' => array()); |
| 158 | + |
| 159 | + foreach( $groups as $group ) { |
| 160 | + if ( isset( $changeable[$group] ) && is_array( $changeable[$group] ) ) |
| 161 | + $result = array_merge_recursive( $result, $changeable[$group] ); |
| 162 | + } |
| 163 | + |
| 164 | + return $result; |
| 165 | + } |
| 166 | + |
| 167 | + /** |
| 168 | + * Get a list of groups changeable by a particular user. |
| 169 | + * @param $user \type{\object{User}} User to check. |
| 170 | + * @return \type{\array} Array of action => groups |
| 171 | + */ |
| 172 | + function getChangeableGroupsForUser( $user ) { |
| 173 | + $groups = $this->getUserGroups( $user ); |
| 174 | + return $this->getChangeableGroups( $groups ); |
| 175 | + } |
| 176 | + |
| 177 | + /** |
| 178 | + * Get a list of all defined groups. |
| 179 | + * @return \type{\arrayof{\string}} |
| 180 | + */ |
| 181 | + function getAllGroups() { |
| 182 | + $groupPerms = $this->getAllGroupPermissions(); |
| 183 | + $changeableGroups = $this->getAllChangeableGroups(); |
| 184 | + |
| 185 | + return array_unique( array_merge( array_keys( $groupPerms ), array_keys( $changeableGroups ) ) ); |
| 186 | + } |
| 187 | + |
| 188 | + /** |
| 189 | + * Get a list of groups assigned to a user account. |
| 190 | + * @param $user \type{\object{User}} |
| 191 | + * @return \type{\arrayof{\string}} |
| 192 | + */ |
| 193 | + abstract function getUserGroups( $user ); |
| 194 | + |
| 195 | + /** |
| 196 | + * Get a list of permissions assigned to a user account. |
| 197 | + * @param $user \type{\object{User}} |
| 198 | + * @return \type{\arrayof{\string}} |
| 199 | + */ |
| 200 | + function getPermissionsForUser( $user ) { |
| 201 | + $groups = $this->getUserGroups( $user ); |
| 202 | + return $this->getGroupPermissions( $groups ); |
| 203 | + } |
| 204 | + |
| 205 | + /** |
| 206 | + * Get a list of all defined groups with a given permission. |
| 207 | + * @param $permission \type{\string} The permission to check for. |
| 208 | + * @return \type{\arrayof{\string}} List of group names with that permission. |
| 209 | + */ |
| 210 | + function getGroupsWithPermission( $permission ) { |
| 211 | + $groupPerms = $this->getAllGroupPermissions(); |
| 212 | + |
| 213 | + $allowedGroups = array(); |
| 214 | + foreach ( $groupPerms as $group => $rights ) { |
| 215 | + if ( isset( $rights[$permission] ) && $rights[$permission] ) { |
| 216 | + $allowedGroups[] = $group; |
| 217 | + } |
| 218 | + } |
| 219 | + return $allowedGroups; |
| 220 | + } |
| 221 | + |
| 222 | + /** |
| 223 | + * Get a list of all permissions assigned to the groups given. |
| 224 | + * @param $groups \type{\arrayof{\string}} Array of groups to check. |
| 225 | + * @return \type{\arrayof{\string}} List of permissions assigned to those groups. |
| 226 | + */ |
| 227 | + function getGroupPermissions( $groups ) { |
| 228 | + $groupPerms = $this->getAllGroupPermissions(); |
| 229 | + $rights = array(); |
| 230 | + foreach( $groups as $group ) { |
| 231 | + if( isset( $groupPerms[$group] ) ) { |
| 232 | + $rights = array_merge( $rights, |
| 233 | + array_keys( array_filter( $groupPerms[$group] ) ) ); |
| 234 | + } |
| 235 | + } |
| 236 | + return $rights; |
| 237 | + } |
| 238 | + |
| 239 | + /** |
| 240 | + * Show the logs for recent changes for a given group. |
| 241 | + * @param $group \type{\string} The group to show changes for. |
| 242 | + * @param $output \type{\object{OutputPage}} The OutputPage to print output to. |
| 243 | + */ |
| 244 | + function showGroupLogFragment( $group, $output ) { |
| 245 | + $title = SpecialPage::getTitleFor( 'ListUsers', $group ); |
| 246 | + $output->addHTML( Xml::element( 'h2', null, LogPage::logName( 'rights' ) . "\n" ) ); |
| 247 | + LogEventsList::showLogExtract( $output, 'rights', $title->getPrefixedText() ); |
| 248 | + } |
| 249 | + |
| 250 | + function showUserLogFragment( $user, $output ) { |
| 251 | + $output->addHtml( Xml::element( 'h2', null, LogPage::logName( 'rights' ) . "\n" ) ); |
| 252 | + LogEventsList::showLogExtract( $output, 'rights', $user->getUserPage()->getPrefixedText() ); |
| 253 | + } |
| 254 | + |
| 255 | + /** |
| 256 | + * Add a log entry for group rights changes. |
| 257 | + * @param $group \type{\string} The group in question. |
| 258 | + * @param $addRights \type{\arrayof{\string}} The rights added. |
| 259 | + * @param $removeRights \type{\arrayof{\string}} The rights removed. |
| 260 | + * @param $reason \type{\string} The comment attached to the change. |
| 261 | + * @param $user \type{\object{User}} The user doing the change (Optional) |
| 262 | + */ |
| 263 | + abstract function addGroupLogEntry( $group, $addRights, $removeRights, $reason, $user ); |
| 264 | + |
| 265 | + /** |
| 266 | + * Add a log entry for user groups changes. |
| 267 | + * @param $user \type{\object{User}} The user |
| 268 | + * @param $addgroups \type{\arrayof{\string}} The groups added. |
| 269 | + * @param $removegroups \type{\arrayof{\string}} The groups removed. |
| 270 | + */ |
| 271 | + abstract function addUserGroupsLogEntry( $user, $addgroups, $removegroups, $reason, $doer ); |
| 272 | + |
| 273 | + /** |
| 274 | + * Checks whether a given right on a given group may be modified. |
| 275 | + * @param $group \type{\string} The group in question. |
| 276 | + * @param $right \type{\string} The right in question. |
| 277 | + * @return \type{\bool} Whether or not the given group-right may be modified. |
| 278 | + */ |
| 279 | + function rightEditable( $group, $right ) { return true; } |
| 280 | + |
| 281 | + /** |
| 282 | + * Add any extra desired fields onto the group edit page. |
| 283 | + * @param &$fields \type{\array} Pre-filled array of fields ready to be passed to Xml::buildForm. |
| 284 | + * @param $group \type{\string} The group in question. |
| 285 | + */ |
| 286 | + function doExtraGroupForm( &$fields, $group ) {} |
| 287 | + |
| 288 | + /** |
| 289 | + * Does any necessary extra processing for the group editing form. |
| 290 | + * @param $group \type{\string} The group in question. |
| 291 | + * @param $reason \type{\string} The reason given for the change. |
| 292 | + * @param $request \type{\string} The HTTP request for the submission. |
| 293 | + */ |
| 294 | + function doExtraGroupSubmit( $group, $reason, $request ) {} |
| 295 | +} |
| 296 | + |
| 297 | +// Derive from this class to produce a rights manager which is read-only. |
| 298 | +abstract class RightsManagerReadOnly extends RightsManager { |
| 299 | + // These functions are disabled. |
| 300 | + function setChangeableGroups( $group, $add, $remove, $addself, $removeself ) { return false; } |
| 301 | + function setRightsStatus( $group, $rights ) { return false; } |
| 302 | + function addUserGroups( $user, $groups ) { return false; } |
| 303 | + function removeUserGroups( $user, $groups ) { return false; } |
| 304 | + function canEditRights( $user ) {return false;} |
| 305 | +} |
| 306 | + |
| 307 | +// Pseudo-concrete implementation of a rights manager |
| 308 | +// -Pools rights and groups from multiple sources. |
| 309 | +class RightsManagerMulti extends RightsManagerReadOnly { |
| 310 | + |
| 311 | + // Functions left unimplemented because it makes no sense. |
| 312 | + function fetchUser( $username ) { return null; } |
| 313 | + function addGroupLogEntry( $group, $addRights, $removeRights, $reason, $user ) { return false; } |
| 314 | + function addUserGroupsLogEntry( $user, $addgroups, $removegroups, $reason, $doer ) { return false; } |
| 315 | + function getAllChangeableGroups() { return false; } |
| 316 | + |
| 317 | + function getAllGroupPermissions() { |
| 318 | + global $wgRightsManagers; |
| 319 | + |
| 320 | + $groupPerms = array(); |
| 321 | + foreach( $wgRightsManagers as $rmClass ) { |
| 322 | + $rm = new $rmClass; |
| 323 | + |
| 324 | + $rights = $rm->getAllGroupPermissions(); |
| 325 | + |
| 326 | + foreach ($rights as $group => $grouprights) { |
| 327 | + if ( !isset( $groupPerms[$group] ) ) |
| 328 | + $groupPerms[$group] = array(); |
| 329 | + |
| 330 | + $grouprights = array_keys( array_filter( $grouprights ) ); |
| 331 | + foreach( $grouprights as $right ) { |
| 332 | + $groupPerms[$group][$right] = true; |
| 333 | + } |
| 334 | + } |
| 335 | + } |
| 336 | + |
| 337 | + return $groupPerms; |
| 338 | + } |
| 339 | + |
| 340 | + function getGroupPermissions( $groups ) { |
| 341 | + global $wgRightsManagers; |
| 342 | + |
| 343 | + if (!is_array( $wgRightsManagers ) ) { |
| 344 | + die( var_dump( $wgRightsManagers ) ); |
| 345 | + } |
| 346 | + |
| 347 | + $perms = array(); |
| 348 | + foreach( $wgRightsManagers as $rmClass ) { |
| 349 | + $rm = new $rmClass; |
| 350 | + |
| 351 | + $perms = array_merge( $perms, $rm->getGroupPermissions( $groups ) ); |
| 352 | + } |
| 353 | + |
| 354 | + return array_unique( $perms ); |
| 355 | + } |
| 356 | + |
| 357 | + function getUserGroups( $user ) { |
| 358 | + global $wgRightsManagers; |
| 359 | + |
| 360 | + $groups = array(); |
| 361 | + foreach( $wgRightsManagers as $rmClass ) { |
| 362 | + $rm = new $rmClass; |
| 363 | + |
| 364 | + $groups = array_merge( $groups, $rm->getUserGroups( $user ) ); |
| 365 | + } |
| 366 | + |
| 367 | + return array_unique( $groups ); |
| 368 | + } |
| 369 | + |
| 370 | + function getPermissionsForUser( $user ) { |
| 371 | + global $wgRightsManagers; |
| 372 | + |
| 373 | + $perms = array(); |
| 374 | + foreach( $wgRightsManagers as $rmClass ) { |
| 375 | + $rm = new $rmClass; |
| 376 | + |
| 377 | + $perms = array_merge( $perms, $rm->getPermissionsForUser( $user ) ); |
| 378 | + } |
| 379 | + |
| 380 | + return array_unique( $perms ); |
| 381 | + } |
| 382 | + |
| 383 | + function getAllGroups() { |
| 384 | + global $wgRightsManagers; |
| 385 | + |
| 386 | + $groups = array(); |
| 387 | + foreach( $wgRightsManagers as $rmClass ) { |
| 388 | + $rm = new $rmClass; |
| 389 | + |
| 390 | + $groups = array_merge( $groups, $rm->getAllGroups( ) ); |
| 391 | + } |
| 392 | + |
| 393 | + return array_unique( $groups ); |
| 394 | + } |
| 395 | +} |
| 396 | + |
| 397 | +// Concrete implementation of a rights manager - uses the default DB and configuration setup. |
| 398 | +class RightsManagerConfigDB extends RightsManager { |
| 399 | + function getAllGroupPermissions() { |
| 400 | + global $wgGroupPermissions,$wgAllowDBRightSubtraction; |
| 401 | + $groupPerms = $wgGroupPermissions; |
| 402 | + $dbGroupPerms = $this->loadGroupPermissions(); |
| 403 | + |
| 404 | + foreach( $dbGroupPerms as $group => $rights ) { |
| 405 | + foreach( $rights as $right => $value ) { |
| 406 | + if ($value || $wgAllowDBRightSubtraction) |
| 407 | + $groupPerms[$group][$right] = $value; |
| 408 | + } |
| 409 | + } |
| 410 | + |
| 411 | + return $groupPerms; |
| 412 | + } |
| 413 | + |
| 414 | + function canEditRights( $user ) { |
| 415 | + return $user->isAllowed( 'grouprights' ); |
| 416 | + } |
| 417 | + |
| 418 | + /** |
| 419 | + * Load all group permissions from the database. |
| 420 | + */ |
| 421 | + function loadGroupPermissions( ) { |
| 422 | + static $groupPerms = null; |
| 423 | + |
| 424 | + // In-process caching... |
| 425 | + if ( is_array($groupPerms) ) { |
| 426 | + return $groupPerms; |
| 427 | + } |
| 428 | + |
| 429 | + // Memcached caching |
| 430 | + global $wgMemc; |
| 431 | + $groupPerms = $wgMemc->get( wfMemcKey( 'grouprights' ) ); |
| 432 | + if ( is_array( $groupPerms ) ) { |
| 433 | + return $groupPerms; |
| 434 | + } |
| 435 | + |
| 436 | + // Fetch from DB |
| 437 | + |
| 438 | + $groupPerms = array(); |
| 439 | + |
| 440 | + $dbr = wfGetDB( DB_SLAVE ); |
| 441 | + $res = $dbr->select( 'group_rights', '*', array(), __METHOD__ ); |
| 442 | + |
| 443 | + while ($row = $dbr->fetchObject( $res ) ) { |
| 444 | + $groupPerms[$row->gr_group][$row->gr_right] = (bool)$row->gr_enabled; |
| 445 | + } |
| 446 | + |
| 447 | + $wgMemc->set( wfMemcKey( 'grouprights' ), $groupPerms ); |
| 448 | + |
| 449 | + return $groupPerms; |
| 450 | + } |
| 451 | + |
| 452 | + function getUserGroups( $user ) { |
| 453 | + if ( !isset( $user->mGroups ) || is_null( $user->mGroups ) ) { |
| 454 | + $dbr = wfGetDB( DB_MASTER ); |
| 455 | + $res = $dbr->select( 'user_groups', |
| 456 | + array( 'ug_group' ), |
| 457 | + array( 'ug_user' => $user->getId() ), |
| 458 | + __METHOD__ ); |
| 459 | + $this->mGroups = array(); |
| 460 | + while( $row = $dbr->fetchObject( $res ) ) { |
| 461 | + $user->mGroups[] = $row->ug_group; |
| 462 | + } |
| 463 | + |
| 464 | + $user->mGroups = array_unique( array_filter( $user->mGroups ) ); |
| 465 | + } |
| 466 | + |
| 467 | + return $user->mGroups; |
| 468 | + } |
| 469 | + |
| 470 | + function getAllChangeableGroups() { |
| 471 | + static $changeableGroups = null; |
| 472 | + |
| 473 | + // In-process caching |
| 474 | + if ( is_array( $changeableGroups ) ) { |
| 475 | + return $changeableGroups; |
| 476 | + } |
| 477 | + |
| 478 | + global $wgMemc; |
| 479 | + $changeableGroups = $wgMemc->get( wfMemcKey( 'changeablegroups' ) ); |
| 480 | + if ( is_array( $changeableGroups ) ) { |
| 481 | + return $changeableGroups; |
| 482 | + } |
| 483 | + |
| 484 | + // Fetch from DB |
| 485 | + $changeableGroups = array(); |
| 486 | + $groupTemplate = array( 'add' => array(), 'remove' => array(), 'add-self' => array(), 'remove-self' => array() ); |
| 487 | + |
| 488 | + $dbr = wfGetDB( DB_SLAVE ); |
| 489 | + $res = $dbr->select( 'changeable_groups', '*', array(), __METHOD__ ); |
| 490 | + |
| 491 | + while ( $row = $dbr->fetchObject( $res ) ) { |
| 492 | + $changer = $row->cg_changer; |
| 493 | + $group = $row->cg_group; |
| 494 | + $action = $row->cg_action; |
| 495 | + |
| 496 | + if ( !isset( $changeableGroups[$changer] ) || !is_array( $changeableGroups[$changer] ) ) { |
| 497 | + $changeableGroups[$changer] = $groupTemplate; |
| 498 | + } |
| 499 | + |
| 500 | + if ($changer && $group && $action) |
| 501 | + $changeableGroups[$changer][$action][] = $group; |
| 502 | + } |
| 503 | + |
| 504 | + // People who can change all groups. |
| 505 | + foreach( $this->getGroupsWithPermission( 'userrights' ) as $group ) { |
| 506 | + $changeableGroups[$group] = array_fill_keys( array( 'add', 'remove' ), array_diff( $this->getAllGroups(), User::getImplicitGroups() ) ); |
| 507 | + $changeableGroups[$group] = array_merge_recursive( $groupTemplate, $changeableGroups[$group] ); |
| 508 | + } |
| 509 | + |
| 510 | + $wgMemc->set( wfMemcKey('changeablegroups'), $changeableGroups ); |
| 511 | + |
| 512 | + return $changeableGroups; |
| 513 | + } |
| 514 | + |
| 515 | + function setChangeableGroups( $group, $addable, $removable, $addself, $removeself ) { |
| 516 | + $orig = $this->getChangeableGroups( array( $group )); |
| 517 | + |
| 518 | + $rows = array(); |
| 519 | + $delete = array(); |
| 520 | + |
| 521 | + if ( count( array_diff( $addable, $orig['add'] ) ) ) { |
| 522 | + $delete[] = 'add'; |
| 523 | + |
| 524 | + foreach( $addable as $cgroup ) { |
| 525 | + $rows[] = array( 'cg_changer' => $group, 'cg_group' => $cgroup, 'cg_action' => 'add' ); |
| 526 | + } |
| 527 | + } |
| 528 | + |
| 529 | + if ( count( array_diff( $removable, $orig['remove'] ) ) ) { |
| 530 | + $delete[] = 'remove'; |
| 531 | + |
| 532 | + foreach( $removable as $cgroup ) { |
| 533 | + $rows[] = array( 'cg_changer' => $group, 'cg_group' => $cgroup, 'cg_action' => 'remove' ); |
| 534 | + } |
| 535 | + } |
| 536 | + |
| 537 | + if ( count( array_diff( $addself, $orig['add-self'] ) ) ) { |
| 538 | + $delete[] = 'add-self'; |
| 539 | + |
| 540 | + foreach( $addself as $cgroup ) { |
| 541 | + $rows[] = array( 'cg_changer' => $group, 'cg_group' => $cgroup, 'cg_action' => 'add-self' ); |
| 542 | + } |
| 543 | + } |
| 544 | + |
| 545 | + if ( count( array_diff( $removeself, $orig['remove-self'] ) ) ) { |
| 546 | + $delete[] = 'remove-self'; |
| 547 | + |
| 548 | + foreach( $removeself as $cgroup ) { |
| 549 | + $rows[] = array( 'cg_changer' => $group, 'cg_group' => $cgroup, 'cg_action' => 'remove-self' ); |
| 550 | + } |
| 551 | + } |
| 552 | + |
| 553 | + $dbw = wfGetDB( DB_MASTER ); |
| 554 | + |
| 555 | + $dbw->begin(); |
| 556 | + $dbw->delete( 'changeable_groups', array( 'cg_changer' => $group, 'cg_action' => $delete ), __METHOD__ ); |
| 557 | + $dbw->insert( 'changeable_groups', $rows, __METHOD__ ); |
| 558 | + $dbw->commit(); |
| 559 | + $this->invalidateGroupCache( $group ); |
| 560 | + } |
| 561 | + |
| 562 | + function setRightsStatus( $group, $rights ) { |
| 563 | + $dbw = wfGetDB( DB_MASTER ); |
| 564 | + |
| 565 | + $toDelete = array(); |
| 566 | + $toSet = array(); |
| 567 | + foreach( $rights as $right => $status ) { |
| 568 | + if ($this->rightInConfig( $group, $right ) == $status) { |
| 569 | + $toDelete[] = $right; |
| 570 | + } else { |
| 571 | + $toSet[] = array( 'gr_group' => $group, 'gr_right' => $right, 'gr_enabled' => $status ); |
| 572 | + } |
| 573 | + } |
| 574 | + |
| 575 | + if ( count($toDelete) ) |
| 576 | + $dbw->delete( 'group_rights', array( 'gr_group' => $group, 'gr_right' => $toDelete), __METHOD__ ); |
| 577 | + |
| 578 | + global $wgAllowDBRightSubtraction; |
| 579 | + if ( $wgAllowDBRightSubtraction && count($toSet) ) { |
| 580 | + $dbw->replace( 'group_rights', 'gr_group,gr_right', $toSet, __METHOD__ ); |
| 581 | + } |
| 582 | + |
| 583 | + $this->invalidateGroupCache( $group ); |
| 584 | + } |
| 585 | + |
| 586 | + protected function rightInConfig( $group, $right ) { |
| 587 | + global $wgGroupPermissions; |
| 588 | + |
| 589 | + return isset($wgGroupPermissions[$group]) && isset($wgGroupPermissions[$group][$right]) && $wgGroupPermissions[$group][$right]; |
| 590 | + } |
| 591 | + |
| 592 | + function changeUserGroups( $user, $addgroups, $removegroups, $reason, $doer ) { |
| 593 | + parent::changeUserGroups( $user, $addgroups, $removegroups, $reason, $doer ); |
| 594 | + wfRunHooks( 'UserRights', array( &$user, $addgroups, $removegroups, $reason, $doer ) ); |
| 595 | + } |
| 596 | + |
| 597 | + function addUserGroups( $user, $groups ) { |
| 598 | + $groups = array_filter( $groups ); |
| 599 | + |
| 600 | + if (!count($groups)) |
| 601 | + return; |
| 602 | + |
| 603 | + $dbw = wfGetDB( DB_MASTER ); |
| 604 | + |
| 605 | + $rows = array(); |
| 606 | + |
| 607 | + foreach( $groups as $group ) { |
| 608 | + $rows[] = array( 'ug_user' => $user->getId(), 'ug_group' => $group ); |
| 609 | + } |
| 610 | + |
| 611 | + $dbw->insert( 'user_groups', |
| 612 | + $rows, |
| 613 | + __METHOD__, |
| 614 | + array( 'IGNORE' ) ); |
| 615 | + } |
| 616 | + |
| 617 | + function removeUserGroups( $user, $groups ) { |
| 618 | + $groups = array_filter( $groups ); |
| 619 | + |
| 620 | + if (!count($groups)) |
| 621 | + return; |
| 622 | + |
| 623 | + $dbw = wfGetDB( DB_MASTER ); |
| 624 | + $dbw->delete( 'user_groups', |
| 625 | + array( |
| 626 | + 'ug_user' => $user->getID(), |
| 627 | + 'ug_group' => $groups, |
| 628 | + ), |
| 629 | + __METHOD__ ); |
| 630 | + |
| 631 | + $user->invalidateCache(); |
| 632 | + } |
| 633 | + |
| 634 | + function invalidateGroupCache( $group ) { |
| 635 | + global $wgMemc; |
| 636 | + |
| 637 | + $wgMemc->delete( wfMemcKey( 'changeablegroups' ) ); |
| 638 | + $wgMemc->delete( wfMemcKey( 'grouprights' ) ); |
| 639 | + } |
| 640 | + |
| 641 | + function invalidateUserCache( $user ) { |
| 642 | + $user->invalidateCache(); |
| 643 | + } |
| 644 | + |
| 645 | + function rightEditable( $group, $right ) { |
| 646 | + global $wgAllowDBRightSubtraction; |
| 647 | + |
| 648 | + return $wgAllowDBRightSubtraction || !$this->rightInConfig( $group, $right ); |
| 649 | + } |
| 650 | + |
| 651 | + function addGroupLogEntry( $group, $addRights, $removeRights, $reason, $user ) { |
| 652 | + global $wgRequest,$wgUser; |
| 653 | + |
| 654 | + if ($user == null) |
| 655 | + $user = $wgUser; |
| 656 | + |
| 657 | + $log = new LogPage( 'rights' ); |
| 658 | + |
| 659 | + $log->addEntry( 'grprights', |
| 660 | + SpecialPage::getTitleFor( 'ListUsers', $group ), |
| 661 | + $reason, |
| 662 | + array( |
| 663 | + $this->makeRightsList( $addRights ), |
| 664 | + $this->makeRightsList( $removeRights ) |
| 665 | + ) |
| 666 | + , $user); |
| 667 | + } |
| 668 | + |
| 669 | + function addUserGroupsLogEntry( $user, $addgroups, $removegroups, $reason, $doer ) { |
| 670 | + global $wgRequest; |
| 671 | + $log = new LogPage( 'rights' ); |
| 672 | + |
| 673 | + $log->addEntry( 'rights2', |
| 674 | + $user->getUserPage(), |
| 675 | + $reason, |
| 676 | + array( |
| 677 | + $this->makeGroupNameListForLog( $addgroups ), |
| 678 | + $this->makeGroupNameListForLog( $removegroups ) |
| 679 | + ) |
| 680 | + ); |
| 681 | + } |
| 682 | + |
| 683 | + function makeGroupNameListForLog( $ids ) { |
| 684 | + if( empty( $ids ) ) { |
| 685 | + return ''; |
| 686 | + } else { |
| 687 | + return implode( ', ', $ids ); |
| 688 | + } |
| 689 | + } |
| 690 | + |
| 691 | + function fetchUser( $username ) { |
| 692 | + if( $username{0} == '#' ) { |
| 693 | + // Numeric ID can be specified... |
| 694 | + // We'll do a lookup for the name internally. |
| 695 | + $id = intval( substr( $username, 1 ) ); |
| 696 | + |
| 697 | + $username = User::whoIs( $id ); |
| 698 | + |
| 699 | + if( !$username ) { |
| 700 | + return null; |
| 701 | + } |
| 702 | + } |
| 703 | + |
| 704 | + $user = User::newFromName( $username ); |
| 705 | + |
| 706 | + if (!$user || $user->isAnon()) { |
| 707 | + return null; |
| 708 | + } |
| 709 | + |
| 710 | + return $user; |
| 711 | + } |
| 712 | + |
| 713 | + function getChangeableGroupsForUser( $user ) { |
| 714 | + $cg = parent::getChangeableGroupsForUser( $user ); |
| 715 | + |
| 716 | + $allgroups = array_diff( $this->getAllGroups(), User::getImplicitGroups() ); |
| 717 | + |
| 718 | + if ($user->isAllowed( 'userrights' )) { |
| 719 | + $cg = array_merge_recursive( $cg, array_fill_keys( array( 'add', 'remove', 'add-self', 'remove-self' ), $allgroups ) ); |
| 720 | + } |
| 721 | + |
| 722 | + return $cg; |
| 723 | + } |
| 724 | +} |
Property changes on: branches/group_rights/includes/RightsManager.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 725 | + native |
Index: branches/group_rights/includes/SpecialPage.php |
— | — | @@ -148,6 +148,7 @@ |
149 | 149 | 'Lockdb' => array( 'SpecialPage', 'Lockdb', 'siteadmin' ), |
150 | 150 | 'Unlockdb' => array( 'SpecialPage', 'Unlockdb', 'siteadmin' ), |
151 | 151 | 'Userrights' => 'UserrightsPage', |
| 152 | + 'GroupRights' => 'SpecialGroupRights', |
152 | 153 | 'MIMEsearch' => array( 'SpecialPage', 'MIMEsearch' ), |
153 | 154 | 'FileDuplicateSearch' => array( 'SpecialPage', 'FileDuplicateSearch' ), |
154 | 155 | 'Unwatchedpages' => array( 'SpecialPage', 'Unwatchedpages', 'unwatchedpages' ), |
Index: branches/group_rights/includes/LogPage.php |
— | — | @@ -171,7 +171,7 @@ |
172 | 172 | $rv = wfMsg( $wgLogActions[$key] ); |
173 | 173 | } else { |
174 | 174 | $titleLink = self::getTitleLink( $type, $skin, $title, $params ); |
175 | | - if( $key == 'rights/rights' ) { |
| 175 | + if( $key == 'rights/rights' || $key = 'rights/rights2' ) { |
176 | 176 | if( $skin ) { |
177 | 177 | $rightsnone = wfMsg( 'rightsnone' ); |
178 | 178 | foreach ( $params as &$param ) { |
Index: branches/group_rights/languages/messages/MessagesEn.php |
— | — | @@ -416,7 +416,7 @@ |
417 | 417 | 'Import' => array( 'Import' ), |
418 | 418 | 'Lockdb' => array( 'LockDB' ), |
419 | 419 | 'Unlockdb' => array( 'UnlockDB' ), |
420 | | - 'Userrights' => array( 'UserRights' ), |
| 420 | + 'Userrights' => array( 'UserGroups', 'UserRights' ), |
421 | 421 | 'MIMEsearch' => array( 'MIMESearch' ), |
422 | 422 | 'FileDuplicateSearch' => array( 'FileDuplicateSearch' ), |
423 | 423 | 'Unwatchedpages' => array( 'UnwatchedPages' ), |
— | — | @@ -1538,12 +1538,12 @@ |
1539 | 1539 | 'files' => 'Files', |
1540 | 1540 | |
1541 | 1541 | # User rights |
1542 | | -'userrights' => 'User rights management', # Not used as normal message but as header for the special page itself |
| 1542 | +'userrights' => 'Edit user groups', # Not used as normal message but as header for the special page itself |
1543 | 1543 | 'userrights-summary' => '', # do not translate or duplicate this message to other languages |
1544 | 1544 | 'userrights-lookup-user' => 'Manage user groups', |
1545 | 1545 | 'userrights-user-editname' => 'Enter a username:', |
1546 | 1546 | 'editusergroup' => 'Edit user groups', |
1547 | | -'editinguser' => "Changing user rights of user '''[[User:$1|$1]]''' ([[User talk:$1|{{int:talkpagelinktext}}]] | [[Special:Contributions/$1|{{int:contribslink}}]])", |
| 1547 | +'editinguser' => "Changing group membership for user '''[[User:$1|$1]]''' ([[User talk:$1|{{int:talkpagelinktext}}]] | [[Special:Contributions/$1|{{int:contribslink}}]])", |
1548 | 1548 | 'userrights-editusergroup' => 'Edit user groups', |
1549 | 1549 | 'saveusergroups' => 'Save user groups', |
1550 | 1550 | 'userrights-groupsmember' => 'Member of:', |
— | — | @@ -1552,13 +1552,15 @@ |
1553 | 1553 | * An unchecked box means the user is not in that group. |
1554 | 1554 | * A * indicates that you cannot remove the group once you have added it, or vice versa.', |
1555 | 1555 | 'userrights-reason' => 'Reason for change:', |
1556 | | -'userrights-no-interwiki' => 'You do not have permission to edit user rights on other wikis.', |
| 1556 | +'userrights-no-interwiki' => 'You do not have permission to edit user group membership on other wikis.', |
1557 | 1557 | 'userrights-nodatabase' => 'Database $1 does not exist or is not local.', |
1558 | | -'userrights-nologin' => 'You must [[Special:UserLogin|log in]] with an administrator account to assign user rights.', |
1559 | | -'userrights-notallowed' => 'Your account does not have permission to assign user rights.', |
| 1558 | +'userrights-nologin' => 'You must [[Special:UserLogin|log in]] with an administrator account to assign user groups.', |
| 1559 | +'userrights-notallowed' => 'Your account does not have permission to assign user groups.', |
1560 | 1560 | 'userrights-changeable-col' => 'Groups you can change', |
1561 | 1561 | 'userrights-unchangeable-col' => 'Groups you cannot change', |
1562 | 1562 | 'userrights-irreversible-marker' => '$1*', # only translate this message to other languages if you have to change it |
| 1563 | +'userrights-backendselect-subtitle' => 'Select a rights manager', |
| 1564 | +'userrights-backendselect-text' => "You are permitted to edit user groups for more than one rights management system. Please select the rights management system for which you wish to edit user groups from the list below:", |
1563 | 1565 | |
1564 | 1566 | # Groups |
1565 | 1567 | 'group' => 'Group:', |
— | — | @@ -1633,14 +1635,16 @@ |
1634 | 1636 | 'right-unwatchedpages' => 'View a list of unwatched pages', |
1635 | 1637 | 'right-trackback' => 'Submit a trackback', |
1636 | 1638 | 'right-mergehistory' => 'Merge the history of pages', |
1637 | | -'right-userrights' => 'Edit all user rights', |
| 1639 | +'right-userrights' => 'Modify membership of all user groups', |
1638 | 1640 | 'right-userrights-interwiki' => 'Edit user rights of users on other wikis', |
1639 | 1641 | 'right-siteadmin' => 'Lock and unlock the database', |
| 1642 | +'right-grouprights' => 'Edit permissions assigned to local groups', |
1640 | 1643 | |
1641 | 1644 | # User rights log |
1642 | 1645 | 'rightslog' => 'User rights log', |
1643 | 1646 | 'rightslogtext' => 'This is a log of changes to user rights.', |
1644 | 1647 | 'rightslogentry' => 'changed group membership for $1 from $2 to $3', |
| 1648 | +'rightslogentry2' => 'changed group membership for $1: added $2, removed $3', |
1645 | 1649 | 'rightsnone' => '(none)', |
1646 | 1650 | |
1647 | 1651 | # Recent changes |
— | — | @@ -2152,6 +2156,10 @@ |
2153 | 2157 | 'listgrouprights-removegroup' => 'Can remove {{PLURAL:$2|group|groups}}: $1', |
2154 | 2158 | 'listgrouprights-addgroup-all' => 'Can add all groups', |
2155 | 2159 | 'listgrouprights-removegroup-all' => 'Can remove all groups', |
| 2160 | +'listgrouprights-addselfgroup-all'=> 'Can add all groups to self', |
| 2161 | +'listgrouprights-addselfgroup' => 'Can add {{PLURAL:$2|group|groups}} to self: $1', |
| 2162 | +'listgrouprights-removeselfgroup-all' => 'Can remove all groups from self', |
| 2163 | +'listgrouprights-removeselfgroup' => 'Can add {{PLURAL:$2|group|groups}} from self: $1', |
2156 | 2164 | |
2157 | 2165 | # E-mail user |
2158 | 2166 | 'mailnologin' => 'No send address', |
— | — | @@ -3662,6 +3670,46 @@ |
3663 | 3671 | 'blankpage' => 'Blank page', |
3664 | 3672 | 'intentionallyblankpage' => 'This page is intentionally left blank', |
3665 | 3673 | |
| 3674 | +# Special:GroupRights |
| 3675 | +'grouprights' => "Edit group rights", |
| 3676 | +'grouprights-grouplist' => 'The following groups have been configured. |
| 3677 | +You may view and edit the rights assigned to any group. |
| 3678 | +A group may be deleted by removing all rights from it.', |
| 3679 | +'grouprights-editlink' => 'view/edit', |
| 3680 | +'grouprights-existinggroup-legend' => 'Existing groups', |
| 3681 | +'grouprights-newgroup-legend' => 'Create a new group', |
| 3682 | +'grouprights-newgroup-intro' => 'You can use this form to assign rights to a new group. |
| 3683 | +Note that a group does not exist unless it has rights assigned to it.', |
| 3684 | +'grouprights-newgroupname' => 'New group name:', |
| 3685 | +'grouprights-creategroup-submit' => 'Assign rights', |
| 3686 | +'grouprights-subtitle' => 'Editing $1', |
| 3687 | +'grouprights-fieldset' => 'Rights for $1', |
| 3688 | +'grouprights-editgroup-name' => 'Name of group:', |
| 3689 | +'grouprights-editgroup-display' => 'Localised name of group:', |
| 3690 | +'grouprights-editgroup-display-edit' => '$2 ([[MediaWiki:Group-$1|edit]])', |
| 3691 | +'grouprights-editgroup-member' => 'Localised name of group members:', |
| 3692 | +'grouprights-editgroup-member-edit' => '$2 ([[MediaWiki:Group-$1-member|edit]])', |
| 3693 | +'grouprights-editgroup-members' => 'Member list:', |
| 3694 | +'grouprights-editgroup-members-link' => '[[Special:ListUsers/$1|List of users with $2 rights]]', |
| 3695 | +'grouprights-editgroup-restrictions' => 'Set of wikis where this group is active:', |
| 3696 | +'grouprights-editgroup-noset' => '(none)', |
| 3697 | +'grouprights-editgroup-submit' => 'Save changes to group rights', |
| 3698 | +'grouprights-editgroup-perms' => 'Assigned rights:', |
| 3699 | +'grouprights-editgroup-reason' => 'Reason for change:', |
| 3700 | +'grouprights-editgroup-success' => 'Group rights changed', |
| 3701 | +'grouprights-editgroup-success-text' => 'You have successfully changed the group rights for the $1 group.', |
| 3702 | +'grouprightslog' => 'changed group rights for $1. Added: $2; Removed: $3', |
| 3703 | +'grouprights-return' => 'Return to group rights', |
| 3704 | +'grouprights-backendselect-subtitle' => 'Select a rights manager', |
| 3705 | +'grouprights-backendselect-text' => "You are permitted to edit group rights for more than one rights management system. Please select the rights management system for which you wish to edit group rights from the list below:", |
| 3706 | +'grouprights-editgroup' => "'''Changeable groups'''", |
| 3707 | +'grouprights-editgroup-add' => 'Can add groups:', |
| 3708 | +'grouprights-editgroup-remove' => 'Can remove groups:', |
| 3709 | +'grouprights-editgroup-add-self' => 'Can add groups to self:', |
| 3710 | +'grouprights-editgroup-remove-self' => 'Can remove groups from self:', |
| 3711 | + |
| 3712 | +'rights-backend-RightsManagerConfigDB' => "Users and groups for this MediaWiki site.", |
| 3713 | + |
3666 | 3714 | # External image whitelist |
3667 | 3715 | 'external_image_whitelist' => ' #Leave this line exactly as it is<pre> |
3668 | 3716 | #Put regular expression fragments (just the part that goes between the //) below |