Test Failed
Pull Request — master (#160)
by Maximo
07:00
created

AuthController::changeUserEmail()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 27
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 0
Metric Value
cc 4
eloc 13
nc 4
nop 1
dl 0
loc 27
ccs 0
cts 18
cp 0
crap 20
rs 9.8333
c 0
b 0
f 0
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\ServerErrorHttpException;
11
use Canvas\Exception\ModelException;
12
use Baka\Auth\Models\Users as BakaUsers;
13
use Canvas\Traits\AuthTrait;
14
use Canvas\Traits\SocialLoginTrait;
15
use Exception;
16
use Phalcon\Http\Response;
17
use Phalcon\Validation;
18
use Phalcon\Validation\Validator\Confirmation;
19
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...
20
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...
21
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...
22
use Baka\Auth\Models\Sessions;
23
use Canvas\Auth\Factory;
24
use Canvas\Validation as CanvasValidation;
25
26
/**
27
 * Class AuthController.
28
 *
29
 * @package Canvas\Api\Controllers
30
 *
31
 * @property Users $userData
32
 * @property Request $request
33
 * @property Config $config
34
 * @property \Baka\Mail\Message $mail
35
 * @property Apps $app
36
 */
37
class AuthController extends \Baka\Auth\AuthController
38
{
39
    /**
40
     * Auth Trait.
41
     */
42
    use AuthTrait;
43
    use SocialLoginTrait;
44
45
    /**
46
     * Setup for this controller.
47
     *
48
     * @return void
49
     */
50
    public function onConstruct()
51
    {
52
        $this->userLinkedSourcesModel = new UserLinkedSources();
53
        $this->userModel = new Users();
54
55
        if (!isset($this->config->jwt)) {
56
            throw new ServerErrorHttpException('You need to configure your app JWT');
57
        }
58
    }
59
60
    /**
61
     * User Login.
62
     * @method POST
63
     * @url /v1/auth
64
     *
65
     * @return Response
66
     */
67
    public function login() : Response
68
    {
69
        $email = trim($this->request->getPost('email', 'string', ''));
70
        $password = trim($this->request->getPost('password', 'string', ''));
71
        $admin = 0;
72
        $userIp = !defined('API_TESTS') ? $this->request->getClientAddress() : '127.0.0.1'; //help getting the client ip on scrutinizer :(
73
        $remember = $this->request->getPost('remember', 'int', 1);
74
75
        //Ok let validate user password
76
        $validation = new CanvasValidation();
77
        $validation->add('email', new PresenceOf(['message' => _('The email is required.')]));
78
        $validation->add('password', new PresenceOf(['message' => _('The password is required.')]));
79
80
        //validate this form for password
81
        $validation->validate($this->request->getPost());
82
83
        /**
84
         * Login the user via ecosystem or app.
85
         */
86
        $auth = Factory::create($this->app->ecosystemAuth());
87
        $userData = $auth::login($email, $password, $remember, $admin, $userIp);
0 ignored issues
show
Bug introduced by
The method login() does not exist on Canvas\Auth\Auth. Since it exists in all sub-types, consider adding an abstract or default implementation to Canvas\Auth\Auth. ( Ignorable by Annotation )

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

87
        /** @scrutinizer ignore-call */ 
88
        $userData = $auth::login($email, $password, $remember, $admin, $userIp);
Loading history...
88
        $token = $userData->getToken();
89
90
        //start session
91
        $session = new Sessions();
92
        $session->start($userData, $token['sessionId'], $token['token'], $userIp, 1);
93
94
        return $this->response([
95
            'token' => $token['token'],
96
            'time' => date('Y-m-d H:i:s'),
97
            'expires' => date('Y-m-d H:i:s', time() + $this->config->jwt->payload->exp),
98
            'id' => $userData->getId(),
99
        ]);
100
    }
101
102
    /**
103
     * User Signup.
104
     *
105
     * @method POST
106
     * @url /v1/users
107
     *
108
     * @return Response
109
     */
110
    public function signup() : Response
111
    {
112
        $user = $this->userModel;
113
114
        $user->email = $this->request->getPost('email', 'email');
115
        $user->firstname = ltrim(trim($this->request->getPost('firstname', 'string', '')));
116
        $user->lastname = ltrim(trim($this->request->getPost('lastname', 'string', '')));
117
        $user->password = ltrim(trim($this->request->getPost('password', 'string', '')));
118
        $userIp = !defined('API_TESTS') ? $this->request->getClientAddress() : '127.0.0.1'; //help getting the client ip on scrutinizer :(
119
        $user->displayname = ltrim(trim($this->request->getPost('displayname', 'string', '')));
120
        $user->defaultCompanyName = ltrim(trim($this->request->getPost('default_company', 'string', '')));
121
122
        //Ok let validate user password
123
        $validation = new CanvasValidation();
124
        $validation->add('password', new PresenceOf(['message' => _('The password is required.')]));
125
        $validation->add('firstname', new PresenceOf(['message' => _('The firstname is required.')]));
126
        $validation->add('email', new EmailValidator(['message' => _('The email is not valid.')]));
127
128
        $validation->add(
129
            'password',
130
            new StringLength([
131
                'min' => 8,
132
                'messageMinimum' => _('Password is too short. Minimum 8 characters.'),
133
            ])
134
        );
135
136
        $validation->add('password', new Confirmation([
137
            'message' => _('Password and confirmation do not match.'),
138
            'with' => 'verify_password',
139
        ]));
140
141
        //validate this form for password
142
        $validation->validate($this->request->getPost());
143
144
        //user registration
145
        try {
146
            $this->db->begin();
147
148
            $user->signup();
149
150
            $this->db->commit();
151
        } catch (Exception $e) {
152
            $this->db->rollback();
153
154
            throw new Exception($e->getMessage());
155
        }
156
157
        $token = $user->getToken();
158
159
        //start session
160
        $session = new Sessions();
161
        $session->start($user, $token['sessionId'], $token['token'], $userIp, 1);
162
163
        $authSession = [
164
            'token' => $token['token'],
165
            'time' => date('Y-m-d H:i:s'),
166
            'expires' => date('Y-m-d H:i:s', time() + $this->config->jwt->payload->exp),
167
            'id' => $user->getId(),
168
        ];
169
170
        $user->password = null;
171
        $this->sendEmail($user, 'signup');
172
173
        return $this->response([
174
            'user' => $user,
175
            'session' => $authSession
176
        ]);
177
    }
178
179
    /**
180
     * Send email to change current email for user.
181
     * @param int $id
182
     * @return Response
183
     */
184
    public function sendEmailChange(int $id): Response
185
    {
186
        //Search for user
187
        $user = Users::getById($id);
188
189
        if (!is_object($user)) {
190
            throw new NotFoundHttpException(_('User not found'));
0 ignored issues
show
Bug introduced by
The type Canvas\Api\Controllers\NotFoundHttpException 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...
191
        }
192
193
        //Send email
194
        $this->sendEmail($user, 'email-change');
195
196
        return $this->response($user);
197
    }
198
199
    /**
200
    * Set the email config array we are going to be sending.
201
    *
202
    * @param String $emailAction
203
    * @param Users  $user
204
    * @return void
205
    */
206
    protected function sendEmail(BakaUsers $user, string $type): void
207
    {
208
        $send = true;
209
        $subject = null;
210
        $body = null;
211
        switch ($type) {
212
            case 'recover':
213
                $recoveryLink = $this->config->app->frontEndUrl . '/users/reset-password/' . $user->user_activation_forgot;
214
                $subject = _('Password Recovery');
215
                $body = sprintf(_('Click %shere%s to set a new password for your account.'), '<a href="' . $recoveryLink . '" target="_blank">', '</a>');
216
                // send email to recover password
217
                break;
218
            case 'reset':
219
                $activationUrl = $this->config->app->frontEndUrl . '/user/activate/' . $user->user_activation_key;
220
                $subject = _('Password Updated!');
221
                $body = sprintf(_('Your password was update please, use this link to activate your account: %sActivate account%s'), '<a href="' . $activationUrl . '">', '</a>');
222
                // send email that password was update
223
                break;
224
            case 'email-change':
225
                $emailChangeUrl = $this->config->app->frontEndUrl . '/user/' . $user->user_activation_email . '/email';
226
                $subject = _('Email Change Request');
227
                $body = sprintf(_('Click %shere%s to set a new email for your account.'), '<a href="' . $emailChangeUrl . '">', '</a>');
228
                break;
229
            default:
230
                $send = false;
231
                break;
232
        }
233
234
        if ($send) {
235
            $this->mail
236
            ->to($user->email)
237
            ->subject($subject)
238
            ->content($body)
239
            ->sendNow();
240
        }
241
    }
242
243
    /**
244
     * Change user's email.
245
     * @param string $hash
246
     * @return Response
247
     */
248
    public function changeUserEmail(string $hash): Response
249
    {
250
        $newEmail = $this->request->getPost('new_email', 'string');
251
        $password = $this->request->getPost('password', 'string');
252
253
        //Search user by key
254
        $user = Users::getByUserActivationEmail($hash);
255
256
        if (!is_object($user)) {
257
            throw new NotFoundHttpException(_('User not found'));
258
        }
259
260
        $this->db->begin();
261
262
        $user->email = $newEmail;
263
264
        if (!$user->update()) {
265
            throw new ModelException((string)current($user->getMessages()));
266
        }
267
268
        if (!$userData = $this->loginUsers($user->email, $password)) {
269
            $this->db->rollback();
270
        }
271
272
        $this->db->commit();
273
274
        return $this->response($userData);
275
    }
276
277
    /**
278
     * Login user using Access Token.
279
     * @return Response
280
     */
281
    public function loginBySocial(): Response
282
    {
283
        $request = $this->request->getPostData();
284
285
        $source = Sources::findFirstOrFail([
286
            'title = ?0 and is_deleted = 0',
287
            'bind' => [$request['provider']]
288
        ]);
289
290
        return $this->response($this->providerLogin($source, $request['social_id'], $request['email']));
291
    }
292
}
293