Completed
Push — master ( 6a9a57...36877f )
by Derek Stephen
04:37
created

UserController   A

Complexity

Total Complexity 34

Size/Duplication

Total Lines 383
Duplicated Lines 0 %

Test Coverage

Coverage 29.8%

Importance

Changes 0
Metric Value
wmc 34
eloc 138
dl 0
loc 383
ccs 31
cts 104
cp 0.298
rs 9.68
c 0
b 0
f 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
A lostPasswordAction() 0 19 4
A indexAction() 0 16 3
B resetPassAction() 0 47 9
B activateAction() 0 48 6
A init() 0 4 1
A resendActivationAction() 0 19 4
B registerAction() 0 51 7
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 5
    public function init()
23
    {
24 5
        $c = ContainerService::getInstance()->getContainer();
25 5
        $this->userService = $c['service.user'];
26 5
    }
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
    public function indexAction()
47
    {
48
        if (!$this->httpMethodCheck('GET')) { return; }
49
50
        $id = $this->getParam('id');
51
52
        /** @var UserService $userSvc */
53
        $userSvc = ContainerService::getInstance()->getContainer()['service.user'];
54
55
        $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
        if (!$user) {
57
            $this->sendJsonResponse(['error' => 'User not found'], 404);
58
            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 1
    public function activateAction()
93
    {
94 1
        if (!$this->httpMethodCheck('GET')) { return; }
95
96 1
        $email = $this->getParam('email');
97 1
        $token = $this->getParam('token');
98
99 1
        $userService = $this->userService;
100
101
        try {
102
103 1
            $link = $userService->findEmailLink($email, $token);
104
105
            $user = $link->getUser();
106
            $user->setState(new State(State::STATE_ACTIVATED));
107
            $userService->saveUser($user);
108
            $userService->deleteEmailLink($link);
109
            $data = ['success' => true];
110
            $code = 200;
111
112 1
        } catch (EmailLinkException $e) {
113 1
            switch ($e->getMessage()) {
114 1
                case EmailLinkException::LINK_EXPIRED:
115 1
                case EmailLinkException::LINK_NO_MATCH:
116
                    $data = [
117
                        'success' => false,
118
                        'error' => $e->getMessage(),
119
                    ];
120
                    $code = 403;
121
                    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 1
        $this->sendJsonResponse($data, $code);
140 1
    }
141
142
143
    /**
144
     * Refresh the activation email link token.
145
     *
146
     * @SWG\Get(
147
     *     path="/user/activate/resend/{email}",
148
     *     tags={"users"},
149
     *     @SWG\Parameter(
150
     *         name="email",
151
     *         in="path",
152
     *         type="string",
153
     *         description="the email of the user registering",
154
     *         required=true,
155
     *         default="[email protected]"
156
     *     ),
157
     *     @SWG\Response(response="200", description="Sends email link details")
158
     * )
159
     * @throws Exception
160
     */
161 1
    public function resendActivationAction()
162
    {
163 1
        if (!$this->httpMethodCheck('GET')) { return; }
164
165 1
        $email = $this->getParam('email');
166
167 1
        $user = $this->userService->findUserByEmail($email);
168 1
        if (!$user) {
169 1
            $this->sendJsonResponse(['error' => UserException::USER_NOT_FOUND], 404);
170 1
            return;
171
        }
172
173
        if ($user->getState()->getValue() == State::STATE_ACTIVATED) {
174
            $this->sendJsonResponse(['error' => UserException::USER_ACTIVATED], 400);
175
            return;
176
        }
177
178
        $link = $this->userService->generateEmailLink($user);
179
        $this->sendJsonObjectResponse($link);
180
    }
181
182
    /**
183
     * Get a lost password email link token.
184
     *
185
     * @SWG\Get(
186
     *     path="/user/lost-password/{email}",
187
     *     tags={"users"},
188
     *     @SWG\Parameter(
189
     *         name="email",
190
     *         in="path",
191
     *         type="string",
192
     *         description="the email of the user",
193
     *         required=true,
194
     *         default="[email protected]"
195
     *     ),
196
     *     @SWG\Response(response="200", description="Sends email link details")
197
     * )
198
     * @throws Exception
199
     */
200
    public function lostPasswordAction()
201
    {
202
        if (!$this->httpMethodCheck('GET')) { return; }
203
204
        $email = $this->getParam('email');
205
206
        $user = $this->userService->findUserByEmail($email);
207
        if (!$user) {
208
            $this->sendJsonResponse(['error' => UserException::USER_NOT_FOUND], 404);
209
            return;
210
        }
211
212
        if ($user->getState()->getValue() == State::STATE_UNACTIVATED) {
213
            $this->sendJsonResponse(['error' => UserException::USER_UNACTIVATED], 400);
214
            return;
215
        }
216
217
        $link = $this->userService->generateEmailLink($user);
218
        $this->sendJsonObjectResponse($link);
219
    }
220
221
    /**
222
     * Register as a new user. Returns an email link token.
223
     *
224
     * @SWG\Post(
225
     *     path="/user/register",
226
     *     tags={"users"},
227
     *     @SWG\Response(response="200", description="Registers a new unactivated user"),
228
     *     @SWG\Parameter(
229
     *         name="email",
230
     *         in="formData",
231
     *         type="string",
232
     *         description="the users email",
233
     *         required=true,
234
     *         default="[email protected]"
235
     *     ),
236
     *     @SWG\Parameter(
237
     *         name="password",
238
     *         in="formData",
239
     *         type="string",
240
     *         description="a password for the user",
241
     *         required=true,
242
     *         default="password"
243
     *     ),
244
     *     @SWG\Parameter(
245
     *         name="confirm",
246
     *         in="formData",
247
     *         type="string",
248
     *         description="password confirmation",
249
     *         required=true,
250
     *         default="password"
251
     *     )
252
     * )
253
     * @throws Exception
254
     */
255 5
    public function registerAction()
256
    {
257 5
        if (!$this->httpMethodCheck('POST')) { return; }
258 5
phpinfo(); exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
259
        $form = new RegistrationForm('register');
0 ignored issues
show
Unused Code introduced by
$form = new App\Form\Use...trationForm('register') is not reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
260
261
        if ($this->getRequest()->getMethod() == 'POST') {
262
263
            $formData = $this->getRequest()->getParsedBody();
264
            $form->populate($formData);
265
266
            if ($form->isValid()) {
267
                try {
268
                    $data = $form->getValues();
269
                    $user = $this->userService->registerUser($data);
270
                    $link = $this->userService->generateEmailLink($user);
271
                    $mail = $this->getMailService();
272
                    $env = $this->getServerEnvironment();
273
                    $siteURL = $env->getRequestScheme() . '://' . $env->getHttpHost();
274
                    $email = $user->getEmail();
275
                    $token = $link->getToken();
276
277
                    $message =
278
                        <<<END
279
                        Thank you for registering with $siteURL. You must now activate your account by clicking on the link below.<br /&nbsp;<br />
280
<a href="$siteURL/user/activate/$email/$token">Activate my Account</a>.
281
END;
282
283
                    $mail->setFrom('noreply@' . $env->getHttpHost())
284
                        ->setTo($user->getEmail())
285
                        ->setSubject('Thank you for registering with ' . Registry::ahoy()->get('site')['name'])
286
                        ->setHeader('MAIL HEADER')
287
//                        ->setHeader(Template::getHeader())
288
                        ->setFooter('MAIL FOOTER')
289
//                        ->setFooter(Template::getFooter())
290
                        ->setMessage($message)
291
                        ->send();
292
                    $this->sendJsonObjectResponse($link);
293
294
                } catch (UserException $e) {
295
296
                    switch ($e->getMessage()) {
297
                        case UserException::USER_EXISTS:
298
                        case UserException::WRONG_PASSWORD:
299
                            throw new Exception($e->getMessage(), 400);
300
                            break;
301
                    }
302
                    throw $e;
303
                }
304
            } else {
305
                throw new Exception('Invalid request data;', 400);
306
            }
307
308
        }
309
    }
310
311
    /**
312
     * Resets the users password. Requires an email link token.
313
     *
314
     * @SWG\Post(
315
     *     path="/user/reset-password/{email}/{token}",
316
     *     tags={"users"},
317
     *     @SWG\Response(response="200", description="Resets a users email"),
318
     *     @SWG\Parameter(
319
     *         name="email",
320
     *         in="path",
321
     *         type="string",
322
     *         description="the email of the user",
323
     *         required=true,
324
     *         default="[email protected]"
325
     *     ),
326
     *     @SWG\Parameter(
327
     *         name="token",
328
     *         in="path",
329
     *         type="string",
330
     *         description="the email link token",
331
     *         required=true,
332
     *         default="r4nd0mT0k3n"
333
     *     ),
334
     *     @SWG\Parameter(
335
     *         name="password",
336
     *         in="formData",
337
     *         type="string",
338
     *         description="a password for the user",
339
     *         required=true,
340
     *         default="password"
341
     *     ),
342
     *     @SWG\Parameter(
343
     *         name="confirm",
344
     *         in="formData",
345
     *         type="string",
346
     *         description="password confirmation",
347
     *         required=true,
348
     *         default="password"
349
     *     )
350
     * )
351
     * @throws Exception
352
     */
353
    public function resetPassAction()
354
    {
355
        if (!$this->httpMethodCheck('POST')) { return; }
356
357
        $email = $this->getParam('email');
358
        $token = $this->getParam('token');
359
360
        $user = $this->userService->findUserByEmail($email);
361
        if (!$user) {
362
            $this->sendJsonResponse(['error' => UserException::USER_NOT_FOUND], 404);
363
            return;
364
        }
365
366
        try {
367
            $link = $this->userService->findEmailLink($email, $token);
368
        } catch (EmailLinkException $e) {
369
            $code = $e->getMessage() == EmailLinkException::LINK_EXPIRED ? 400 : 404;
370
            $this->sendJsonResponse(['error' => $e->getMessage(), $code]);
371
            return;
372
        }
373
374
        $form = new ResetPasswordForm('reset-pass');
375
376
        $data = $this->getRequest()->getParsedBody();
377
378
        $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

378
        $form->populate(/** @scrutinizer ignore-type */ $data);
Loading history...
379
380
        if ($form->isValid()) {
381
382
            if ($data['password'] == $data['confirm']) {
383
                $this->userService->changePassword($user, $data['password']);
384
                $this->userService->deleteEmailLink($link);
385
                $this->sendJsonResponse(['success' => 'Password successfully changed']);
386
                return;
387
            } else {
388
                $this->sendJsonResponse(['error' => 'Passwords did not match, please try again.'], 400);
389
            }
390
        } else {
391
            $errors = [];
392
            $fields = $form->getFields();
393
            foreach ($fields as $field) {
394
                $validators = $field->getValidators();
395
                foreach ($validators as $validator) {
396
                    $errors[$field->getName()] = $validator->getMessages();
397
                }
398
            }
399
            $this->sendJsonResponse(['error' => $errors], 400);
400
        }
401
    }
402
}
403