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

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