Extension:SimpleSecurity

 Note that this extension is still in beta state as there are still problems to iron out

This is a simple solution involving a single snippet of code to be included from the LocalSettings.php file, it's been tested on version 1.6.7 and 1.9.3, and is being maintained at. It allows security directives to be placed in an article which affect the article's permissions, but are not rendered. The security directives are similar to how category links work in that they perform a function but do not render on the page. It's not very robust (see below for current flaws), and there's no encryption of data, but it's fine for general purpose use, and very easy to install.

Syntax & usage examples

 * {{#security:actions|users/groups}}

Actions and users/groups are both comma-separated lists. Allowed actions are view, edit, history, move, delete, raw, watch/unwatch and protect. Users names start with an uppercase letter, group names are all lowercase. Assign users to groups using the usual Special:Userrights page. Following are a few examples:
 * {{#security:*|admin,Fred}}
 * {{#security:edit,delete|Sam,Fred}}
 * {</tt>{#security:view,history|staff,consultants}}</tt>

Here's an example of using a pair of directives to allow everyone view-only access to an article
 * {</tt>{#security:*|sysop}}</tt> {</tt>{#security:view|*}}</tt>

Notes:
 * The syntax has changed in version 2.0 from square-brackets to curly-braces
 * The * refers to any action and allows one to specify default permissions. The defaults will be overridden if another security link matches the action specifically.
 * You can change the name used for security links with the $wgSecurityMagic global variable, by default it is "Security".
 * In MediaWiki version 1.6.x, the magic words must include the hash (#) symbol explicitly if you want that syntax. In version 1.9.x the hash format is mandatory and implicit, and so must not be included in the global magic-names variables.

Groups & rights
The groups used in the security links refer to the usual MediaWiki groups managed in the Special:Userrights page. As of MediaWiki version 1.9.x group management only allows users to be added or removed from existing groups, but adding or removing the available groups needs to be done by changing either the LocalSettings.php or Security.php file/article. The $wgSecurityGroupsArticle global variable allows an article to be designated to hold a bullet list of additional group names for the available groups list in the userrights special page.

Denying anonymous access
Users who are logged in are automatically part of a group called user, so if you say  </tt>, then all actions require the user to be logged in.

Inheriting article security from categories
Security settings can be assigned to articles in a category-wide way simply by adding the security link to the category article. Articles automatically inherit the security settings exhibited by any of the categories they're in. If an article also contains its own security links, they will override the inherited ones.

You can use an exclamation mark after the hash (a shebang) in a category page's security links to prevent them from being inherited by the contained articles, for example:
 * {</tt>{#!Security:history|timelord}}</tt>

This will mean that you need to be in the timelord group to access the history of the category page, but access to the history of any of the articles in the category is unaffected.

Notes:
 * The latest versions (and some older versions) of MediaWiki need the security info to be wikitext, other need it HTML. If the default setting is wrong for your setup, the $wgSecurityParseInfo global to true.
 * You can enable/disable inhertited security with the $wgSecurityInheritable global variable
 * You can change the name used for recursive security links with the $wgSecurityMagicNoi global variable, by default it is the same name as the normal security links but with a preceeding asterisk.
 * Security inheritence is not recursive, i.e. any security that a category inherits will not be passed on to the articles it contains, only the security links it exhibits itself will be passed down (except those with preceeding asterisk as described above).

Security-based conditions
In version 3.0 a new feature has been added allowing content to be rendered depending on a security query. Here's an example which makes a message render only if the user can edit the main page page.

You can also add a forth parameter which will render if the condition is not satisfied. This functionality was designed to work with Extension:Tree view to make trees filter some of its nodes out depending on user groups and permissions. The tree view extension helps this by not rendering any empty nodes.

Security on images & files
If security links are placed into articles in the Image:</tt> namespace, the code can prevent the images or its thumbnails from being returned to the client if they don't have readable permission. This feature requires Apache's mod-rewrite to be running and have the following condition and rule (update to your own wiki's path if necessary). RewriteEngine On RewriteCond %{REQUEST_URI} ^/wiki/images/.+ RewriteRule ^/wiki/images/(.+) /wiki/index.php/Download/$1 [L] This allows all requests into the images structure to be redirected to an article title which is intercepted by the security code and validated against security before the file is sent to the client. If the requested file is refused, then the file specified in the $wgSecurityDenyImage</tt> is returned in its place.

Security on Recent-changes and Watchlists
This extension doesn't directly support this feature, but another extension called Extension:TransformChanges will check if SimpleSecurity is installed and if so will filter any changes to non-readable articles from the list. Extension:TransformChanges is converts the rendered output format of Special:Recentchanges and Special:Watchlist from a list into a table for easy adjustment through CSS classes.

Installation
The code is a single snippet available from SimpleSecurity.php which you must should as a file of the same name in your extensions directory. You then include this from your LocalSettings.php file as follows: include('extensions/SimpleSecurity.php'); If you're using MediaWiki 1.6.x but want the same hash syntax as normal parser functions, add the following lines after the include. $wgSecurityMagic = '#security'; $wgSecurityMagicNoi = '#!security'; $wgSecurityMagicIf = '#ifusercan';

Template examples
Here's an example of each of the templates which you can refine to your own needs:

Template:Action not permitted
<p style="font-size:125%;color:#c00;">Sorry, action not permitted! Your user rights do not permit the ' action to be performed on the ' article.

Dependencies
You'll need to install Apache's mod-rewrite for security on images and files to work. Also, the security.php code refers to a number of other articles. The article names and their purpose are listed below, and they link to the Organic Design wiki where they're maintained.

Testing
This extension has been tested in the following environments:
 * works with PHP 4.x and PHP 5.x
 * works with MediaWiki 1.6.7
 * works with MediaWiki 1.9.3 - more bugs found and fixed 04:28, 20 April 2007 (UTC)

Bugs & Todo

 * Change users/groups handling to not rely on case of first letter
 * Still failing on diffs under certain circumstances --Nad 10:30, 1 May 2007 (UTC)
 * Page is empty except for the "access denied" message when viewing diff's for articles you're not allowed to see
 * Many of the same directives should only be displayed once
 * Subsequent inherited items should overwrite (care needs to be taken with cat order)
 * Users shouldn't be able to set security that prevents them from accessing it themselves

Security holes
There is a list of flaws often found in MediaWiki security extensions here, and I've included the ones that this extension currently suffers from below. There is a solution to these issues in progress.
 * diff: Under some circumstances article content is being shown in diffs when it shouldn't be.
 * Search article: Do you get results with partially displayed text? See also 8825
 * Atom/RSS feeds: Does the article get delivered? There are two feeds, one in the Recent changes special pages and other on the page history. For extensions using the userCan hook, this has been fixed in MW 1.10, 19944.
 * XML export (Special:Export): Is it possible to export the contents of a protected page? For extensions using the userCan hook, this has been fixed in MW 1.10, 19935.

New solution in progress to fix remaining security flaws
Fixing the remaining flaws of search, XML-exports and diff's containing information which should be inaccessible is quite a problem because those functions are obtaining article content with their own SQL queries, rather than fetching the content via the $wgArticle object. XmlWiki overcomes the problems by intercepting and filtering the rendered content, but that method is a hack and doesn't protect against other extensions which render differently structured content.

What's really needed is a way to intercept the database rows as they're retrieved for rendering, but there are no official hooks in that level of the MediaWiki code (not in version 1.6.x anyway). But I've found a method of dynamically adding a new hook to the DatabaseXXX::fetchObject method which is the method called by search, XML-export and RSS-feeds (and probably anything else which plans on iterating through the results of an SQL query).

This hook has been created and tested on MediaWiki 1.6.8 and is called DatabaseFetchObject which is a separate extension. It will be used by the SimpleSecurity.php code if the hook is installed, or will just work as usual if the hook is not present.

Version 3.44 (2007-05-19)

 * Fixed a bug causing the global $wgGroupPermissions operations to be ignored.

Version 3.41 (2007-05-01)

 * Fixed deny-template wikitext showing up.

Version 3.40 (2007-05-01)

 * Added the $wgSecurityGroupsArticle</tt> global for adding extra available groups for the userrights special page.

Version 3.31 (2007-04-21)

 * Added the $wgSecurityParseInfo</tt> global to cater for older versions of MediaWiki not parsing the security info message.

Version 3.3 (2007-04-20)

 * Security was failing to work for diff's which is fixed, but clears the page for some reason
 * Security was failing for view action under various circumstances on 1.9.x which has been fixed
 * Security info was rendering in weird places which has been fixed by using a different hook

Version 3.2

 * Global $action set to "raw" if request is an intercepted file/image so processing not wasted rendering page which isn't used

Version 3.1

 * The file/image security had to be re-implemented to work with the version 3.0 and is working again now.
 * Two additional gloals were added to enable/disable file-based security, and to specify a file to return if the requested one is denied.
 * Checks if encoding type is gzip and gzips before sending for file security

Version 3.0

 * The whole thing has been rewritten based on the parser functions extension so that it works in accord with the MediaWiki object-oriented convensions and works across the MediaWiki versions better.
 * It now installs in the same way as other extensions.
 * The #ifusercan function was added for allowing rendered content to be dependent on permissions

Version 2.0
The major difference in this version 2.0 is that the newer version has changed the syntax of the security links from square brackets to braces. The problem with the brackets method is that it required the code to extract and remove the security information from the article using a pattern match and replace on the text, which is very inefficient. Using braces allows a tighter integration with the MediaWiki parser so that the parser itself calls a function to process the security directives as it comes across them.

The second difference is that the security validation is done on the ArticleAfterFetchContent hook so that the security is assessed for transcluded articles as well as the main title article. I thought this would also fix the security holes listed above, but those still need a little more work!