Completed
Push — master ( 91e054...12ace7 )
by Kamil
31:08 queued 26:39
created

UserController   C

Complexity

Total Complexity 32

Size/Duplication

Total Lines 255
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 19

Importance

Changes 1
Bugs 0 Features 1
Metric Value
wmc 32
c 1
b 0
f 1
lcom 1
cbo 19
dl 0
loc 255
rs 6.6

13 Methods

Rating   Name   Duplication   Size   Complexity  
B changePasswordAction() 0 27 5
A requestPasswordResetTokenAction() 0 6 1
A requestPasswordResetPinAction() 0 6 1
B resetPasswordAction() 0 30 5
B prepareResetPasswordRequest() 0 34 6
A addFlash() 0 5 1
A createResourceForm() 0 8 2
A handleExpiredToken() 0 17 2
A handleResetPasswordRequest() 0 13 1
A handleResetPassword() 0 20 2
A handleChangePassword() 0 18 2
A findUserByToken() 0 9 2
A generateResetPasswordRequestUrl() 0 10 2
1
<?php
2
3
/*
4
 * This file is part of the Sylius package.
5
 *
6
 * (c) Paweł Jędrzejewski
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 Sylius\Bundle\UserBundle\Controller;
13
14
use FOS\RestBundle\View\View;
15
use Sylius\Bundle\ResourceBundle\Controller\RequestConfiguration;
16
use Sylius\Bundle\ResourceBundle\Controller\ResourceController;
17
use Sylius\Bundle\UserBundle\Form\Model\ChangePassword;
18
use Sylius\Bundle\UserBundle\Form\Model\PasswordReset;
19
use Sylius\Bundle\UserBundle\Form\Model\PasswordResetRequest;
20
use Sylius\Bundle\UserBundle\UserEvents;
21
use Sylius\Component\User\Model\UserInterface;
22
use Sylius\Component\User\Security\TokenProviderInterface;
23
use Symfony\Component\EventDispatcher\GenericEvent;
24
use Symfony\Component\HttpFoundation\RedirectResponse;
25
use Symfony\Component\HttpFoundation\Request;
26
use Symfony\Component\HttpFoundation\Response;
27
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
28
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
29
30
/**
31
 * @author Łukasz Chruściel <[email protected]>
32
 */
33
class UserController extends ResourceController
34
{
35
    public function changePasswordAction(Request $request)
36
    {
37
        $configuration = $this->requestConfigurationFactory->create($this->metadata, $request);
38
39
        if (!$this->container->get('security.context')->isGranted('IS_AUTHENTICATED_REMEMBERED')) {
40
            throw new AccessDeniedException('You have to be registered user to access this section.');
41
        }
42
43
        $user = $this->container->get('security.context')->getToken()->getUser();
44
45
        $changePassword = new ChangePassword();
46
        $formType = $request->attributes->get('_sylius[form]', 'sylius_user_change_password', true);
47
        $form = $this->createResourceForm($configuration, $formType, $changePassword);
48
49
        if (in_array($request->getMethod(), array('POST', 'PUT', 'PATCH')) && $form->submit($request, !$request->isMethod('PATCH'))->isValid()) {
50
            return $this->handleChangePassword($configuration, $user, $changePassword->getNewPassword());
51
        }
52
53
        if (!$configuration->isHtmlRequest()) {
54
            return $this->viewHandler->handle(View::create($form, 400));
55
        }
56
57
        return $this->container->get('templating')->renderResponse(
58
            $configuration->getTemplate('changePassword.html'),
59
            array('form' => $form->createView())
60
        );
61
    }
62
63
    public function requestPasswordResetTokenAction(Request $request)
64
    {
65
        $generator = $this->container->get('sylius.user.token_provider');
66
67
        return $this->prepareResetPasswordRequest($request, $generator, UserEvents::REQUEST_RESET_PASSWORD_TOKEN);
68
    }
69
70
    public function requestPasswordResetPinAction(Request $request)
71
    {
72
        $generator = $this->container->get('sylius.user.pin_provider');
73
74
        return $this->prepareResetPasswordRequest($request, $generator, UserEvents::REQUEST_RESET_PASSWORD_PIN);
75
    }
76
77
    public function resetPasswordAction(Request $request, $token)
78
    {
79
        $configuration = $this->requestConfigurationFactory->create($this->metadata, $request);
80
        $user = $this->findUserByToken($token);
81
82
        $lifetime = new \DateInterval($this->container->getParameter('sylius.user.resetting.token_ttl'));
83
        if (!$user->isPasswordRequestNonExpired($lifetime)) {
84
            return $this->handleExpiredToken($configuration, $token, $user);
85
        }
86
87
        $changePassword = new PasswordReset();
88
        $formType = $request->attributes->get('_sylius[form]', 'sylius_user_reset_password', true);
89
        $form = $this->createResourceForm($configuration, $formType, $changePassword);
90
91
        if (in_array($request->getMethod(), array('POST', 'PUT', 'PATCH')) && $form->submit($request, !$request->isMethod('PATCH'))->isValid()) {
92
            return $this->handleResetPassword($user, $changePassword->getPassword());
93
        }
94
95
        if (!$configuration->isHtmlRequest()) {
96
            return $this->viewHandler->handle(View::create($form, 400));
97
        }
98
99
        return $this->container->get('templating')->renderResponse(
100
            $configuration->getTemplate('resetPassword.html'),
101
            array(
102
                'form' => $form->createView(),
103
                'user' => $user,
104
            )
105
        );
106
    }
107
108
    protected function prepareResetPasswordRequest(Request $request, TokenProviderInterface $generator, $senderEvent)
109
    {
110
        $configuration = $this->requestConfigurationFactory->create($this->metadata, $request);
111
112
        $passwordReset = new PasswordResetRequest();
113
        $formType = $request->attributes->get('_sylius[form]', 'sylius_user_request_password_reset', true);
114
        $form = $this->createResourceForm($configuration, $formType, $passwordReset);
115
116
        if (in_array($request->getMethod(), array('POST', 'PUT', 'PATCH')) && $form->submit($request, !$request->isMethod('PATCH'))->isValid()) {
117
            $user = $this->repository->findOneByEmail($passwordReset->getEmail());
118
            if (null !== $user) {
119
                $this->handleResetPasswordRequest($generator, $user, $senderEvent);
120
            }
121
122
            if (!$configuration->isHtmlRequest()) {
123
                return $this->viewHandler->handle(View::create($user, 204));
124
            }
125
126
            $this->addFlash('success', 'sylius.user.reset_password.requested');
127
128
            return new RedirectResponse($this->container->get('router')->generate('sylius_user_security_login'));
129
        }
130
131
        if (!$configuration->isHtmlRequest()) {
132
            return $this->viewHandler->handle(View::create($form, 400));
133
        }
134
135
        return $this->container->get('templating')->renderResponse(
136
            $configuration->getTemplate('requestPasswordReset.html'),
137
            array(
138
                'form' => $form->createView(),
139
            )
140
        );
141
    }
142
143
    protected function addFlash($type, $message)
144
    {
145
        $translator = $this->container->get('translator');
146
        $this->container->get('session')->getFlashBag()->add($type, $translator->trans($message, array(), 'flashes'));
147
    }
148
149
    protected function createResourceForm(RequestConfiguration $configuration, $type, $resource)
150
    {
151
        if (!$configuration->isHtmlRequest()) {
152
            return $this->container->get('form.factory')->createNamed('', $type, $resource, array('csrf_protection' => false));
153
        }
154
155
        return $this->container->get('form.factory')->create($type, $resource);
156
    }
157
158
    /**
159
     * @param string        $token
160
     * @param UserInterface $user
161
     *
162
     * @return RedirectResponse
163
     */
164
    protected function handleExpiredToken(RequestConfiguration $configuration, $token, UserInterface $user)
165
    {
166
        $user->setConfirmationToken(null);
167
        $user->setPasswordRequestedAt(null);
168
169
        $this->manager->flush();
170
171
        if (!$configuration->isHtmlRequest()) {
172
            return $this->viewHandler->handle(View::create($user, 400));
173
        }
174
175
        $this->addFlash('error', 'sylius.user.password.token_expired');
176
177
        $url = $this->generateResetPasswordRequestUrl($token);
178
179
        return new RedirectResponse($url);
180
    }
181
182
    /**
183
     * @param TokenProviderInterface $generator
184
     * @param UserInterface          $user
185
     * @param string                 $senderEvent
186
     *
187
     * @return Response
188
     */
189
    protected function handleResetPasswordRequest(TokenProviderInterface $generator, UserInterface $user, $senderEvent)
190
    {
191
        $user->setConfirmationToken($generator->generateUniqueToken());
192
        $user->setPasswordRequestedAt(new \DateTime());
193
194
        /** I have to use doctrine manager directly, because domain manager functions add a flash messages. I can't get rid of them.*/
195
        $manager = $this->container->get('doctrine.orm.default_entity_manager');
196
        $manager->persist($user);
197
        $manager->flush();
198
199
        $dispatcher = $this->container->get('event_dispatcher');
200
        $dispatcher->dispatch($senderEvent, new GenericEvent($user));
201
    }
202
203
    /**
204
     * @param UserInterface $user
205
     * @param string        $newPassword
206
     *
207
     * @return RedirectResponse
208
     */
209
    protected function handleResetPassword(RequestConfiguration $configuration, UserInterface $user, $newPassword)
210
    {
211
        $user->setPlainPassword($newPassword);
212
        $user->setConfirmationToken(null);
213
        $user->setPasswordRequestedAt(null);
214
215
        $dispatcher = $this->container->get('event_dispatcher');
216
        $dispatcher->dispatch(UserEvents::PRE_PASSWORD_RESET, new GenericEvent($user));
217
218
        $this->manager->flush();
219
        $this->addFlash('success', 'sylius.user.password.reset.success');
220
221
        $dispatcher->dispatch(UserEvents::POST_PASSWORD_RESET, new GenericEvent($user));
222
223
        if (!$configuration->isHtmlRequest()) {
224
            return $this->viewHandler->handle(View::create($user, 204));
225
        }
226
227
        return new RedirectResponse($this->container->get('router')->generate('sylius_user_security_login'));
228
    }
229
230
    /**
231
     * @param UserInterface $user
232
     * @param string        $newPassword
233
     *
234
     * @return RedirectResponse
235
     */
236
    protected function handleChangePassword(RequestConfiguration $configuration, UserInterface $user, $newPassword)
237
    {
238
        $user->setPlainPassword($newPassword);
239
240
        $dispatcher = $this->container->get('event_dispatcher');
241
        $dispatcher->dispatch(UserEvents::PRE_PASSWORD_CHANGE, new GenericEvent($user));
242
243
        $this->manager->flush();
244
        $this->addFlash('success', 'sylius.user.password.change.success');
245
246
        $dispatcher->dispatch(UserEvents::POST_PASSWORD_CHANGE, new GenericEvent($user));
247
248
        if (!$configuration->isHtmlRequest()) {
249
            return $this->viewHandler->handle(View::create($user, 204));
250
        }
251
252
        return new RedirectResponse($this->container->get('router')->generate('sylius_account_profile_show'));
253
    }
254
255
    /**
256
     * @param string $token
257
     *
258
     * @throws NotFoundHttpException
259
     *
260
     * @return UserInterface
261
     */
262
    protected function findUserByToken($token)
263
    {
264
        $user = $this->repository->findOneBy(array('confirmationToken' => $token));
265
        if (null === $user) {
266
            throw new NotFoundHttpException('This token does not exist');
267
        }
268
269
        return $user;
270
    }
271
272
    /**
273
     * @param string $token
274
     *
275
     * @return string
276
     */
277
    protected function generateResetPasswordRequestUrl($token)
278
    {
279
        $router = $this->container->get('router');
280
281
        if (is_numeric($token)) {
282
            return $router->generate('sylius_user_request_password_reset_pin');
283
        }
284
285
        return $router->generate('sylius_user_request_password_reset_token');
286
    }
287
}
288