Skip to content

Commit

Permalink
feature symfony#834 Add ability to edit user's informations and passw…
Browse files Browse the repository at this point in the history
…ord (ker0x)

This PR was squashed before being merged into the master branch (closes symfony#834).

Discussion
----------

Add ability to edit user's informations and password

As requested in symfony#820

Commits
-------

83570a0 Add ability to edit user's informations and password
  • Loading branch information
javiereguiluz committed Oct 4, 2018
2 parents c164d94 + 83570a0 commit 611fc54
Show file tree
Hide file tree
Showing 10 changed files with 490 additions and 3 deletions.
3 changes: 3 additions & 0 deletions config/packages/security.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,6 @@ security:
# this is a catch-all for the admin area
# additional security lives in the controllers
- { path: '^/(%app_locales%)/admin', roles: ROLE_ADMIN }

role_hierarchy:
ROLE_ADMIN: ROLE_USER
79 changes: 79 additions & 0 deletions src/Controller/UserController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace App\Controller;

use App\Form\Type\ChangePasswordType;
use App\Form\UserType;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;

/**
* Controller used to manage current user.
*
* @Route("/profile")
* @Security("has_role('ROLE_USER')")
*
* @author Romain Monteil <monteil.romain@gmail.com>
*/
class UserController extends AbstractController
{
/**
* @Route("/edit", methods={"GET", "POST"}, name="user_edit")
*/
public function edit(Request $request): Response
{
$user = $this->getUser();

$form = $this->createForm(UserType::class, $user);
$form->handleRequest($request);

if ($form->isSubmitted() && $form->isValid()) {
$this->getDoctrine()->getManager()->flush();

$this->addFlash('success', 'user.updated_successfully');

return $this->redirectToRoute('user_edit');
}

return $this->render('user/edit.html.twig', [
'user' => $user,
'form' => $form->createView(),
]);
}

/**
* @Route("/change-password", methods={"GET", "POST"}, name="user_change_password")
*/
public function changePassword(Request $request, UserPasswordEncoderInterface $encoder): Response
{
$user = $this->getUser();

$form = $this->createForm(ChangePasswordType::class);
$form->handleRequest($request);

if ($form->isSubmitted() && $form->isValid()) {
$user->setPassword($encoder->encodePassword($user, $form->get('newPassword')->getData()));

$this->getDoctrine()->getManager()->flush();

return $this->redirectToRoute('security_logout');
}

return $this->render('user/change_password.html.twig', [
'form' => $form->createView(),
]);
}
}
63 changes: 63 additions & 0 deletions src/Form/Type/ChangePasswordType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace App\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
use Symfony\Component\Form\Extension\Core\Type\RepeatedType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Security\Core\Encoder\BCryptPasswordEncoder;
use Symfony\Component\Security\Core\Validator\Constraints\UserPassword;
use Symfony\Component\Validator\Constraints\Length;
use Symfony\Component\Validator\Constraints\NotBlank;

/**
* Defines the custom form field type used to change user's password.
*
* @author Romain Monteil <monteil.romain@gmail.com>
*/
class ChangePasswordType extends AbstractType
{
/**
* {@inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('currentPassword', PasswordType::class, [
'constraints' => [
new UserPassword(),
],
'label' => 'label.current_password',
'attr' => [
'autocomplete' => 'off',
],
])
->add('newPassword', RepeatedType::class, [
'type' => PasswordType::class,
'constraints' => [
new NotBlank(),
new Length([
'min' => 5,
'max' => BCryptPasswordEncoder::MAX_PASSWORD_LENGTH,
]),
],
'first_options' => [
'label' => 'label.new_password',
],
'second_options' => [
'label' => 'label.new_password_confirm',
],
])
;
}
}
65 changes: 65 additions & 0 deletions src/Form/UserType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace App\Form;

use App\Entity\User;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

/**
* Defines the form used to edit an user.
*
* @author Romain Monteil <monteil.romain@gmail.com>
*/
class UserType extends AbstractType
{
/**
* {@inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options): void
{
// For the full reference of options defined by each form field type
// see https://symfony.com/doc/current/reference/forms/types.html

// By default, form fields include the 'required' attribute, which enables
// the client-side form validation. This means that you can't test the
// server-side validation errors from the browser. To temporarily disable
// this validation, set the 'required' attribute to 'false':
// $builder->add('title', null, ['required' => false, ...]);

$builder
->add('username', TextType::class, [
'label' => 'label.username',
'disabled' => true,
])
->add('fullName', TextType::class, [
'label' => 'label.fullname',
])
->add('email', EmailType::class, [
'label' => 'label.email',
])
;
}

/**
* {@inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => User::class,
]);
}
}
21 changes: 18 additions & 3 deletions templates/base.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,25 @@
</li>

{% if app.user %}
<li>
<a href="{{ path('security_logout') }}">
<i class="fa fa-sign-out" aria-hidden="true"></i> {{ 'menu.logout'|trans }}
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false" id="user">
<i class="fa fa-user" aria-hidden="true"></i>
<span class="caret"></span>
<span class="sr-only">{{ app.user.fullname }}</span>
</a>
<ul class="dropdown-menu user" role="menu" aria-labelledby="user">
<li>
<a href="{{ path('user_edit') }}">
<i class="fa fa-edit" aria-hidden="true"></i> {{ 'menu.user'|trans }}
</a>
</li>
<li class="divider"></li>
<li>
<a href="{{ path('security_logout') }}">
<i class="fa fa-sign-out" aria-hidden="true"></i> {{ 'menu.logout'|trans }}
</a>
</li>
</ul>
</li>
{% endif %}

Expand Down
29 changes: 29 additions & 0 deletions templates/user/change_password.html.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{% extends 'base.html.twig' %}

{% block body_id 'user_password' %}

{% block main %}
<h1>{{ 'title.change_password'|trans }}</h1>

<div class="alert alert-info" role="alert">{{ 'info.change_password'|trans }}</div>

{{ form_start(form) }}
{{ form_widget(form) }}

<button type="submit" class="btn btn-primary">
<i class="fa fa-save" aria-hidden="true"></i> {{ 'action.save'|trans }}
</button>
{{ form_end(form) }}
{% endblock %}

{% block sidebar %}
<div class="section">
<a href="{{ path('user_edit') }}" class="btn btn-lg btn-block btn-danger">
<i class="fa fa-edit" aria-hidden="true"></i> {{ 'action.edit_user'|trans }}
</a>
</div>

{{ parent() }}

{{ show_source_code(_self) }}
{% endblock %}
27 changes: 27 additions & 0 deletions templates/user/edit.html.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{% extends 'base.html.twig' %}

{% block body_id 'user_edit' %}

{% block main %}
<h1>{{ 'title.edit_user'|trans }}</h1>

{{ form_start(form) }}
{{ form_widget(form) }}

<button type="submit" class="btn btn-primary">
<i class="fa fa-save" aria-hidden="true"></i> {{ 'action.save'|trans }}
</button>
{{ form_end(form) }}
{% endblock %}

{% block sidebar %}
<div class="section">
<a href="{{ path('user_change_password') }}" class="btn btn-lg btn-block btn-danger">
<i class="fa fa-lock" aria-hidden="true"></i> {{ 'action.change_password'|trans }}
</a>
</div>

{{ parent() }}

{{ show_source_code(_self) }}
{% endblock %}
Loading

0 comments on commit 611fc54

Please sign in to comment.