MarkAHershberger has uploaded a new change for review. (
https://gerrit.wikimedia.org/r/398414 )
Change subject: [WIP] Update for extension registration
......................................................................
[WIP] Update for extension registration
Also fix what look like a couple of bugs
Change-Id: I7e0659872a273fc2026b9bf8d4c4e05f1338c381
---
D Lockdown.php
A extension.json
A src/Hook.php
3 files changed, 279 insertions(+), 223 deletions(-)
git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Lockdown
refs/changes/14/398414/1
diff --git a/Lockdown.php b/Lockdown.php
deleted file mode 100644
index 9deef15..0000000
--- a/Lockdown.php
+++ /dev/null
@@ -1,223 +0,0 @@
-<?php
-
-/**
- * Lockdown extension - implements restrictions on individual namespaces and
special pages.
- *
- * @file
- * @ingroup Extensions
- * @author Daniel Kinzler, brightbyte.de
- * @copyright © 2007 Daniel Kinzler
- * @license GNU General Public Licence 2.0 or later
- */
-
-/*
-* WARNING: you can use this extension to deny read access to some namespaces.
Keep in mind that this
-* may be circumvented in several ways. This extension doesn't try to
-* plug such holes. Also note that pages that are not readable will still be
shown in listings,
-* such as the search page, categories, etc.
-*
-* Known ways to access "hidden" pages:
-* - transcluding as template. can be avoided using $wgNonincludableNamespaces.
-* Some search messages may reveal the page existance by producing links to it
(MediaWiki:searchsubtitle,
-* MediaWiki:noexactmatch, MediaWiki:searchmenu-exists,
MediaWiki:searchmenu-new...).
-* - supplying oldid=<revisionfromhiddenpage> may work in some versions of
mediawiki. Same with diff, etc.
-*
-* NOTE: you cannot GRANT access to things forbidden by $wgGroupPermissions.
You can only DENY access
-* granted there.
-*/
-
-if ( !defined( 'MEDIAWIKI' ) ) {
- echo( "This file is an extension to the MediaWiki software and cannot
be used standalone.\n" );
- die( 1 );
-}
-
-$wgExtensionCredits['other'][] = array(
- 'path' => __FILE__,
- 'name' => 'Lockdown',
- 'author' => array(
- 'Daniel Kinzler',
- 'Platonides',
- '...'
- ),
- 'url' => 'https://mediawiki.org/wiki/Extension:Lockdown',
- 'descriptionmsg' => 'lockdown-desc',
- 'license-name' => 'GPL-2.0+'
-);
-
-$wgMessagesDirs['Lockdown'] = __DIR__ . '/i18n';
-
-$wgNamespacePermissionLockdown = array();
-$wgSpecialPageLockdown = array();
-$wgActionLockdown = array();
-
-$wgHooks['getUserPermissionsErrors'][] = 'lockdownUserPermissionsErrors';
-$wgHooks['MediaWikiPerformAction'][] = 'lockdownMediawikiPerformAction';
-$wgHooks['SearchableNamespaces'][] = 'lockdownSearchableNamespaces';
-$wgHooks['SearchGetNearMatchComplete'][] =
'lockdownSearchGetNearMatchComplete';
-
-/**
- * @param Title $title
- * @param User $user
- * @param string $action
- * @param MessageSpecifier|array|string|bool|null $result
- * @return bool
- */
-function lockdownUserPermissionsErrors(
- Title $title,
- User $user,
- $action,
- &$result = null
-) {
- global $wgNamespacePermissionLockdown, $wgSpecialPageLockdown,
$wgWhitelistRead, $wgLang;
-
- $result = null;
-
- // don't impose extra restrictions on UI pages
- if ( $title->isCssJsSubpage() ) {
- return true;
- }
-
- if ( $action == 'read' && is_array( $wgWhitelistRead ) ) {
- // don't impose read restrictions on whitelisted pages
- if ( in_array( $title->getPrefixedText(), $wgWhitelistRead ) ) {
- return true;
- }
- }
-
- $groups = null;
- $ns = $title->getNamespace();
- if ( NS_SPECIAL == $ns ) {
- foreach ( $wgSpecialPageLockdown as $page => $g ) {
- if ( !$title->isSpecial( $page ) ) continue;
- $groups = $g;
- break;
- }
- }
- else {
- $groups = @$wgNamespacePermissionLockdown[$ns][$action];
- if ( $groups === null ) {
- $groups = @$wgNamespacePermissionLockdown['*'][$action];
- }
- if ( $groups === null ) {
- $groups = @$wgNamespacePermissionLockdown[$ns]['*'];
- }
- }
-
- if ( $groups === null ) {
- #no restrictions
- return true;
- }
-
- if ( !$groups ) {
- #no groups allowed
-
- $result = array(
- 'badaccess-group0'
- );
-
- return false;
- }
-
- $ugroups = $user->getEffectiveGroups();
-
- $match = array_intersect( $ugroups, $groups );
-
- if ( $match ) {
- # group is allowed - keep processing
- $result = null;
- return true;
- } else {
- # group is denied - abort
- $groupLinks = array_map( array( 'User', 'makeGroupLinkWiki' ),
$groups );
-
- $result = array(
- 'badaccess-groups',
- $wgLang->commaList( $groupLinks ),
- count( $groups )
- );
-
- return false;
- }
-}
-
-function lockdownMediawikiPerformAction (
- OutputPage $output,
- Article $article,
- Title $title,
- User $user,
- WebRequest $request,
- MediaWiki $wiki
-) {
- global $wgActionLockdown, $wgLang;
-
- $action = $wiki->getAction();
-
- if ( !isset( $wgActionLockdown[$action] ) ) {
- return true;
- }
-
- $groups = $wgActionLockdown[$action];
- if ( $groups === null ) {
- return true;
- }
- if ( !$groups ) {
- return false;
- }
-
- $ugroups = $user->getEffectiveGroups();
- $match = array_intersect( $ugroups, $groups );
-
- if ( $match ) {
- return true;
- } else {
- $groupLinks = array_map( array( 'User', 'makeGroupLinkWiki' ),
$groups );
-
- $err = array( 'badaccess-groups', $wgLang->commaList(
$groupLinks ), count( $groups ) );
- throw new PermissionsError( $request->getVal('action'), array(
$err ) );
- }
-}
-
-function lockdownSearchableNamespaces( array &$searchableNs ) {
- $user = RequestContext::getMain()->getUser();
- $ugroups = $user->getEffectiveGroups();
-
- foreach ( $searchableNs as $ns => $name ) {
- if ( !lockdownNamespace( $ns, $ugroups ) ) {
- unset( $searchableNs[$ns] );
- }
- }
- return true;
-}
-
-function lockdownNamespace( $ns, array $ugroups ) {
- global $wgNamespacePermissionLockdown;
-
- $groups = @$wgNamespacePermissionLockdown[$ns]['read'];
- if ( $groups === null ) {
- $groups = @$wgNamespacePermissionLockdown['*']['read'];
- }
- if ( $groups === null ) {
- $groups = @$wgNamespacePermissionLockdown[$ns]['*'];
- }
-
- if ( $groups === null ) {
- return false;
- }
-
- if ( !$groups || !array_intersect($ugroups, $groups) ) {
- $title = null;
- return false;
- }
-
- return true;
-}
-
-#Stop a Go search for a hidden title to send you to the login required page.
Will show a no such page message instead.
-function lockdownSearchGetNearMatchComplete( $searchterm, Title $title = null
) {
- global $wgUser;
-
- if ( $title ) {
- $ugroups = $wgUser->getEffectiveGroups();
- return lockdownNamespace( $title->getNamespace(), $ugroups );
- }
-}
diff --git a/extension.json b/extension.json
new file mode 100644
index 0000000..6fa24f1
--- /dev/null
+++ b/extension.json
@@ -0,0 +1,36 @@
+{
+ "name": "Lockdown",
+ "author": [
+ "Daniel Kinzler",
+ "Platonides",
+ "Mark A. Hershberger",
+ "..."
+ ],
+ "url": "https://mediawiki.org/wiki/Extension:Lockdown",
+ "descriptionmsg": "lockdown-desc",
+ "license-name": "GPL-2.0+",
+ "type": "other",
+ "MessagesDirs": {
+ "Lockdown": [
+ "i18n"
+ ]
+ },
+ "Hooks": {
+ "getUserPermissionsErrors":
"MediaWiki\\Extensions\\Lockdown\\Hook::onGetUserPermissionsErrors",
+ "MediaWikiPerformAction":
"MediaWiki\\Extensions\\Lockdown\\Hook::onMediawikiPerformAction",
+ "SearchableNamespaces":
"MediaWiki\\Extensions\\Lockdown\\Hook::onSearchableNamespaces",
+ "SearchGetNearMatchComplete":
"MediaWiki\\Extensions\\Lockdown\\Hook::onSearchGetNearMatchComplete"
+ },
+ "config": {
+ "NamespacePermissionLockdown": {
+ "value": []
+ },
+ "SpecialPageLockdown": {
+ "value": []
+ },
+ "ActionLockdown": {
+ "value": []
+ }
+ },
+ "manifest_version": 2
+}
diff --git a/src/Hook.php b/src/Hook.php
new file mode 100644
index 0000000..090bdf5
--- /dev/null
+++ b/src/Hook.php
@@ -0,0 +1,243 @@
+<?php
+/**
+ * Lockdown extension - implements restrictions on individual
+ * namespaces and special pages.
+ *
+ * Copyright (C) 2007, 2016 Daniel Kinzler
+ * Copyright (C) 2017 NicheWork, LLC
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * @file
+ * @ingroup Extensions
+ * @author Daniel Kinzler, brightbyte.de
+ * @author Mark A. Hershberger <[email protected]>
+ * @license GNU General Public Licence 2.0 or later
+ */
+namespace MediaWiki\Extensions\Lockdown;
+
+/**
+ * Holds the hooks for the Lockdown extension.
+ */
+class Hook {
+
+ /**
+ * Fetch an appropriate permission error (or none!)
+ *
+ * @param Title $title being checked
+ * @param User $user whose access is being checked
+ * @param string $action being checked
+ * @param MessageSpecifier|array|string|bool|null &$result User
+ * permissions error to add. If none, return true. $result can be
+ * returned as a single error message key (string), or an array of
+ * error message keys when multiple messages are needed
+ * @return bool
+ * @see
https://www.mediawiki.org/wiki/Manual:Hooks/getUserPermissionsErrors
+ */
+ public static function onGetUserPermissionsErrors(
+ Title $title, User $user, $action, &$result = null
+ ) {
+ global $wgSpecialPageLockdown, $wgWhitelistRead, $wgLang;
+
+ $result = null;
+
+ // don't impose extra restrictions on UI pages
+ if ( $title->isCssJsSubpage() ) {
+ return true;
+ }
+
+ if ( $action == 'read' && is_array( $wgWhitelistRead ) ) {
+ // don't impose read restrictions on whitelisted pages
+ if ( in_array( $title->getPrefixedText(),
$wgWhitelistRead ) ) {
+ return true;
+ }
+ }
+
+ $groups = null;
+ $ns = $title->getNamespace();
+ if ( NS_SPECIAL == $ns ) {
+ foreach ( $wgSpecialPageLockdown as $page => $g ) {
+ if ( !$title->isSpecial( $page ) ) {
+ continue;
+ }
+ $groups = $g;
+ break;
+ }
+ } else {
+ $groups = self::namespaceGroups( $ns, $action );
+ }
+
+ if ( $groups === null ) {
+ # no restrictions
+ return true;
+ }
+
+ if ( !$groups ) {
+ # no groups allowed
+ $result = [
+ 'badaccess-group0'
+ ];
+
+ return false;
+ }
+
+ $ugroups = $user->getEffectiveGroups();
+
+ $match = array_intersect( $ugroups, $groups );
+
+ if ( $match ) {
+ # group is allowed - keep processing
+ $result = null;
+ return true;
+ } else {
+ # group is denied - abort
+ $groupLinks = array_map( [ 'User', 'makeGroupLinkWiki'
], $groups );
+
+ $result = [
+ 'badaccess-groups',
+ $wgLang->commaList( $groupLinks ),
+ count( $groups )
+ ];
+
+ return false;
+ }
+ }
+
+ /**
+ * See if the user is in an allowed group for this action
+ *
+ * @param OutputPage $output to use for output
+ * @param Article $article the article being acted on
+ * @param Title $title the title being acted on
+ * @param User $user who is trying this
+ * @param WebRequest $request to get any input
+ * @param MediaWiki $wiki for other info
+ * @return bool false if permission is denied
+ * @see
https://www.mediawiki.org/wiki/Manual:Hooks/MediaWikiPerformAction
+ */
+ function onMediawikiPerformAction(
+ OutputPage $output, Article $article, Title $title, User $user,
WebRequest $request,
+ MediaWiki $wiki
+ ) {
+ global $wgActionLockdown, $wgLang;
+
+ $action = $wiki->getAction();
+
+ if ( !isset( $wgActionLockdown[$action] ) ) {
+ return true;
+ }
+
+ $groups = $wgActionLockdown[$action];
+ if ( $groups === null ) {
+ return true;
+ }
+ if ( !$groups ) {
+ return false;
+ }
+
+ $ugroups = $user->getEffectiveGroups();
+ $match = array_intersect( $ugroups, $groups );
+
+ if ( $match ) {
+ return true;
+ } else {
+ $groupLinks = array_map( [ 'User', 'makeGroupLinkWiki'
], $groups );
+
+ $err = [
+ 'badaccess-groups', $wgLang->commaList(
$groupLinks ), count( $groups )
+ ];
+ throw new PermissionsError( $request->getVal( 'action'
), [ $err ] );
+ }
+ }
+
+ /**
+ * Hide the namespaces that this user doesn't have permission to serch
+ *
+ * @param array &$searchableNs from which namespaces will be removed
+ * @see https://www.mediawiki.org/wiki/Manual:Hooks/SearchableNamespaces
+ */
+ public static function onSearchableNamespaces( array &$searchableNs ) {
+ $user = RequestContext::getMain()->getUser();
+ $ugroups = $user->getEffectiveGroups();
+
+ foreach ( $searchableNs as $ns => $name ) {
+ if ( !self::namespaceCheck( $ns, $ugroups ) ) {
+ unset( $searchableNs[$ns] );
+ }
+ }
+ }
+
+ /**
+ * Get groups that this action is restricted to in this namespace.
+ *
+ * @param int $ns to check
+ * @param string $action to check (default: read)
+ * @return null|array of groups
+ */
+ protected static function namespaceGroups( $ns, $action = 'read' ) {
+ global $wgNamespacePermissionLockdown;
+
+ $groups = isset( $wgNamespacePermissionLockdown[$ns][$action] )
+ ? $wgNamespacePermissionLockdown[$ns][$action]
+ : null;
+ if ( $groups === null ) {
+ $groups = isset(
$wgNamespacePermissionLockdown['*'][$action] )
+ ?
$wgNamespacePermissionLockdown['*'][$action]
+ : null;
+ }
+ if ( $groups === null ) {
+ $groups = isset(
$wgNamespacePermissionLockdown[$ns]['*'] )
+ ?
$wgNamespacePermissionLockdown[$ns]['*']
+ : null;
+ }
+ return $groups;
+ }
+
+ /**
+ * Determine if this the user has the group to read this namespace
+ *
+ * @param int $ns to check
+ * @param array $ugroups that the user is in
+ * @return bool false if the user does not have permission
+ */
+ protected static function namespaceCheck( $ns, array $ugroups ) {
+ $groups = namespaceGroups( $ns );
+ if ( $groups && !array_intersect( $ugroups, $groups ) ) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Stop a Go search for a hidden title to send you to the login
+ * required page. Will show a no such page message instead.
+ *
+ * @param string $searchterm that the user is searching
+ * @param Title $title that the user would end up on
+ * @see
https://www.mediawiki.org/wiki/Manual:Hooks/SearchGetNearMatchComplete
+ */
+ function onSearchGetNearMatchComplete( $searchterm, Title $title = null
) {
+ global $wgUser;
+
+ if ( $title ) {
+ $ugroups = $wgUser->getEffectiveGroups();
+ if ( self::namespaceCheck( $title->getNamespace(),
$ugroups ) ) {
+ $title = null;
+ }
+ }
+ }
+}
--
To view, visit https://gerrit.wikimedia.org/r/398414
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I7e0659872a273fc2026b9bf8d4c4e05f1338c381
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/Lockdown
Gerrit-Branch: master
Gerrit-Owner: MarkAHershberger <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits