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)

Need help on CategoryPermissions
Hi,

I'm trying to use the extension but somehow can't get it to work as I expected it. I have pages that have different categories, and one page can be in multiple categories. I also have groups that have the same name as the category. I wanted to set up permissions such that a group has read access to pages only in his category and no one else's.

The extension works for pages that have only 1 category, but for pages with multiple categories, it doesn't work. None of the groups can access the page.

Is there something wrong I'm doing or is this a limitation?

Example - (my groups are MBG, WDG and IDG. IDG has access to all categories, while MBG only has access to the MBG category, WDG only has access to the WDG category):

$wgGroupDefaultAllow=true; $wgCategoryExclusive=array("Category:MBG","Category:WDG");

$wgGroupPermissions['IDG']['Category:MBG_read']=true; $wgGroupPermissions['IDG']['Category:MBG_edit']=true; $wgGroupPermissions['IDG']['Category:MBG_move']=true; $wgGroupPermissions['IDG']['Category:MBG_create']=true; $wgGroupPermissions['IDG']['Category:WDG_read']=true; $wgGroupPermissions['IDG']['Category:WDG_edit']=true; $wgGroupPermissions['IDG']['Category:WDG_move']=true; $wgGroupPermissions['IDG']['Category:WDG_create']=true;

$wgGroupPermissions['MBG']['Category:MBG_read']=true; $wgGroupPermissions['WDG']['Category:WDG_read']=true;


 * The problem is $wgCategoryExclusive. Each category that you have in the array will block anyone who is not part of the group. In this case, the user would have to be in both groups so IDG should have access. For your use, leave $wgCategoryExclusive empty. --Sunergos 00:52, 25 July 2007 (UTC)

Can't get it to work on MediaWiki 1.7 on Ubuntu
I have defined 3 groups and 3 categories. The groups and categories have the same name. (NOC,NTC,BTS) The desired result is that each group will only be able to access the content of their own category. I am using the instance of CategoryPermissions.php posted by Carp above. I used the advice provided by Sunergos in leaving the CategoryExclusive array blank. Unfortunately, any page with a Category assigned is inaccessible by users that have appropriate group assignments and I can't figure out why. My LocalSettings.php is configured as follows:

require_once('extensions/CategoryPermissions.php'); $wgGroupDefaultAllow=true; $wgCategoryExclusive=array("");

$wgGroupPermissions['NOC']['Category:NOC_read']=true; $wgGroupPermissions['NOC']['Category:NOC_edit']=true; $wgGroupPermissions['NOC']['Category:NOC_move']=true; $wgGroupPermissions['NOC']['Category:NOC_create']=true;

$wgGroupPermissions['NTC']['Category:NTC_read']=true; $wgGroupPermissions['NTC']['Category:NTC_edit']=true; $wgGroupPermissions['NTC']['Category:NTC_move']=true; $wgGroupPermissions['NTC']['Category:NTC_create']=true;

$wgGroupPermissions['BTS']['Category:BTS_read']=true; $wgGroupPermissions['BTS']['Category:BTS_edit']=true; $wgGroupPermissions['BTS']['Category:BTS_move']=true; $wgGroupPermissions['BTS']['Category:BTS_create']=true;

Any help would be greatly appreciated.

At a glance nothing stands out as wrong. One common problem is that users are denied by the normal MW permissions. The first thing to try is comment out the require_once line and see if users have access with the extension disabled. The CategoryPermissions does not explicitly allow access - the normal permissions scheme still applies.

If users have access with the extension disabled, then enable it again and change the line define("__debug_permissions",0); to define("__debug_permissions",true);. This will print a message to the MW log file (if Manual:$wgDebugLogFile is set to a file name) for every allow or deny event. --Sunergos 00:53, 21 July 2008 (UTC)

Patches for better debugging and some minor fixes
RichiH 16:04, 18 September 2007 (UTC)

Diff
--- CategoryPermissions_orig.php       2007-09-18 17:53:08.919059061 +0200 +++ CategoryPermissions.php    2007-09-18 17:46:06.800678311 +0200 @@ -7,7 +7,7 @@ * on category tags on pages. * * Author: Matthew Vernon - * Additional Contributions by Carsten Zimmermann + * Additional Contributions by Carsten Zimmermann and Richard Hartmann en:User:RichiH * * Licensed under GPL - use,change,enjoy * @@ -24,7 +24,7 @@ * $wgGroupPermissions['group_name']['Category:categoryname_edit']=true; * $wgGroupPermissions['group_name']['Category:categoryname_move']=true; * $wgGroupPermissions['group_name']['Category:categoryname_create']=true; * - * //allow access to all groups like this + * //allow access to all categories like this * $wgGroupPermissions['group_name']['*_read']=true; */

@@ -45,8 +45,9 @@ $wgExtensionCredits['parserhook'][] = array( 'name'=>'CategoryPermissions', 'author'=>'Matthew Vernon', 'url'=>'http://www.mediawiki.org/wiki/Extension:CategoryPermissions');

-//turn on debug messages by changing to 1 or true ... is there a better way to do this? -define("__debug_permissions",0); +//turn on debug messages by changing to 1 or true +// Remember to set $wgDebugLogFile as well. +define("__debug_permissions", 0);

function checkCategoryPermissions( $title, $user, $action, $result ) { @@ -60,19 +61,19 @@  //scan list of categories, if any if(is_array($parentCategories)) { -    foreach( $parentCategories as $category=>$dd) { +     if(__debug_permissions)wfDebug("checkCategoryPermissions on line ".__LINE__.": Trying action {$action} on category {$category} for user {$user->mName}\n"); if( $user->isAllowed("{$category}_{$action}") ) { -       if(__debug_permissions)wfDebug("checkCategoryPermissions:{$category}_{$action} allowed on {$title->mPrefixedText} to {$user->mName}\n"); +       if(__debug_permissions)wfDebug("checkCategoryPermissions on line ".__LINE__.": Category-action {$category}_{$action} ALLOWED on {$title->mPrefixedText} to user {$user->mName}\n"); $user_allowed=true; }      else {        if(in_array($category,$wgCategoryExclusive)) { //if category is in $wgCategoryExclusive then deny anyone who doesn't have explicit access -         if(__debug_permissions)wfDebug("checkCategoryPermissions:{$category}_{$action} DENIED on {$title->mPrefixedText} to {$user->mName} : Exlcusive Category\n"); +         if(__debug_permissions)wfDebug("checkCategoryPermissions on line ".__LINE__.": Category-action {$category}_{$action} DENIED on {$title->mPrefixedText} to user {$user->mName}: Exclusive Category\n"); $result=false; return false; } @@ -86,32 +87,34 @@

//always allow groups with *_read etc. regardless of categories + if(__debug_permissions)wfDebug("checkCategoryPermissions on line ".__LINE__.": Trying action {$action} on * (all categories for user {$user->mName}\n");   if( $user->isAllowed("*_{$action}") )   { -    if(__debug_permissions)wfDebug("checkCategoryPermissions:{$action} allowed on {$title->mPrefixedText} to {$user->mName} : AlwaysAllow\n"); +    if(__debug_permissions)wfDebug("checkCategoryPermissions on line ".__LINE__.": Action {$action} ALLOWED on {$title->mPrefixedText} to user {$user->mName}: AlwaysAllow\n");     return null;   }

+ if(__debug_permissions)wfDebug("checkCategoryPermissions on line ".__LINE__.": Trying action {$action} on {$title->mPrefixedText} for user {$user->mName}: No categories\n"); if(!($parentCategories)) {    //handle special case of no categories //default action is based on wgGroupDefaultAllow if($wgGroupDefaultAllow) { -     if(__debug_permissions)wfDebug("checkCategoryPermissions:{$action} allowed on {$title->mPrefixedText} to {$user->mName} : No Categories\n"); +     if(__debug_permissions)wfDebug("checkCategoryPermissions on line ".__LINE__.": Action {$action} ALLOWED on {$title->mPrefixedText} to user {$user->mName}: No categories\n"); return null; }    else { -     if(__debug_permissions)wfDebug("checkCategoryPermissions:{$action} DENIED on {$title->mPrefixedText} to {$user->mName} : No Categories\n"); +     if(__debug_permissions)wfDebug("checkCategoryPermissions on line ".__LINE__.": Action {$action} DENIED on {$title->mPrefixedText} to user {$user->mName}: No categories\n"); $result=false; return false; }  }

//default action=deny - if(__debug_permissions)wfDebug("checkCategoryPermissions:{$action} DENIED on {$title->mPrefixedText} to {$user->mName}\n"); + if(__debug_permissions)wfDebug("checkCategoryPermissions on line ".__LINE__.": Action {$action} DENIED on {$title->mPrefixedText} to user {$user->mName}: Default action\n"); $result=false; return false; }

Full 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 * Additional Contributions by Carsten Zimmermann and Richard Hartmann en:User:RichiH * * Licensed under GPL - use,change,enjoy * * Usage: * * require_once('extensions/CategoryPermissions.php'); * $wgCategoryExclusive=array("Category:cat_name","Category:cat2_name");//deny acces to these categories for anyone not in the group * $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 * * * //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; * * //allow access to all categories like this * $wgGroupPermissions['group_name']['*_read']=true; */

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

function wfCategoryPermissions { global $wgHooks;

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

//register extension $wgExtensionCredits['parserhook'][] = array( 'name'=>'CategoryPermissions', 'author'=>'Matthew Vernon', 'url'=>'http://www.mediawiki.org/wiki/Extension:CategoryPermissions');

//turn on debug messages by changing to 1 or true // Remember to set $wgDebugLogFile as well. define("__debug_permissions", 0);

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

$user_allowed=false;

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

//scan list of categories, if any if(is_array($parentCategories)) {   foreach( $parentCategories as $category=>$dd) {     if(__debug_permissions)wfDebug("checkCategoryPermissions on line ".__LINE__.": Trying action {$action} on category {$category} for user {$user->mName}\n"); if( $user->isAllowed("{$category}_{$action}") ) {       if(__debug_permissions)wfDebug("checkCategoryPermissions on line ".__LINE__.": Category-action {$category}_{$action} ALLOWED on {$title->mPrefixedText} to user {$user->mName}\n"); $user_allowed=true; }     else {       if(in_array($category,$wgCategoryExclusive)) { //if category is in $wgCategoryExclusive then deny anyone who doesn't have explicit access if(__debug_permissions)wfDebug("checkCategoryPermissions on line ".__LINE__.": Category-action {$category}_{$action} DENIED on {$title->mPrefixedText} to user {$user->mName}: Exclusive Category\n"); $result=false; return false; }     }    }//foreach( $parentCategories as $category=>$dd) }//if($parentCategories)

//if we are here, then no exclusive categories have rejected us if($user_allowed==true) {   return null;  }

//always allow groups with *_read etc. regardless of categories if(__debug_permissions)wfDebug("checkCategoryPermissions on line ".__LINE__.": Trying action {$action} on * (all categories for user {$user->mName}\n"); if( $user->isAllowed("*_{$action}") )  {    if(__debug_permissions)wfDebug("checkCategoryPermissions on line ".__LINE__.": Action {$action} ALLOWED on {$title->mPrefixedText} to user {$user->mName}: AlwaysAllow\n");    return null;  }

if(__debug_permissions)wfDebug("checkCategoryPermissions on line ".__LINE__.": Trying action {$action} on {$title->mPrefixedText} for user {$user->mName}: No categories\n"); if(!($parentCategories)) {   //handle special case of no categories //default action is based on wgGroupDefaultAllow if($wgGroupDefaultAllow) {     if(__debug_permissions)wfDebug("checkCategoryPermissions on line ".__LINE__.": Action {$action} ALLOWED on {$title->mPrefixedText} to user {$user->mName}: No categories\n"); return null; }   else {     if(__debug_permissions)wfDebug("checkCategoryPermissions on line ".__LINE__.": Action {$action} DENIED on {$title->mPrefixedText} to user {$user->mName}: No categories\n"); $result=false; return false; } }

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

?>

Version question
You say GPL, but I doubt you want GPLv1. Do you mean GPLv2[.1] [or later] or GPLv3 [or later]? -- RichiH 16:03, 18 September 2007 (UTC)

The current one at the time was v2 (v3 was still in draft). I am not aware of a GPL v2.1 (only the LGPL which is different). I will update the main page with the clarification. --Sunergos 00:14, 21 July 2008 (UTC)

Extension Bug (1.11)
In trying to set up this extension, I received this error in MediaWiki 1.11: how can I rectify this? When this extension works for me, it will be enormously helpful, thank you!

Error: "Detected bug in an extension! Hook checkCategoryPermissions failed to return a value; should return true to continue hook processing or false to abort." --jaemarr

Code ok for MW 1.11.0
I had problems with CategoryPermissions code. I was trying to use the code published on article page. First problem was the “return null;” instruction. I changed it for “result=null; return true;”. Second problem was the “$category”. The value of this variable starts with “Category:” just if the language is English, but I’m using Portuguese and the variable starts with “Categoria:”. To fix it, I removed everything before the “:”. So, I removed the string “Category:” from arrays on LocalSetings.php for a correct comparison. I'm using the last version 1.11.0 of MW and this code is ok. The final code is: <?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 * Additional Contributions by Carsten Zimmermann * * Licensed under GPL - use,change,enjoy * * Usage: * * require_once('extensions/CategoryPermissions.php'); * $wgCategoryExclusive=array("Cat_name","Cat2_name");//deny acces to these categories for anyone not in the group * $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 * * * //add groups to category permissions by: * $wgGroupPermissions['group_name']['Categoryname_read']=true; * $wgGroupPermissions['group_name']['Categoryname_edit']=true; * $wgGroupPermissions['group_name']['Categoryname_move']=true; * $wgGroupPermissions['group_name']['Categoryname_create']=true; * * //allow access to all categories like this * $wgGroupPermissions['group_name']['*_read']=true; */

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

function wfCategoryPermissions { global $wgHooks;

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

//register extension $wgExtensionCredits['parserhook'][] = array( 'name'=>'CategoryPermissions', 'author'=>'Matthew Vernon', 'url'=>'http://www.mediawiki.org/wiki/Extension:CategoryPermissions');

//turn on debug messages by changing to 1 or true ... is there a better way to do this? define("__debug_permissions",1);

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

$user_allowed=false;

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

//scan list of categories, if any if(is_array($parentCategories)) {

foreach( $parentCategories as $category=>$dd) {		if(strpos($category,":")) $category = substr($category,strpos($category,":")+1); if( $user->isAllowed("{$category}_{$action}") ) {       if(__debug_permissions)wfDebug("checkCategoryPermissions:{$category}_{$action} allowed on {$title->mPrefixedText} to {$user->mName}\n"); $result = null; return true; }     else {		if( $user->isAllowed("*_{$action}") )//always allow groups with *_read etc. regardless of categories {			if(__debug_permissions)wfDebug("checkCategoryPermissions:{$action} allowed on {$title->mPrefixedText} to {$user->mName} : AlwaysAllow\n"); $result = null; return true; }       		elseif(in_array($category,$wgCategoryExclusive))//if category is in $wgCategoryExclusive then deny anyone who doesn't have explicit access {			if(__debug_permissions)wfDebug("checkCategoryPermissions:{$category}_{$action} DENIED on {$title->mPrefixedText} to {$user->mName} : Exlcusive Category\n"); $result=false; return false; }     }    }//foreach( $parentCategories as $category=>$dd) }//if($parentCategories) elseif(!($parentCategories)) {	//handle special case of no categories //default action is based on wgGroupDefaultAllow if($wgGroupDefaultAllow) {		if(__debug_permissions)wfDebug("checkCategoryPermissions:{$action} allowed on {$title->mPrefixedText} to {$user->mName} : No Categories\n"); $result = null; return true; }	else {		if(__debug_permissions)wfDebug("checkCategoryPermissions:{$action} DENIED on {$title->mPrefixedText} to {$user->mName} : No Categories\n"); $result=false; return false; } }  else {	if(__debug_permissions)wfDebug("checkCategoryPermissions:{$action} allowed on {$title->mPrefixedText} to {$user->mName} : No Categories\n"); $result=null; return true; } // default if(__debug_permissions)wfDebug("checkCategoryPermissions:{$action} allowed on {$title->mPrefixedText} to {$user->mName} : No Categories\n"); $result=null; return true; }

?>

Note: I also had the bug of null values for Mediawiki 1.11.0. Replacing null by true makes the original script working fine. I haven't the case of the Category language. --195.115.78.114 14:14, 25 October 2007 (UTC)

While this fix works, it would be better to change the lines in LocalSettings.php from using 'Category:categoryname_read' to something like "$namespaceNames[NS_CATEGORY]:categoryname_read" or just use 'Categoria:categoryname_read'. The former needs to be tested, but would make it work for any language without having to do additional text processing with every page access. --Sunergos 01:41, 21 July 2008 (UTC)

Problem with MW 1.10
Hi, I´m using this easy configuration, but when I enter with a user in PMO group the access is rejected.

$wgGroupDefaultAllow=true; //set to true to allow everyone access to pages without a category $wgCategoryExclusive=array("Category:PMO");//deny access to these categories for anyone not in the group $wgGroupPermissions['PMO']['Category:PMO_read']=true; $wgGroupPermissions['PMO']['Category:PMO_edit']=true; $wgGroupPermissions['PMO']['Category:PMO_create']=true;
 * 1) Cateogory permissions
 * 1) $wgGroupPermissions['PMO']['*_read']=true; //allow access to all categories

Also I detect that if this line is uncommented I can see the page, the problem is with specific categories. $wgGroupPermissions['PMO']['*_read']=true; //allow access to all categories

I think that this change in the category (because of language) must be implemented. foreach( $parentCategories as $category=>$dd) {     $real_category = substr($category,strpos($category,":")+1); $category = "Category:{$real_category}"; //$b = $user->isAllowed("{$category}_{$action}"); if( $user->isAllowed("{$category}_{$action}") )

Also I realize that this line is another fail, I don't know exactly if I misunderstand the usage or the algorithm was wrong. $wgCategoryExclusive=array("Category:PMO");//deny access to these categories for anyone not in the group I recomend that this functionality needs to be more explained in detail.

Please see my comment to the section above. The problem here is that isAllowed is using the language specific word for Category while the lines added in LocalSettings.php are using the literal Category. Simply change the lines in LocalSettings.php to reflect the language specific word for Category and it should all work fine.

As for wgCategoryExclusive, I will add more explanation. If a category is in that list, a user must have rights to that category to access/edit a page marked with that category. The key difference is if a page has multiple categories. For instance, if a page has categories 'A', 'B', and 'C'. Normally, a user that is in any of these three groups can access the page. If 'B' is added to CategoryExclusive, then users with rights to 'A' or 'C' will be denied if they do not have rights to 'B'. If all three are in wgCategoryExclusive, then a user must have rights to all three groups in order to access the page.

--Sunergos 01:54, 21 July 2008 (UTC)

Bugging
I am getting the following bug when I try to use this extention:

Detected bug in an extension! Hook checkCategoryPermissions failed to return a value; should return true to continue hook processing or false to abort.

Backtrace:


 * 1) 0 /wiki/includes/Title.php(1264): wfRunHooks('userCan', Array)
 * 2) 1 /wiki/includes/Wiki.php(133): Title->userCanRead
 * 3) 2 /wiki/includes/Wiki.php(43): MediaWiki->preliminaryChecks(Object(Title), Object(StubObject), Object(WebRequest))
 * 4) 3 /wiki/index.php(89): MediaWiki->initialize(Object(Title), Object(StubObject), Object(User), Object(WebRequest))
 * 5) 4 {main}

Create
Hi, Thank you for your very handy extension.

I have a problem. How can you prevent someone to create a page in a category he's not allowed ?

Example : A has not the right to create a page or to edit the content of category C1 (but he can read its content). A has the right to edit pages without categories. A create a link to a non-existing article and click on the link, he puts into the textarea :. And the page is created. (but a message is displayed to say him thaht he can't read the page)

Is it normal ? What does your create right refers to ? Regards, --Teriblus 14:22, 17 April 2008 (UTC)

This is an expected side effect. In order for any user to create a page, they must have rights for a page without any category. The only way to get around this would be to set categories at save time automatically. On the site I created this extension for, most of the editors have rights to all pages while viewers have rights to only a subset. I have simply told people that if they lock themselves out of a page they should contact an admin. Sorry this isn't much help. --Sunergos 23:54, 20 July 2008 (UTC)

Return null bug fix
Let me say first that I am very sorry for not responding sooner. I assumed that there were no changes or comments. It turns out that even though I have this page I my watchlist I haven't been getting emails.

For anyone having trouble with return null errors:

"Detected bug in an extension! Hook checkCategoryPermissions failed to return a value; should return true to continue hook processing or false to abort."

The newest version has all return null; statements replaced with $result=null; return true;. Please copy the newest version.

--Sunergos 01:12, 21 July 2008 (UTC)