Étienne Beaulé <beauleetienne0@gmail.com>
Željko Filipin <zeljko.filipin@gmail.com>
Željko Filipin <zeljko.filipin@gmail.com> <zfilipin@wikimedia.org>
+星耀晨曦 <razesoldier@outlook.com>
+星耀晨曦 <razesoldier@outlook.com> <liguangjie4399@hotmail.com>
* rahul21
* Raimond Spekking
* Ramunas Geciauskas
-* RazeSoldier
* Remember the dot
* René Kijewski
* Reza
* The PasswordPolicy 'PasswordCannotBePopular' has been deprecated. To
follow best practices, it is reccommended to use 'PasswordNotInLargeBlacklist'
instead which blacklists 100,000 commonly used passwords.
+* (T208862) Action::requiresUnblock() is now called from
+ Title::getUserPermissionsErrors() and Title::userCan(). Previously, the method
+ was only called in Action::checkCanExecute(). Actions should ensure that their
+ requiresUnblock() returns the proper result (the default is `true`).
* …
=== Other changes in 1.33 ===
}
$useReplica = ( $rigor !== 'secure' );
- if ( ( $action == 'edit' || $action == 'create' )
- && !$user->isBlockedFrom( $this, $useReplica )
- ) {
- // Don't block the user from editing their own talk page unless they've been
- // explicitly blocked from that too.
- } elseif ( $user->isBlocked() && $user->getBlock()->prevents( $action ) !== false ) {
+ $block = $user->getBlock( $useReplica );
+
+ // The block may explicitly allow an action (like "read" or "upload").
+ if ( $block && $block->prevents( $action ) === false ) {
+ return $errors;
+ }
+
+ // Determine if the user is blocked from this action on this page.
+ // What gets passed into this method is a user right, not an action nmae.
+ // There is no way to instantiate an action by restriction. However, this
+ // will get the action where the restriction is the same. This may result
+ // in actions being blocked that shouldn't be.
+ if ( Action::exists( $action ) ) {
// @todo FIXME: Pass the relevant context into this function.
- $errors[] = $user->getBlock()->getPermissionsError( RequestContext::getMain() );
+ $action = Action::factory( $action, WikiPage::factory( $this ), RequestContext::getMain() );
+ } else {
+ $action = null;
+ }
+
+ // If no action object is returned, assume that the action requires unblock
+ // which is the default.
+ if ( !$action || $action->requiresUnblock() ) {
+ if ( $user->isBlockedFrom( $this, $useReplica ) ) {
+ // @todo FIXME: Pass the relevant context into this function.
+ $errors[] = $block
+ ? $block->getPermissionsError( RequestContext::getMain() )
+ : [ 'actionblockedtext' ];
+ }
}
return $errors;
* );
* @endcode
*
+ * Example usage (key that is expensive with too many DB dependencies for "check keys"):
+ * @code
+ * $catToys = $cache->getWithSetCallback(
+ * // Key to store the cached value under
+ * $cache->makeKey( 'cat-toys', $catId ),
+ * // Time-to-live (seconds)
+ * $cache::TTL_HOUR,
+ * // Function that derives the new key value
+ * function ( $oldValue, &$ttl, array &$setOpts ) {
+ * // Determine new value from the DB
+ * $dbr = wfGetDB( DB_REPLICA );
+ * // Account for any snapshot/replica DB lag
+ * $setOpts += Database::getCacheSetOptions( $dbr );
+ *
+ * return CatToys::newFromResults( $dbr->select( ... ) );
+ * },
+ * [
+ * // Get the highest timestamp of any of the cat's toys
+ * 'touchedCallback' => function ( $value ) use ( $catId ) {
+ * $dbr = wfGetDB( DB_REPLICA );
+ * $ts = $dbr->selectField( 'cat_toys', 'MAX(ct_touched)', ... );
+ *
+ * return wfTimestampOrNull( TS_UNIX, $ts );
+ * },
+ * // Avoid DB queries for repeated access
+ * 'pcTTL' => $cache::TTL_PROC_SHORT
+ * ]
+ * );
+ * @endcode
+ *
* Example usage (hot key holding most recent 100 events):
* @code
* $lastCatActions = $cache->getWithSetCallback(
* expired for this specified time. This is useful if adaptiveTTL() is used on the old
* value's as-of time when it is verified as still being correct.
* Default: WANObjectCache::STALE_TTL_NONE
- * - touchedCallback: A callback that takes the current value and returns a timestamp that
- * indicates the last time a dynamic dependency changed. Null can be returned if there
+ * - touchedCallback: A callback that takes the current value and returns a UNIX timestamp
+ * indicating the last time a dynamic dependency changed. Null can be returned if there
* are no relevant dependency changes to check. This can be used to check against things
* like last-modified times of files or DB timestamp fields. This should generally not be
* used for small and easily queried values in a DB if the callback itself ends up doing
"blockedtext": "<strong>Your username or IP address has been blocked.</strong>\n\nThe block was made by $1.\nThe reason given is <em>$2</em>.\n\n* Start of block: $8\n* Expiration of block: $6\n* Intended blockee: $7\n\nYou can contact $1 or another [[{{MediaWiki:Grouppage-sysop}}|administrator]] to discuss the block.\nYou cannot use the \"{{int:emailuser}}\" feature unless a valid email address is specified in your [[Special:Preferences|account preferences]] and you have not been blocked from using it.\nYour current IP address is $3, and the block ID is #$5.\nPlease include all above details in any queries you make.",
"autoblockedtext": "Your IP address has been automatically blocked because it was used by another user, who was blocked by $1.\nThe reason given is:\n\n:<em>$2</em>\n\n* Start of block: $8\n* Expiration of block: $6\n* Intended blockee: $7\n\nYou may contact $1 or one of the other [[{{MediaWiki:Grouppage-sysop}}|administrators]] to discuss the block.\n\nNote that you may not use the \"{{int:emailuser}}\" feature unless you have a valid email address registered in your [[Special:Preferences|user preferences]] and you have not been blocked from using it.\n\nYour current IP address is $3, and the block ID is #$5.\nPlease include all above details in any queries you make.",
"systemblockedtext": "Your username or IP address has been automatically blocked by MediaWiki.\nThe reason given is:\n\n:<em>$2</em>\n\n* Start of block: $8\n* Expiration of block: $6\n* Intended blockee: $7\n\nYour current IP address is $3.\nPlease include all above details in any queries you make.",
+ "actionblockedtext": "You have been blocked from performing this action.",
"blockednoreason": "no reason given",
"whitelistedittext": "Please $1 to edit pages.",
"confirmedittext": "You must confirm your email address before editing pages.\nPlease set and validate your email address through your [[Special:Preferences|user preferences]].",
"blockedtext": "Text displayed to blocked users.\n\n\"email this user\" should be consistent with {{msg-mw|Emailuser}}.\n\nParameters:\n* $1 - the blocking sysop (with a link to his/her userpage)\n* $2 - the reason for the block\n* $3 - the current IP address of the blocked user\n* $4 - (Unused) the blocking sysop's username (plain text, without the link)\n* $5 - the unique numeric identifier of the applied autoblock\n* $6 - the expiry of the block\n* $7 - the intended target of the block (what the blocking user specified in the blocking form)\n* $8 - the timestamp when the block started\nSee also:\n* {{msg-mw|Grouppage-sysop}}\n* {{msg-mw|Autoblockedtext|notext=1}}\n* {{msg-mw|Systemblockedtext|notext=1}}",
"autoblockedtext": "Text displayed to automatically blocked users.\n\n\"email this user\" should be consistent with {{msg-mw|Emailuser}}.\n\nParameters:\n* $1 - the blocking sysop (with a link to his/her userpage)\n* $2 - the reason for the block (in case of autoblocks: {{msg-mw|autoblocker}})\n* $3 - the current IP address of the blocked user\n* $4 - (Unused) the blocking sysop's username (plain text, without the link). Use it for GENDER.\n* $5 - the unique numeric identifier of the applied autoblock\n* $6 - the expiry of the block\n* $7 - the intended target of the block (what the blocking user specified in the blocking form)\n* $8 - the timestamp when the block started\nSee also:\n* {{msg-mw|Grouppage-sysop}}\n* {{msg-mw|Blockedtext|notext=1}}\n* {{msg-mw|Systemblockedtext|notext=1}}",
"systemblockedtext": "Text displayed to requests blocked by MediaWiki configuration.\n\n\"email this user\" should be consistent with {{msg-mw|Emailuser}}.\n\nParameters:\n* $1 - (Unused) A dummy user attributed as the blocker, possibly as a link to a user page.\n* $2 - the reason for the block\n* $3 - the current IP address of the blocked user\n* $4 - (Unused) the dummy blocking user's username (plain text, without the link).\n* $5 - A short string indicating the type of system block.\n* $6 - the expiry of the block\n* $7 - the intended target of the block\n* $8 - the timestamp when the block started\nSee also:\n* {{msg-mw|Grouppage-sysop}}\n* {{msg-mw|Blockedtext|notext=1}}\n* {{msg-mw|Autoblockedtext|notext=1}}",
+ "actionblockedtext": "Text displayed when a user is blocked from perofmring an action, but no matching block for the user exists. This can happen if an extension forces a user to be blocked.",
"blockednoreason": "Substituted with <code>$2</code> in the following message if the reason is not given:\n* {{msg-mw|cantcreateaccount-text}}.\n{{Identical|No reason given}}",
"whitelistedittext": "Used as error message. Parameters:\n* $1 - a link to [[Special:UserLogin]] with {{msg-mw|loginreqlink}} as link description\n* $2 - an URL to the same\n\nSee also:\n* {{msg-mw|Nocreatetext}}\n* {{msg-mw|Uploadnologintext}}\n* {{msg-mw|Loginreqpagetext}}",
"confirmedittext": "Used as error message.",
<?php
+use MediaWiki\Block\Restriction\PageRestriction;
use MediaWiki\MediaWikiServices;
/**
'wgEmailAuthentication' => true,
] );
- $this->setUserPerm( [ "createpage", "move" ] );
+ $this->setUserPerm( [ 'createpage', 'edit', 'move', 'rollback', 'patrol', 'upload', 'purge' ] );
$this->setTitle( NS_HELP, "test page" );
# $wgEmailConfirmToEdit only applies to 'edit' action
'expiry' => 10,
'systemBlock' => 'test',
] );
- $this->assertEquals( [ [ 'systemblockedtext',
+
+ $errors = [ [ 'systemblockedtext',
'[[User:Useruser|Useruser]]', 'no reason given', '127.0.0.1',
'Useruser', 'test', '23:00, 31 December 1969', '127.0.8.1',
- $wgLang->timeanddate( wfTimestamp( TS_MW, $now ), true ) ] ],
+ $wgLang->timeanddate( wfTimestamp( TS_MW, $now ), true ) ] ];
+
+ $this->assertEquals( $errors,
+ $this->title->getUserPermissionsErrors( 'edit', $this->user ) );
+ $this->assertEquals( $errors,
$this->title->getUserPermissionsErrors( 'move-target', $this->user ) );
+ $this->assertEquals( $errors,
+ $this->title->getUserPermissionsErrors( 'rollback', $this->user ) );
+ $this->assertEquals( $errors,
+ $this->title->getUserPermissionsErrors( 'patrol', $this->user ) );
+ $this->assertEquals( $errors,
+ $this->title->getUserPermissionsErrors( 'upload', $this->user ) );
+ $this->assertEquals( [],
+ $this->title->getUserPermissionsErrors( 'purge', $this->user ) );
// partial block message test
$this->user->mBlockedby = $this->user->getName();
'expiry' => 10,
] );
- $this->assertEquals( [ [ 'blockedtext-partial',
+ $this->assertEquals( [],
+ $this->title->getUserPermissionsErrors( 'edit', $this->user ) );
+ $this->assertEquals( [],
+ $this->title->getUserPermissionsErrors( 'move-target', $this->user ) );
+ $this->assertEquals( [],
+ $this->title->getUserPermissionsErrors( 'rollback', $this->user ) );
+ $this->assertEquals( [],
+ $this->title->getUserPermissionsErrors( 'patrol', $this->user ) );
+ $this->assertEquals( [],
+ $this->title->getUserPermissionsErrors( 'upload', $this->user ) );
+ $this->assertEquals( [],
+ $this->title->getUserPermissionsErrors( 'purge', $this->user ) );
+
+ $this->user->mBlock->setRestrictions( [
+ ( new PageRestriction( 0, $this->title->getArticleID() ) )->setTitle( $this->title ),
+ ] );
+
+ $errors = [ [ 'blockedtext-partial',
'[[User:Useruser|Useruser]]', 'no reason given', '127.0.0.1',
'Useruser', null, '23:00, 31 December 1969', '127.0.8.1',
- $wgLang->timeanddate( wfTimestamp( TS_MW, $now ), true ) ] ],
+ $wgLang->timeanddate( wfTimestamp( TS_MW, $now ), true ) ] ];
+
+ $this->assertEquals( $errors,
+ $this->title->getUserPermissionsErrors( 'edit', $this->user ) );
+ $this->assertEquals( $errors,
$this->title->getUserPermissionsErrors( 'move-target', $this->user ) );
+ $this->assertEquals( $errors,
+ $this->title->getUserPermissionsErrors( 'rollback', $this->user ) );
+ $this->assertEquals( $errors,
+ $this->title->getUserPermissionsErrors( 'patrol', $this->user ) );
+ $this->assertEquals( [],
+ $this->title->getUserPermissionsErrors( 'upload', $this->user ) );
+ $this->assertEquals( [],
+ $this->title->getUserPermissionsErrors( 'purge', $this->user ) );
}
}