Skip to content

Commit

Permalink
Add ability to edit user's informations and password
Browse files Browse the repository at this point in the history
  • Loading branch information
Romain Monteil authored and javiereguiluz committed Oct 4, 2018
1 parent 559b771 commit 83570a0
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 83570a0

Please sign in to comment.