r105851 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r105850‎ | r105851 | r105852 >
Date:06:03, 12 December 2011
Author:tstarling
Status:ok
Tags:
Comment:
Reverted r92364 (per-namespace permissions).

This is the wrong configuration format for such a feature, and the wrong interface. We already have certain per-namespace permissions in the Title class, and we didn't need to add extra formal parameters to a whole lot of User methods in order to get them. The feature should be implemented wholly in Title, and the concept of user rights should remain relatively simple and easy to understand, and independent of its many applications, i.e. a user either has a right or doesn't. Rights are just a tool for developing access policies; the complexity should be in the caller.

The revert was mostly done by hand, since there were a lot of conflicts. I tried to preserve the gist of conflicting changes in r102187 and r102873. The test changes are not simple reverts, rather I just edited out the per-namespace tests. I reverted the followups r92589 and r104310.
Modified paths:
  • /trunk/phase3/docs/hooks.txt (modified) (history)
  • /trunk/phase3/includes/DefaultSettings.php (modified) (history)
  • /trunk/phase3/includes/Title.php (modified) (history)
  • /trunk/phase3/includes/User.php (modified) (history)
  • /trunk/phase3/tests/phpunit/includes/ArticleTablesTest.php (modified) (history)
  • /trunk/phase3/tests/phpunit/includes/TitlePermissionTest.php (modified) (history)
  • /trunk/phase3/tests/phpunit/includes/UserTest.php (modified) (history)

Diff [purge]

Index: trunk/phase3/docs/hooks.txt
@@ -2091,7 +2091,6 @@
20922092 'UserGetRights': Called in User::getRights()
20932093 $user: User to get rights for
20942094 &$rights: Current rights
2095 -$namespace: Namespace to get permissions for; if null all namespaces
20962095
20972096 'UserIsBlockedFrom': Check if a user is blocked from a specific page (for specific block
20982097 exemptions).
Index: trunk/phase3/tests/phpunit/includes/ArticleTablesTest.php
@@ -11,7 +11,7 @@
1212 $title = Title::newFromText("Bug 14404");
1313 $article = new Article( $title );
1414 $wgUser = new User();
15 - $wgUser->mRights['*'] = array( 'createpage', 'edit', 'purge' );
 15+ $wgUser->mRights = array( 'createpage', 'edit', 'purge' );
1616 $wgLanguageCode = 'es';
1717 $wgContLang = Language::factory( 'es' );
1818
Index: trunk/phase3/tests/phpunit/includes/UserTest.php
@@ -38,13 +38,6 @@
3939 $wgRevokePermissions['formertesters'] = array(
4040 'runtest' => true,
4141 );
42 -
43 - # Data for namespace based $wgGroupPermissions test
44 - $wgGroupPermissions['unittesters']['writedocumentation'] = array(
45 - NS_MAIN => false, NS_UNITTEST => true,
46 - );
47 - $wgGroupPermissions['testwriters']['writedocumentation'] = true;
48 -
4942 }
5043 private function setUpUser() {
5144 $this->user = new User;
@@ -79,89 +72,42 @@
8073 $this->assertNotContains( 'nukeworld', $rights );
8174 }
8275
83 - public function testNamespaceGroupPermissions() {
84 - $rights = User::getGroupPermissions( array( 'unittesters' ) );
85 - $this->assertNotContains( 'writedocumentation', $rights );
86 -
87 - $rights = User::getGroupPermissions( array( 'unittesters' ) , NS_MAIN );
88 - $this->assertNotContains( 'writedocumentation', $rights );
89 - $this->assertNotContains( 'modifytest', $rights );
90 -
91 - $rights = User::getGroupPermissions( array( 'unittesters' ), NS_HELP );
92 - $this->assertNotContains( 'writedocumentation', $rights );
93 - $this->assertNotContains( 'modifytest', $rights );
94 -
95 - $rights = User::getGroupPermissions( array( 'unittesters' ), NS_UNITTEST );
96 - $this->assertContains( 'writedocumentation', $rights );
97 -
98 - $rights = User::getGroupPermissions(
99 - array( 'unittesters', 'testwriters' ), NS_MAIN );
100 - $this->assertContains( 'writedocumentation', $rights );
101 - }
102 -
10376 public function testUserPermissions() {
10477 $rights = $this->user->getRights();
10578 $this->assertContains( 'runtest', $rights );
10679 $this->assertNotContains( 'writetest', $rights );
10780 $this->assertNotContains( 'modifytest', $rights );
10881 $this->assertNotContains( 'nukeworld', $rights );
109 - $this->assertNotContains( 'writedocumentation', $rights );
110 -
111 - $rights = $this->user->getRights( NS_MAIN );
112 - $this->assertNotContains( 'writedocumentation', $rights );
113 - $this->assertNotContains( 'modifytest', $rights );
114 -
115 - $rights = $this->user->getRights( NS_HELP );
116 - $this->assertNotContains( 'writedocumentation', $rights );
117 - $this->assertNotContains( 'modifytest', $rights );
118 -
119 - $rights = $this->user->getRights( NS_UNITTEST );
120 - $this->assertContains( 'writedocumentation', $rights );
12182 }
12283
12384 /**
12485 * @dataProvider provideGetGroupsWithPermission
12586 */
126 - public function testGetGroupsWithPermission( $expected, $right, $ns ) {
127 - $result = User::getGroupsWithPermission( $right, $ns );
 87+ public function testGetGroupsWithPermission( $expected, $right ) {
 88+ $result = User::getGroupsWithPermission( $right );
12889 sort( $result );
12990 sort( $expected );
13091
131 - $this->assertEquals( $expected, $result, "Groups with permission $right" .
132 - ( is_null( $ns ) ? '' : "in namespace $ns" ) );
 92+ $this->assertEquals( $expected, $result, "Groups with permission $right" );
13393 }
13494 public function provideGetGroupsWithPermission() {
13595 return array(
13696 array(
13797 array( 'unittesters', 'testwriters' ),
138 - 'test',
139 - null
 98+ 'test'
14099 ),
141100 array(
142101 array( 'unittesters' ),
143 - 'runtest',
144 - null
 102+ 'runtest'
145103 ),
146104 array(
147105 array( 'testwriters' ),
148 - 'writetest',
149 - null
 106+ 'writetest'
150107 ),
151108 array(
152109 array( 'testwriters' ),
153 - 'modifytest',
154 - null
 110+ 'modifytest'
155111 ),
156 - array(
157 - array( 'testwriters' ),
158 - 'writedocumentation',
159 - NS_MAIN
160 - ),
161 - array(
162 - array( 'unittesters', 'testwriters' ),
163 - 'writedocumentation',
164 - NS_UNITTEST
165 - ),
166112 );
167113 }
168114
Index: trunk/phase3/tests/phpunit/includes/TitlePermissionTest.php
@@ -62,15 +62,11 @@
6363 function setUserPerm( $perm ) {
6464 // Setting member variables is evil!!!
6565
66 - if ( !is_array( $perm ) ) {
67 - $perm = array( $perm );
 66+ if ( is_array( $perm ) ) {
 67+ $this->user->mRights = $perm;
 68+ } else {
 69+ $this->user->mRights = array( $perm );
6870 }
69 - for ($i = 0; $i < 100; $i++) {
70 - $this->user->mRights[$i] = $perm;
71 - }
72 -
73 - // Hack, hack hack ...
74 - $this->user->mRights['*'] = $perm;
7571 }
7672
7773 function setTitle( $ns, $title = "Main_Page" ) {
Index: trunk/phase3/includes/User.php
@@ -2316,29 +2316,16 @@
23172317
23182318 /**
23192319 * Get the permissions this user has.
2320 - * @param $ns int If numeric, get permissions for this namespace
23212320 * @return Array of String permission names
23222321 */
2323 - public function getRights( $ns = null ) {
2324 - $key = is_null( $ns ) ? '*' : intval( $ns );
2325 -
 2322+ public function getRights() {
23262323 if ( is_null( $this->mRights ) ) {
2327 - $this->mRights = array();
2328 - }
2329 -
2330 - if ( !isset( $this->mRights[$key] ) ) {
2331 - $this->mRights[$key] = self::getGroupPermissions( $this->getEffectiveGroups(), $ns );
2332 - wfRunHooks( 'UserGetRights', array( $this, &$this->mRights[$key], $ns ) );
 2324+ $this->mRights = self::getGroupPermissions( $this->getEffectiveGroups() );
 2325+ wfRunHooks( 'UserGetRights', array( $this, &$this->mRights ) );
23332326 // Force reindexation of rights when a hook has unset one of them
2334 - $this->mRights[$key] = array_values( $this->mRights[$key] );
 2327+ $this->mRights = array_values( $this->mRights );
23352328 }
2336 - if ( is_null( $ns ) ) {
2337 - return $this->mRights[$key];
2338 - } else {
2339 - // Merge non namespace specific rights
2340 - return array_merge( $this->mRights[$key], $this->getRights() );
2341 - }
2342 -
 2329+ return $this->mRights;
23432330 }
23442331
23452332 /**
@@ -2463,7 +2450,7 @@
24642451 }
24652452 $this->loadGroups();
24662453 $this->mGroups[] = $group;
2467 - $this->mRights = null;
 2454+ $this->mRights = User::getGroupPermissions( $this->getEffectiveGroups( true ) );
24682455
24692456 $this->invalidateCache();
24702457 }
@@ -2493,7 +2480,7 @@
24942481 }
24952482 $this->loadGroups();
24962483 $this->mGroups = array_diff( $this->mGroups, array( $group ) );
2497 - $this->mRights = null;
 2484+ $this->mRights = User::getGroupPermissions( $this->getEffectiveGroups( true ) );
24982485
24992486 $this->invalidateCache();
25002487 }
@@ -2550,10 +2537,9 @@
25512538 /**
25522539 * Internal mechanics of testing a permission
25532540 * @param $action String
2554 - * @param $ns int|null Namespace optional
25552541 * @return bool
25562542 */
2557 - public function isAllowed( $action = '', $ns = null ) {
 2543+ public function isAllowed( $action = '' ) {
25582544 if ( $action === '' ) {
25592545 return true; // In the spirit of DWIM
25602546 }
@@ -2565,7 +2551,7 @@
25662552 }
25672553 # Use strict parameter to avoid matching numeric 0 accidentally inserted
25682554 # by misconfiguration: 0 == 'foo'
2569 - return in_array( $action, $this->getRights( $ns ), true );
 2555+ return in_array( $action, $this->getRights(), true );
25702556 }
25712557
25722558 /**
@@ -3544,70 +3530,40 @@
35453531 * Get the permissions associated with a given list of groups
35463532 *
35473533 * @param $groups Array of Strings List of internal group names
3548 - * @param $ns int
3549 - *
35503534 * @return Array of Strings List of permission key names for given groups combined
35513535 */
3552 - public static function getGroupPermissions( array $groups, $ns = null ) {
 3536+ public static function getGroupPermissions( $groups ) {
35533537 global $wgGroupPermissions, $wgRevokePermissions;
35543538 $rights = array();
3555 -
3556 - // Grant every granted permission first
 3539+ // grant every granted permission first
35573540 foreach( $groups as $group ) {
35583541 if( isset( $wgGroupPermissions[$group] ) ) {
3559 - $rights = array_merge( $rights, self::extractRights(
3560 - $wgGroupPermissions[$group], $ns ) );
 3542+ $rights = array_merge( $rights,
 3543+ // array_filter removes empty items
 3544+ array_keys( array_filter( $wgGroupPermissions[$group] ) ) );
35613545 }
35623546 }
3563 -
3564 - // Revoke the revoked permissions
 3547+ // now revoke the revoked permissions
35653548 foreach( $groups as $group ) {
35663549 if( isset( $wgRevokePermissions[$group] ) ) {
3567 - $rights = array_diff( $rights, self::extractRights(
3568 - $wgRevokePermissions[$group], $ns ) );
 3550+ $rights = array_diff( $rights,
 3551+ array_keys( array_filter( $wgRevokePermissions[$group] ) ) );
35693552 }
35703553 }
35713554 return array_unique( $rights );
35723555 }
35733556
35743557 /**
3575 - * Helper for User::getGroupPermissions
3576 - * @param $list array
3577 - * @param $ns int
3578 - * @return array
3579 - */
3580 - private static function extractRights( $list, $ns ) {
3581 - $rights = array();
3582 - foreach( $list as $right => $value ) {
3583 - if ( is_array( $value ) ) {
3584 - # This is a list of namespaces where the permission applies
3585 - if ( !is_null( $ns ) && !empty( $value[$ns] ) ) {
3586 - $rights[] = $right;
3587 - }
3588 - } else {
3589 - # This is a boolean indicating that the permission applies
3590 - if ( $value ) {
3591 - $rights[] = $right;
3592 - }
3593 - }
3594 - }
3595 - return $rights;
3596 - }
3597 -
3598 - /**
35993558 * Get all the groups who have a given permission
36003559 *
36013560 * @param $role String Role to check
3602 - * @param $ns int
3603 - *
3604 - *
36053561 * @return Array of Strings List of internal group names with the given permission
36063562 */
3607 - public static function getGroupsWithPermission( $role, $ns = null ) {
 3563+ public static function getGroupsWithPermission( $role ) {
36083564 global $wgGroupPermissions;
36093565 $allowedGroups = array();
36103566 foreach ( $wgGroupPermissions as $group => $rights ) {
3611 - if ( in_array( $role, self::getGroupPermissions( array( $group ), $ns ), true ) ) {
 3567+ if ( isset( $rights[$role] ) && $rights[$role] ) {
36123568 $allowedGroups[] = $group;
36133569 }
36143570 }
Index: trunk/phase3/includes/Title.php
@@ -1559,33 +1559,34 @@
15601560 * @return Array list of errors
15611561 */
15621562 private function checkQuickPermissions( $action, $user, $errors, $doExpensiveQueries, $short ) {
1563 - $ns = $this->getNamespace();
1564 -
15651563 if ( $action == 'create' ) {
1566 - if ( ( $this->isTalkPage() && !$user->isAllowed( 'createtalk', $ns ) ) ||
1567 - ( !$this->isTalkPage() && !$user->isAllowed( 'createpage', $ns ) ) ) {
 1564+ if ( ( $this->isTalkPage() && !$user->isAllowed( 'createtalk' ) ) ||
 1565+ ( !$this->isTalkPage() && !$user->isAllowed( 'createpage' ) ) ) {
15681566 $errors[] = $user->isAnon() ? array( 'nocreatetext' ) : array( 'nocreate-loggedin' );
15691567 }
15701568 } elseif ( $action == 'move' ) {
1571 - if ( !$user->isAllowed( 'move-rootuserpages', $ns )
1572 - && $ns == NS_USER && !$this->isSubpage() ) {
 1569+ if ( !$user->isAllowed( 'move-rootuserpages' )
 1570+ && $this->mNamespace == NS_USER && !$this->isSubpage() ) {
15731571 // Show user page-specific message only if the user can move other pages
15741572 $errors[] = array( 'cant-move-user-page' );
15751573 }
15761574
15771575 // Check if user is allowed to move files if it's a file
1578 - if ( $ns == NS_FILE && !$user->isAllowed( 'movefile', $ns ) ) {
 1576+ if ( $this->mNamespace == NS_FILE && !$user->isAllowed( 'movefile' ) ) {
15791577 $errors[] = array( 'movenotallowedfile' );
15801578 }
15811579
1582 - if ( !$user->isAllowed( 'move', $ns) ) {
 1580+ if ( !$user->isAllowed( 'move' ) ) {
15831581 // User can't move anything
1584 -
1585 - $userCanMove = in_array( 'move', User::getGroupPermissions(
1586 - array( 'user' ), $ns ), true );
1587 - $autoconfirmedCanMove = in_array( 'move', User::getGroupPermissions(
1588 - array( 'autoconfirmed' ), $ns ), true );
1589 -
 1582+ global $wgGroupPermissions;
 1583+ $userCanMove = false;
 1584+ if ( isset( $wgGroupPermissions['user']['move'] ) ) {
 1585+ $userCanMove = $wgGroupPermissions['user']['move'];
 1586+ }
 1587+ $autoconfirmedCanMove = false;
 1588+ if ( isset( $wgGroupPermissions['autoconfirmed']['move'] ) ) {
 1589+ $autoconfirmedCanMove = $wgGroupPermissions['autoconfirmed']['move'];
 1590+ }
15901591 if ( $user->isAnon() && ( $userCanMove || $autoconfirmedCanMove ) ) {
15911592 // custom message if logged-in users without any special rights can move
15921593 $errors[] = array( 'movenologintext' );
@@ -1594,15 +1595,15 @@
15951596 }
15961597 }
15971598 } elseif ( $action == 'move-target' ) {
1598 - if ( !$user->isAllowed( 'move', $ns ) ) {
 1599+ if ( !$user->isAllowed( 'move' ) ) {
15991600 // User can't move anything
16001601 $errors[] = array( 'movenotallowed' );
1601 - } elseif ( !$user->isAllowed( 'move-rootuserpages', $ns )
1602 - && $ns == NS_USER && !$this->isSubpage() ) {
 1602+ } elseif ( !$user->isAllowed( 'move-rootuserpages' )
 1603+ && $this->mNamespace == NS_USER && !$this->isSubpage() ) {
16031604 // Show user page-specific message only if the user can move other pages
16041605 $errors[] = array( 'cant-move-to-user-page' );
16051606 }
1606 - } elseif ( !$user->isAllowed( $action, $ns ) ) {
 1607+ } elseif ( !$user->isAllowed( $action ) ) {
16071608 $errors[] = $this->missingPermissionError( $action, $short );
16081609 }
16091610
@@ -1740,10 +1741,10 @@
17411742 if ( $right == 'sysop' ) {
17421743 $right = 'protect';
17431744 }
1744 - if ( $right != '' && !$user->isAllowed( $right, $this->mNamespace ) ) {
 1745+ if ( $right != '' && !$user->isAllowed( $right ) ) {
17451746 // Users with 'editprotected' permission can edit protected pages
17461747 // without cascading option turned on.
1747 - if ( $action != 'edit' || !$user->isAllowed( 'editprotected', $this->mNamespace )
 1748+ if ( $action != 'edit' || !$user->isAllowed( 'editprotected' )
17481749 || $this->mCascadeRestriction )
17491750 {
17501751 $errors[] = array( 'protectedpagetext', $right );
@@ -1780,7 +1781,7 @@
17811782 if ( isset( $restrictions[$action] ) ) {
17821783 foreach ( $restrictions[$action] as $right ) {
17831784 $right = ( $right == 'sysop' ) ? 'protect' : $right;
1784 - if ( $right != '' && !$user->isAllowed( $right, $this->mNamespace ) ) {
 1785+ if ( $right != '' && !$user->isAllowed( $right ) ) {
17851786 $pages = '';
17861787 foreach ( $cascadingSources as $page )
17871788 $pages .= '* [[:' . $page->getPrefixedText() . "]]\n";
@@ -1817,8 +1818,8 @@
18181819 $title_protection['pt_create_perm'] = 'protect'; // B/C
18191820 }
18201821 if( $title_protection['pt_create_perm'] == '' ||
1821 - !$user->isAllowed( $title_protection['pt_create_perm'],
1822 - $this->mNamespace ) ) {
 1822+ !$user->isAllowed( $title_protection['pt_create_perm'] ) )
 1823+ {
18231824 $errors[] = array( 'titleprotected', User::whoIs( $title_protection['pt_user'] ), $title_protection['pt_reason'] );
18241825 }
18251826 }
@@ -1950,7 +1951,7 @@
19511952 }
19521953
19531954 # If the user is allowed to read pages, he is allowed to read all pages
1954 - if ( $user->isAllowed( 'read', $this->mNamespace ) ) {
 1955+ if ( $user->isAllowed( 'read' ) ) {
19551956 return $errors;
19561957 }
19571958
@@ -2017,7 +2018,7 @@
20182019 }
20192020
20202021 $groups = array_map( array( 'User', 'makeGroupLinkWiki' ),
2021 - User::getGroupsWithPermission( $action, $this->mNamespace ) );
 2022+ User::getGroupsWithPermission( $action ) );
20222023
20232024 if ( count( $groups ) ) {
20242025 global $wgLang;
Index: trunk/phase3/includes/DefaultSettings.php
@@ -3379,9 +3379,8 @@
33803380
33813381 /**
33823382 * Permission keys given to users in each group.
3383 - * This is an array where the keys are all groups and each value is either:
3384 - * a) An array of the format (right => boolean)
3385 - * b) An array of the format (right => namespace => boolean)
 3383+ * This is an array where the keys are all groups and each value is an
 3384+ * array of the format (right => boolean).
33863385 *
33873386 * The second format is used to support per-namespace permissions.
33883387 * Note that this feature does not fully work for all permission types.

Past revisions this follows-up on

RevisionCommit summaryAuthorDate
r92364First steps for bug 14801: add backend support for per-namespace permissions ...btongminh16:09, 16 July 2011
r92589Since r92364 UserTest.php needs a databaseplatonides21:41, 19 July 2011
r102187* Merged Title::userCanRead() check in Title::getUserPermissionsErrors()...ialex19:59, 6 November 2011
r102873Document $wgGroupPermissions better, including per-NS stuffaaron22:36, 12 November 2011
r104310Follow-up r92364: Update hooks documentationbtongminh21:31, 26 November 2011

Status & tagging log