Completed
Push — master ( 244d05...62ce01 )
by Derek Stephen
06:36
created

UserController::indexAction()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 16
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
eloc 8
dl 0
loc 16
ccs 0
cts 9
cp 0
rs 10
c 0
b 0
f 0
cc 3
nc 3
nop 0
crap 12
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
            $this->sendJsonResponse(['error' => UserException::USER_NOT_FOUND], 404);
170
            return;
171
        }
172
173 1
        if ($user->getState()->getValue() == State::STATE_ACTIVATED) {
174
            $this->sendJsonResponse(['error' => UserException::USER_ACTIVATED], 400);
175
            return;
176
        }
177
178 1
        $link = $this->userService->generateEmailLink($user);
179 1
        $this->sendJsonObjectResponse($link);
180 1
    }
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
259 5
        $form = new RegistrationForm('register');
260
261 5
        if ($this->getRequest()->getMethod() == 'POST') {
262
263 5
            $formData = $this->getRequest()->getParsedBody();
264 5
            $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

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

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