Drawing from comments associated with `User::newSystemUser` for
checking if a user is a system user, a new method, `User:isSystemUser`
is split out to avoid duplication elsewhere.
Bug: T237356
Change-Id: I73f25a10df2c28a69f612eb1db3e91b7125383d9
DatabaseBlock methods for handling block cookies are deprecated, so
stop using these methods in tests and throw warnings.
Change-Id: I2b5cfd579aa14bbfc7a292587a288ee5032eb5ab
To avoid preference bloat, this preference is hidden unless the new
sysadmin config $wgSearchMatchRedirectPreference is set.
Bug: T235263
Change-Id: Ic16f53a4e6ddb6da071d63cd5da28d937d4692c8
Various maintenance scripts assume reserved usernames like
"MediaWiki default" exist, but since they're reserved
User::isUsableName() returns false and therefore the actor migration
created them as anonymous actors. Which would then prevent those
maintenance scripts from using User::newSystemUser() to ensure they
actually exist.
This adjusts User::newSystemUser() to be able to create users for
those anonymous actors.
This also adjusts uses of "MediaWiki default" in core to create it as a
system user.
Bug: T236444
Change-Id: I59a646df36ff9343cc43c05aa20b2b69b2ee124a
Before this commit, several tests in UserTest set User::mBlock, then
call BlockManager::trackBlockWithCookie, which indirectly sets
User::mBlock. These lines are safe to remove, ahead of deprecating
public access to the property (see T229035).
Change-Id: I36a833ee0904ed1573ac414c8524b60210d97feb
This was previously hardcoded from three places: 1) Upon viewing EditPage,
2) Upon viewing SpecialCreateAccount, 3) For any url if the user is
logged-in (User::loadFromSession/isLoggedIn).
== User::loadFromSession
Performing cookie blocks from here created a circular dependency because
Block may need the user language for localisation, which is determined by
asking the User object. This was previously worked around by using a
DeferredUpdate (T180050, T226777). Moving this logic explicitly to the
end of the pre-send cycle in MediaWiki::preOutputCommit breaks the cycle.
This is also where other request-specific handling resides already.
== Limited effect on unregistered users
When an unregistered user performs an edit, and gets blocked,
the cookie block is not applied until they open built-in editor
or CreateAccount page. This makes it more likely for a user's
IP to change meanwhile. Either intentionally, or simply due to
IPs varying naturally (e.g. between mobile locations, or when
going on/off WiFi). By applying it throughout sessioned page
views for unregistered users, it is more likely to get set.
Similar to what was already done for logged-in users.
This commit also makes the intent of not caching EditPage and
SpecialCreateAccount explicit. This was previously implicit
through nothing having called setCdnMaxage() and/or due to
Session::persist being checked for by OutputPage::sendCacheControl.
Bug: T233594
Change-Id: Icf5a00f9b41d31bb6d4742c049feca0039d0c9d9
assertSame() is guaranteed to not do any type conversion. This can be
critical when acciden tially comparing, for example, 0 to 0.0.
Change-Id: Iffcc9bda69573623ba14af655dcd697d0fcce525
Blocks are checked from the User object. Specifically,
User::getBlockedStatus instantiates a BlockManager and calls
BlockManager::getUserBlock. However, checking the block often depends
on knowing more about the state than the User should know. As a result,
the global user and request objects were passed into the block manager
on construction.
Whether the global request object should be passed into a service
constructor is still up for debate, so this moves the check for the
global state back to User::getBlockedStatus for now. (Note that it
reintroduces the problem of the User knowing more about state than it
should.)
This change also makes clearer the cases in which
BlockManager::getUserBlock is called from the User.
Different blocks may be sought, depending on the user and their
permissions. The user may be:
(1) The global user (and can be affected by IP blocks). The global
request object is needed for checking the IP address, the XFF
header and the cookies.
(2) The global user (and exempt from IP blocks). The global request
object is needed for checking the cookies.
(3) Another user (not the global user). No request object is available
or needed; just look for a block against the user account.
Cases #1 and #2 check whether the global user is blocked in practice;
the block may due to their user account being blocked or to an IP
address block or cookie block (or multiple of these). Case #3 simply
checks whether a user's account is blocked, and does not determine
whether the person using that account is affected in practice by any
IP address or cookie blocks.
Bug: T231919
Change-Id: I3f51fd3579514b83b567dfe20926df2f0930dc85
This removes most of the pre-actor user and user_text columns, and the
$wgActorTableSchemaMigrationStage setting that used to determine
whether the columns were used.
rev_user and rev_user_text remain in the code, as on Wikimedia wikis the
revision table is too large to alter at this time. A future change will
combine that with the removal of rev_comment, rev_content_model, and
rev_content_format (and the addition of rev_comment_id and rev_actor).
ActorMigration's constructor continues to take a $stage parameter, and
continues to have the logic for handling it, for the benefit of
extensions that might need their own migration process. Code using
ActorMigration for accessing the core fields should be updated to use
the new actor fields directly. That will be done for in a followup.
Bug: T188327
Change-Id: Id35544b879af1cd708f3efd303fce8d9a1b9eb02
Was reverted by I549810a4cd2e424cc4a438887d2f24614a24cc00 due to
T224607.
Original change by Vedmaka Wakalaka was
Ia0d840b772ea5f20c9594ce151cc57adc270e48b.
Original commit message:
The following methods should are factored out of the User class into PermissionManager,
leaving only deprecated stubs:
- User::isAllowed -> PermissionManager::userHasRight
- User::getRights -> PermissionManager::getUserPermissions
- User::groupHasPermission -> PermissionManager::groupHasPermission
- User::getGroupPermissions -> PermissionManager::getGroupPermissions
-User::getGroupsWithPermission -> PermissionManager::getGroupsWithPermission
- User::groupHasPermission -> PermissionManager::groupHasPermission
- User::isEveryoneAllowed -> PermissionManager::isEveryoneAllowed
- User::getAllRights -> PermissionManager::getAllPermissions
Depends-On: I7909e9bd6bbfbd708c0a00b861a9b22a38c6665d
Bug: T218558
Bug: T223294
Change-Id: I8899240378f636ea70f447616710516c0a3c5c31
Create a CompositeBlock class which extends AbstractBlock and
adds the property $originalBlocks. This is for situations where
more than one block applies to a user/IP, and avoids the need
to choose just one of these blocks to enforce.
Behaviour of the resulting block is determined by combining the
strictest parameters of the original blocks.
Also add DatabaseBlock::newListFromTarget, which is similar to
DatabaseBlock::newFromTarget, but returns all relevant blocks,
rather than choosing the most specific one.
For tracking a CompositeBlock with a cookie, examine the
original blocks and only track the first trackable block that
is found.
Bug: T206163
Change-Id: I088401105ac8ceb2c6117c6d2fcdb277c754d882
Move the cookie blocking logic into one place. Specifically, move
these methods to the BlockManager:
* User::trackBlockWithCookie
* DatabaseBlock::setCookie
* DatabaseBlock::clearCookie
* DatabaseBlock::getCookieValue
* DatabaseBlock::getIdFromCookieValue
* AbstractBlock::shouldTrackWithCookie
After this, BlockManager::trackBlockWithCookie should be called to
track a block, and BlockManager::clearBlockCookie should be called
to unset the cookie. The other methods in the above list are
helper methods that are made private or marked internal.
Also update places in core that call User::trackBlockWithCookie to
BlockManager::trackBlockWithCookie
Bug: T225141
Change-Id: I818962c6932c01c841a549a101637e00a7593e48
Keep Block as a deprecated class alias for DatabaseBlock.
Update calls to the Block constructor and Block static
methods from external classes.
Also update documentation in several places that refer to
blocks as Blocks.
Bug: T222737
Change-Id: I6d96b63ca0a84bee19486471e0a16a53a79d768a
This commit splits the existing Block class into AbstractBlock, Block
and SystemBlock.
Before this patch, the Block class represents several types of
blocks, which can be separated into blocks stored in the database,
and temporary blocks created by the system. These are now
represented by Block and SystemBlock, which inherit from
AbstractBlock.
This lays the foundations for:
* enforcing block parameters from multiple blocks that apply to a
user/IP address
* improvements to the Block API, including the addition of services
Breaking changes: functions expecting a Block object should still
expect a Block object if it came from the database, but other
functions may now need to expect an AbstractBlock or SystemBlock
object. (Note that an alternative naming scheme, in which the
abstract class is called Block and the subclasses are DatabaseBlock
and SystemBlock, avoids this breakage. However, it introduces more
breakages to calls to static Block methods and new Block
instantiations.)
Changes to tests: system blocks don't set the $blockCreateAccount or
$mExipry block properties, so remove/change any tests that assume
they do.
Bug: T222737
Change-Id: I83bceb5e5049e254c90ace060f8f8fad44696c67
Stop-gap solution for the problem described in T222212.
Force the User ID and Actor ID to zero for users loaded
from the database of another wiki, to prevent subtle data
corruption and confusing failure modes.
Bug: T222381
Change-Id: Ic585f972d61da136744d080df13d8eb1ecd04cf5
I wasn't able to port some places that rely on isAllowed, getOption, or
related methods.
This adds isRegistered() to UserIdentity, which works like
User::isLoggedIn() but with a better name.
I also cleaned up User mocks in WatchedItemQueryServiceUnitTest in the
course of debugging test failures when switching them to
UserIdentityValue instead of mock Users where possible. They now specify
explicitly which methods are allowed to be called on their User objects,
which I believe is good practice for mocks (and unfortunately PHPUnit
makes it awkward).
Bug: T207972
Depends-On: I883d506197a011fe4c102b72df4d9deb58ab5ca2
Change-Id: Iadbf7bc31a496899dbef44e49065ff89f37aea89
Probably good to start testing this in CI sometime soon.
This also updates a bunch of tests that were forcing an older stage to
force SCHEMA_COMPAT_NEW instead, or to test both ways (until a future
patch removes the _OLD version).
Bug: T188327
Change-Id: Icb9b55cb9d754f2d30d6883005658b9670834756
This patch makes sure, that idFromName always returns either an int
or null value. The $idCacheByName can contain string values so we cast
the values if necessary.
An alternative could have been to make sure that just int values go
into the cache. But since the cache is public the current approach
to seems to be better atm.
Change-Id: I3085d89b93db2b888c190ba193623b86dc93759a
This introduces a minimal BlockManager service, for getting blocks
that apply to a User.
Move the part of User::getBlockedStatus that checks for the blocks
into BlockManager::getUserBlock, and move the related helper
methods from User to BlockManager.
Hard deprecate or remove these helper methods, and move to private
methods in the BlockManager:
* User::getBlockFromCookieValue
* User::isLocallyBlockedProxy
* User::inDnsBlacklist
Soft deprecate these helper methods, and move to public methods in
the BlockManager:
* User::isDnsBlacklisted
Add tests to cover the methods moved to BlockManager.
Bug: T219441
Change-Id: I0af658d71288376735cebe541215383b56bb72e5
The method User::isBlocked() attempts to answer two questions:
(1) Does the user have a block?
(2) Is the user prevented from performing this action?
The method can answer #1, but it cannot answer #2. Since User::getBlock() can
also answer #1, this method is redundant. The method cannot answer #2 because
there is not enough context in order to answer that question.
If access is being checked against a Title object, all access checks can be
performed with PermissionManager:userCan() which will also check the user's
blocks.
If performing all access checks is not desirable, using
PermissionManager::isBlockedFrom() is also acceptable for only checking if the
user is blocked. This method does *not* determine if the action is allowed,
only that the user's block applies to that Title.
If access is being checked without an existing Title, User::getBlock() can be
used to get the user's block. Then Block::appliesToRight() can be used to
determine if the block applies explicitly to a right (or returns null if
it is unknown or false if explicitly allowed). If the user is creating a new
Title, but the text of the title is not yet known (as in the case of Wikibase),
access should be checked with Block::appliesToNamespace().
Bug: T209004
Change-Id: Ic0ad1b92e957797fee8dcd00bd1092fe69fa58f1
Use getters and setters for $mReason, $mTimestamp, $mExpiry and
$mHideName; use Block::getType to check if a block is an autoblock
instead of checking $mAuto; no change needed for $mParentBlockId,
which is not accessed externally.
Change-Id: I767ed44ce4c2e21f53962d75fb86891add2282f6
$wgUser is not guaranteed to exist until MediaWiki has been fully
initialized; block status needs to be checked early on for
authentication-related permission checks.
Bug: T218608
Change-Id: I16315c071855024bc0412d5360c95f843420d9a9
This will be used by the GrowthExperiments
Mentorship module to show when a user made their
latest contribution.
* Introduce a private function to reduce duplication with
getFirstEditTimestamp()
* Add unit tests for both
Bug: T216631
Change-Id: Ica3e6e7165496bdc9b8f12972cf93847ecfffa50
In the complicated decision tree for checking if a blocked
user is blocked from their talk page, one situation was not
being tested: there's a partial block to the user talk
namespace, the block is flagged as allowing a user to edit
their talk page, BUT $wgBlockAllowsUTEdit is false. In this
circumstance, the user should be blocked from editing their
talk page, as outlined in T210475.
Also, fix whitespace and make messages clearer, since this
is now quite complicated.
Change-Id: I234f3019d55a6da0da091a2eaae6c791be01b436
This begins work on making namespaces a valid restriction type. The CRUD
operations of BlockRestriction can now handle namespaces. Since
NamespaceRestriction implements Restriction, enforcement should start working
immediately, but testing enforcement will come in a subsequent patch since it's
impossible to create them.
Bug: T204991
Change-Id: I7264b452d9ad788c146d6ea25d01d4d7cb5ac4f6
Unused, the return format does not seem useful.
Also improve the documentation of $wgPasswordPolicy
and PasswordPolicyChecks.
Change-Id: Ic01e80cfefc4cfb0eee1eccc6a66942f692278a0
No changes for sitewide blocks when "Prevent user... edit own talk page"
is checked. On partial blocks, this option will be disabled and ignored. All users
will be allowed to edit their own talk page unless a page restriction
for their page is in place.
New rules will be implemented for Namespace restrictions in a different
patch when Namespace blocking is ready.
Bug: T210475
Change-Id: I096edf2887441bccd59f09bf0eceb3988b36db1e
blocked' option on partial blocks.
Partial blocks currently ignore this option as it gets into an edge case. The
option should take precidence if it is true, but should be ignored if it is
false. On sitewide blocks, the option should always be honored.
Bug: T210475
Change-Id: I33177b48a5c261ec3f510ce01998c1b096077b85
The fix applied in d67121f6d took care of the immediate issue in
T208398, but after further analysis it was not a correct fix.
* Near line 770, the method shouldn't even be called unless the target
is TYPE_USER.
* Near line 1598, it isn't dealing with a target at all.
* Near line 1813, you're not going to get a sensible result trying to
call `$user->getTalkPage()` for a range or auto-block ID. What you
would really need there to handle range and auto-blocks correctly is
to pass in the User actually making the edit.
But after some pushback in code review about passing the User into
Block::preventsEdit() to make line 1813 work, we'll instead replace the
method with Block::appliesToTitle() and put the check for user talk
pages back into User::isBlockedFrom().
Bug: T208398
Bug: T208472
Change-Id: I23d3a3a1925e97f0cabe328c1cc74e978cb4d24a
This should reduce excess contention and lock timeouts.
Previously, it used a pre-commit hook which ran just before the
end of the DB transaction round.
Also removed unused User::incEditCountImmediate() method.
Bug: T202715
Depends-on: I6d239a5ea286afb10d9e317b2ee1436de60f7e4f
Depends-on: I0ad3d17107efc7b0e59f1dd54d5733cd1572a2b7
Change-Id: I0d6d7ddd91bbb21995142808248d162e05696d47