jenkins-bot has submitted this change and it was merged. (
https://gerrit.wikimedia.org/r/399544 )
Change subject: Move code into a Lockdown class
......................................................................
Move code into a Lockdown class
* Elminate final phpcs warnings
* Use class instead of global functions
* Break up NS checking into reusable code
* Credit self
Change-Id: Ief7034bc7b308e3250b4a3241d9bacbc9f49c595
---
M .phpcs.xml
M Lockdown.php
2 files changed, 212 insertions(+), 196 deletions(-)
Approvals:
Legoktm: Looks good to me, approved
jenkins-bot: Verified
Thiemo Kreuz (WMDE): Looks good to me, but someone else must approve
diff --git a/.phpcs.xml b/.phpcs.xml
index 634226c..9292826 100644
--- a/.phpcs.xml
+++ b/.phpcs.xml
@@ -1,9 +1,6 @@
<?xml version="1.0"?>
<ruleset>
- <rule ref="./vendor/mediawiki/mediawiki-codesniffer/MediaWiki">
- <exclude name="Generic.PHP.NoSilencedErrors.Discouraged"/>
- <exclude
name="MediaWiki.NamingConventions.PrefixedGlobalFunctions.wfPrefix"/>
- </rule>
+ <rule ref="./vendor/mediawiki/mediawiki-codesniffer/MediaWiki"/>
<file>.</file>
<arg name="extensions" value="php"/>
<arg name="encoding" value="UTF-8"/>
diff --git a/Lockdown.php b/Lockdown.php
index 871a667..1e2bcde 100644
--- a/Lockdown.php
+++ b/Lockdown.php
@@ -7,7 +7,9 @@
* @file
* @ingroup Extensions
* @author Daniel Kinzler, brightbyte.de
- * @copyright © 2007 Daniel Kinzler
+ * @author Mark A. Hershberger, NicheWork, LLC
+ * @copyright © 2007, 2016 Daniel Kinzler
+ * @copyright © 2017 NicheWork, LLC
* @license GNU General Public Licence 2.0 or later
*/
@@ -22,6 +24,7 @@
'name' => 'Lockdown',
'author' => [
'Daniel Kinzler',
+ 'Mark A. Hershberger',
'Platonides',
'...'
],
@@ -36,217 +39,233 @@
$wgSpecialPageLockdown = [];
$wgActionLockdown = [];
-$wgHooks['getUserPermissionsErrors'][] = 'lockdownUserPermissionsErrors';
-$wgHooks['MediaWikiPerformAction'][] = 'lockdownMediawikiPerformAction';
-$wgHooks['SearchableNamespaces'][] = 'lockdownSearchableNamespaces';
-$wgHooks['SearchGetNearMatchComplete'][] =
'lockdownSearchGetNearMatchComplete';
+$wgHooks['getUserPermissionsErrors'][] =
'Lockdown::onGetUserPermissionsErrors';
+$wgHooks['MediaWikiPerformAction'][] = 'Lockdown::onMediawikiPerformAction';
+$wgHooks['SearchableNamespaces'][] = 'Lockdown::onSearchableNamespaces';
+$wgHooks['SearchGetNearMatchComplete'][]
+ = 'Lockdown::onSearchGetNearMatchComplete';
-/**
- * Return an error if the user is locked out of this namespace.
- *
- * @param Title $title that is being requested
- * @param User $user who is requesting
- * @param string $action they are performing
- * @param MessageSpecifier|array|string|bool|null &$result response
- * @return bool
- * @see https://www.mediawiki.org/wiki/Manual:Hooks/getUserPermissionsErrors
- */
-function lockdownUserPermissionsErrors(
- Title $title,
- User $user,
- $action,
- &$result = null
-) {
- global $wgNamespacePermissionLockdown, $wgSpecialPageLockdown,
- $wgWhitelistRead, $wgLang;
+class Lockdown {
- $result = null;
+ /**
+ * 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;
- // don't impose extra restrictions on UI pages
- if ( $title->isCssJsSubpage() ) {
- return true;
- }
+ $result = null;
- if ( $action == 'read' && is_array( $wgWhitelistRead ) ) {
- // don't impose read restrictions on whitelisted pages
- if ( in_array( $title->getPrefixedText(), $wgWhitelistRead ) ) {
+ // don't impose extra restrictions on UI pages
+ if ( $title->isCssJsSubpage() ) {
return true;
}
- }
- $groups = null;
- $ns = $title->getNamespace();
- if ( NS_SPECIAL == $ns ) {
- foreach ( $wgSpecialPageLockdown as $page => $g ) {
- if ( !$title->isSpecial( $page ) ) {
- continue;
+ if ( $action == 'read' && is_array( $wgWhitelistRead ) ) {
+ // don't impose read restrictions on whitelisted pages
+ if ( in_array( $title->getPrefixedText(),
$wgWhitelistRead ) ) {
+ return true;
}
- $groups = $g;
- break;
}
- } else {
- $groups = @$wgNamespacePermissionLockdown[$ns][$action];
+
+ $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 ) {
- $groups = @$wgNamespacePermissionLockdown['*'][$action];
+ // 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;
+ }
+ }
+
+ /**
+ * Determine if the user is a member of a group that is allowed to
+ * perform the given action.
+ *
+ * @param OutputPage $output n/a
+ * @param Article $article n/a
+ * @param Title $title n/a
+ * @param User $user whose groups we will check
+ * @param WebRequest $request used to get the raw action
+ * @param MediaWiki $wiki used to get the parsed action
+ * @return bool
+ * @see
https://www.mediawiki.org/wiki/Manual:Hooks/MediaWikiPerformAction
+ */
+ public static 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 ]
+ );
+ }
+ }
+
+ /**
+ * Filter out the namespaces that the user is locked out of
+ *
+ * @param array &$searchableNs Is filled with searchable namespaces
+ * @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 = @$wgNamespacePermissionLockdown[$ns]['*'];
+ $groups = isset(
$wgNamespacePermissionLockdown[$ns]['*'] )
+ ?
$wgNamespacePermissionLockdown[$ns]['*']
+ : null;
}
+ return $groups;
}
- 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;
- }
-}
-
-/**
- * Determine if the user is a member of a group that is allowed to
- * perform the given action.
- *
- * @param OutputPage $output n/a
- * @param Article $article n/a
- * @param Title $title n/a
- * @param User $user whose groups we will check
- * @param WebRequest $request used to get the raw action
- * @param MediaWiki $wiki used to get the parsed action
- * @return bool
- * @see https://www.mediawiki.org/wiki/Manual:Hooks/MediaWikiPerformAction
- */
-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( [ 'User', 'makeGroupLinkWiki' ],
$groups );
-
- $err = [
- 'badaccess-groups', $wgLang->commaList( $groupLinks ),
- count( $groups )
- ];
- throw new PermissionsError( $request->getVal( 'action' ), [
$err ] );
- }
-}
-
-/**
- * Filter out the namespaces that the user is locked out of
- *
- * @param array &$searchableNs Is filled with searchable namespaces
- * @return bool
- * @see https://www.mediawiki.org/wiki/Manual:Hooks/SearchableNamespaces
- */
-function lockdownSearchableNamespaces( array &$searchableNs ) {
- $user = RequestContext::getMain()->getUser();
- $ugroups = $user->getEffectiveGroups();
-
- foreach ( $searchableNs as $ns => $name ) {
- if ( !lockdownNamespace( $ns, $ugroups ) ) {
- unset( $searchableNs[$ns] );
+ /**
+ * 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 ( is_array( $groups ) && !array_intersect( $ugroups, $groups
) ) {
+ return false;
}
- }
- return true;
-}
-/**
- * Convenience function for internal use only. Determine if one of the
- * list of groups is allowed in this namespace.
- *
- * @param int $ns Namespace being checked
- * @param array $ugroups list of user's groups
- * @return bool
- */
-function lockdownNamespace( $ns, array $ugroups ) {
- global $wgNamespacePermissionLockdown;
-
- $groups = @$wgNamespacePermissionLockdown[$ns]['read'];
- if ( $groups === null ) {
- $groups = @$wgNamespacePermissionLockdown['*']['read'];
- }
- if ( $groups === null ) {
- $groups = @$wgNamespacePermissionLockdown[$ns]['*'];
+ return true;
}
- if ( is_array( $groups ) && !array_intersect( $ugroups, $groups ) ) {
- return false;
- }
+ /**
+ * 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 the term being searched
+ * @param Title $title Title the user is being sent to
+ * @see
https://www.mediawiki.org/wiki/Manual:Hooks/SearchGetNearMatchComplete
+ */
+ public static function onSearchGetNearMatchComplete(
+ $searchterm,
+ Title $title = null
+ ) {
+ global $wgUser;
- 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 the term being searched
- * @param Title $title Title the user is being sent to
- * @see https://www.mediawiki.org/wiki/Manual:Hooks/SearchGetNearMatchComplete
- */
-function lockdownSearchGetNearMatchComplete(
- $searchterm,
- Title $title = null
-) {
- global $wgUser;
-
- if ( $title ) {
- $ugroups = $wgUser->getEffectiveGroups();
- if ( !lockdownNamespace( $title->getNamespace(), $ugroups ) ) {
- $title = null;
+ if ( $title ) {
+ $ugroups = $wgUser->getEffectiveGroups();
+ if ( !self::namespaceCheck( $title->getNamespace(),
$ugroups ) ) {
+ $title = null;
+ }
}
}
}
--
To view, visit https://gerrit.wikimedia.org/r/399544
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: Ief7034bc7b308e3250b4a3241d9bacbc9f49c595
Gerrit-PatchSet: 2
Gerrit-Project: mediawiki/extensions/Lockdown
Gerrit-Branch: master
Gerrit-Owner: MarkAHershberger <[email protected]>
Gerrit-Reviewer: Daniel Kinzler <[email protected]>
Gerrit-Reviewer: Legoktm <[email protected]>
Gerrit-Reviewer: MarkAHershberger <[email protected]>
Gerrit-Reviewer: Thiemo Kreuz (WMDE) <[email protected]>
Gerrit-Reviewer: jenkins-bot <>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits