SecurityController::actionLogin()   B
last analyzed

Complexity

Conditions 10
Paths 8

Size

Total Lines 52

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 19
CRAP Score 11.3824

Importance

Changes 0
Metric Value
dl 0
loc 52
ccs 19
cts 25
cp 0.76
rs 7.1806
c 0
b 0
f 0
cc 10
nc 8
nop 0
crap 11.3824

How to fix   Long Method    Complexity   

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
/*
4
 * This file is part of the 2amigos/yii2-usuario project.
5
 *
6
 * (c) 2amigOS! <http://2amigos.us/>
7
 *
8
 * For the full copyright and license information, please view
9
 * the LICENSE file that was distributed with this source code.
10
 */
11
12
namespace Da\User\Controller;
13
14
use Da\User\Contracts\AuthClientInterface;
15
use Da\User\Event\FormEvent;
16
use Da\User\Event\UserEvent;
17
use Da\User\Form\LoginForm;
18
use Da\User\Query\SocialNetworkAccountQuery;
19
use Da\User\Service\SocialNetworkAccountConnectService;
20
use Da\User\Service\SocialNetworkAuthenticateService;
21
use Da\User\Traits\ContainerAwareTrait;
22
use Da\User\Traits\ModuleAwareTrait;
23
use Yii;
24
use yii\authclient\AuthAction;
25
use yii\base\InvalidConfigException;
26
use yii\base\InvalidParamException;
27
use yii\base\Module;
28
use yii\filters\AccessControl;
29
use yii\filters\VerbFilter;
30
use yii\web\Controller;
31
use yii\web\Response;
32
use yii\widgets\ActiveForm;
33
34
class SecurityController extends Controller
35
{
36
    use ContainerAwareTrait;
37
    use ModuleAwareTrait;
38
39
    protected $socialNetworkAccountQuery;
40
41
    /**
42
     * SecurityController constructor.
43
     *
44
     * @param string                    $id
45
     * @param Module                    $module
46
     * @param SocialNetworkAccountQuery $socialNetworkAccountQuery
47
     * @param array                     $config
48
     */
49 4
    public function __construct(
50
        $id,
51
        Module $module,
52
        SocialNetworkAccountQuery $socialNetworkAccountQuery,
53
        array $config = []
54
    ) {
55 4
        $this->socialNetworkAccountQuery = $socialNetworkAccountQuery;
56 4
        parent::__construct($id, $module, $config);
57 4
    }
58
59
    /**
60
     * {@inheritdoc}
61
     */
62 4
    public function behaviors()
63
    {
64
        return [
65 4
            'access' => [
66
                'class' => AccessControl::class,
67
                'rules' => [
68
                    [
69
                        'allow' => true,
70
                        'actions' => ['login', 'confirm', 'auth'],
71
                        'roles' => ['?'],
72
                    ],
73
                    [
74
                        'allow' => true,
75
                        'actions' => ['login', 'auth', 'logout'],
76
                        'roles' => ['@'],
77
                    ],
78
                ],
79
            ],
80
            'verbs' => [
81
                'class' => VerbFilter::class,
82
                'actions' => [
83
                    'logout' => ['post'],
84
                ],
85
            ],
86
        ];
87
    }
88
89
    /**
90
     * {@inheritdoc}
91
     */
92 4
    public function actions()
93
    {
94
        return [
95 4
            'auth' => [
96
                'class' => AuthAction::class,
97
                // if user is not logged in, will try to log him in, otherwise
98
                // will try to connect social account to user.
99 4
                'successCallback' => Yii::$app->user->isGuest
100 4
                    ? [$this, 'authenticate']
101 4
                    : [$this, 'connect'],
102
            ],
103
        ];
104
    }
105
106
    /**
107
     * Controller action responsible for handling login page and actions.
108
     *
109
     * @throws InvalidConfigException
110
     * @throws InvalidParamException
111
     * @return array|string|Response
112
     */
113 4
    public function actionLogin()
114
    {
115 4
        if (!Yii::$app->user->getIsGuest()) {
116
            return $this->goHome();
117
        }
118
119
        /** @var LoginForm $form */
120 4
        $form = $this->make(LoginForm::class);
121
122
        /** @var FormEvent $event */
123 4
        $event = $this->make(FormEvent::class, [$form]);
124
125 4
        if (Yii::$app->request->isAjax && $form->load(Yii::$app->request->post())) {
126
            Yii::$app->response->format = Response::FORMAT_JSON;
127
128
            return ActiveForm::validate($form);
129
        }
130
131 4
        if ($form->load(Yii::$app->request->post())) {
132 4
            if ($this->module->enableTwoFactorAuthentication && $form->validate()) {
133
                if ($form->getUser()->auth_tf_enabled) {
134
                    Yii::$app->session->set('credentials', ['login' => $form->login, 'pwd' => $form->password]);
135
136
                    return $this->redirect(['confirm']);
137
                }
138
            }
139
140 4
            $this->trigger(FormEvent::EVENT_BEFORE_LOGIN, $event);
141 4
            if ($form->login()) {
142 4
                $form->getUser()->updateAttributes([
143 4
                    'last_login_at' => time(),
144 4
                    'last_login_ip' => $this->module->disableIpLogging ? '127.0.0.1' : Yii::$app->request->getUserIP(),
145
                ]);
146
147 4
                $this->trigger(FormEvent::EVENT_AFTER_LOGIN, $event);
148
149 4
                return $this->goBack();
150
            }
151
            else
152
            {
153 3
                $this->trigger(FormEvent::EVENT_FAILED_LOGIN, $event);    
154
            }
155
        }
156
157 4
        return $this->render(
158 4
            'login',
159
            [
160 4
                'model' => $form,
161 4
                'module' => $this->module,
162
            ]
163
        );
164
    }
165
166
    public function actionConfirm()
167
    {
168
        if (!Yii::$app->user->getIsGuest()) {
169
            return $this->goHome();
170
        }
171
172
        if (!Yii::$app->session->has('credentials')) {
173
            return $this->redirect(['login']);
174
        }
175
176
        $credentials = Yii::$app->session->get('credentials');
177
        /** @var LoginForm $form */
178
        $form = $this->make(LoginForm::class);
179
        $form->login = $credentials['login'];
180
        $form->password = $credentials['pwd'];
181
        $form->setScenario('2fa');
182
183
        /** @var FormEvent $event */
184
        $event = $this->make(FormEvent::class, [$form]);
185
186
        if (Yii::$app->request->isAjax && $form->load(Yii::$app->request->post())) {
187
            Yii::$app->response->format = Response::FORMAT_JSON;
188
189
            return ActiveForm::validate($form);
190
        }
191
192
        if ($form->load(Yii::$app->request->post())) {
193
            $this->trigger(FormEvent::EVENT_BEFORE_LOGIN, $event);
194
195
            if ($form->login()) {
196
                Yii::$app->session->set('credentials', null);
197
198
                $form->getUser()->updateAttributes(['last_login_at' => time()]);
199
200
                $this->trigger(FormEvent::EVENT_AFTER_LOGIN, $event);
201
202
                return $this->goBack();
203
            }
204
        }
205
206
        return $this->render(
207
            'confirm',
208
            [
209
                'model' => $form,
210
                'module' => $this->module,
211
            ]
212
        );
213
    }
214
215
    public function actionLogout()
216
    {
217
        $event = $this->make(UserEvent::class, [Yii::$app->getUser()->getIdentity()]);
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...
218
219
        $this->trigger(UserEvent::EVENT_BEFORE_LOGOUT, $event);
220
221
        if (Yii::$app->getUser()->logout()) {
222
            $this->trigger(UserEvent::EVENT_AFTER_LOGOUT, $event);
223
        }
224
225
        return $this->goHome();
226
    }
227
228
    public function authenticate(AuthClientInterface $client)
229
    {
230
        $this->make(SocialNetworkAuthenticateService::class, [$this, $this->action, $client])->run();
231
    }
232
233
    public function connect(AuthClientInterface $client)
234
    {
235
        if (Yii::$app->user->isGuest) {
236
            Yii::$app->session->setFlash('danger', Yii::t('usuario', 'Something went wrong'));
237
238
            return;
239
        }
240
241
        $this->make(SocialNetworkAccountConnectService::class, [$this, $client])->run();
242
    }
243
}
244