-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[Security][DX] Added SecurityPasswordType #35654
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
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like this idea! I've left two minor comments.
src/Symfony/Bundle/SecurityBundle/Form/SecurityPasswordType.php
Outdated
Show resolved
Hide resolved
src/Symfony/Bundle/SecurityBundle/Form/SecurityPasswordType.php
Outdated
Show resolved
Hide resolved
I would move everything in the Form component. We have already a system for extension |
I moved the form type to the form component in a new I also added some tests. I'm unsure if I need to add a dev-dependency on |
Yes :) IHMO you can target 3.4 because it works with 3.4 :) |
public function configureOptions(OptionsResolver $resolver) | ||
{ | ||
$resolver->setDefault('security_user', null); | ||
$resolver->setAllowedTypes('security_user', [ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the statement should be in one line
$resolver->setAllowedTypes('security_user', [ | ||
'null', | ||
UserInterface::class, | ||
]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we've recently added a fluent interface to define options, let's use it.
throw new InvalidConfigurationException(sprintf('You should either use "%s" inside a parent form where data is an instance of "%s" or specify the user in "security_user" option', self::class, UserInterface::class)); | ||
} | ||
|
||
$securityUser = $parentData; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the aux variable can be avoided here. i.e. $securityUser = $event->getForm()->getParent()->getData()
$securityUser = $event->getForm()->getConfig()->getOption('security_user'); | ||
|
||
if (!$securityUser) { | ||
$parentData = $event->getForm()->getParent()->getData(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the parent form cannot be null here, should we check?
<!-- SecurityExtension --> | ||
<service id="form.extension.security" class="Symfony\Component\Form\Extension\Security\SecurityExtension"> | ||
<argument type="service" id="security.user_password_encoder" on-invalid="ignore"/> | ||
<tag name="form.type_extension" /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The target class isn't a form type extension, but a "form extension" which doesn't need to be registered as service.
<tag name="form.type_extension" /> | ||
</service> | ||
<service id="form.extension.security.type.security_password" class="Symfony\Component\Form\Extension\Security\Type\SecurityPasswordType"> | ||
<argument type="service" id="security.user_password_encoder" on-invalid="ignore"/> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This class would be pointless without the required password encoder, I'd suggest make the argument mandatory and remove the whole service definition if "security" isn't enabled. See form.type_extension.form.validator
as sample.
{ | ||
private $passwordEncoder; | ||
|
||
public function __construct(UserPasswordEncoderInterface $passwordEncoder = null) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please, remove the nullable definition.
I like the idea too! I'm wondering if this implementation fits better in a new "password type" extension rather than creating a new type and enable this feature through a new option "auto_encode". I don't like much the idea to use the user instance. Instead, I would do what @wouterj has suggested here #35654 (comment). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After a second review I realized that this password encoding cannot be done before validation (that happens in POST_SUBMIT
event on the root form) otherwise constraint validators will validate the encoded password (which would be wrong) rather than the plain password. Let's think about the Length()
constraint for instance.
But, also changing the form data in POST_SUBMIT
event is currently impossible, so I don't think the proposal is feasible this way.
|
||
$plainPassword = $event->getData(); | ||
|
||
$event->setData($plainPassword ? $this->passwordEncoder->encodePassword($securityUser, $plainPassword) : $securityUser->getPassword()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The submitted data cannot be changed this way before validating the plain password.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In effect, if the validation step fails, the encoded password will be visible to the end user.
@pyrech Can you have a look at the feedback? |
I agree with the reviews that the current implementation is not ideal at all. I don't know how to improve it enough though so we might just close this PR 👍 |
I worked on a different approach here: #42807 |
Few days ago, I discussed with @lyrixx about how to simplify user password handling in EasyAdmin. Because currently if we want to make user's password administrable we have to create our own custom controller to interact with
UserPasswordEncoder
. For better DX we concluded that it would be better to add a nativeSecurityPasswordType
in Symfony. So here we go:PasswordType
.security_user
.I will see to add tests if the idea is accepted.