Extension:SimpleSecurity

The general problem with implementing a proper security solution in MediaWiki (giving rise to the scary looking warning box shown above) is that although most of the actions one can perform on articles can be restricted easily, the ability to read content cannot be easily restricted on a per-title basis. The reason reading is difficult to restrict is because it's an operation which is not just performed via one action, but rather that many different actions, special-pages and extensions access article content and display it in diverse ways. To make matters worse, many of these diverse means of article access are done by querying the database directly rather than going via the Article class.

See the technical details section below for more details on this problem and the solution that Simple Security 4 uses to overcome it. The solution may be considered rather extreme by some developers, but we've found no other effective way to achieve it. The solution is disabled by default (see configuration settings below), it is still functional without it but there are then simple means available to view restricted content such as exporting it or transcluding it in another page.

If you're using an older version of MediaWiki you may need to use an older version of this extension, but please note that versions prior to 4 are unstable, unreliable and are not used in the same way as version 4 and above. The last 3.x version is available [ here]

Installation
Create a SimpleSecurity folder in your extensions directory. Download the latest snapshot and extract it to your extensions directory. Then include it in your LocalSettings.php file as in the following example.

Usage
Installation of the extension The new version is designed to be in line with MediaWiki's own development plans for security. It seems that they won't have a solution to the read problem for some time, but the current method of article protection already allows for restricting edit, create and move actions by group, and allows for the possibility of other actions to be handled, so the approach that Simple Security 4 has taken is to add a new restriction to the existing protection page called read which you can see in the images below which show the protection page with and without Simple Security installed.

Unreadable links
If the $wgSecurityAllowUnreadableLinks global is set to false (default), then links to local articles which the current user does not have permission to read are rendered as plain text rather than a hyperlink. The image above shows a small fragment of a recent changes list. Notice that the Sandbox article title and its diff and hist show up grey and are not links, their style can be set in CSS by addressing the unreadable class attribute.

Global security settings
Here are the global variables which affect the operation of the extension. These should be set in your LocalSettings file after the include of the SimpleSecurity.php script.

Technical details
For a more in depth explanation, see the development notes at OrganicDesign:Extension talk:SimpleSecurity.php.

To allow restrictions on the reading of article content requires a hook at a very low-level in the programming which is common to all the kinds of operations involved in the retrieving of article content. The MediaWiki code is written to support a number of different database server's each with their own implementation of the SQL language, and it has also been designed to allow a wiki's database to be served from many servers concurrently. To achieve this, a Database class has been created to add a unified database interface to the MediaWiki runtime environment. All database interaction is handled via the methods of the Database class, and specifically, the only way that any legitimate MediaWiki code would obtain any article content is through the fetchRow and fetchObject methods.

So to really solve the per-title read-restriction issue, some of the methods of the Database class would need to be intercepted. There are no official hooks in the methods we need to intercept, so Simple Security version 4 uses a methodology to manipulate the methods at runtime. Some people (probably including most of the core MediaWiki developers) would consider this approach to be bad practice and might even go so far as to call it voodoo. In fact, we ourselves at Organic Design consider the technique to be voodoo, but we have a number of clients running mediawiki for their internal business documentation who have been in dire need of a reasonable means of restricting their content on a per-title basis, and unfortunately this is the only solution we've been able to come up with for them.

The function which implements the voodoo is wfAddDatabaseHooks, it first creates a new Database class which is based on the one currently in use but has "2" appended to its name and has its query and fetchObject methods overridden. Unfortunately this is not the end of the story, because every time a new database connection is requested, it will of course return an instance of the normal class such as DatabaseMysql instead of DatabaseMysql2. So the class responsible for returning database connection objects must also be replaced which is the LoadBalancer class. Luckily the LoadBalancer is a singleton which means we can replace it with another object which is an exact replica except that it's of class LoadBalancer2 which has its reallyOpenConnection method replaced with one that instantiates and returns an instances of the new database class.

All text content is held in the old_text field of the text table, so the row-reading needs to be intercepted. But the SELECT queries also have to be adjusted to ensure that the old_id field is available along with old_text otherwise it cannot be established whether or not the text is allowed to be viewed (since the id is needed to relate the text fragment with a current article title). The query method of the database class has been overridden to patch the SQL, and fetchObject has been overridden to replace the content of the requested old_text field if it should not be accessible.