Skip to content

Commit 17c299b

Browse files
azineXWB
authored andcommitted
fix for #2667: put email-update-confirmation code into separate controller (#2669)
* fix for #2667: put email-update-confirmation code into separate controller Untagled some configuration dependencies between email_confirmation (upon registration) and confirm_email_update (when the users changes her email) Fixed parameter access in Mailer/Mailer.php * synchronize canonical value of email when updating email with confirmation
1 parent 5d1c3ff commit 17c299b

File tree

14 files changed

+212
-102
lines changed

14 files changed

+212
-102
lines changed
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the FOSUserBundle package.
5+
*
6+
* (c) FriendsOfSymfony <http://friendsofsymfony.github.com/>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace FOS\UserBundle\Controller;
13+
14+
use FOS\UserBundle\Event\UserEvent;
15+
use FOS\UserBundle\FOSUserEvents;
16+
use FOS\UserBundle\Model\User;
17+
use FOS\UserBundle\Model\UserInterface;
18+
use FOS\UserBundle\Model\UserManagerInterface;
19+
use FOS\UserBundle\Services\EmailConfirmation\EmailUpdateConfirmation;
20+
use FOS\UserBundle\Util\CanonicalFieldsUpdater;
21+
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
22+
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
23+
use Symfony\Component\HttpFoundation\Request;
24+
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
25+
use Symfony\Component\Translation\TranslatorInterface;
26+
27+
/**
28+
* Controller managing the confirmation of changed user email.
29+
*
30+
* @author Dominik Businger <git@azine.me>
31+
*/
32+
class ConfirmEmailUpdateController extends AbstractController
33+
{
34+
/**
35+
* @var EventDispatcherInterface
36+
*/
37+
private $eventDispatcher;
38+
39+
/**
40+
* @var UserManagerInterface
41+
*/
42+
private $userManager;
43+
44+
/**
45+
* @var EmailUpdateConfirmation
46+
*/
47+
private $emailUpdateConfirmation;
48+
49+
/**
50+
* @var TranslatorInterface
51+
*/
52+
private $translator;
53+
/**
54+
* @var CanonicalFieldsUpdater
55+
*/
56+
private $canonicalFieldsUpdater;
57+
58+
/**
59+
* @param EventDispatcherInterface $eventDispatcher
60+
* @param UserManagerInterface $userManager
61+
* @param EmailUpdateConfirmation $emailUpdateConfirmation
62+
* @param TranslatorInterface $translator
63+
* @param CanonicalFieldsUpdater $canonicalFieldsUpdater
64+
*/
65+
public function __construct(EventDispatcherInterface $eventDispatcher, UserManagerInterface $userManager, EmailUpdateConfirmation $emailUpdateConfirmation, TranslatorInterface $translator, CanonicalFieldsUpdater $canonicalFieldsUpdater)
66+
{
67+
$this->eventDispatcher = $eventDispatcher;
68+
$this->userManager = $userManager;
69+
$this->emailUpdateConfirmation = $emailUpdateConfirmation;
70+
$this->translator = $translator;
71+
$this->canonicalFieldsUpdater = $canonicalFieldsUpdater;
72+
}
73+
74+
/**
75+
* Confirm user`s email update.
76+
*
77+
* @param Request $request
78+
* @param string $token
79+
*
80+
* @return \Symfony\Component\HttpFoundation\RedirectResponse
81+
*/
82+
public function confirmEmailUpdateAction(Request $request, $token)
83+
{
84+
/** @var User $user */
85+
$user = $this->userManager->findUserByConfirmationToken($token);
86+
87+
// If user was not found throw 404 exception
88+
if (!$user) {
89+
throw $this->createNotFoundException($this->translator->trans('email_update.error.message', array(), 'FOSUserBundle'));
90+
}
91+
92+
// Show invalid token message if the user id found via token does not match the current users id (e.g. anon. or other user)
93+
if (!($this->getUser() instanceof UserInterface) || ($user->getId() !== $this->getUser()->getId())) {
94+
throw new AccessDeniedException($this->translator->trans('email_update.error.message', array(), 'FOSUserBundle'));
95+
}
96+
97+
$this->emailUpdateConfirmation->setUser($user);
98+
99+
$newEmail = $this->emailUpdateConfirmation->fetchEncryptedEmailFromConfirmationLink($request->get('target'));
100+
101+
// Update user email
102+
if ($newEmail) {
103+
$user->setConfirmationToken($this->emailUpdateConfirmation->getEmailConfirmedToken());
104+
$user->setEmail($newEmail);
105+
$user->setEmail($this->canonicalFieldsUpdater->canonicalizeEmail($newEmail));
106+
}
107+
108+
$this->userManager->updateUser($user);
109+
110+
$event = new UserEvent($user, $request);
111+
$this->eventDispatcher->dispatch(FOSUserEvents::EMAIL_UPDATE_SUCCESS, $event);
112+
113+
return $this->redirect($this->generateUrl('fos_user_profile_show'));
114+
}
115+
}

Controller/ProfileController.php

Lines changed: 1 addition & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -14,20 +14,16 @@
1414
use FOS\UserBundle\Event\FilterUserResponseEvent;
1515
use FOS\UserBundle\Event\FormEvent;
1616
use FOS\UserBundle\Event\GetResponseUserEvent;
17-
use FOS\UserBundle\Event\UserEvent;
1817
use FOS\UserBundle\Form\Factory\FactoryInterface;
1918
use FOS\UserBundle\FOSUserEvents;
20-
use FOS\UserBundle\Model\User;
2119
use FOS\UserBundle\Model\UserInterface;
2220
use FOS\UserBundle\Model\UserManagerInterface;
23-
use FOS\UserBundle\Services\EmailConfirmation\EmailUpdateConfirmation;
2421
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
2522
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
2623
use Symfony\Component\HttpFoundation\RedirectResponse;
2724
use Symfony\Component\HttpFoundation\Request;
2825
use Symfony\Component\HttpFoundation\Response;
2926
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
30-
use Symfony\Component\Translation\TranslatorInterface;
3127

3228
/**
3329
* Controller managing the user profile.
@@ -51,30 +47,16 @@ class ProfileController extends AbstractController
5147
*/
5248
private $userManager;
5349

54-
/**
55-
* @var EmailUpdateConfirmation
56-
*/
57-
private $emailUpdateConfirmation;
58-
59-
/**
60-
* @var TranslatorInterface
61-
*/
62-
private $translator;
63-
6450
/**
6551
* @param EventDispatcherInterface $eventDispatcher
6652
* @param FactoryInterface $formFactory
6753
* @param UserManagerInterface $userManager
68-
* @param EmailUpdateConfirmation $emailUpdateConfirmation
69-
* @param TranslatorInterface $translator
7054
*/
71-
public function __construct(EventDispatcherInterface $eventDispatcher, FactoryInterface $formFactory, UserManagerInterface $userManager, EmailUpdateConfirmation $emailUpdateConfirmation, TranslatorInterface $translator)
55+
public function __construct(EventDispatcherInterface $eventDispatcher, FactoryInterface $formFactory, UserManagerInterface $userManager)
7256
{
7357
$this->eventDispatcher = $eventDispatcher;
7458
$this->formFactory = $formFactory;
7559
$this->userManager = $userManager;
76-
$this->emailUpdateConfirmation = $emailUpdateConfirmation;
77-
$this->translator = $translator;
7860
}
7961

8062
/**
@@ -140,45 +122,4 @@ public function editAction(Request $request)
140122
'form' => $form->createView(),
141123
));
142124
}
143-
144-
/**
145-
* Confirm user`s email update.
146-
*
147-
* @param Request $request
148-
* @param string $token
149-
*
150-
* @return \Symfony\Component\HttpFoundation\RedirectResponse
151-
*/
152-
public function confirmEmailUpdateAction(Request $request, $token)
153-
{
154-
/** @var User $user */
155-
$user = $this->userManager->findUserByConfirmationToken($token);
156-
157-
// If user was not found throw 404 exception
158-
if (!$user) {
159-
throw $this->createNotFoundException($this->translator->trans('email_update.error.message', array(), 'FOSUserBundle'));
160-
}
161-
162-
// Show invalid token message if the user id found via token does not match the current users id (e.g. anon. or other user)
163-
if (!($this->getUser() instanceof UserInterface) || ($user->getId() !== $this->getUser()->getId())) {
164-
throw new AccessDeniedException($this->translator->trans('email_update.error.message', array(), 'FOSUserBundle'));
165-
}
166-
167-
$this->emailUpdateConfirmation->setUser($user);
168-
169-
$newEmail = $this->emailUpdateConfirmation->fetchEncryptedEmailFromConfirmationLink($request->get('target'));
170-
171-
// Update user email
172-
if ($newEmail) {
173-
$user->setConfirmationToken($this->emailUpdateConfirmation->getEmailConfirmedToken());
174-
$user->setEmail($newEmail);
175-
}
176-
177-
$this->userManager->updateUser($user);
178-
179-
$event = new UserEvent($user, $request);
180-
$this->eventDispatcher->dispatch(FOSUserEvents::EMAIL_UPDATE_SUCCESS, $event);
181-
182-
return $this->redirect($this->generateUrl('fos_user_profile_show'));
183-
}
184125
}

DependencyInjection/FOSUserExtension.php

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -193,13 +193,12 @@ private function loadProfile(array $config, ContainerBuilder $container, XmlFile
193193

194194
if ($config['email_update_confirmation']['enabled']) {
195195
if ('custom' !== $dbDriver && isset(self::$doctrineDrivers[$dbDriver])) {
196-
$loader->load('profile_email_update_listener.xml');
196+
$loader->load('profile_email_update.xml');
197197
}
198+
$container->setParameter('fos_user.email_update_confirmation.template', $config['email_update_confirmation']['email_template']);
199+
$container->setParameter('fos_user.email_update_confirmation.cypher_method', $config['email_update_confirmation']['cypher_method']);
198200
}
199201

200-
$container->setParameter('fos_user.email_update_confirmation.template', $config['email_update_confirmation']['email_template']);
201-
$container->setParameter('fos_user.email_update_confirmation.cypher_method', $config['email_update_confirmation']['cypher_method']);
202-
203202
$this->remapParametersNamespaces($config, $container, array(
204203
'form' => 'fos_user.profile.form.%s',
205204
));

Doctrine/EmailUpdateListener.php

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use Doctrine\ORM\Event\PreUpdateEventArgs;
1515
use FOS\UserBundle\Model\UserInterface;
1616
use FOS\UserBundle\Services\EmailConfirmation\EmailUpdateConfirmation;
17+
use FOS\UserBundle\Util\CanonicalFieldsUpdater;
1718
use Symfony\Component\HttpFoundation\RequestStack;
1819

1920
/**
@@ -30,17 +31,23 @@ class EmailUpdateListener
3031
* @var RequestStack
3132
*/
3233
private $requestStack;
34+
/**
35+
* @var CanonicalFieldsUpdater
36+
*/
37+
private $canonicalFieldsUpdater;
3338

3439
/**
3540
* Constructor.
3641
*
3742
* @param EmailUpdateConfirmation $emailUpdateConfirmation
3843
* @param RequestStack $requestStack
44+
* @param CanonicalFieldsUpdater $canonicalFieldsUpdater
3945
*/
40-
public function __construct(EmailUpdateConfirmation $emailUpdateConfirmation, RequestStack $requestStack)
46+
public function __construct(EmailUpdateConfirmation $emailUpdateConfirmation, RequestStack $requestStack, CanonicalFieldsUpdater $canonicalFieldsUpdater)
4147
{
4248
$this->emailUpdateConfirmation = $emailUpdateConfirmation;
4349
$this->requestStack = $requestStack;
50+
$this->canonicalFieldsUpdater = $canonicalFieldsUpdater;
4451
}
4552

4653
/**
@@ -58,8 +65,8 @@ public function preUpdate(PreUpdateEventArgs $args)
5865
if ($user->getConfirmationToken() != $this->emailUpdateConfirmation->getEmailConfirmedToken() && isset($args->getEntityChangeSet()['email'])) {
5966
$oldEmail = $args->getEntityChangeSet()['email'][0];
6067
$newEmail = $args->getEntityChangeSet()['email'][1];
61-
6268
$user->setEmail($oldEmail);
69+
$user->setEmailCanonical($this->canonicalFieldsUpdater->canonicalizeEmail($oldEmail));
6370

6471
// Configure email confirmation
6572
$this->emailUpdateConfirmation->setUser($user);

Mailer/Mailer.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ public function sendResettingEmailMessage(UserInterface $user)
9393
*/
9494
public function sendUpdateEmailConfirmation(UserInterface $user, $confirmationUrl, $toEmail)
9595
{
96-
$template = $this->parameters['template']['email_updating'];
96+
$template = $this->parameters['email_updating.template'];
9797
$rendered = $this->templating->render($template, array(
9898
'user' => $user,
9999
'confirmationUrl' => $confirmationUrl,

Resources/config/email_confirmation.xml

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,6 @@
1313
<argument type="service" id="session" />
1414
</service>
1515

16-
<service id="fos_user.email_encryption" class="FOS\UserBundle\Services\EmailConfirmation\EmailEncryption">
17-
<argument type="service" id="validator"/>
18-
<argument>%fos_user.email_update_confirmation.cypher_method%</argument>
19-
</service>
20-
21-
<service id="fos_user.email_update_confirmation" class="FOS\UserBundle\Services\EmailConfirmation\EmailUpdateConfirmation">
22-
<argument type="service" id="router" />
23-
<argument type="service" id="fos_user.util.token_generator" />
24-
<argument type="service" id="fos_user.mailer" />
25-
<argument type="service" id="fos_user.email_encryption" />
26-
<argument type="service" id="event_dispatcher" />
27-
</service>
2816
</services>
2917

3018
</container>

Resources/config/profile.xml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,10 @@
1818
<tag name="form.type" alias="fos_user_profile" />
1919
</service>
2020

21-
<service id="fos_user.profiler.controller" class="FOS\UserBundle\Controller\ProfileController" public="true">
21+
<service id="fos_user.profile.controller" class="FOS\UserBundle\Controller\ProfileController" public="true">
2222
<argument type="service" id="event_dispatcher" />
2323
<argument type="service" id="fos_user.profile.form.factory" />
2424
<argument type="service" id="fos_user.user_manager" />
25-
<argument type="service" id="fos_user.email_update_confirmation" />
26-
<argument type="service" id="translator" />
2725
</service>
2826
</services>
2927

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?xml version="1.0" encoding="UTF-8" ?>
2+
3+
<container xmlns="http://symfony.com/schema/dic/services"
4+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5+
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
6+
7+
<services>
8+
<service id="fos_user.email_encryption" class="FOS\UserBundle\Services\EmailConfirmation\EmailEncryption">
9+
<argument type="service" id="validator"/>
10+
<argument>%fos_user.email_update_confirmation.cypher_method%</argument>
11+
</service>
12+
13+
<service id="fos_user.email_update_confirmation" class="FOS\UserBundle\Services\EmailConfirmation\EmailUpdateConfirmation">
14+
<argument type="service" id="router" />
15+
<argument type="service" id="fos_user.util.token_generator" />
16+
<argument type="service" id="fos_user.mailer" />
17+
<argument type="service" id="fos_user.email_encryption" />
18+
<argument type="service" id="event_dispatcher" />
19+
</service>
20+
21+
<service id="fos_user.email_update_listener" class="FOS\UserBundle\Doctrine\EmailUpdateListener" public="false">
22+
<argument type="service" id="fos_user.email_update_confirmation"/>
23+
<argument type="service" id="request_stack" />
24+
<argument type="service" id="fos_user.util.canonical_fields_updater" />
25+
<tag name="doctrine.event_listener" event="preUpdate" lazy="true" />
26+
</service>
27+
28+
<service id="fos_user.confirm.email.update.controller" class="FOS\UserBundle\Controller\ConfirmEmailUpdateController" public="true">
29+
<argument type="service" id="event_dispatcher" />
30+
<argument type="service" id="fos_user.user_manager" />
31+
<argument type="service" id="fos_user.email_update_confirmation" />
32+
<argument type="service" id="translator" />
33+
<argument type="service" id="fos_user.util.canonical_fields_updater" />
34+
</service>
35+
36+
</services>
37+
38+
</container>

Resources/config/profile_email_update_listener.xml

Lines changed: 0 additions & 15 deletions
This file was deleted.

Resources/config/routing/profile.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@
55
xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd">
66

77
<route id="fos_user_profile_show" path="/" methods="GET">
8-
<default key="_controller">fos_user.profiler.controller:showAction</default>
8+
<default key="_controller">fos_user.profile.controller:showAction</default>
99
</route>
1010

1111
<route id="fos_user_profile_edit" path="/edit" methods="GET POST">
12-
<default key="_controller">fos_user.profiler.controller:editAction</default>
12+
<default key="_controller">fos_user.profile.controller:editAction</default>
1313
</route>
1414

1515
</routes>

0 commit comments

Comments
 (0)