-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Add ability to edit user's informations and password #834
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
src/Controller/UserController.php
Outdated
$em->persist($user); | ||
$em->flush(); | ||
|
||
return $this->redirectToRoute('security_logout'); |
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 should remplace redirect to $this->redirectToRoute('user_index') and I add a flashbag message
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 find it safer to logout the user after he has changed his password, but I can be wrong. I would like to get feedback from the community about that.
|
||
public function testChangePassword() | ||
{ | ||
$newUserPassword = $this->generateRandomString(10); |
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 think it's better to use a simple constant here. The test should be simple as possible.
$newUserPassword = 'new-password';
src/Controller/UserController.php
Outdated
/** | ||
* @Route("/", methods={"GET", "POST"}, name="user_index") | ||
* | ||
* @param \Symfony\Component\HttpFoundation\Request $request |
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 docblock comment is not needed.
src/Controller/UserController.php
Outdated
* | ||
* @param \Symfony\Component\HttpFoundation\Request $request | ||
* | ||
* @return \Symfony\Component\HttpFoundation\Response |
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 docblock comment is not needed too.
<trans-unit id="action.change_password"> | ||
<source>action.change_password</source> | ||
<target>Change password</target> | ||
</trans-unit> |
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 action.update_user_info
is missing.
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.
Actually, it was the translation key in the template file that was wrong.
src/Form/Type/ChangePasswordType.php
Outdated
public function configureOptions(OptionsResolver $resolver): void | ||
{ | ||
$resolver->setDefaults([ | ||
'data_class' => 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.
I think this config isn't necessary. If you aren't going to bind any data to this form, it's already null
by default (source).
src/Form/Type/ChangePasswordType.php
Outdated
->add('currentPassword', PasswordType::class, [ | ||
'constraints' => [ | ||
new NotBlank(), | ||
new UserPassword(), |
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 think NotBlank
constraint isn't necessary since a "Not blank" value is already verified in UserPassword
constraint.
src/Form/Type/ChangePasswordType.php
Outdated
new NotBlank(), | ||
new Length([ | ||
'min' => 5, | ||
]), |
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 also suggest adding a callback()
constraint and check by BasePasswordEncoder::isPasswordTooLong($password)
otherwise we could get an uncatched error BadCredentialsException
in controller during password encoding.
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.
That's not something that would happen in a real-life scenario unless really trying to make it fail. No sensible user would try setting a 4096+ chars long password. So I would not showcase it here or instead arbitrary set a reasonable max
value in Length
constraint above.
(relates to #834 (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.
It's 72 chars for BCryptPasswordEncoder
which is the current configured encoder :P but you're right, setting it (BCryptPasswordEncoder::MAX_PASSWORD_LENGTH
) in max
Length
constraint is simple.
src/Controller/UserController.php
Outdated
* @Route("/password", methods={"GET", "POST"}, name="user_password") | ||
* | ||
* @param \Symfony\Component\HttpFoundation\Request $request | ||
* @param \Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface $encoder |
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.
All these PHPDoc can be removed too.
src/Controller/UserController.php
Outdated
$user->setPassword($encoder->encodePassword($user, $form->get('newPassword')->getData())); | ||
|
||
$em = $this->getDoctrine()->getManager(); | ||
$em->persist($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.
persist
is unnecessary here as the entity is not a new one and already managed by doctrine.
src/Form/Type/ChangePasswordType.php
Outdated
new NotBlank(), | ||
new Length([ | ||
'min' => 5, | ||
]), |
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.
That's not something that would happen in a real-life scenario unless really trying to make it fail. No sensible user would try setting a 4096+ chars long password. So I would not showcase it here or instead arbitrary set a reasonable max
value in Length
constraint above.
(relates to #834 (comment))
src/Form/UserType.php
Outdated
|
||
$builder | ||
->add('username', TextType::class, [ | ||
'attr' => ['readonly' => true], |
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.
setting the readonly
attribute will not enforce this field cannot be submit and username not changed.
You must use disabled instead.
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.
If I use disabled, I got an error Argument 1 passed to App\Entity\User::setUsername() must be of the type string, null given
.
So, what should I do ?
- leave readonly
- add the nullable type to
setUsername()
inApp\Entity\User
- allow user to change his username
- remove the username in
UserType
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.
@ker0x, He means a form option, not an HTML attribute:
$builder
->add('username', TextType::class,
'label' => 'label.username',
'disabled' => true,
])
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.
Ho right, i'm so stupid! Thanks 👍
1237860
to
19b0bb5
Compare
src/Controller/UserController.php
Outdated
/** | ||
* @Route("/password", methods={"GET", "POST"}, name="user_password") | ||
*/ | ||
public function password(Request $request, UserPasswordEncoderInterface $encoder): Response |
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.
changePassword ? (same for the template name & route name)
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 changed it for /profile/change-password
src/Controller/UserController.php
Outdated
/** | ||
* @Route("/", methods={"GET", "POST"}, name="user_index") | ||
*/ | ||
public function index(Request $request): Response |
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.
profile / editProfile ? (same for the template name & route name)
$builder | ||
->add('username', TextType::class, [ | ||
'label' => 'label.username', | ||
'disabled' => true, |
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.
If the intention is not to modify the username, how about removing this field and print {{ user.username }}
directly in the template?
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.
As this is a demo application, maybe we can keep the disabled option to show people how to disable an input in a form ?
src/Controller/UserController.php
Outdated
$user->setPassword($encoder->encodePassword($user, $form->get('newPassword')->getData())); | ||
|
||
$em = $this->getDoctrine()->getManager(); | ||
$em->flush(); |
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->getDoctrine()->getManager()->flush()
?
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.
Yep, already change 👍
src/Controller/UserController.php
Outdated
/** | ||
* Controller used to manage current user. | ||
* | ||
* @Route("/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.
/user-profile
, /profile/user
, /user-account
, /account/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.
I changed it for /profile/edit
templates/user/index.html.twig
Outdated
{{ form_widget(form) }} | ||
|
||
<button type="submit" class="{{ button_css|default("btn btn-primary") }}"> | ||
<i class="fa fa-save" aria-hidden="true"></i> {{ button_label|default('action.save'|trans) }} |
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.
same here {{ 'action.save'|trans }}
templates/user/index.html.twig
Outdated
{{ form_start(form, {attr: attr|default({})}) }} | ||
{{ form_widget(form) }} | ||
|
||
<button type="submit" class="{{ button_css|default("btn btn-primary") }}"> |
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.
why not btn btn-primary
directly? same for password.html.twig
template.
templates/user/index.html.twig
Outdated
{% block main %} | ||
<h1>{{ 'title.edit_user'|trans }}</h1> | ||
|
||
{{ form_start(form, {attr: attr|default({})}) }} |
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.
{attr: attr|default({})}
can be removed.
…unnecessary form options
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.
It seems good to me.
Nevertheless, I did not see if there was a check that the new password was different from the old one
Is there a reason that it's |
@bobdenotter I think I can answer your question. |
@ker0x you did it really great. This is a ver well done feature. Thanks for working on this and thanks for your patience during the review. And thanks to all reviewers too! |
As requested in #820