Completed
Push — master ( 5ee4c9...308b6a )
by Antonio
05:05
created

SecurityController::actionLogin()   C

Complexity

Conditions 9
Paths 8

Size

Total Lines 47
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 22.1482

Importance

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