Extension:CategoryPermissions

From MediaWiki.org
Jump to: navigation, search
MediaWiki extensions manual
Crystal Clear action run.png
CategoryPermissions

Release status: beta

Implementation User rights
Description Provides user permission restrictions based on page categories
Author(s) Matthew Vernon
Latest version 0.4 (2008-07-20)
MediaWiki 1.7.1 through 1.11
Database changes No
License GPL v2
Download See here
Parameters
  • $wgGroupDefaultAllow
  • $wgCategoryExclusive
  • $wgGroupAlwaysAllow
Hooks used
userCan

Translate the CategoryPermissions extension if it is available at translatewiki.net

Check usage and version matrix; code metrics

What can this extension do?[edit | edit source]

Extends permissions checking by allowing group access to pages that have specific categories. This extension utilizes the usercan hook, however standard permissions checks are still performed.

Use this extension at your own risk. Any security scheme based on userCan will not prevent page content from being displayed in search results for versions before MW 1.10 - later versions of MediaWiki won't display page excerpts in search results, but will still display page titles[1], and protected content can be included in unprotected pages, allowing unauthorized users to access it (both of these issues can be resolved by using Extension:RemoveProtectedContent in conjunction with this extension).

How secure is this extension?[edit | edit source]

Security issues with authorization extensions
Inclusion/transclusion safe - If Extension:RemoveProtectedContent is used as well
Preloading safe (with MediaWiki 1.12+)
XML export (Special:Export) safe (with MediaWiki 1.10+)
Atom/RSS feeds safe (with MediaWiki 1.12+)
Listings & search safe - If Extension:RemoveProtectedContent is used as well
Diff & revision links safe
API  ?
Action links safe
Related rights  ?
Author backdoor safe
Caching  ?
Files & Images  ?
Redirects safe
Edit Section safe
Watching Pages unsafe
Other extensions  ?
Known bugs
  • Affects categories with a similar name; protecting "Category:Apples" will also protect "Category:Apples by country", but will not extend the user whitelists to those categories (making them unviewable by everyone unless permissions are explicitly granted for every similarly-named category).
  • Users can't login without wgGroupDefaultAllow=true - i.e. fails unsafe allowing users to access all pages which aren't in a protected category

Changes[edit | edit source]

  • 0.4 - Integrated fix for return null bug in version 1.10 and up. Modified debug lines per Richard Hartmann.
  • 0.31 - Changed line 49 per anonymous note
  • 0.3 - No longer bypasses standard permissions except when denying access. Previous version was working around a problem that was outside the extension in my server configuration.

Usage[edit | edit source]

See Installation

Installation[edit | edit source]

  • Copy the code shown in the Code section below to extensions/CategoryPermissions.php
  • Make changes to LocalSettings.php as shown below

Changes to LocalSettings.php[edit | edit source]

require_once("$IP/extensions/CategoryPermissions.php");
$wgGroupDefaultAllow=true; //set to true to allow everyone access to pages without a category
$wgCategoryExclusive=array("Category:cat_name","Category:cat2_name");//deny access to these categories for anyone not in the group
$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;
$wgGroupPermissions['group_name']['*_read']=true; //allow access to all categories

If you are using a language other than English, replace Category in each of the text strings (NOT the variable names) with the language specific word for Category.

The permissions are checked as follows:

  1. Each category in the list is checked for permissions
    1. If a category is in the array $wgCategoryExclusive and the user does not have permissions, access is immediately rejected. Users must have permissions for all categories on the page specified in $wgCategoryExclusive in order to have access granted.
    2. If the user has permissions for any category and has not been rejected by an exclusive category, they are granted access
  2. If global access (*_read, etc) is set for this user, then access is granted
  3. If the page has no categories, $wgGroupDefaultAllow is is used to grant or deny access
  4. Access is denied ... but we should never get to this step

Code[edit | edit source]

<?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;
 */
 
// prevent this as entry point
if ( !defined( 'MEDIAWIKI' ) ) {
        die( 'This file is a MediaWiki extension and not a valid entry point' );
}
 
// register extension
$wgExtensionCredits['parserhook'][] = array(
	'path' => __FILE__,
	'name' => 'CategoryPermissions',
	'version' => '0.4',
	'author' => array( 'Matthew Vernon' ),
	'url' => 'https://www.mediawiki.org/wiki/Extension:CategoryPermissions',
	'description' => 'Provides user permission restrictions based on page categories',
);
 
//set up hook
$wgExtensionFunctions[] = "wfCategoryPermissions";
 
function wfCategoryPermissions()
{
  global $wgHooks;
 
  // use the userCan hook to check permissions
  $wgHooks[ 'userCan' ][] = 'checkCategoryPermissions';
}
 
//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 $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)
  {    $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;
}

Notes[edit | edit source]

  1. According to Security issues with authorization extensions this has been addressed in MW 1.10, rev:21821: The search page no longer shows excerpts from pages that are not readable (but it still lists the titles)