r108717 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r108716‎ | r108717 | r108718 >
Date:11:52, 12 January 2012
Author:daniel
Status:deferred (Comments)
Tags:
Comment:
new extension: PrivatePageProtection
Modified paths:
  • /trunk/extensions/PrivatePageProtection (added) (history)
  • /trunk/extensions/PrivatePageProtection/PrivatePageProtection.i18n.php (added) (history)
  • /trunk/extensions/PrivatePageProtection/PrivatePageProtection.php (added) (history)

Diff [purge]

Index: trunk/extensions/PrivatePageProtection/PrivatePageProtection.i18n.php
@@ -0,0 +1,49 @@
 2+<?php
 3+/**
 4+ * Internationalisation for PrivatePageProtection extension
 5+ *
 6+ * @file
 7+ * @ingroup Extensions
 8+ */
 9+
 10+$messages = array();
 11+
 12+/** English
 13+ * @author Daniel Kinzler
 14+ */
 15+$messages['en'] = array(
 16+ 'privatepp-desc' => 'Allowes restricting page access based on user group',
 17+
 18+ 'privatepp-lockout-prevented' => 'Lockout prevented: You have tried to restrict access to this page to {{PLURAL:$2|the group|one of the groups}} $1. '
 19+ . 'Since you are not a member of {{PLURAL:$2|this group|any of these groups}}, you would not be able to access the page after saving it. '
 20+ . 'Saving was aborted to avoid this.',
 21+
 22+);
 23+
 24+/** Message documentation (Message documentation)
 25+ * @author Daniel Kinzler
 26+ */
 27+$messages['qqq'] = array(
 28+ 'privatepp-desc' => '{{desc}}',
 29+);
 30+
 31+/** German (Deutsch)
 32+ * @author Daniel Kinzler
 33+ */
 34+$messages['de'] = array(
 35+ 'privatepp-desc' => 'Beschränkt den Zugang zu Wikiseite auf der Basis von benutzergruppen.',
 36+
 37+ 'privatepp-lockout-prevented' => 'Aussperrung verhindert: Du hast versucht, den Zugang zu dieser Seite auf {{PLURAL:$2|die Gruppe|die gruppen}} $1 zu beschränken. '
 38+ . 'Da du kein Mitglied {{PLURAL:$2|dieser Gruppe|einer dieser Gruppen}} bist, könntest du nach dem Speichern nicht mehr auf die Seite zugreifen. '
 39+ . 'Um dies zu vermeiden wurde das Speichern abgebrochen.',
 40+);
 41+
 42+/** German (Deutsch)
 43+ * @author Daniel Kinzler
 44+ */
 45+$messages['de_formal'] = array(
 46+ 'privatepp-lockout-prevented' => 'Aussperrung verhindert: Sie haben versucht, den Zugang zu dieser Seite auf {{PLURAL:$2|die Gruppe|die gruppen}} $1 zu beschränken. '
 47+ . 'Da sie kein Mitglied {{PLURAL:$2|dieser Gruppe|einer dieser Gruppen}} sind, könnten sie nach dem Speichern nicht mehr auf die Seite zugreifen. '
 48+ . 'Um dies zu vermeiden wurde das Speichern abgebrochen.',
 49+);
 50+
Index: trunk/extensions/PrivatePageProtection/PrivatePageProtection.php
@@ -0,0 +1,175 @@
 2+<?php
 3+
 4+/**
 5+ * PrivatePageProtection extension - implements per page acccess restrictions based on user group.
 6+ * Which groups are authorized for viewing is defined on-page, using a parser function.
 7+ *
 8+ * @file
 9+ * @ingroup Extensions
 10+ * @author Daniel Kinzler, brightbyte.de
 11+ * @copyright © 2007 Daniel Kinzler
 12+ * @license GNU General Public Licence 2.0 or later
 13+ */
 14+
 15+/*
 16+* WARNING: you can use this extension to deny read access to some pages. Keep in mind that this
 17+* may be circumvented in several ways. This extension doesn't try to
 18+* plug such holes. Also note that pages that are not readable will still be shown in listings,
 19+* such as the search page, categories, etc.
 20+*
 21+* Known ways to access "hidden" pages:
 22+* - transcluding as template. can be avoided using $wgNonincludableNamespaces.
 23+* Some search messages may reveal the page existance by producing links to it (MediaWiki:searchsubtitle,
 24+* MediaWiki:noexactmatch, MediaWiki:searchmenu-exists, MediaWiki:searchmenu-new...).
 25+*
 26+* NOTE: you cannot GRANT access to things forbidden by $wgGroupPermissions. You can only DENY access
 27+* granted there.
 28+*/
 29+
 30+if ( !defined( 'MEDIAWIKI' ) ) {
 31+ echo( "This file is an extension to the MediaWiki software and cannot be used standalone.\n" );
 32+ die( 1 );
 33+}
 34+
 35+$wgExtensionCredits['parserfunction'][] = array(
 36+ 'path' => __FILE__,
 37+ 'name' => 'PrivatePageProtection',
 38+ 'author' => array( 'Daniel Kinzler'),
 39+ 'url' => 'http://mediawiki.org/wiki/Extension:PrivatePageProtection',
 40+ 'descriptionmsg' => 'privatepp-desc',
 41+);
 42+
 43+$wgExtensionMessagesFiles['PrivatePageProtection'] = dirname(__FILE__) . '/PrivatePageProtection.i18n.php';
 44+
 45+$wgHooks['ParserFirstCallInit'][] = 'privateppParserFirstCallInit';
 46+$wgHooks['LanguageGetMagic'][] = 'privateppLanguageGetMagic';
 47+$wgHooks['getUserPermissionsErrorsExpensive'][] = 'privateppUserPermissionsErrors';
 48+$wgHooks['ArticleSave'][] = 'privateppArticleSave';
 49+
 50+// Tell MediaWiki that the parser function exists.
 51+function privateppParserFirstCallInit( &$parser ) {
 52+
 53+ // Create a function hook associating the magic word
 54+ $parser->setFunctionHook('allow-groups', 'privateppRenderTag');
 55+ return true;
 56+}
 57+
 58+// Tell MediaWiki which magic words can invoke the parser function.
 59+function privateppLanguageGetMagic( &$magicWords, $langCode ) {
 60+
 61+ // Add the magic words.
 62+ // If the first element of the array is 0, the magic word is case insensitive.
 63+ $magicWords['allow-groups'] = array( 0, 'allow-groups', 'allowed-groups', 'ppp' ); #TODO: i18n?!
 64+ return true;
 65+}
 66+
 67+// Render the output of the parser function.
 68+function privateppRenderTag( $parser, $param1 = '', $param2 = '' ) {
 69+ $args = func_get_args();
 70+
 71+ if ( count( $args ) <= 1 ) {
 72+ return true;
 73+ }
 74+
 75+ $groups = array();
 76+
 77+ for ( $i = 1; $i < count( $args ); $i++ ) {
 78+ $groups[] = strtolower( trim( $args[$i] ) ); #XXX: allow localized group names?!
 79+ }
 80+
 81+ $groups = implode( "|", $groups );
 82+
 83+ $out = $parser->getOutput();
 84+
 85+ $ppp = $out->getProperty('ppp_allowed_groups');
 86+ if ( $ppp ) {
 87+ $groups = $ppp . '|' . $groups;
 88+ }
 89+
 90+ $out->setProperty('ppp_allowed_groups', $groups);
 91+
 92+ return array( 'text' => '', 'ishtml' => true, 'inline' => true );
 93+}
 94+
 95+/**
 96+ * Returns a list of allowed groups for the given page.
 97+ */
 98+function privateppGetAllowedGroups( $title ) {
 99+ $result = array();
 100+ $id = $title->getArticleID();
 101+
 102+ if ( $id == 0 ) {
 103+ return array();
 104+ }
 105+
 106+ $dbr = wfGetDB( DB_SLAVE );
 107+ $res = $dbr->select( array( 'page_props' ),
 108+ array( 'pp_value' ),
 109+ array( 'pp_page' => $id, 'pp_propname' => 'ppp_allowed_groups' ),
 110+ __METHOD__ );
 111+
 112+ if ( $res !== false ) {
 113+ foreach ( $res as $row ) {
 114+ $result[] = $row->pp_value;
 115+ }
 116+ }
 117+
 118+ #TODO: use object cache?! get from parser cache?!
 119+ return $result;
 120+}
 121+
 122+function privateppGetAccessError( $groups, $user ) {
 123+ global $wgLang;
 124+
 125+ if ( !$groups ) return null;
 126+ if ( is_string( $groups ) ) $groups = explode('|', $groups);
 127+
 128+ $ugroups = $user->getEffectiveGroups( true );;
 129+
 130+ $match = array_intersect( $ugroups, $groups );
 131+
 132+ if ( $match ) {
 133+ # group is allowed - keep processing
 134+ return null;
 135+ } else {
 136+ # group is denied - abort
 137+ $groupLinks = array_map( array( 'User', 'makeGroupLinkWiki' ), $groups );
 138+
 139+ $err = array(
 140+ 'badaccess-groups',
 141+ $wgLang->commaList( $groupLinks ),
 142+ count( $groups )
 143+ );
 144+
 145+ return $err;
 146+ }
 147+}
 148+
 149+function privateppUserPermissionsErrors( $title, $user, $action, &$result ) {
 150+ $groups = privateppGetAllowedGroups( $title );
 151+ $result = privateppGetAccessError( $groups, $user );
 152+
 153+ if ( !$result ) return true;
 154+ else return false;
 155+}
 156+
 157+function privateppArticleSave( &$wikipage, &$user, &$text, &$summary,
 158+ $minor, $watchthis, $sectionanchor, &$flags, &$status ) {
 159+
 160+ # prevent users from saving a page with access restrictions that
 161+ # would lock them out opf the page.
 162+
 163+ #XXX: calling prepareTextForEdit() causes the text to be parsed a second time!
 164+ # but there doesn't seem to be a hook that has access to the parseroutput...
 165+ $editInfo = $wikipage->prepareTextForEdit( $text, null, $user );
 166+ $groups = $editInfo->output->getProperty('ppp_allowed_groups');
 167+
 168+ $err = privateppGetAccessError( $groups, $user );
 169+ if ( !$err ) return true;
 170+
 171+ $err[0] = 'privatepp-lockout-prevented'; #override message key
 172+ throw new PermissionsError( 'edit', array( $err ) );
 173+
 174+ #$status->fatal( $err[0], $err[1], $err[2] ); # message, groups, count
 175+ #return false;
 176+}

Follow-up revisions

RevisionCommit summaryAuthorDate
r108718followup to: r108717: use multiline strings instead of concatenationdaniel12:30, 12 January 2012
r110416r108717: Consistency tweaks in preparation for adding extension to translatew...raymond19:10, 31 January 2012
r110417r108717: Register extension for translatewiki.net.raymond19:13, 31 January 2012

Comments

#Comment by Duesentrieb (talk | contribs)   12:14, 12 January 2012

this extension is complementary to Lockdown. It implements group based access on a per-page basis, using a parser function to list the groups on-page

#Comment by Siebrand (talk | contribs)   12:23, 12 January 2012
+	'privatepp-desc' => 'Allowes restricting page access based on user group',
+	
+	'privatepp-lockout-prevented' => 'Lockout prevented: You have tried to restrict access to this page to {{PLURAL:$2|the group|one of the groups}} $1. '
+									. 'Since you are not a member of {{PLURAL:$2|this group|any of these groups}}, you would not be able to access the page after saving it. '
+									. 'Saving was aborted to avoid this.',

Status & tagging log