Updated: Comment #N
Problem/Motivation
There are multiple issues like #2057607: The request does not contain the _account on exception pages (403/404) and many more which shows that we can't deal with just the request object anymore
but have to copy the _account object all the time from the "parent" request.
Proposed resolution
Create a current user service, which just has the account stored in there magically, so no method call will be needed.
Remaining tasks
#2062265: _account is not available in Request in _block_get_renderable_region()
#2062269: _account is not available in Request in during any UnitTest
update change notice https://drupal.org/node/2068221
API changes
Instead of using $request->attributes->get('_account') you can just use Durpal::currentUser() or inject the 'current_user' service, which is an account interface object.
Related Issues
#2061899: Remove references to global $user in Comment module
#2062091: Remove references to global $user in Block module Assigned to: m1r1k
#2062097: Remove calls to deprecated global $user in theme.inc
#2061907: Remove calls to deprecated global $user in shortcut module
Comment | File | Size | Author |
---|---|---|---|
#41 | current_user-2062151-41.patch | 7.82 KB | dawehner |
#41 | interdiff.txt | 3.77 KB | dawehner |
#40 | current_user-2062151-40.patch | 11.26 KB | dawehner |
#40 | interdiff.txt | 7.46 KB | dawehner |
#37 | user-2062151-37.patch | 7.08 KB | dawehner |
Comments
Comment #1
dawehnerOne potential solution would be to proxy the access to the _account object through a service which is request aware.
Once the _account is set on the request, use it, otherwise ask AuthenticationManager to do so.
Comment #2
dawehnerJust as a reference here is the way how symfony handles it: http://symfony.com/doc/current/book/security.html#where-do-users-come-fr... . In our world this would be a method on the authentication manager directly.
Comment #2.0
m1r1k CreditAttribution: m1r1k commentedAdd Remaining tasks that have same problem and related issues
Comment #3
dawehnerHere is a patch which introduces a current user service.
Comment #4
larowlanAwesome!
Trailing space, needs newline (nitpick)
Should we convert one of the problematic ones listed in the related issues above to demonstrate it works?
Should we add a unit test?
Comment #5
dawehnerThis time this actually works and has a test.
Comment #6
larowlanstill persists (nitpick)
but looks good otherwise
Comment #6.0
larowlanAdd related issue
Comment #7
larowlanNew title and updated issue summary
Comment #8
dawehnerAlso added a bit of documentation.
Comment #9
webchickThis blocks a critical (#2040065: Remove _account from request and use the current user service instead.), so it's critical.
It's also approved by catch and I. Tagging.
Comment #10
andypostagree with #4 - one of problematic issues should be used to demo the introduced concept
Comment #10.0
andypostUpdated issue summary.
Comment #11
dawehnerI have chosen the block one, as it has the smallest amount of code.
Comment #12
catchShould this also remove _account from the request object or is that a follow-up?
Comment #13
Crell CreditAttribution: Crell commentedWhy are we removing _account from the request at all?
Comment #14
catchWhy have it there if there's a service handling it?
Comment #15
andypostThe approach is nice but require to inject the service into all controllers that accept request as well so probably better:
1) leave _account in global request object
2) when no _account in request use \Drupal::account()
anyway this breaks encapsulation or require to inject service to all controllers
Comment #16
catchI don't see a problem with injecting this into controllers that need it.
Comment #17
tim.plunkettRight now, any controller can just put
Request $request
in their method and it is automatically passed to them. That's a really nice feature.Comment #18
catchRequest is automatically passed, _account gets lost all over the place like #2040065: Remove _account from request and use the current user service instead. so you either have to explicitly set it whenever creating a request or can't rely on it being there anyway.
Also the way _account is accessed from request is really, really ugly.
Comment #19
dawehnerMe neither. Does that mean that we would have to convert every instance in this issue?
Comment #20
catchAnother reason we should remove _account: https://drupal.org/node/2036351#comment-7752121
@dawehner - we either need to do it here, or open another critical follow-up. I'm not too fussed either way but since there's disagreement on doing it at all, I think we should probably make the final decision here regardless - I don't want to have the same conversation twice about the same thing once immediately after the other.
Comment #21
dawehnerI absolutely agree that we should stop the _account conversions based upon this issue.
When converting I would suggest to do just $request->attributes->get(_account) => Drupal::account() or now, or should we also inject things? This would make the patch way bigger.
Comment #22
Damien Tournoud CreditAttribution: Damien Tournoud commentedThe
CurrentAccount
service introduced in this patch (registered ascurrent_account
) is very close to SymfonySecurityContext
service, usually registered atsecurity.context
.This brings us one step further in our piece-by-piece reimplementation of Symfony's security component. Is it time to stop and just leverage the component that exists?
Comment #23
Crell CreditAttribution: Crell commentedDamien: I am not going to burn any karma on that drastic of an API change at this stage of the game. Our authorization system is also, as I understand it, very different than Symfony's so it's not like we could just drop it in without a lot of work.
Comment #24
Damien Tournoud CreditAttribution: Damien Tournoud commentedCrell: I did the research, and described what need to happen. It's clearly less complicated than rebuilding the whole thing from scratch, piece by piece. But of course, it's also fine to ship Drupal 8 with an half-backed API that nobody will want to touch with a ten-foot pole.
Comment #25
dawehnerAre there more issues which are not solvable by without changing APIs on the authentication system?
We not only maybe have bugs, but we also have a limited amount of people/time.
Comment #26
andypost#22 makes sense because we already have bits of this invented here. Symfony have great doc about security so Drupal is implementing same code step-by-step...
Initially in #335411: Switch to Symfony2-based session handling was proposed to use
SessionProxy
then context approach #1260864: Convert global $user to a context key was wont-fixed by Crell and finally #1858196: [meta] Leverage Symfony Session components we have 40k patch that passes tests and implements listener on request|response and uses global $user object.#1890878: Add modular authentication system, including Http Basic; deprecate global $user implements route enhancer to home-grown authentication system very similar to symfony's
As masquerade module maintainer I'd like to have swappable service but I think domain module will bring more questions.
@dawehner suppose more bugs will be filed when contrib will start porting to 8.x, all issues about _account are filed within One week as result of 1 day testing d7 upgrade and 1 day code sprint on issues #2047951: [META] Remove calls to deprecated global $user and $GLOBALS['user'] and #2048171: [meta] Replace user_access() calls with $account->hasPermission() wherever possible.
Suppose at the current release phase better to investigate all known issues and available implementations
Comment #27
msonnabaum CreditAttribution: msonnabaum commented#11 looks ok to me. I don't see why we'd try to expand the scope here beyond that. We just need a simple service that returns the current user.
Even if we ended up using symfony's security component in d9 I'd still keep this interface and delegate so that people didnt have to call ->getToken()->getUser().
Comment #28
dawehnerWe talked a bit in IRC about it, so we will automatically generate a AccountInterface object in the service container using the authentication manager as factory.
Even there was a beer lost on this patch ...
Comment #28.0
dawehnerAdded related issue.
Comment #29
tim.plunkettOne of the nice things about it being on the request is that when we use the controller resolver, a controller can always get the request passed to it, with no need for our static factory injection pattern.
This is really common for forms.
This will mean that a lot of forms will now need to get this service, and switch to needing full injection...
Comment #30
tim.plunkettMy last comment becomes almost obsolete if #2059245: Add a FormBase class containing useful methods goes in.
Comment #31
Damien Tournoud CreditAttribution: Damien Tournoud commentedI agree that getting the current account from the request is what you would expect... but Symfony's
Request
object is very inextensible, and the only API that we can use for that is the current ugly, non-semantic and error-prone:The only way to do that right now would be to sub-class the
Request
object. I'm not sure I would recommend that.Comment #32
dawehnerLet's also add a method to the ControllerBase as talked in IRC.
Comment #33
JohnAlbin$request->attributes->get('_account');
is procedural code with a dead-OO pelt draped over it.Comment #33.0
JohnAlbinblub
Comment #34
Crell CreditAttribution: Crell commentedI want to have a test to verify that this does work cleanly through a subrequest properly. It should, but I want to be extra careful here. If we can test that it stacks properly then I am OK with committing this approach.
Comment #35
dawehnerThere we go.
Comment #36
Crell CreditAttribution: Crell commentedWas this supposed to be in the patch? (A lot of test methods have it now.)
This TODO seems TODONE. :-)
Comment #37
dawehnerUps.
Comment #38
Crell CreditAttribution: Crell commentedMuch better. :-) I don't see how the test works, though. It's not changing the user that I can see, is it?
Comment #39
msonnabaum CreditAttribution: msonnabaum commented#37 looks great.
Comment #40
dawehnerDo you mean something like this?
Comment #41
dawehnerOr in other words ... https://drupal.org/project/issues/search/drupal?issue_tags=phpunit
Comment #42
Crell CreditAttribution: Crell commentedOK, let's do this thing.
Comment #43
catchOK. Committed/pushed to 8.x.
I opened #2073531: Use current user service instead of _account, remove _account from the request object for the follow-up.
Comment #44
dawehnerSome of the changed change-records:
https://drupal.org/node/2049309
https://drupal.org/node/2032447
https://drupal.org/node/2017231
Should there we another one, or does 2) actually describes enough?
Comment #45
chx CreditAttribution: chx commented2) is enough.
Comment #46.0
(not verified) CreditAttribution: commentedadded https://drupal.org/node/2068221