Extension talk:CategoryPermissions

Please add comments or suggestions

Special pages (well.. namespaces)
Hey there. A category-bases permission system is just what I need, so I am trying to get this one working on my Mediawiki installation (now if only I could find out its version, but think it's 1.6'ish). I use the proposed default rule to deny for all categories in CustomPermission.php. Unfortunately, it doesn't allow anonymous users to access the "meta-namespace" (sorry for lacking the appropriate term here) even though $wgGroupDefaultAllow == true. The start page for example doesn't have a category (at least none that I can see) and neither has the login page, amongst others. So, I cannot even log on to alter my access level. Does this work as expected? --Carp 08:39, 20 April 2007 (UTC)
 * Got a running version - I changed quite a bit, so I'm posting a diff instead of editing the code on the main site. It had nothing to do with namespace, instead I found that a few variables and properties where never checked. I'm running it on a production site now. Seems to work smoothly. Thanks for your work! --Carp 13:03, 20 April 2007 (UTC)


 * Deleted buggy diff -> didn't work with more than category, see below --Carp 11:28, 22 April 2007 (UTC)

Thanks for posting your version. I have made several changes to the code that I am currently running and have not had time to update the page. I will look through your version and update the page sometime this week ... and I suppose i should create an account so I can watch the talk page.

Working version
Hey again. Forget the diff I submitted the other day. I found out that it didn't work on a page that was listed in more than one category, hence I rewrote the entire block that checks for parentCategories. Another LocalSettings.php variable can be set to set default allow / deny to categories that haven't been explicitly denied in the LocalSettings.php file. --- CustomPermissions.php.old	Sat Apr 21 17:39:56 2007 +++ CustomPermissions.php	Sat Apr 21 17:39:27 2007 @@ -11,73 +11,87 @@ * Usage: * * require_once('extensions/CategoryPermissions.php'); - * =''; //set a group name to ALWAYS allow access to this group - * =true; //set to true to allow everyone access to pages without a category + * $wgGroupAlwaysAllow=''; //set a group name to ALWAYS allow access to this group + * $wgGroupDefaultAllow=true; //set to true to allow everyone access to pages without a category + * $wgGroupDefaultAllowCategory=true; //set to true to allow everyone access to pages with a category that is not explicitly restricted * *  * //add groups to category permissions by: - * ['group_name']['Category:categoryname_read']=true; - * ['group_name']['Category:categoryname_edit']=true; - * ['group_name']['Category:categoryname_move']=true; - * ['group_name']['Category:categoryname_create']=true; + * $wgGroupPermissions['group_name']['Category:categoryname_read']=true; + * $wgGroupPermissions['group_name']['Category:categoryname_edit']=true; + * $wgGroupPermissions['group_name']['Category:categoryname_move']=true; + * $wgGroupPermissions['group_name']['Category:categoryname_create']=true; */ //set up hook -[] = "wfCategoryPermissions"; +$wgExtensionFunctions[] = "wfCategoryPermissions"; function wfCategoryPermissions { - global ; + global $wgHooks; // use the userCan hook to check permissions - [ 'userCan' ][] = 'checkCategoryPermissions'; + $wgHooks[ 'userCan' ][] = 'checkCategoryPermissions'; } -function checkCategoryPermissions { - global, , ; - +function checkCategoryPermissions( $title, $user, $action, $result ) { + global $wgGroupAlwaysAllow, $wgGroupDefaultAllow, $wgGroupPermissions, $wgGroupDefaultAllowCategory; //get categories for this page - =->getParentCategories; + $parentCategories=$title->getParentCategories; //always allow wgGroupAlwaysAllow group - if(in_array(,->mGroups)) + if(in_array($wgGroupAlwaysAllow,$user->mGroups)) { -   wfDebug("checkCategoryPermissions:{} allowed on {->mPrefixedText} to {->mName} : AlwaysAllow\n"); -    = true; +   wfDebug("checkCategoryPermissions:{$action} allowed on {$title->mPrefixedText} to {$user->mName} : AlwaysAllow\n"); +   $result = true; return null; }  //scan list of categories, if any - if{ -   foreach(  as =>){ - -      = ->isAllowed("{}_{}"); -     if{ -       wfDebug("checkCategoryPermissions:{}_{} allowed on {->mPrefixedText} to {->mName}\n"); -       if(->isAnon){ -         =true; -         return true; -       } -        else{ -         return null; -       } +  if(is_array($parentCategories)) { +   if ($user->isAnon or sizeof($user->mGroups) == 0) { +     $groups = array( '*' ); +   } +    else { +     $groups = $user->mGroups; +   } +    // Defaults to deny acces unless category is $wgGroupDefaultAllowCategory is true +   $allowed_in_category = isset($wgGroupDefaultAllowCategory) ? $wgGroupDefaultAllowCategory : false; +   // Search permissions for groups (or '*') and store result for each +   // group the user is in +    foreach ($groups as $group) { +     // Iterate through all of the article's categories +     foreach( $parentCategories as $category=>$dd){ +	if (isset($wgGroupPermissions["$group"]["{$category}_{$action}"])) { +         // if there's one false in the chain, access is not granted ... +	  // which is exactly what we want. +         $allowed_in_category = $allowed_in_category && $wgGroupPermissions["$group"]["{$category}_{$action}"]; +	}      }     } +    if ($allowed_in_category) { +     wfDebug("checkCategoryPermissions:{$category}_{$action} allowed on {$title->mPrefixedText} to {$user->mName}\n"); +   } +    else { +     wfDebug("checkCategoryPermissions:{$category}_{$action} DENIED on {$title->mPrefixedText} to {$user->mName}\n"); +   } +    $result = $allowed_in_category; +   return $result; } + // No categories found -> grant access based on $wgGroupDefaultAllow else { -   wfDebug("checkCategoryPermissions:{} DENIED on {->mPrefixedText} to {->mName} : No Categories\n"); -   =false; -   return false; +   wfDebug("checkCategoryPermissions:{$action} allowed on {$title->mPrefixedText} to {$user->mName} : No Categories\n"); +   $result= $wgGroupDefaultAllow; +   return $result; }  //default action=deny - wfDebug("checkCategoryPermissions:{} DENIED on {->mPrefixedText} to {->mName}\n"); - =false; - return false; + wfDebug("checkCategoryPermissions:{$action} DENIED on {$title->mPrefixedText} to {$user->mName}\n"); + $result=false; + return $result; } -

And here's is the entire new file: <?php /* * Custom Permissions Scheme using Categories * based on Extension:NamespacePermissions by Petr Andreev * * Provides separate permissions for each action (read,edit,create,move) based * on category tags on pages. * * Author: Matthew Vernon * * Usage: * * require_once('extensions/CategoryPermissions.php'); * $wgGroupAlwaysAllow=''; //set a group name to ALWAYS allow access to this group * $wgGroupDefaultAllow=true; //set to true to allow everyone access to pages without a category * $wgGroupDefaultAllowCategory=true; //set to true to allow everyone access to pages with a category that is not explicitly restricted * * * //add groups to category permissions by: * $wgGroupPermissions['group_name']['Category:categoryname_read']=true; * $wgGroupPermissions['group_name']['Category:categoryname_edit']=true; * $wgGroupPermissions['group_name']['Category:categoryname_move']=true; * $wgGroupPermissions['group_name']['Category:categoryname_create']=true; */

//set up hook $wgExtensionFunctions[] = "wfCategoryPermissions";

function wfCategoryPermissions { global $wgHooks;

// use the userCan hook to check permissions $wgHooks[ 'userCan' ][] = 'checkCategoryPermissions';

}

function checkCategoryPermissions( $title, $user, $action, $result ) { global $wgGroupAlwaysAllow, $wgGroupDefaultAllow, $wgGroupPermissions, $wgGroupDefaultAllowCategory;

//get categories for this page $parentCategories=$title->getParentCategories;

//always allow wgGroupAlwaysAllow group if(in_array($wgGroupAlwaysAllow,$user->mGroups)) {   wfDebug("checkCategoryPermissions:{$action} allowed on {$title->mPrefixedText} to {$user->mName} : AlwaysAllow\n"); $result = true; return null; }

//scan list of categories, if any if(is_array($parentCategories)) { if ($user->isAnon or sizeof($user->mGroups) == 0) { $groups = array( '*' ); }   else { $groups = $user->mGroups; }   // Defaults to deny acces unless category is $wgGroupDefaultAllowCategory is true $allowed_in_category = isset($wgGroupDefaultAllowCategory) ? $wgGroupDefaultAllowCategory : false; // Search permissions for groups (or '*') and store result for each // group the user is in   foreach ($groups as $group) { // Iterate through all of the article's categories foreach( $parentCategories as $category=>$dd){ if (isset($wgGroupPermissions["$group"]["{$category}_{$action}"])) { // if there's one false in the chain, access is not granted ... // which is exactly what we want. $allowed_in_category = $allowed_in_category && $wgGroupPermissions["$group"]["{$category}_{$action}"]; }     }    }    if ($allowed_in_category) { wfDebug("checkCategoryPermissions:{$category}_{$action} allowed on {$title->mPrefixedText} to {$user->mName}\n"); }   else { wfDebug("checkCategoryPermissions:{$category}_{$action} DENIED on {$title->mPrefixedText} to {$user->mName}\n"); }   $result = $allowed_in_category; return $result; } // No categories found -> grant access based on $wgGroupDefaultAllow else { wfDebug("checkCategoryPermissions:{$action} allowed on {$title->mPrefixedText} to {$user->mName} : No Categories\n"); $result= $wgGroupDefaultAllow; return $result; }

//default action=deny wfDebug("checkCategoryPermissions:{$action} DENIED on {$title->mPrefixedText} to {$user->mName}\n"); $result=false; return $result; }

Sorry for the long page now, but I can't upload arbitrary files here (which is probably a Good Thing).--Carp 11:43, 22 April 2007 (UTC)

Licensing
Maybe I only didn't see it ... but I think you didn't mention a licence for your original file. I hope I was allowed to modify and / or use it at all ;) . If your CustomPermissions isn't GPL'ed, I put my modified file under a BSD Licence - in which case I'd be happy if you could list me, Carsten Zimmermann somewhere should you decide to incorporate the code. But I am really not that concerned ;) Cheers, --Carp 11:47, 22 April 2007 (UTC)

This is my first foray into posting code, so I don't know all the semantics of licensing or documentation requirements yet. Everything I post is GPL ... I suppose I should add it to the file. As far as adding names, my philosophy is that if you contribute your name can be included. --Sunergos 18:48, 22 April 2007 (UTC)

Updated Code
I have updated the code to the current version that I am running. The main difference between my code and what is above is that I set categories that should deny access by default while the code above sets categories that should accept access by default. I have also added permissions of type *_read etc to allow a user that permission on all categories. This is evaluated after the categories are scanned. Thank you Carp for your contribution, as my previous code would only deny access to an exclusive category if it ocurred before another category granted access.

--Sunergos 17:18, 23 April 2007 (UTC)