r84249 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r84248‎ | r84249 | r84250 >
Date:14:48, 18 March 2011
Author:happy-melon
Status:resolved (Comments)
Tags:
Comment:
Allow User::isAllowed() to take varargs. "is allowed X or Y" is by far the more common multiple permission check in core, so this is now the behaviour of isAllowed( X, Y ); also add isAllowedAll(...) for testing "is allowed X and Y". Has the nice side effect of adding visibility to a very old function.
Modified paths:
  • /trunk/phase3/includes/Article.php (modified) (history)
  • /trunk/phase3/includes/HistoryPage.php (modified) (history)
  • /trunk/phase3/includes/ImagePage.php (modified) (history)
  • /trunk/phase3/includes/ProtectionForm.php (modified) (history)
  • /trunk/phase3/includes/Title.php (modified) (history)
  • /trunk/phase3/includes/User.php (modified) (history)
  • /trunk/phase3/includes/api/ApiFileRevert.php (modified) (history)
  • /trunk/phase3/includes/specials/SpecialImport.php (modified) (history)

Diff [purge]

Index: trunk/phase3/includes/ProtectionForm.php
@@ -133,7 +133,7 @@
134134 // Prevent users from setting levels that they cannot later unset
135135 if( $val == 'sysop' ) {
136136 // Special case, rewrite sysop to either protect and editprotected
137 - if( !$wgUser->isAllowed('protect') && !$wgUser->isAllowed('editprotected') )
 137+ if( !$wgUser->isAllowed( 'protect', 'editprotected' ) )
138138 continue;
139139 } else {
140140 if( !$wgUser->isAllowed($val) )
@@ -527,7 +527,7 @@
528528 //don't let them choose levels above their own (aka so they can still unprotect and edit the page). but only when the form isn't disabled
529529 if( $key == 'sysop' ) {
530530 //special case, rewrite sysop to protect and editprotected
531 - if( !$wgUser->isAllowed('protect') && !$wgUser->isAllowed('editprotected') && !$this->disabled )
 531+ if( !$wgUser->isAllowed( 'protect', 'editprotected' ) && !$this->disabled )
532532 continue;
533533 } else {
534534 if( !$wgUser->isAllowed($key) && !$this->disabled )
Index: trunk/phase3/includes/User.php
@@ -2245,10 +2245,39 @@
22462246
22472247 /**
22482248 * Check if user is allowed to access a feature / make an action
2249 - * @param $action String action to be checked
2250 - * @return Boolean: True if action is allowed, else false
 2249+ * @param varargs String permissions to test
 2250+ * @return Boolean: True if user is allowed to perform *any* of the given actions
22512251 */
2252 - function isAllowed( $action = '' ) {
 2252+ public function isAllowed( /*...*/ ){
 2253+ $permissions = func_get_args();
 2254+ foreach( $permissions as $permission ){
 2255+ if( $this->isAllowedInternal( $permission ) ){
 2256+ return true;
 2257+ }
 2258+ }
 2259+ return false;
 2260+ }
 2261+
 2262+ /**
 2263+ * @param varargs String
 2264+ * @return bool True if the user is allowed to perform *all* of the given actions
 2265+ */
 2266+ public function isAllowedAll( /*...*/ ){
 2267+ $permissions = func_get_args();
 2268+ foreach( $permissions as $permission ){
 2269+ if( !$this->isAllowedInternal( $permission ) ){
 2270+ return false;
 2271+ }
 2272+ }
 2273+ return true;
 2274+ }
 2275+
 2276+ /**
 2277+ * Internal mechanics of testing a permission
 2278+ * @param $action String
 2279+ * @return bool
 2280+ */
 2281+ private function isAllowedInternal( $action = '' ) {
22532282 if ( $action === '' ) {
22542283 return true; // In the spirit of DWIM
22552284 }
@@ -2269,7 +2298,7 @@
22702299 */
22712300 public function useRCPatrol() {
22722301 global $wgUseRCPatrol;
2273 - return( $wgUseRCPatrol && ( $this->isAllowed( 'patrol' ) || $this->isAllowed( 'patrolmarks' ) ) );
 2302+ return $wgUseRCPatrol && $this->isAllowedAny( 'patrol', 'patrolmarks' );
22742303 }
22752304
22762305 /**
@@ -2278,7 +2307,7 @@
22792308 */
22802309 public function useNPPatrol() {
22812310 global $wgUseRCPatrol, $wgUseNPPatrol;
2282 - return( ( $wgUseRCPatrol || $wgUseNPPatrol ) && ( $this->isAllowed( 'patrol' ) || $this->isAllowed( 'patrolmarks' ) ) );
 2311+ return( ( $wgUseRCPatrol || $wgUseNPPatrol ) && ( $this->isAllowedAny( 'patrol', 'patrolmarks' ) ) );
22832312 }
22842313
22852314 /**
Index: trunk/phase3/includes/Article.php
@@ -3458,7 +3458,7 @@
34593459 $flags |= EDIT_MINOR;
34603460 }
34613461
3462 - if ( $bot && ( $wgUser->isAllowed( 'markbotedits' ) || $wgUser->isAllowed( 'bot' ) ) ) {
 3462+ if ( $bot && ( $wgUser->isAllowed( 'markbotedits', 'bot' ) ) ) {
34633463 $flags |= EDIT_FORCE_BOT;
34643464 }
34653465
Index: trunk/phase3/includes/ImagePage.php
@@ -930,7 +930,7 @@
931931 . $navLinks . "\n"
932932 . Xml::openElement( 'table', array( 'class' => 'wikitable filehistory' ) ) . "\n"
933933 . '<tr><td></td>'
934 - . ( $this->current->isLocal() && ( $wgUser->isAllowed( 'delete' ) || $wgUser->isAllowed( 'deletedhistory' ) ) ? '<td></td>' : '' )
 934+ . ( $this->current->isLocal() && ( $wgUser->isAllowed( 'delete', 'deletedhistory' ) ) ? '<td></td>' : '' )
935935 . '<th>' . wfMsgHtml( 'filehist-datetime' ) . '</th>'
936936 . ( $this->showThumb ? '<th>' . wfMsgHtml( 'filehist-thumb' ) . '</th>' : '' )
937937 . '<th>' . wfMsgHtml( 'filehist-dimensions' ) . '</th>'
@@ -961,7 +961,7 @@
962962 $row = $selected = '';
963963
964964 // Deletion link
965 - if ( $local && ( $wgUser->isAllowed( 'delete' ) || $wgUser->isAllowed( 'deletedhistory' ) ) ) {
 965+ if ( $local && ( $wgUser->isAllowed( 'delete', 'deletedhistory' ) ) ) {
966966 $row .= '<td>';
967967 # Link to remove from history
968968 if ( $wgUser->isAllowed( 'delete' ) ) {
Index: trunk/phase3/includes/HistoryPage.php
@@ -510,7 +510,7 @@
511511
512512 $del = '';
513513 // Show checkboxes for each revision
514 - if ( $wgUser->isAllowed( 'deleterevision' ) || $wgUser->isAllowed( 'revisionmove' ) ) {
 514+ if ( $wgUser->isAllowed( 'deleterevision', 'revisionmove' ) ) {
515515 $this->preventClickjacking();
516516 // If revision was hidden from sysops, disable the checkbox
517517 // However, if the user has revisionmove rights, we cannot disable the checkbox
Index: trunk/phase3/includes/api/ApiFileRevert.php
@@ -78,7 +78,7 @@
7979 * @param $user User The user to check.
8080 */
8181 protected function checkPermissions( $user ) {
82 - $permission = $user->isAllowed( 'edit' ) && $user->isAllowed( 'upload' );
 82+ $permission = $user->isAllowedAll( 'edit', 'upload' );
8383
8484 if ( $permission !== true ) {
8585 if ( !$user->isLoggedIn() ) {
Index: trunk/phase3/includes/Title.php
@@ -1999,7 +1999,7 @@
20002000 */
20012001 public function userCanEditCssSubpage() {
20022002 global $wgUser;
2003 - return ( ( $wgUser->isAllowed( 'editusercssjs' ) && $wgUser->isAllowed( 'editusercss' ) )
 2003+ return ( ( $wgUser->isAllowedAll( 'editusercssjs', 'editusercss' ) )
20042004 || preg_match( '/^' . preg_quote( $wgUser->getName(), '/' ) . '\//', $this->mTextform ) );
20052005 }
20062006
@@ -2012,7 +2012,7 @@
20132013 */
20142014 public function userCanEditJsSubpage() {
20152015 global $wgUser;
2016 - return ( ( $wgUser->isAllowed( 'editusercssjs' ) && $wgUser->isAllowed( 'edituserjs' ) )
 2016+ return ( ( $wgUser->isAllowedAll( 'editusercssjs', 'edituserjs' ) )
20172017 || preg_match( '/^' . preg_quote( $wgUser->getName(), '/' ) . '\//', $this->mTextform ) );
20182018 }
20192019
Index: trunk/phase3/includes/specials/SpecialImport.php
@@ -144,7 +144,7 @@
145145
146146 private function showForm() {
147147 global $wgUser, $wgOut, $wgImportSources, $wgExportMaxLinkDepth;
148 - if( !$wgUser->isAllowed( 'import' ) && !$wgUser->isAllowed( 'importupload' ) )
 148+ if( !$wgUser->isAllowed( 'import', 'importupload' ) )
149149 return $wgOut->permissionRequired( 'import' );
150150
151151 $action = $this->getTitle()->getLocalUrl( array( 'action' => 'submit' ) );

Follow-up revisions

RevisionCommit summaryAuthorDate
r84266Follow-up r84249: reimplement isAllowedAny(), and restore isAllowed() to only...happy-melon21:07, 18 March 2011

Comments

#Comment by Aaron Schulz (talk | contribs)   16:43, 18 March 2011

Hmm, I worry about people using these wrongly by mistake. Maybe isAllowed() should do AND and there should be an isAllowedAny() to do OR. That seems more intuitive. I'd recommend that isAllowed() just check one right as before and there could be an isAllowedAll() and isAllowedAny() for verbosity.

#Comment by Happy-melon (talk | contribs)   18:05, 18 March 2011

I did originally implement it as isAllowedAll() and isAllowedAny(), but in the process of implementing them I realised that any is overwhelmingly the dominant usecase. I didn't implement it in any extensions because it makes them B/C incompatible with earlier MW versions, but that trend continues there as well. It's a balance between ease of use and safety-of-use, I guess.

#Comment by Aaron Schulz (talk | contribs)   18:11, 18 March 2011

I'd rather the safety of isAllowed() doing AND at least, rather than OR. That looks like a pitfall in the waiting :)

#Comment by Aaron Schulz (talk | contribs)   18:17, 18 March 2011

Also, I don't think an extra function like this is that bad for safety in terms of something as important as permission checks.

#Comment by Duplicatebug (talk | contribs)   20:39, 18 March 2011

You are using isAllowedAny in two places...

Status & tagging log