Problem:
Some key functionality attached to user relies on global state to gain access to the current user's session as well as HTTP request information such as the client's IP address and cookies. This is needed in particular for abuse prevention via auto-blocking (based on IP and cookies) as well as rate limit (per user, per session, or per IP). We need a way to provide access to this information without having to rely on global state. However, refactoring all relevant code to explicitly pass down a WebRequest object seems undesirable, if at all feasible.
Examples of this can be found in PermissionManager and RequestManager, or by looking for usages of User::getRequest or User::pingLimiter. Callers of RequestContent::getMain() are also problematic, though that method is often called for other reasons as well.
Proposal:
Introduce ActingUser as an interface that extends UserIdentity. Critical checks, such as calls to PermissionManager::userCan with RIGOR_SECURE, must fail if presented with a UserIdentity that is not an ActingUser, or should require an ActingUser in the signature. The ActingUser represents not a user as such, but a user acting withing a certain context (a device, a session, oath token, address, etc). This context represents the execution context of the entire application (thanks th PHP's per-request execution model). For maintenance scripts and async jobs, the execution context would essentially just be "CLI" or "JOB".
Code that needs to check for context-based blocks or limits (session,IP address, cookies, device) will need access to some aspects of the http request. ActingUser could provide methods to access this information, but it's unclear how exactly these methods should behave in a non-web execution context. The relevant calling code will probably have to know about web-mode and cli-mode ActingUsers in any case.
Code that makes direct use of ActingUsers should be rare. However, it's likely to be used via many code paths for many use cases.
NOTE: this supersedes T218555