Passed
Push — master ( d18b27...059609 )
by Derek Stephen
02:54
created

UserController::indexAction()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 16
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 3.0123

Importance

Changes 0
Metric Value
eloc 8
dl 0
loc 16
ccs 8
cts 9
cp 0.8889
rs 10
c 0
b 0
f 0
cc 3
nc 3
nop 0
crap 3.0123
1
<?php
2
3
namespace App\Controller;
4
5
use App\Form\User\RegistrationForm;
6
use App\Form\User\ResetPasswordForm;
7
use Bone\Mvc\Registry;
8
use Bone\Service\MailService;
9
use Del\Common\ContainerService;
10
use Del\Exception\EmailLinkException;
11
use Del\Exception\UserException;
12
use Del\Service\UserService;
13
use Del\Value\User\State;
14
use Exception;
15
use Zend\Validator\EmailAddress;
16
17
class UserController extends BaseController
18
{
19
    /** @var UserService */
20
    private $userService;
21
22 8
    public function init()
23
    {
24 8
        $c = ContainerService::getInstance()->getContainer();
25 8
        $this->userService = $c['service.user'];
26 8
    }
27
28
    /**
29
     * Fetch user details by ID.
30
     *
31
     * @SWG\Get(
32
     *     path="/user/{id}",
33
     *     tags={"users"},
34
     *     @SWG\Parameter(
35
     *         name="id",
36
     *         in="path",
37
     *         type="integer",
38
     *         description="the type of response",
39
     *         required=false,
40
     *         default=1
41
     *     ),
42
     *     @SWG\Response(response="200", description="Sends user details")
43
     * )
44
     *
45
     */
46 1
    public function indexAction()
47
    {
48 1
        if (!$this->httpMethodCheck('GET')) { return; }
49
50 1
        $id = $this->getParam('id');
51
52
        /** @var UserService $userSvc */
53 1
        $userSvc = ContainerService::getInstance()->getContainer()['service.user'];
54
55 1
        $user = $userSvc->findUserById($id);
0 ignored issues
show
Bug introduced by
It seems like $id can also be of type string; however, parameter $id of Del\Service\UserService::findUserById() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

55
        $user = $userSvc->findUserById(/** @scrutinizer ignore-type */ $id);
Loading history...
56 1
        if (!$user) {
57 1
            $this->sendJsonResponse(['error' => 'User not found'], 404);
58 1
            return;
59
        }
60
61
        $this->sendJsonObjectResponse($user);
62
    }
63
64
65
66
    /**
67
     * Activate from the email link token.
68
     *
69
     * @SWG\Get(
70
     *     path="/user/activate/{email}/{token}",
71
     *     tags={"users"},
72
     *     @SWG\Response(response="200", description="Registers a new unactivated user"),
73
     *     @SWG\Parameter(
74
     *         name="email",
75
     *         in="path",
76
     *         type="string",
77
     *         description="the users email",
78
     *         required=true,
79
     *         default="[email protected]"
80
     *     ),
81
     *     @SWG\Parameter(
82
     *         name="token",
83
     *         in="path",
84
     *         type="string",
85
     *         description="the email link token",
86
     *         required=true,
87
     *         default="r4nd0mT0k3n"
88
     *     )
89
     * )
90
     * @throws Exception
91
     */
92 4
    public function activateAction()
93
    {
94 4
        if (!$this->httpMethodCheck('GET')) { return; }
95
96 4
        $email = $this->getParam('email');
97 4
        $token = $this->getParam('token');
98
99 4
        $userService = $this->userService;
100
101
        try {
102
103 4
            $link = $userService->findEmailLink($email, $token);
104
105 2
            $user = $link->getUser();
106 2
            $user->setState(new State(State::STATE_ACTIVATED));
107 2
            $userService->saveUser($user);
108 2
            $userService->deleteEmailLink($link);
109 2
            $data = ['success' => true];
110 2
            $code = 200;
111
112 2
        } catch (EmailLinkException $e) {
113 2
            switch ($e->getMessage()) {
114 2
                case EmailLinkException::LINK_EXPIRED:
115 1
                case EmailLinkException::LINK_NO_MATCH:
116
                    $data = [
117 1
                        'success' => false,
118 1
                        'error' => $e->getMessage(),
119
                    ];
120 1
                    $code = 403;
121 1
                    break;
122 1
                case EmailLinkException::LINK_NOT_FOUND:
123
                    $data = [
124 1
                        'success' => false,
125 1
                        'error' => $e->getMessage(),
126
                    ];
127 1
                    $code = 404;
128 1
                    break;
129
                default:
130
                    $data = [
131
                        'success' => false,
132
                        'error' => $e->getMessage(),
133
                    ];
134
                    $code = 500;
135
                    break;
136
            }
137
        }
138
139 4
        $this->sendJsonResponse($data, $code);
140 4
    }
141
142
143
    /**
144
     * Refresh the activation email link token.
145
     *
146
     * @SWG\Get(
147
     *     path="/{locale}/user/activate/resend/{email}",
148
     *     tags={"users"},
149
     *     @SWG\Parameter(
150
     *         name="locale",
151
     *         in="path",
152
     *         type="string",
153
     *         description="the locale to use",
154
     *         required=true,
155
     *         default="en_GB"
156
     *     ),
157
     *     @SWG\Parameter(
158
     *         name="email",
159
     *         in="path",
160
     *         type="string",
161
     *         description="the email of the user registering",
162
     *         required=true,
163
     *         default="[email protected]"
164
     *     ),
165
     *     @SWG\Response(response="200", description="Sends email link details")
166
     * )
167
     * @throws Exception
168
     */
169 2
    public function resendActivationAction()
170
    {
171 2
        if (!$this->httpMethodCheck('GET')) { return; }
172
173 2
        $email = $this->getParam('email');
174
175 2
        $user = $this->userService->findUserByEmail($email);
176 2
        if (!$user) {
177 1
            $this->sendJsonResponse(['error' => UserException::USER_NOT_FOUND], 404);
178 1
            return;
179
        }
180
181 1
        if ($user->getState()->getValue() == State::STATE_ACTIVATED) {
182
            $this->sendJsonResponse(['error' => UserException::USER_ACTIVATED], 400);
183
            return;
184
        }
185
186 1
        $link = $this->userService->generateEmailLink($user);
187
188 1
        $mail = $this->getMailService();
189 1
        $env = $this->getServerEnvironment();
190 1
        $email = $user->getEmail();
191 1
        $token = $link->getToken();
192
193 1
        $message = $this->getViewEngine()->render('emails/user_registration/user_registration', [
194 1
            'siteUrl' => $env->getSiteURL(),
195 1
            'activationLink' => '/' . $this->getParam('locale') . '/user/activate/' . $email . '/' . $token,
196
        ]);
197
198 1
        $mail->setFrom('noreply@' . $env->getServerName())
199 1
            ->setTo($user->getEmail())
200 1
            ->setSubject($this->getTranslator()
201 1
                    ->translate('email.user.register.thankswith') . ' ' . Registry::ahoy()->get('site')['name'])
202 1
            ->setMessage($message)
203 1
            ->send();
204
205
206 1
        $this->sendJsonObjectResponse($link);
207 1
    }
208
209
    /**
210
     * Get a lost password email link token.
211
     *
212
     * @SWG\Get(
213
     *     path="/user/lost-password/{email}",
214
     *     tags={"users"},
215
     *     @SWG\Parameter(
216
     *         name="email",
217
     *         in="path",
218
     *         type="string",
219
     *         description="the email of the user",
220
     *         required=true,
221
     *         default="[email protected]"
222
     *     ),
223
     *     @SWG\Response(response="200", description="Sends email link details")
224
     * )
225
     * @throws Exception
226
     */
227 1
    public function lostPasswordAction()
228
    {
229 1
        if (!$this->httpMethodCheck('GET')) { return; }
230
231 1
        $email = $this->getParam('email');
232
233 1
        $user = $this->userService->findUserByEmail($email);
234 1
        if (!$user) {
235
            $this->sendJsonResponse(['error' => UserException::USER_NOT_FOUND], 404);
236
            return;
237
        }
238
239 1
        if ($user->getState()->getValue() == State::STATE_UNACTIVATED) {
240
            $this->sendJsonResponse(['error' => UserException::USER_UNACTIVATED], 400);
241
            return;
242
        }
243
244 1
        $link = $this->userService->generateEmailLink($user);
245 1
        $this->sendJsonObjectResponse($link);
246 1
    }
247
248
    /**
249
     * Register as a new user. Returns an email link token.
250
     *
251
     * @SWG\Post(
252
     *     path="/{locale}/user/register",
253
     *     tags={"users"},
254
     *     @SWG\Response(response="200", description="Registers a new unactivated user"),
255
     *     @SWG\Parameter(
256
     *         name="locale",
257
     *         in="path",
258
     *         type="string",
259
     *         description="the locale to use",
260
     *         required=true,
261
     *         default="en_GB"
262
     *     ),
263
     *     @SWG\Parameter(
264
     *         name="email",
265
     *         in="formData",
266
     *         type="string",
267
     *         description="the users email",
268
     *         required=true,
269
     *         default="[email protected]"
270
     *     ),
271
     *     @SWG\Parameter(
272
     *         name="password",
273
     *         in="formData",
274
     *         type="string",
275
     *         description="a password for the user",
276
     *         required=true,
277
     *         default="password"
278
     *     ),
279
     *     @SWG\Parameter(
280
     *         name="confirm",
281
     *         in="formData",
282
     *         type="string",
283
     *         description="password confirmation",
284
     *         required=true,
285
     *         default="password"
286
     *     )
287
     * )
288
     * @throws Exception
289
     */
290 6
    public function registerAction()
291
    {
292 6
        if (!$this->httpMethodCheck('POST')) { return; }
293
294 6
        $form = new RegistrationForm('register');
295
296 6
        if ($this->getRequest()->getMethod() == 'POST') {
297
298 6
            $formData = $this->getRequest()->getParsedBody();
299 6
            $form->populate($formData);
0 ignored issues
show
Bug introduced by
It seems like $formData can also be of type null and object; however, parameter $data of Del\Form\AbstractForm::populate() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

299
            $form->populate(/** @scrutinizer ignore-type */ $formData);
Loading history...
300
301 6
            if ($form->isValid()) {
302
                try {
303 6
                    $data = $form->getValues();
304 6
                    $user = $this->userService->registerUser($data);
305 6
                    $link = $this->userService->generateEmailLink($user);
306 6
                    $mail = $this->getMailService();
307 6
                    $env = $this->getServerEnvironment();
308 6
                    $email = $user->getEmail();
309 6
                    $token = $link->getToken();
310
311 6
                    $message = $this->getViewEngine()->render('emails/user_registration/user_registration', [
312 6
                        'siteUrl' => $env->getSiteURL(),
313 6
                        'activationLink' => '/' . $this->getParam('locale') . '/user/activate/' . $email . '/' . $token,
314
                    ]);
315
316 6
                    $mail->setFrom('noreply@' . $env->getServerName())
317 6
                        ->setTo($user->getEmail())
318 6
                        ->setSubject($this->getTranslator()
319 6
                            ->translate('email.user.register.thankswith') . ' ' . Registry::ahoy()->get('site')['name'])
320 6
                        ->setMessage($message)
321 6
                        ->send();
322 6
                    $this->sendJsonObjectResponse($link);
323
324
                } catch (UserException $e) {
325
326
                    switch ($e->getMessage()) {
327
                        case UserException::USER_EXISTS:
328
                        case UserException::WRONG_PASSWORD:
329
                            throw new Exception($e->getMessage(), 400);
330
                            break;
331
                    }
332
                    throw $e;
333
                }
334
            } else {
335
                throw new Exception('Invalid request data;', 400);
336
            }
337
338
        }
339 6
    }
340
341
    /**
342
     * Resets the users password. Requires an email link token.
343
     *
344
     * @SWG\Post(
345
     *     path="/user/reset-password/{email}/{token}",
346
     *     tags={"users"},
347
     *     @SWG\Response(response="200", description="Resets a users email"),
348
     *     @SWG\Parameter(
349
     *         name="email",
350
     *         in="path",
351
     *         type="string",
352
     *         description="the email of the user",
353
     *         required=true,
354
     *         default="[email protected]"
355
     *     ),
356
     *     @SWG\Parameter(
357
     *         name="token",
358
     *         in="path",
359
     *         type="string",
360
     *         description="the email link token",
361
     *         required=true,
362
     *         default="r4nd0mT0k3n"
363
     *     ),
364
     *     @SWG\Parameter(
365
     *         name="password",
366
     *         in="formData",
367
     *         type="string",
368
     *         description="a password for the user",
369
     *         required=true,
370
     *         default="password"
371
     *     ),
372
     *     @SWG\Parameter(
373
     *         name="confirm",
374
     *         in="formData",
375
     *         type="string",
376
     *         description="password confirmation",
377
     *         required=true,
378
     *         default="password"
379
     *     )
380
     * )
381
     * @throws Exception
382
     */
383
    public function resetPassAction()
384
    {
385
        if (!$this->httpMethodCheck('POST')) { return; }
386
387
        $email = $this->getParam('email');
388
        $token = $this->getParam('token');
389
390
        $user = $this->userService->findUserByEmail($email);
391
        if (!$user) {
392
            $this->sendJsonResponse(['error' => UserException::USER_NOT_FOUND], 404);
393
            return;
394
        }
395
396
        try {
397
            $link = $this->userService->findEmailLink($email, $token);
398
        } catch (EmailLinkException $e) {
399
            $code = $e->getMessage() == EmailLinkException::LINK_EXPIRED ? 400 : 404;
400
            $this->sendJsonResponse(['error' => $e->getMessage(), $code]);
401
            return;
402
        }
403
404
        $form = new ResetPasswordForm('reset-pass');
405
406
        $data = $this->getRequest()->getParsedBody();
407
408
        $form->populate($data);
0 ignored issues
show
Bug introduced by
It seems like $data can also be of type null and object; however, parameter $data of Del\Form\AbstractForm::populate() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

408
        $form->populate(/** @scrutinizer ignore-type */ $data);
Loading history...
409
410
        if ($form->isValid()) {
411
412
            if ($data['password'] == $data['confirm']) {
413
                $this->userService->changePassword($user, $data['password']);
414
                $this->userService->deleteEmailLink($link);
415
                $this->sendJsonResponse(['success' => 'Password successfully changed']);
416
                return;
417
            } else {
418
                $this->sendJsonResponse(['error' => 'Passwords did not match, please try again.'], 400);
419
            }
420
        } else {
421
            $errors = [];
422
            $fields = $form->getFields();
423
            foreach ($fields as $field) {
424
                $validators = $field->getValidators();
425
                foreach ($validators as $validator) {
426
                    $errors[$field->getName()] = $validator->getMessages();
427
                }
428
            }
429
            $this->sendJsonResponse(['error' => $errors], 400);
430
        }
431
    }
432
}
433