GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Passed
Push — master ( c721cc...3ff35f )
by Ivan
09:59
created

UserController::actionChangePassword()   C

Complexity

Conditions 7
Paths 8

Size

Total Lines 27
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 27
rs 6.7272
c 0
b 0
f 0
cc 7
eloc 19
nc 8
nop 0
1
<?php
2
3
namespace app\modules\user\controllers;
4
5
use app\components\AuthClientHelper;
6
use app\modules\user\actions\AuthAction;
7
use app\modules\user\models\LoginForm;
8
use app\modules\user\models\PasswordResetRequestForm;
9
use app\modules\user\models\RegistrationForm;
10
use app\modules\user\models\ResetPasswordForm;
11
use app\modules\user\models\User;
12
use app\modules\user\models\UserService;
13
use Yii;
14
use yii\base\ErrorException;
15
use yii\base\InvalidParamException;
16
use yii\caching\TagDependency;
17
use yii\filters\AccessControl;
18
use yii\helpers\ArrayHelper;
19
use yii\web\BadRequestHttpException;
20
use yii\web\Controller;
21
use yii\web\NotFoundHttpException;
22
use yii\web\Response;
23
24
/**
25
 * Base DotPlant2 controller for handling user's login/signup/logout and etc. functions
26
 * @package app\controllers
27
 */
28
class UserController extends Controller
29
{
30
    /**
31
     * @inheritdoc
32
     */
33
    public function behaviors()
34
    {
35
        return [
36
            'access' => [
37
                'class' => AccessControl::className(),
38
                'only' => ['change-password', 'signup', 'profile'],
39
                'rules' => [
40
                    [
41
                        'actions' => ['signup'],
42
                        'allow' => true,
43
                        'roles' => ['?'],
44
                    ],
45
                    [
46
                        'actions' => ['profile', 'change-password'],
47
                        'allow' => true,
48
                        'roles' => ['@'],
49
                    ],
50
                ],
51
            ],
52
        ];
53
    }
54
55
    /**
56
     * @inheritdoc
57
     */
58
    public function actions()
59
    {
60
        return [
61
            'auth' => [
62
                'class' => 'app\modules\user\actions\AuthAction',
63
                'successCallback' => [$this, 'successCallback'],
64
            ],
65
        ];
66
    }
67
68
    /**
69
     * Action for loggin in users
70
     * @param null $returnUrl
71
     * @return string|Response
72
     */
73
    public function actionLogin($returnUrl = null)
74
    {
75
        TagDependency::invalidate(Yii::$app->cache, ['Session:'.Yii::$app->session->id]);
76
        if (\Yii::$app->user->isGuest === false) {
77
            $this->goHome();
78
        }
79
        $model = new LoginForm();
80
        if ($model->load(Yii::$app->request->post()) && $model->login()) {
81
            return $this->goBack($returnUrl);
82
        } else {
83
            return $this->render(
84
                'login',
85
                [
86
                    'model' => $model,
87
                ]
88
            );
89
        }
90
    }
91
92
    /**
93
     * Action for user's logout
94
     * @return Response
95
     */
96
    public function actionLogout()
97
    {
98
        if (!Yii::$app->user->isGuest) {
99
            TagDependency::invalidate(Yii::$app->cache, ['Session:' . Yii::$app->session->id]);
100
            Yii::$app->user->logout();
101
        }
102
        return $this->goHome();
103
    }
104
105
    /**
106
     * Action for standard registration handling
107
     * @return string|Response
108
     * @throws ErrorException
109
     */
110
    public function actionSignup()
111
    {
112
        TagDependency::invalidate(Yii::$app->cache, ['Session:'.Yii::$app->session->id]);
113
        $model = new RegistrationForm();
114
        if ($model->load(Yii::$app->request->post())) {
115
            $user = $model->signup();
116
            if ($user !== null) {
117
                if (Yii::$app->getUser()->login($user)) {
0 ignored issues
show
Bug introduced by
The method getUser does only exist in yii\web\Application, but not in yii\console\Application.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
118
                    return $this->goHome();
119
                }
120
            } else {
0 ignored issues
show
Unused Code introduced by
This else statement is empty and can be removed.

This check looks for the else branches of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These else branches can be removed.

if (rand(1, 6) > 3) {
print "Check failed";
} else {
    //print "Check succeeded";
}

could be turned into

if (rand(1, 6) > 3) {
    print "Check failed";
}

This is much more concise to read.

Loading history...
121
                // there were errors
122
            }
123
        }
124
        return $this->render('signup', [
125
            'model' => $model,
126
        ]);
127
    }
128
129
    /**
130
     * Action for retrieving needed information from user that wasn't got from social network
131
     * @return string|Response
132
     */
133
    public function actionCompleteRegistration()
134
    {
135
        /** @var \app\modules\user\models\User $model */
136
        $model = Yii::$app->user->identity;
137
        if (intval($model->username_is_temporary) === 1) {
0 ignored issues
show
Bug introduced by
The property username_is_temporary does not seem to exist. Did you mean username?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
138
            // reset username
139
            $model->username = '';
140
        }
141
        $model->setScenario('completeRegistration');
142
        $model->load(Yii::$app->request->post());
143
        if (Yii::$app->request->isPost && $model->validate()) {
144
            $model->username_is_temporary = 0;
0 ignored issues
show
Bug introduced by
The property username_is_temporary does not seem to exist. Did you mean username?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
145
            $model->save();
146
            $auth_action = new AuthAction('post-registration', $this);
147
            return $auth_action->redirect('/');
148
        } else {
149
            $this->layout = $this->module->postRegistrationLayout;
0 ignored issues
show
Bug introduced by
The property postRegistrationLayout does not seem to exist. Did you mean layout?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
150
            return $this->render('post-registration', [
151
                'model' => $model,
152
            ]);
153
        }
154
    }
155
156
    /**
157
     * Success callback for social networks authentication
158
     * @param $client
159
     * @throws ErrorException
160
     * @throws \yii\base\ExitException
161
     */
162
    public function successCallback($client)
163
    {
164
        $model = AuthClientHelper::findUserByService($client);
165
        if (is_object($model) === false) {
166
            // user not found, retrieve additional data
167
            $client = AuthClientHelper::retrieveAdditionalData($client);
168
            $attributes = AuthClientHelper::mapUserAttributesWithService($client);
169
            // check if it is anonymous user
170
            if (Yii::$app->user->isGuest === true) {
171
                $model = new User(['scenario' => 'registerService']);
172
                $security = Yii::$app->security;
173
                $model->setAttributes($attributes['user']);
174
                $model->status = User::STATUS_ACTIVE;
175
                if (empty($model->username) === true) {
176
                    // if we doesn't have username - generate unique random temporary username
177
                    // it will be needed for saving purposes
178
                    $model->username = $security->generateRandomString(18);
179
                    $model->username_is_temporary = 1;
0 ignored issues
show
Bug introduced by
The property username_is_temporary does not seem to exist. Did you mean username?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
180
                }
181
                $model->setPassword($security->generateRandomString(16));
182
                $model->generateAuthKey();
183
                if ($model->save() === false) {
184
                    if (isset($model->errors['username'])) {
185
                        // regenerate username
186
                        $model->username = $security->generateRandomString(18);
187
                        $model->username_is_temporary = 1;
0 ignored issues
show
Bug introduced by
The property username_is_temporary does not seem to exist. Did you mean username?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
188
                        $model->save();
189
                    }
190
                    if (isset($model->errors['email'])) {
191
                        // empty email
192
                        $model->email = null;
193
                        $model->save();
194
                    }
195
                    if (count($model->errors) > 0) {
196
                        throw new ErrorException(Yii::t('app', "Temporary error signing up user"));
197
                    }
198
                }
199
            } else {
200
                // non anonymous - link to existing account
201
                /** @var \app\modules\user\models\User $model */
202
                $model = Yii::$app->user->identity;
203
            }
204
            $service = new UserService();
205
            $service->service_type = $client->className();
206
            $service->service_id = '' . $attributes['service']['service_id'];
207
            $service->user_id = $model->id;
208
            if ($service->save() === false) {
209
                throw new ErrorException(Yii::t('app', "Temporary error saving social service"));
210
            }
211
        } elseif (Yii::$app->user->isGuest === false) {
212
            // service exists and user logged in
213
            // check if this service is binded to current user
214
            if ($model->id != Yii::$app->user->id) {
215
                throw new ErrorException(Yii::t('app', "This service is already binded to another user"));
216
            } else {
217
                $attributes = AuthClientHelper::mapUserAttributesWithService($client);
218
                if (isset($attributes['service']['service_id'])) {
219
                    UserService::deleteAll(
220
                        [
221
                            'user_id' => $model->id,
222
                            'service_type' => $client->className(),
223
                            'service_id' => '' . $attributes['service']['service_id'],
224
                        ]
225
                    );
226
                }
227
            }
228
        }
229
        TagDependency::invalidate(Yii::$app->cache, ['Session:'.Yii::$app->session->id]);
230
        Yii::$app->user->login($model, 86400);
231
        if ($model->username_is_temporary == 1 || empty($model->email)) {
0 ignored issues
show
Bug introduced by
The property username_is_temporary does not seem to exist. Did you mean username?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
232
            // show post-registration form
233
            $this->layout = $this->module->postRegistrationLayout;
0 ignored issues
show
Bug introduced by
The property postRegistrationLayout does not seem to exist. Did you mean layout?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
234
            $model->setScenario('completeRegistration');
235
            echo $this->render('post-registration', [
236
                'model' => $model,
237
            ]);
238
            Yii::$app->end();
239
            return;
240
        }
241
    }
242
243
    /**
244
     * Action for requesting password rest
245
     * @return string|Response
246
     */
247
    public function actionRequestPasswordReset()
248
    {
249
        $model = new PasswordResetRequestForm();
250
        if ($model->load(Yii::$app->request->post()) && $model->validate()) {
251
            if ($model->sendEmail()) {
252
                Yii::$app->getSession()->setFlash(
0 ignored issues
show
Bug introduced by
The method getSession does only exist in yii\web\Application, but not in yii\console\Application.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
253
                    'success',
254
                    Yii::t('app', 'Check your email for further instructions.')
255
                );
256
                return $this->goHome();
257
            } else {
258
                Yii::$app->getSession()->setFlash(
259
                    'error',
260
                    Yii::t('app', 'Sorry, we are unable to reset password for email provided.')
261
                );
262
            }
263
        }
264
265
        return $this->render('requestPasswordResetToken', [
266
            'model' => $model,
267
        ]);
268
    }
269
270
    /**
271
     * Action for reset password - user follows here by link from email message.
272
     * @param $token
273
     * @return string|Response
274
     * @throws BadRequestHttpException
275
     */
276
    public function actionResetPassword($token)
277
    {
278
        try {
279
            $model = new ResetPasswordForm($token);
280
        } catch (InvalidParamException $e) {
281
            throw new BadRequestHttpException($e->getMessage());
282
        }
283
284
        if ($model->load(Yii::$app->request->post()) && $model->validate() && $model->resetPassword()) {
285
            Yii::$app->getSession()->setFlash(
0 ignored issues
show
Bug introduced by
The method getSession does only exist in yii\web\Application, but not in yii\console\Application.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
286
                'success',
287
                Yii::t('app', 'New password was saved.')
288
            );
289
290
            return $this->goHome();
291
        }
292
293
        return $this->render('resetPassword', [
294
            'model' => $model,
295
        ]);
296
    }
297
298
    /**
299
     * Action for changing profile fields
300
     * @return string
301
     */
302
    public function actionProfile()
303
    {
304
        /** @var \app\modules\user\models\User|app\properties\HasProperties $model */
305
        $model = User::findIdentity(Yii::$app->user->id);
306
        $model->scenario = 'updateProfile';
307
        $model->getPropertyGroups(false, false, true);
0 ignored issues
show
Documentation Bug introduced by
The method getPropertyGroups does not exist on object<app\modules\user\models\User>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
308
        $model->abstractModel->setAttributesValues(Yii::$app->request->post());
309
        if ($model->load(Yii::$app->request->post()) && $model->validate() && $model->abstractModel->validate()) {
310
            if ($model->save()) {
311
                $model->saveProperties(Yii::$app->request->post());
0 ignored issues
show
Documentation Bug introduced by
The method saveProperties does not exist on object<app\modules\user\models\User>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
312
                Yii::$app->session->setFlash('success', Yii::t('app', 'Your profile has been updated'));
313
                $this->refresh();
314
            } else {
315
                Yii::$app->session->setFlash('error', Yii::t('app', 'Internal error'));
316
            }
317
        }
318
319
320
        return $this->render(
321
            'profile',
322
            [
323
                'model' => $model,
324
                'services' => ArrayHelper::map($model->services, 'id', 'service_type'),
325
            ]
326
        );
327
    }
328
329
    /**
330
     * Action for handling password changing
331
     * @return string
0 ignored issues
show
Documentation introduced by
Should the return type not be Response|string?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
332
     * @throws NotFoundHttpException
333
     */
334
    public function actionChangePassword()
335
    {
336
        /** @var app\modules\user\models\User|\yii\web\IdentityInterface $model */
337
        $model = User::findIdentity(Yii::$app->user->id);
338
        if (is_null($model)) {
339
            throw new NotFoundHttpException;
340
        }
341
        $model->scenario = 'changePassword';
342
        if (Yii::$app->request->isPost) {
343
            $model->load(Yii::$app->request->post());
344
            $formIsValid = $model->validate();
0 ignored issues
show
Bug introduced by
The method validate() does not exist on yii\web\IdentityInterface. Did you maybe mean validateAuthKey()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
345
            $passwordIsValid = $model->validatePassword($model->password);
346
            if (!$passwordIsValid) {
347
                $model->addError('password', Yii::t('app', 'Wrong password'));
348
            }
349
            if ($formIsValid && $passwordIsValid) {
350
                $model->setPassword($model->newPassword);
351
                if ($model->save(true, ['password_hash'])) {
352
                    Yii::$app->session->setFlash('success', Yii::t('app', 'Password has been changed'));
353
                    return $this->refresh();
354
                } else {
355
                    Yii::$app->session->setFlash('error', Yii::t('app', 'Internal error'));
356
                }
357
            }
358
        }
359
        return $this->render('change-password', ['model' => $model]);
360
    }
361
}
362