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)

User in Group
I'm new in using a Wiki,perhaps it's a stupid question but:

How can I get an User into a group? I havn't found any information about that on the side of this extension. Perhaps someone can tell me, how I can do that!

Thx Lukas

See Help:Assigning_permissions. Basically, you just have to go to Special:Userrights on your wiki and there is an interface to change groups. --70.102.39.189 14:38, 24 July 2008 (UTC)

$wgCategoryExclusive is not working for me
Hi. I am running this extension with MW 1.12 and I cannot get $wgCategoryExclusive to work. I have some categories specified in this list: $wgCategoryExclusive=array("Category:EI Category","Category:ADP","Category:PREQ"); but all users can see articles in these categories. Even if you do not login you can still see these articles in these categories. I have followed the instructions carefully, but cannot see where I'm going wrong. I have tried specifically barring the user group with: $wgGroupPermissions['user']['Category:ADP_create'] = false; $wgGroupPermissions['user']['Category:ADP_edit'] = false; $wgGroupPermissions['user']['Category:ADP_move'] = false; $wgGroupPermissions['user']['Category:ADP_read'] = false; $wgGroupPermissions['user']['Category:EI_Category_create'] = false; $wgGroupPermissions['user']['Category:EI_Category_edit'] = false; $wgGroupPermissions['user']['Category:EI_Category_move'] = false; $wgGroupPermissions['user']['Category:EI_Category_read'] = false; $wgGroupPermissions['user']['Category:PREQ_create'] = false; $wgGroupPermissions['user']['Category:PREQ_edit'] = false; $wgGroupPermissions['user']['Category:PREQ_move'] = false; $wgGroupPermissions['user']['Category:PREQ_read'] = false; But users can still read (but not edit) articles in the categories.

Any help gratefully received. --Mitchelln 15:42, 28 July 2008 (UTC)

CategoryPermissions doesn't work on MW 1.12
I have installed the Extension on MW 1.12. I can't find an installation-error. If access is denied the extension returns: $result = false; return false; Otherwise: $result=null; return true; It seems to me that everything is correct. But $wgHooks['userCan'] ignores the returned argument.

Any suggestions where the problem is? -- FritzMueller 17:44, 10 August 2008


 * I've seen the same problem. I'm using identical configurations (and the same DB) on two MW installations, versions 1.10.0, and 1.12.0, respectively. On the v1.10.0 installation, CategoryPermissions works as expected. On v1.12.0, however, CategoryPermissions settings appears to have no effect whatsoever on the read action for anonymous users. (Edit permissions still work as expected.) If  is not set, everyone can read everything, regardless of settings by CategoryPermissions; and if   is set to , anonymous users can't read anything, even if allowed by  , e.g. Can someone please confirm this bug or alternatively post a sample configuration that allows to set category-based read permissions for anonymous users? Thanks, --ThorstenNY 21:58, 21 August 2008 (UTC)
 * I have since found that Extension:PermissionACL also offers category-based access permissions (in addition to permissions based on namespaces, pages, users, and groups); it also appears to work flawlessly in MW 1.12.0 and 1.13.0. --ThorstenNY 13:23, 23 August 2008 (UTC)

CategoryPermissions and MediaWiki 1.12
Hi all,

I'm not a php developer, so please bear with me on this ...

I have added a section to check for users in the "Always Allowed" group from some snippets I'v found here and found the same problems as the previous comment with it not checking the read permission for that group properly. Edit and Move seem to work fine. The de-bug output indicates that for the first permissions pass my username is not known (I doubt it makes any difference, but I'm also using the LDAPAuthentication extension).

The work around fix I've used below gives me the desred output, but I don't actually know if this is a bug in MediaWiki 1.12, or just part of the way the php normally works.

I found that somewhere between lines 79 and 83 (in my version) my username is suddenly recognised, and the only code in between those lines is: if( $user->isAllowed("{$category}_{$action}") ) So, I've added the line $user->isAllowed("{$category}_{$action}") near the top of the checkCategoryPermissions function, and now everything seems fine and dandy.

Here are my changes line 56 - global $wgGroupDefaultAllow, $wgGroupPermissions, $wgCategoryExclusive; + global $wgGroupAlwaysAllow, $wgGroupDefaultAllow, $wgGroupPermissions, $wgCategoryExclusive;

line 63 + $user->isAllowed("{$category}_{$action}");

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

here's my LocalSettings.php changes:

require_once("extensions/CategoryPermissions.php"); $wgCategoryExclusive=array("Category:ItOps");//deny access to these categories for anyone not in a group with permissions.

$wgGroupAlwaysAllow='CategoryAdmin'; //always allow admins to see everything $wgGroupDefaultAllow=true; //set to true to allow everyone access to pages without a category

$wgGroupPermissions['CategoryAdmin']['*_read']=true; //Create a admin group by assigning any permission.

$wgGroupPermissions['user']['*_read']=true; //Allow everyone access to read all categories by default $wgGroupPermissions['user']['*_edit']=true; //Allow everyone access to edit all categories by default

$wgGroupPermissions['itops']['Category:ItOps_read']=true; $wgGroupPermissions['itops']['Category:ItOps_edit']=true; $wgGroupPermissions['itops']['Category:ItOps_create']=true;
 * 1) Set individual category group permissions.

and here's my whole new CategoryPermissions.php 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 * * Licensed under GPL v2 - 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 for a group 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 in LocalSettings.php as well. define("__debug_permissions", 0); function checkCategoryPermissions( $title, $user, $action, $result ) { global $wgGroupAlwaysAllow, $wgGroupDefaultAllow, $wgGroupPermissions, $wgCategoryExclusive; $user_allowed=false; //get categories for this page $parentCategories=$title->getParentCategories;

$user->isAllowed("{$category}_{$action}");

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

Good luck, and thanks to the original author for a neat extension. Chris.

No Access anymore
After I installed the extension and configured some rights, evan the sysop doesn't have any rights any more. I can't create new pages and I'm not able to search after pages any more.

Could you please help me to solve this problem? I'm using MediaWiki 13.1

--Fightgnome 11:27, 3 December 2008 (UTC)

Extesion shows wrong error message
I've installed the extension with MW 1.13.

When i'm logged in and try to open a page, limited to a group I do not belong to, it show's me This action is limited to users, belonging to one of these groups: „*, Users“. But that's not correct. It should show me the name of the group it is really limited to.

Mediawiki 1.12 and newer
Per some above comments, the extension does not work with MW 1.12 and newer. A hack was added by midom to shortcut security checks which pretty well destroyed the consistency of the permissions model and made the userCan hook entirely useless. The change was reverted by minuteelectron with the comment '''Partially reverting r29721, this causes a massive flaw in the userCan hook -- breaking a variety of extensions that rely on it -- due to the circumvention of logic. Reccomend backport to 1.12 branch.''' User midom put it back in later without any justification.

The result is that you must have $wgGroupPermissions['*']['read']=false; in your LocalSettings.php in order for any userCan based extension to function. Unfortunately, the extension was designed to permit other userCan hooks or builtin checks to override.

Bottom line: to make everything function properly may require a major rework. --Sunergos 16:22, 5 December 2008 (UTC)