Completed
Push — master ( d14457...da0e1e )
by Derek Stephen
25:25 queued 19:55
created

UserController   A

Complexity

Total Complexity 33

Size/Duplication

Total Lines 357
Duplicated Lines 0 %

Test Coverage

Coverage 47.06%

Importance

Changes 0
Metric Value
wmc 33
eloc 117
dl 0
loc 357
ccs 56
cts 119
cp 0.4706
rs 9.76
c 0
b 0
f 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
A lostPasswordAction() 0 19 4
A resendActivationAction() 0 19 4
A indexAction() 0 16 3
B resetPassAction() 0 47 9
B activateAction() 0 48 6
A registerAction() 0 26 6
A init() 0 4 1
1
<?php
2
3
namespace App\Controller;
4
5
use App\Form\User\RegistrationForm;
6
use App\Form\User\ResetPasswordForm;
7
use Del\Common\ContainerService;
8
use Del\Exception\EmailLinkException;
9
use Del\Exception\UserException;
10
use Del\Service\UserService;
11
use Del\Value\User\State;
12
use Exception;
13
use Zend\Validator\EmailAddress;
14
15
class UserController extends BaseController
16
{
17
    /** @var UserService */
18
    private $userService;
19
20 5
    public function init()
21
    {
22 5
        $c = ContainerService::getInstance()->getContainer();
23 5
        $this->userService = $c['service.user'];
24 5
    }
25
26
    /**
27
     * Fetch user details by ID.
28
     *
29
     * @SWG\Get(
30
     *     path="/user/{id}",
31
     *     tags={"users"},
32
     *     @SWG\Parameter(
33
     *         name="id",
34
     *         in="path",
35
     *         type="integer",
36
     *         description="the type of response",
37
     *         required=false,
38
     *         default=1
39
     *     ),
40
     *     @SWG\Response(response="200", description="Sends user details")
41
     * )
42
     *
43
     */
44
    public function indexAction()
45
    {
46
        if (!$this->httpMethodCheck('GET')) { return; }
47
48
        $id = $this->getParam('id');
49
50
        /** @var UserService $userSvc */
51
        $userSvc = ContainerService::getInstance()->getContainer()['service.user'];
52
53
        $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

53
        $user = $userSvc->findUserById(/** @scrutinizer ignore-type */ $id);
Loading history...
54
        if (!$user) {
55
            $this->sendJsonResponse(['error' => 'User not found'], 404);
56
            return;
57
        }
58
59
        $this->sendJsonObjectResponse($user);
60
    }
61
62
63
64
    /**
65
     * Activate from the email link token.
66
     *
67
     * @SWG\Get(
68
     *     path="/user/activate/{email}/{token}",
69
     *     tags={"users"},
70
     *     @SWG\Response(response="200", description="Registers a new unactivated user"),
71
     *     @SWG\Parameter(
72
     *         name="email",
73
     *         in="path",
74
     *         type="string",
75
     *         description="the users email",
76
     *         required=true,
77
     *         default="[email protected]"
78
     *     ),
79
     *     @SWG\Parameter(
80
     *         name="token",
81
     *         in="path",
82
     *         type="string",
83
     *         description="the email link token",
84
     *         required=true,
85
     *         default="r4nd0mT0k3n"
86
     *     )
87
     * )
88
     * @throws Exception
89
     */
90 3
    public function activateAction()
91
    {
92 3
        if (!$this->httpMethodCheck('GET')) { return; }
93
94 3
        $email = $this->getParam('email');
95 3
        $token = $this->getParam('token');
96
97 3
        $userService = $this->userService;
98
99
        try {
100
101 3
            $link = $userService->findEmailLink($email, $token);
102
103 2
            $user = $link->getUser();
104 2
            $user->setState(new State(State::STATE_ACTIVATED));
105 2
            $userService->saveUser($user);
106 2
            $userService->deleteEmailLink($link);
107 2
            $data = ['success' => true];
108 2
            $code = 200;
109
110 1
        } catch (EmailLinkException $e) {
111 1
            switch ($e->getMessage()) {
112 1
                case EmailLinkException::LINK_EXPIRED:
113 1
                case EmailLinkException::LINK_NO_MATCH:
114
                    $data = [
115
                        'success' => false,
116
                        'error' => $e->getMessage(),
117
                    ];
118
                    $code = 403;
119
                    break;
120 1
                case EmailLinkException::LINK_NOT_FOUND:
121
                    $data = [
122 1
                        'success' => false,
123 1
                        'error' => $e->getMessage(),
124
                    ];
125 1
                    $code = 404;
126 1
                    break;
127
                default:
128
                    $data = [
129
                        'success' => false,
130
                        'error' => $e->getMessage(),
131
                    ];
132
                    $code = 500;
133
                    break;
134
            }
135
        }
136
137 3
        $this->sendJsonResponse($data, $code);
138 3
    }
139
140
141
    /**
142
     * Refresh the activation email link token.
143
     *
144
     * @SWG\Get(
145
     *     path="/user/activate/resend/{email}",
146
     *     tags={"users"},
147
     *     @SWG\Parameter(
148
     *         name="email",
149
     *         in="path",
150
     *         type="string",
151
     *         description="the email of the user registering",
152
     *         required=true,
153
     *         default="[email protected]"
154
     *     ),
155
     *     @SWG\Response(response="200", description="Sends email link details")
156
     * )
157
     * @throws Exception
158
     */
159 1
    public function resendActivationAction()
160
    {
161 1
        if (!$this->httpMethodCheck('GET')) { return; }
162
163 1
        $email = $this->getParam('email');
164
165 1
        $user = $this->userService->findUserByEmail($email);
166 1
        if (!$user) {
167
            $this->sendJsonResponse(['error' => UserException::USER_NOT_FOUND], 404);
168
            return;
169
        }
170
171 1
        if ($user->getState()->getValue() == State::STATE_ACTIVATED) {
172
            $this->sendJsonResponse(['error' => UserException::USER_ACTIVATED], 400);
173
            return;
174
        }
175
176 1
        $link = $this->userService->generateEmailLink($user);
177 1
        $this->sendJsonObjectResponse($link);
178 1
    }
179
180
    /**
181
     * Get a lost password email link token.
182
     *
183
     * @SWG\Get(
184
     *     path="/user/lost-password/{email}",
185
     *     tags={"users"},
186
     *     @SWG\Parameter(
187
     *         name="email",
188
     *         in="path",
189
     *         type="string",
190
     *         description="the email of the user",
191
     *         required=true,
192
     *         default="[email protected]"
193
     *     ),
194
     *     @SWG\Response(response="200", description="Sends email link details")
195
     * )
196
     * @throws Exception
197
     */
198 1
    public function lostPasswordAction()
199
    {
200 1
        if (!$this->httpMethodCheck('GET')) { return; }
201
202 1
        $email = $this->getParam('email');
203
204 1
        $user = $this->userService->findUserByEmail($email);
205 1
        if (!$user) {
206
            $this->sendJsonResponse(['error' => UserException::USER_NOT_FOUND], 404);
207
            return;
208
        }
209
210 1
        if ($user->getState()->getValue() == State::STATE_UNACTIVATED) {
211
            $this->sendJsonResponse(['error' => UserException::USER_UNACTIVATED], 400);
212
            return;
213
        }
214
215 1
        $link = $this->userService->generateEmailLink($user);
216 1
        $this->sendJsonObjectResponse($link);
217 1
    }
218
219
    /**
220
     * Register as a new user. Returns an email link token.
221
     *
222
     * @SWG\Post(
223
     *     path="/user/register",
224
     *     tags={"users"},
225
     *     @SWG\Response(response="200", description="Registers a new unactivated user"),
226
     *     @SWG\Parameter(
227
     *         name="email",
228
     *         in="formData",
229
     *         type="string",
230
     *         description="the users email",
231
     *         required=true,
232
     *         default="[email protected]"
233
     *     ),
234
     *     @SWG\Parameter(
235
     *         name="password",
236
     *         in="formData",
237
     *         type="string",
238
     *         description="a password for the user",
239
     *         required=true,
240
     *         default="password"
241
     *     ),
242
     *     @SWG\Parameter(
243
     *         name="confirm",
244
     *         in="formData",
245
     *         type="string",
246
     *         description="password confirmation",
247
     *         required=true,
248
     *         default="password"
249
     *     )
250
     * )
251
     * @throws Exception
252
     */
253 5
    public function registerAction()
254
    {
255 5
        if (!$this->httpMethodCheck('POST')) { return; }
256
257 5
        $form = new RegistrationForm('register');
258
259 5
        if ($this->getRequest()->getMethod() == 'POST') {
260
261 5
            $formData = $this->getRequest()->getParsedBody();
262 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

262
            $form->populate(/** @scrutinizer ignore-type */ $formData);
Loading history...
263
264
            try {
265 5
                $data = $form->getValues();
266 5
                $user = $this->userService->registerUser($data);
267 5
                $link = $this->userService->generateEmailLink($user);
268 5
                $this->sendJsonObjectResponse($link);
269
270
            } catch (UserException $e) {
271
272
                switch ($e->getMessage()) {
273
                    case UserException::USER_EXISTS:
274
                    case UserException::WRONG_PASSWORD:
275
                        throw new Exception($e->getMessage(), 400);
276
                        break;
277
                }
278
                throw $e;
279
            }
280
        }
281 5
    }
282
283
    /**
284
     * Resets the users password. Requires an email link token.
285
     *
286
     * @SWG\Post(
287
     *     path="/user/reset-password/{email}/{token}",
288
     *     tags={"users"},
289
     *     @SWG\Response(response="200", description="Resets a users email"),
290
     *     @SWG\Parameter(
291
     *         name="email",
292
     *         in="path",
293
     *         type="string",
294
     *         description="the email of the user",
295
     *         required=true,
296
     *         default="[email protected]"
297
     *     ),
298
     *     @SWG\Parameter(
299
     *         name="token",
300
     *         in="path",
301
     *         type="string",
302
     *         description="the email link token",
303
     *         required=true,
304
     *         default="r4nd0mT0k3n"
305
     *     ),
306
     *     @SWG\Parameter(
307
     *         name="password",
308
     *         in="formData",
309
     *         type="string",
310
     *         description="a password for the user",
311
     *         required=true,
312
     *         default="password"
313
     *     ),
314
     *     @SWG\Parameter(
315
     *         name="confirm",
316
     *         in="formData",
317
     *         type="string",
318
     *         description="password confirmation",
319
     *         required=true,
320
     *         default="password"
321
     *     )
322
     * )
323
     * @throws Exception
324
     */
325
    public function resetPassAction()
326
    {
327
        if (!$this->httpMethodCheck('POST')) { return; }
328
329
        $email = $this->getParam('email');
330
        $token = $this->getParam('token');
331
332
        $user = $this->userService->findUserByEmail($email);
333
        if (!$user) {
334
            $this->sendJsonResponse(['error' => UserException::USER_NOT_FOUND], 404);
335
            return;
336
        }
337
338
        try {
339
            $link = $this->userService->findEmailLink($email, $token);
340
        } catch (EmailLinkException $e) {
341
            $code = $e->getMessage() == EmailLinkException::LINK_EXPIRED ? 400 : 404;
342
            $this->sendJsonResponse(['error' => $e->getMessage(), $code]);
343
            return;
344
        }
345
346
        $form = new ResetPasswordForm('reset-pass');
347
348
        $data = $this->getRequest()->getParsedBody();
349
350
        $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

350
        $form->populate(/** @scrutinizer ignore-type */ $data);
Loading history...
351
352
        if ($form->isValid()) {
353
354
            if ($data['password'] == $data['confirm']) {
355
                $this->userService->changePassword($user, $data['password']);
356
                $this->userService->deleteEmailLink($link);
357
                $this->sendJsonResponse(['success' => 'Password successfully changed']);
358
                return;
359
            } else {
360
                $this->sendJsonResponse(['error' => 'Passwords did not match, please try again.'], 400);
361
            }
362
        } else {
363
            $errors = [];
364
            $fields = $form->getFields();
365
            foreach ($fields as $field) {
366
                $validators = $field->getValidators();
367
                foreach ($validators as $validator) {
368
                    $errors[$field->getName()] = $validator->getMessages();
369
                }
370
            }
371
            $this->sendJsonResponse(['error' => $errors], 400);
372
        }
373
    }
374
}
375