Failed Conditions
Pull Request — master (#342)
by Maximo
02:30
created

AuthController::signup()   A

Complexity

Conditions 3
Paths 8

Size

Total Lines 73
Code Lines 46

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 46
nc 8
nop 0
dl 0
loc 73
ccs 0
cts 47
cp 0
crap 12
rs 9.1781
c 1
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Canvas\Api\Controllers;
6
7
use Canvas\Models\Users;
8
use Canvas\Models\Sources;
9
use Canvas\Models\UserLinkedSources;
10
use Canvas\Exception\ModelException;
11
use Baka\Auth\Models\Users as BakaUsers;
0 ignored issues
show
Bug introduced by
The type Baka\Auth\Models\Users was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
12
use Canvas\Traits\AuthTrait;
13
use Canvas\Traits\SocialLoginTrait;
14
use Canvas\Http\Exception\NotFoundException;
15
use Exception;
16
use Phalcon\Http\Response;
0 ignored issues
show
Bug introduced by
The type Phalcon\Http\Response was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
17
use Phalcon\Validation\Validator\Confirmation;
0 ignored issues
show
Bug introduced by
The type Phalcon\Validation\Validator\Confirmation was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
18
use Phalcon\Validation\Validator\Email as EmailValidator;
0 ignored issues
show
Bug introduced by
The type Phalcon\Validation\Validator\Email was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
19
use Phalcon\Validation\Validator\PresenceOf;
0 ignored issues
show
Bug introduced by
The type Phalcon\Validation\Validator\PresenceOf was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
20
use Phalcon\Validation\Validator\StringLength;
0 ignored issues
show
Bug introduced by
The type Phalcon\Validation\Validator\StringLength was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
21
use Baka\Auth\Models\Sessions;
0 ignored issues
show
Bug introduced by
The type Baka\Auth\Models\Sessions was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
22
use Canvas\Auth\Factory;
23
use Canvas\Http\Exception\InternalServerErrorException;
24
use Canvas\Validation as CanvasValidation;
25
use Canvas\Notifications\ResetPassword;
26
use Canvas\Notifications\PasswordUpdate;
27
use Canvas\Notifications\Signup;
28
use Canvas\Notifications\UpdateEmail;
29
use Canvas\Validations\PasswordValidation;
30
use Canvas\Traits\TokenTrait;
31
32
/**
33
 * Class AuthController.
34
 *
35
 * @package Canvas\Api\Controllers
36
 *
37
 * @property Users $userData
38
 * @property Request $request
39
 * @property Config $config
40
 * @property \Baka\Mail\Message $mail
41
 * @property Apps $app
42
 */
43
class AuthController extends \Baka\Auth\AuthController
0 ignored issues
show
Bug introduced by
The type Baka\Auth\AuthController was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
44
{
45
    /**
46
     * Auth Trait.
47
     */
48
    use AuthTrait;
49
    use TokenTrait;
50
    use SocialLoginTrait;
51
52
    /**
53
     * Setup for this controller.
54
     *
55
     * @return void
56
     */
57
    public function onConstruct()
58
    {
59
        $this->userLinkedSourcesModel = new UserLinkedSources();
0 ignored issues
show
Bug Best Practice introduced by
The property userLinkedSourcesModel does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
60
        $this->userModel = new Users();
0 ignored issues
show
Bug Best Practice introduced by
The property userModel does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
61
62
        if (!isset($this->config->jwt)) {
63
            throw new InternalServerErrorException('You need to configure your app JWT');
64
        }
65
    }
66
67
    /**
68
     * User Login.
69
     * @method POST
70
     * @url /v1/auth
71
     *
72
     * @return Response
73
     */
74
    public function login() : Response
75
    {
76
        $request = $this->request->getPostData();
77
78
        $userIp = !defined('API_TESTS') ? $this->request->getClientAddress() : '127.0.0.1'; //help getting the client ip on scrutinizer :(
79
        $admin = 0;
80
        $remember = 1;
81
82
        //Ok let validate user password
83
        $validation = new CanvasValidation();
84
        $validation->add('email', new EmailValidator(['message' => _('The email is not valid')]));
85
        $validation->add('password', new PresenceOf(['message' => _('The password is required.')]));
86
87
        $validation->setFilters('name', 'trim');
88
        $validation->setFilters('password', 'trim');
89
90
        //validate this form for password
91
        $validation->validate($request);
92
93
        $email = $validation->getValue('email');
94
        $password = $validation->getValue('password');
95
96
        /**
97
         * Login the user via ecosystem or app.
98
         */
99
        $auth = Factory::create($this->app->ecosystemAuth());
100
        $userData = $auth::login($email, $password, $remember, $admin, $userIp);
101
        $token = $userData->getToken();
102
103
        //start session
104
        $session = new Sessions();
105
        $session->start($userData, $token['sessionId'], $token['token'], $userIp, 1);
106
107
        return $this->response([
108
            'token' => $token['token'],
109
            'refresh_token' => $token['refresh_token'],
110
            'time' => date('Y-m-d H:i:s'),
111
            'expires' => date('Y-m-d H:i:s', time() + $this->config->jwt->payload->exp),
112
            'refresh_token_expires' => date('Y-m-d H:i:s', time() + 31536000),
113
            'id' => $userData->getId()
114
        ]);
115
    }
116
117
    /**
118
     * User Signup.
119
     *
120
     * @method POST
121
     * @url /v1/users
122
     *
123
     * @return Response
124
     */
125
    public function signup() : Response
126
    {
127
        $user = $this->userModel;
128
129
        $request = $this->request->getPostData();
130
131
        //Ok let validate user password
132
        $validation = new CanvasValidation();
133
        $validation->add('password', new PresenceOf(['message' => _('The password is required.')]));
134
        $validation->add('firstname', new PresenceOf(['message' => _('The firstname is required.')]));
135
        $validation->add('lastname', new PresenceOf(['message' => _('The lastname is required.')]));
136
        $validation->add('email', new EmailValidator(['message' => _('The email is not valid.')]));
137
138
        $validation->add(
139
            'password',
140
            new StringLength([
141
                'min' => 8,
142
                'messageMinimum' => _('Password is too short. Minimum 8 characters.'),
143
            ])
144
        );
145
146
        $validation->add('password', new Confirmation([
147
            'message' => _('Password and confirmation do not match.'),
148
            'with' => 'verify_password',
149
        ]));
150
151
        $validation->setFilters('password', 'trim');
152
        $validation->setFilters('displayname', 'trim');
153
        $validation->setFilters('default_company', 'trim');
154
155
        //validate this form for password
156
        $validation->validate($request);
157
158
        $user->email = $validation->getValue('email');
159
        $user->firstname = $validation->getValue('firstname');
160
        $user->lastname = $validation->getValue('lastname');
161
        $user->password = $validation->getValue('password');
162
        $userIp = !defined('API_TESTS') ? $this->request->getClientAddress() : '127.0.0.1'; //help getting the client ip on scrutinizer :(
163
        $user->displayname = $validation->getValue('displayname');
164
        $user->defaultCompanyName = $validation->getValue('default_company');
165
166
        //user registration
167
        try {
168
            $this->db->begin();
169
170
            $user->signUp();
171
172
            $this->db->commit();
173
        } catch (Exception $e) {
174
            $this->db->rollback();
175
176
            throw new Exception($e->getMessage());
177
        }
178
179
        $token = $user->getToken();
180
181
        //start session
182
        $session = new Sessions();
183
        $session->start($user, $token['sessionId'], $token['token'], $userIp, 1);
184
185
        $authSession = [
186
            'token' => $token['token'],
187
            'time' => date('Y-m-d H:i:s'),
188
            'expires' => date('Y-m-d H:i:s', time() + $this->config->jwt->payload->exp),
189
            'id' => $user->getId(),
190
        ];
191
192
        $user->password = null;
193
        $user->notify(new Signup($user));
194
195
        return $this->response([
196
            'user' => $user,
197
            'session' => $authSession
198
        ]);
199
    }
200
201
    /**
202
     * Refresh user auth.
203
     *
204
     * @return Response
205
     * @todo Validate acces_token and refresh token, session's user email and relogin
206
     */
207
    public function refresh(): Response
208
    {
209
        $request = $this->request->getPostData();
210
        $accessToken = $this->getToken($request['access_token']);
211
        $refreshToken = $this->getToken($request['refresh_token']);
212
        $user = null;
213
214
        if (time() != $accessToken->getClaim('exp')) {
215
            throw new InternalServerErrorException('Issued Access Token has not expired');
216
        }
217
218
        //Check if both tokens relate to the same user's email
219
        if ($accessToken->getClaim('sessionId') == $refreshToken->getClaim('sessionId')) {
220
            $user = Users::getByEmail($accessToken->getClaim('email'));
221
        }
222
223
        if (!$user) {
224
            throw new NotFoundException(_('User not found'));
225
        }
226
227
        $token = Sessions::restart($user, $refreshToken->getClaim('sessionId'), (string)$this->request->getClientAddress());
228
229
        return $this->response([
230
            'token' => $token['token'],
231
            'time' => date('Y-m-d H:i:s'),
232
            'expires' => date('Y-m-d H:i:s', time() + $this->config->jwt->payload->exp),
233
            'id' => $user->getId(),
234
        ]);
235
    }
236
237
    /**
238
     * Send email to change current email for user.
239
     * @param int $id
240
     * @return Response
241
     */
242
    public function sendEmailChange(int $id): Response
243
    {
244
        //Search for user
245
        $user = Users::getById($id);
246
247
        if (!is_object($user)) {
248
            throw new NotFoundException(_('User not found'));
249
        }
250
251
        $user->notify(new UpdateEmail($user));
252
253
        return $this->response($user);
254
    }
255
256
    /**
257
     * Change user's email.
258
     * @param string $hash
259
     * @return Response
260
     */
261
    public function changeUserEmail(string $hash): Response
262
    {
263
        $request = $this->request->getPostData();
264
265
        //Ok let validate user password
266
        $validation = new CanvasValidation();
267
        $validation->add('password', new PresenceOf(['message' => _('The password is required.')]));
268
        $validation->add('new_email', new EmailValidator(['message' => _('The email is not valid.')]));
269
270
        $validation->add(
271
            'password',
272
            new StringLength([
273
                'min' => 8,
274
                'messageMinimum' => _('Password is too short. Minimum 8 characters.'),
275
            ])
276
        );
277
278
        //validate this form for password
279
        $validation->setFilters('password', 'trim');
280
        $validation->setFilters('default_company', 'trim');
281
        $validation->validate($request);
282
283
        $newEmail = $validation->getValue('new_email');
284
        $password = $validation->getValue('password');
285
286
        //Search user by key
287
        $user = Users::getByUserActivationEmail($hash);
288
289
        if (!is_object($user)) {
290
            throw new NotFoundException(_('User not found'));
291
        }
292
293
        $this->db->begin();
294
295
        $user->email = $newEmail;
0 ignored issues
show
Bug Best Practice introduced by
The property email does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
296
297
        if (!$user->update()) {
298
            throw new ModelException((string) current($user->getMessages()));
0 ignored issues
show
Deprecated Code introduced by
The class Canvas\Exception\ModelException has been deprecated: version 0.1.5 ( Ignorable by Annotation )

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

298
            throw /** @scrutinizer ignore-deprecated */ new ModelException((string) current($user->getMessages()));
Loading history...
299
        }
300
301
        if (!$userData = $this->loginUsers($user->email, $password)) {
302
            $this->db->rollback();
303
        }
304
305
        $this->db->commit();
306
307
        return $this->response($userData);
308
    }
309
310
    /**
311
     * Login user using Access Token.
312
     * @return Response
313
     */
314
    public function loginBySocial(): Response
315
    {
316
        $request = $this->request->getPostData();
317
318
        $source = Sources::findFirstOrFail([
319
            'title = ?0 and is_deleted = 0',
320
            'bind' => [$request['provider']]
321
        ]);
322
323
        if ($source->isApple()) {
324
            $appleUserInfo = $source->validateAppleUser($request['social_id']);
325
            $request['social_id'] = $appleUserInfo->sub;
326
            $request['email'] = $appleUserInfo->email;
327
        }
328
329
        return $this->response($this->providerLogin($source, $request['social_id'], $request));
330
    }
331
332
    /**
333
     * Send the user how filled out the form to the specify email
334
     * a link to reset his password.
335
     *
336
     * @return Response
337
     */
338
    public function recover(): Response
339
    {
340
        $request = $this->request->getPostData();
341
342
        $validation = new CanvasValidation();
343
        $validation->add('email', new EmailValidator(['message' => _('The email is not valid.')]));
344
345
        $validation->validate($request);
346
347
        $email = $validation->getValue('email');
348
349
        $recoverUser = Users::getByEmail($email);
350
        $recoverUser->generateForgotHash();
351
352
        $recoverUser->notify(new ResetPassword($recoverUser));
353
354
        return $this->response(_('Check your email to recover your password'));
355
    }
356
357
    /**
358
     * Reset the user password.
359
     * @method PUT
360
     * @url /v1/reset
361
     *
362
     * @return Response
363
     */
364
    public function reset(string $key) : Response
365
    {
366
        //is the key empty or does it existe?
367
        if (empty($key) || !$userData = Users::findFirst(['user_activation_forgot = :key:', 'bind' => ['key' => $key]])) {
368
            throw new Exception(_('This Key to reset password doesn\'t exist'));
369
        }
370
371
        $request = $this->request->getPostData();
372
373
        // Get the new password and the verify
374
        $newPassword = trim($request['new_password']);
375
        $verifyPassword = trim($request['verify_password']);
376
377
        //Ok let validate user password
378
        PasswordValidation::validate($newPassword, $verifyPassword);
379
380
        // Has the password and set it
381
        $userData->resetPassword($newPassword);
382
        $userData->user_activation_forgot = '';
383
        $userData->updateOrFail();
384
385
        //log the user out of the site from all devices
386
        $session = new Sessions();
387
        $session->end($userData);
388
389
        $userData->notify(new PasswordUpdate($userData));
390
391
        return $this->response(_('Password Updated'));
392
    }
393
394
    /**
395
    * Set the email config array we are going to be sending.
396
    *
397
    * @todo deprecated move to notifications
398
    * @param String $emailAction
399
    * @param Users  $user
400
    * @deprecated version 1
401
    * @return void
402
    */
403
    protected function sendEmail(BakaUsers $user, string $type): void
404
    {
405
        return ;
406
    }
407
}
408