Extension:DisallowAccessOnCategory

Introduction
This Extension was created out of a desire to make it possible to restrict access to a set of pages quickly. For now, in its initial version, the extension itself is only 25 lines long, but I plan on adding a little more functionality later.

Warning: This extension was specifically developed for our internal wiki. Some of the features came more as a side-effect and are not very well tested (read: not at all). The basic functionality works though. Please feel free to post suggestions and bugreports to the DiscussionPage.

Features
When properly configured any page that belongs to the category "Protected" is only viewable by users that belong to a certain group. It is thus very easy for everyone (even users not in that group!) to restrict access quickly and easily.

Note that a user cannot gain additional privileges with this extension. If, for example, an anonymous user has no read-access in the first place, he won't be able to gain it either.

Please read about security issues with authorization extensions. It may be a good Idea to have an extra page for checking security, so this is done here.

Configuration
First you have to download DisallowAccessOnCategory.php.tar.gz, unpack it into the extensions directory of your MediaWiki-Installation and require-once it in your LocalSettings.php, like this: require_once ("$IP/extensions/DisallowAccessOnCategory.php"); To allow access to a group you have to set the "protected" value of that group to true. In our wiki we define a special group called "protected_group" where only certain users are added to as needed. This is equivalent to a whitelist-based approach on page-access: $wgGroupPermissions['protected_group']['read'] = true; $wgGroupPermissions['protected_group']['edit'] = true; $wgGroupPermissions['protected_group']['createpage'] = true; $wgGroupPermissions['protected_group']['createtalk'] = true; $wgGroupPermissions['protected_group']['minoredit'] = true; $wgGroupPermissions['protected_group']['protected'] = true; This way it is of course easy to, for example, only restrict write-access to these users and still allow everyone to read it.
 * 1) define rights of "protected_group"
 * 1) allow protected_group to use the pages of the "Protected" Category

Of course it would also be easy to allow access only to registered users: $wgGroupPermissions['user']['protected'] = true;

or

$wgGroupPermissions['*']['your category'] = false;    /* <-- prevents anonymous users from seeing the pages */ $wgGroupPermissions['user']['your category'] = false; /* <-- prevents logged in users from seeing the pages */

RecentChanges patch
Not really part of this extension, but noteworthy none the less. We didn't want the pages to appear in RecentChanges, also the RSS Feed still displayed changes to restricted pages to everyone. We solved this problem by patching SpecialRecentchanges.php with this patch. This is only tested with MediaWiki 1.9.0, but should be easy to apply to other versions of MediaWiki as well. Here is the code of the patch: --- SpecialRecentchanges.php.old       2007-02-20 17:00:24.000000000 +0100 +++ SpecialRecentchanges.php   2007-02-22 14:58:02.000000000 +0100 @@ -171,7 +171,23 @@        $rows = array; $batch = new LinkBatch; while( $row = $dbr->fetchObject( $res ) ){ -              $rows[] = $row; +              $nt = Title::newFromText ( $row->rc_title, $row->rc_namespace ) ; +              $id = $nt->getArticleID ; + +              /* Patch for the DissallowAccessOnCategory Extension: +               * The following snippet excludes Articles from RecentChanges +               * if the user is not allowed to view its contents +               */ +               global $wgContLang; +              $categories = $nt->getParentCategories; +              $categoryNSText = $wgContLang->getNSText ( NS_CATEGORY ); +              if ( gettype($categories) == "array" && array_key_exists("$categoryNSText:Protected", $categories) ) { +                      global $wgUser; +                      if ( ! ( $wgUser->isAllowed("$action") && $wgUser->isAllowed('protected') ) ) +                              continue; +              } + +               $rows[] = $row; if ( !$feedFormat ) { // User page link $title = Title::makeTitleSafe( NS_USER, $row->rc_user_text ); @@ -286,6 +302,17 @@        foreach ( $rows AS $k => $r ) { $nt = Title::newFromText ( $r->rc_title, $r->rc_namespace ) ; $id = $nt->getArticleID ; + +              /* patch for the DisallowAccessOnCategory extension: +               * same as above, but this function is only called if  +                * $wgAllowCategorizedRecentChanges is set to true +               */ +               global $wgContLang; +              $categories = $nt->getParentCategories; +              $categoryNSText = $wgContLang->getNSText ( NS_CATEGORY ); +              if ( gettype($categories) == "array" && array_key_exists("$categoryNSText:Protected", $categories) ) +                      continue; +                if ( $id == 0 ) continue ; # Page might have been deleted... if ( !in_array ( $id, $articles ) ) { $articles[] = $id ; I'm not entirely sure if this is the best possible approach but it works. Unfortunately RecentChanges Page doesn't provide any hooks yet.

TODO
There are some thing to to for the next version::


 * Restrict search/RSS results for protected pages (without patch if possible)
 * the use of multiple accesscontrol-tags for use in templates
 * the additional use of single users
 * the accesscontrol-tag has to be on the first line of the wikitext to work correctly, that has to be fixed

Bugs

 * Under MediaWiki 1.8.2: If you add a subpage to the Protected category, its parent-page is also protected. This is caused by the function getParentCategories in Title.php that, in 1.8.2, also returns the Categories of its subpages. I don't know a way around this problem, unfortunately.