Skip to content

Check provider supports user class #29653

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed

Check provider supports user class #29653

wants to merge 3 commits into from

Conversation

HTMLGuyLLC
Copy link

Q A
Branch? master
Bug fix? no
New feature? yes
BC breaks? potentially? shouldn't though.
Deprecations? no
Tests pass? yes
Fixed tickets
License MIT
Doc PR

This feature checks that a user is compatible with a user provider prior to running refreshUser(). It eliminates the need for this logic inside the refreshUser method.

@HTMLGuyLLC
Copy link
Author

HTMLGuyLLC commented Dec 19, 2018

You may want to switch back to \get_class(). I used a variable under the impression that calling that method repeatedly is SLIGHTLY less performant since it's done several times throughout that method.

@HTMLGuyLLC
Copy link
Author

HTMLGuyLLC commented Dec 19, 2018

This pull request is meant to be an example solution for #29652. However, I believe it is good enough to be merged if you agree that it is a satisfactory solution.

@chalasr chalasr added this to the next milestone Dec 19, 2018
@HTMLGuyLLC
Copy link
Author

@chalasr - The appveyor build failed because of an issue with PHP unit unrelated to this pull request.

@ro0NL
Copy link
Contributor

ro0NL commented Dec 20, 2018

It eliminates the need for this logic inside the refreshUser method.

But this is documented to be the expected implementation;

* @throws UnsupportedUserException if the user is not supported
* @throws UsernameNotFoundException if the user is not found
*/
public function refreshUser(UserInterface $user);

Not sure what we're gaining here 🤔

@HTMLGuyLLC
Copy link
Author

HTMLGuyLLC commented Dec 20, 2018

@ro0NL - What brought me to this point was unexpected behavior. Even if documented, it's not clear.

Here was my scenario:

I created a firewall with a user provider and everything was great for a year and a half.
I needed a second firewall with a different user provider for my REST API.

Being stateless, the rest api firewall didn't need the refreshUser method so I didn't bother doing anything inside but returning user (without noticing how my original class was built or looking at the comment you pointed out - my mistake there obviously).

I was having a problem with my main firewall after that point because I assumed it would only use the relevant user provider, but even though my API firewall only applied to a specific host/pattern, the user provider for that firewall was still being tested. If it had run the supports method (like this pull request changes), it wouldn't have done that even with my initial mistake. Frankly, I don't know why there is a supports method if it's not being utilized for this purpose...

Ideally, this is just one step in the right direction. I think it should only loop through user providers for the current applicable firewalls. Since we define a user provider per firewall, I think that would be the natural way for it to work. Otherwise why even define a user provider on the firewall if it's just going to try to use them all anyway?

Furthermore, in the case of a stateless firewall, requiring the refreshUser method via the interface seems strange.

@ro0NL
Copy link
Contributor

ro0NL commented Dec 20, 2018

Im not sure we want to undo @throws UnsupportedUserException if the user is not supported , technically it's not needed anymore if we check supportClass() prior to refreshUser(). But i guess we can do both. Are there any other calls to refreshUser() that needs to be account for now?

firewall didn't need the refreshUser method so I didn't bother doing anything inside but returning user

The thing im skeptical about is now it looks like you support that user, but you have to rely on supportsClass() to be called first. Im not sure we want to go that way as a new feature.

@HTMLGuyLLC
Copy link
Author

HTMLGuyLLC commented Dec 20, 2018

I'd appreciate it if you and a couple other contributors could discuss the three things I mentioned. I'd be interested to see what you guys come up with, but I think there is room for improvement. Thanks for listening and looking into this for me!

@HTMLGuyLLC
Copy link
Author

It appears supports() is just used for remember me functionality at the moment, but the logic should be the same everywhere. To be consistent, I suggest moving forward with my change.

Copy link
Member

@xabbuh xabbuh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general, I think this change could make sense. But we should think very carefully if we can come up with legitimate use cases that we would now break.

@@ -164,11 +164,21 @@ protected function refreshUser(TokenInterface $token)
$userDeauthenticated = false;

foreach ($this->userProviders as $provider) {

$providerClass = \get_class($provider);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These changes should be reverted.

}

try {
$userClass = \get_class($user);
if( !$provider->supportsClass($userClass) )
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would move this outside the try ... catch block. IMO there is no need to use an exception for this. We can instead just continue:

foreach ($this->userProviders as $provider) {
    if (!$provider->supportsClass(\get_class($user)) {
        continue;
    }

    // ...
}

@@ -4,6 +4,7 @@ CHANGELOG
4.2.0
-----

* added a `supportsClass()` check prior to `refreshUser()` for each user provider
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be reverted, if this is a bugfix it should be based off the 3.4 branch. And for bugfixes we do not add entries to the components changelog files. If this is a new feature, it will be part of 4.3.

@nicolas-grekas
Copy link
Member

rebase needed + comments to address

Status: needs work

@curry684
Copy link
Contributor

curry684 commented Apr 6, 2019

I'm 👎 on this PR, as it is implicitly adding overhead to every call which is in most environments not needed. The reason the check is not done by default is that it doesn't matter if your configuration is correct. I don't think we should make all Symfony production environments slower to be able to debug a configuration issue that will never get past QA a bit easier.

@chalasr
Copy link
Member

chalasr commented Apr 6, 2019

Closing as there is no more activity here, feel free to reopen/take over. Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants