LoginAccountsController::actionIndex()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 5
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * @link      https://dukt.net/social/
4
 * @copyright Copyright (c) Dukt
5
 * @license   https://github.com/dukt/social/blob/v2/LICENSE.md
6
 */
7
8
namespace dukt\social\controllers;
9
10
use Craft;
11
use dukt\social\errors\LoginException;
12
use dukt\social\errors\RegistrationException;
13
use dukt\social\events\LoginAccountEvent;
14
use dukt\social\events\OauthTokenEvent;
15
use dukt\social\helpers\SocialHelper;
16
use dukt\social\Plugin;
17
use dukt\social\web\assets\social\SocialAsset;
18
use GuzzleHttp\Exception\BadResponseException;
19
use yii\web\HttpException;
20
use craft\elements\User;
21
use dukt\social\models\Token;
22
use dukt\social\elements\LoginAccount;
23
use yii\web\Response;
24
25
/**
26
 * The LoginAccountsController class is a controller that handles various login account related tasks.
27
 *
28
 * Note that all actions in the controller, except [[actionLogin]], [[actionCallback]], require an authenticated Craft session via [[allowAnonymous]].
29
 *
30
 * @author  Dukt <[email protected]>
31
 * @since   1.0
32
 */
33
class LoginAccountsController extends BaseController
34
{
35
    // Constants
36
    // =========================================================================
37
    /**
38
     * @event LoginAccountEvent The event that is triggered before registering a user.
39
     * @var string
40
     */
41
    public const EVENT_BEFORE_REGISTER = 'beforeRegister';
42
43
    /**
44
     * @event LoginAccountEvent The event that is triggered after registering a user.
45
     * @var string
46
     */
47
    public const EVENT_AFTER_REGISTER = 'afterRegister';
48
49
    /**
50
     * @event LoginAccountEvent The event that is triggered after the OAuth callback.
51
     * @var string
52
     */
53
    public const EVENT_AFTER_OAUTH_CALLBACK = 'afterOauthCallback';
54
55
    // Properties
56
    // =========================================================================
57
58
    /**
59
     * @inheritdoc
60
     */
61
    protected $allowAnonymous = ['login', 'callback'];
62
63
    /**
64
     * URL to redirect to after login.
65
     *
66
     * @var string
67
     */
68
    private $redirectUrl;
69
70
    /**
71
     * URL where the login was initiated from.
72
     *
73
     * @var string
74
     */
75
    private $originUrl;
76
77
    // Public Methods
78
    // =========================================================================
79
80
    /**
81
     * Login Accounts Index.
82
     *
83
     * @return Response
84
     * @throws \yii\base\InvalidConfigException
85
     */
86
    public function actionIndex(): Response
87
    {
88
        Craft::$app->getView()->registerAssetBundle(SocialAsset::class);
89
90
        return $this->renderTemplate('social/loginaccounts/_index');
91
    }
92
93
    /**
94
     * Edit login accounts.
95
     *
96
     * @param $userId
97
     *
98
     * @return Response
99
     * @throws HttpException
100
     * @throws \yii\base\InvalidConfigException
101
     */
102
    public function actionEdit($userId): Response
103
    {
104
        $user = Craft::$app->users->getUserById($userId);
0 ignored issues
show
Bug introduced by
The method getUserById() does not exist on null. ( Ignorable by Annotation )

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

104
        /** @scrutinizer ignore-call */ 
105
        $user = Craft::$app->users->getUserById($userId);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
105
106
        if (!$user) {
107
            throw new HttpException(404);
108
        }
109
110
        $loginAccounts = Plugin::getInstance()->getLoginAccounts()->getLoginAccountsByUserId($user->id);
111
112
        Craft::$app->getView()->registerAssetBundle(SocialAsset::class);
113
114
        return $this->renderTemplate('social/loginaccounts/_edit', [
115
            'userId' => $userId,
116
            'user' => $user,
117
            'loginAccounts' => $loginAccounts
118
        ]);
119
    }
120
121
    /**
122
     * Delete login account.
123
     *
124
     * @return Response
125
     * @throws \Throwable
126
     * @throws \yii\base\InvalidConfigException
127
     * @throws \yii\web\BadRequestHttpException
128
     */
129
    public function actionDeleteLoginAccount(): Response
130
    {
131
        $this->requirePostRequest();
132
        $this->requireAcceptsJson();
133
        $this->requireAdmin();
134
135
        $loginAccountId = Craft::$app->getRequest()->getRequiredBodyParam('id');
136
137
        Plugin::getInstance()->getLoginAccounts()->deleteLoginAccountById($loginAccountId);
138
139
        return $this->asJson(['success' => true]);
140
    }
141
142
    /**
143
     * Login.
144
     *
145
     * @return Response
146
     * @throws \GuzzleHttp\Exception\GuzzleException
147
     * @throws \Throwable
148
     */
149
    public function actionLogin(): Response
150
    {
151
        $isCpRequest = Craft::$app->getRequest()->getIsCpRequest();
152
153
        Craft::$app->getSession()->set('social.isCpRequest', $isCpRequest);
154
155
        $this->originUrl = Craft::$app->getRequest()->referrer;
156
        Craft::$app->getSession()->set('social.originUrl', $this->originUrl);
157
158
        $this->redirectUrl = Craft::$app->getRequest()->getParam('redirect');
159
        Craft::$app->getSession()->set('social.redirectUrl', $this->redirectUrl);
160
161
162
        // Connect
163
164
        $providerHandle = (string)Craft::$app->getRequest()->getParam('provider');
165
        $plugin = Craft::$app->getPlugins()->getPlugin('social');
166
        $pluginSettings = $plugin->getSettings();
167
168
        try {
169
            if (!$pluginSettings['enableSocialLogin']) {
170
                throw new LoginException('Social login is disabled');
171
            }
172
173
            $loginProvider = Plugin::getInstance()->getLoginProviders()->getLoginProvider($providerHandle);
174
175
            if (!$loginProvider instanceof \dukt\social\base\LoginProviderInterface) {
176
                throw new LoginException('Login provider is not configured');
177
            }
178
179
180
            // Redirect to login provider’s authorization page
181
182
            Craft::$app->getSession()->set('social.loginProvider', $providerHandle);
183
184
            return $loginProvider->oauthConnect();
185
        } catch (\Exception $exception) {
186
            $errorMsg = $exception->getMessage();
187
            Craft::error('Couldn’t login. ' . $exception->getTraceAsString(), __METHOD__);
188
            $this->setError($errorMsg);
189
190
            return $this->redirect($this->originUrl);
191
        }
192
    }
193
194
    /**
195
     * @return Response
196
     * @throws \GuzzleHttp\Exception\GuzzleException
197
     * @throws \Throwable
198
     * @throws \craft\errors\MissingComponentException
199
     * @throws \yii\base\InvalidConfigException
200
     */
201
    public function actionCallback(): Response
202
    {
203
        $this->originUrl = Craft::$app->getSession()->get('social.originUrl');
204
        $this->redirectUrl = Craft::$app->getSession()->get('social.redirectUrl');
205
206
        if (!$this->redirectUrl) {
207
            $this->redirectUrl = $this->originUrl;
208
        }
209
210
        $providerHandle = (string)Craft::$app->getSession()->get('social.loginProvider');
211
        $loginProvider = Plugin::getInstance()->getLoginProviders()->getLoginProvider($providerHandle);
212
213
        try {
214
            $callbackResponse = $loginProvider->oauthCallback();
215
216
            if (!$callbackResponse['success']) {
217
                // Unable to log the user in, throw an exception
218
                throw new LoginException($callbackResponse['errorMsg']);
219
            }
220
221
            $token = new Token();
222
            $token->providerHandle = $providerHandle;
223
            $token->token = $callbackResponse['token'];
224
225
            // Fire a 'afterOauthCallback' event
226
            if ($this->hasEventHandlers(self::EVENT_AFTER_OAUTH_CALLBACK)) {
227
                $this->trigger(self::EVENT_AFTER_OAUTH_CALLBACK, new OauthTokenEvent([
228
                    'token' => $token,
229
                ]));
230
            }
231
232
            return $this->connectUser($token);
233
        } catch (BadResponseException $badResponseException) {
234
            $response = $badResponseException->getResponse();
235
            $body = $response->getBody();
236
            $json = json_decode($body, true);
237
238
            $errorMsg = $json ? $json['error']['message'] : 'Couldn’t login.';
239
240
            Craft::error('Couldn’t login. ' . $badResponseException->getTraceAsString(), __METHOD__);
241
            $this->setError($errorMsg);
242
243
            return $this->redirect($this->originUrl);
244
        } catch (\Exception $exception) {
245
            $errorMsg = $exception->getMessage();
246
            Craft::error('Couldn’t login. ' . $exception->getTraceAsString(), __METHOD__);
247
            $this->setError($errorMsg);
248
249
            return $this->redirect($this->originUrl);
250
        }
251
    }
252
253
    /**
254
     * Connect a login account (link).
255
     *
256
     * @return Response
257
     * @throws \GuzzleHttp\Exception\GuzzleException
258
     * @throws \Throwable
259
     */
260
    public function actionConnectLoginAccount(): Response
261
    {
262
        return $this->actionLogin();
263
    }
264
265
    /**
266
     * Disconnect a login account (unlink).
267
     *
268
     * @return Response
269
     * @throws \Throwable
270
     * @throws \yii\base\InvalidConfigException
271
     */
272
    public function actionDisconnectLoginAccount(): Response
273
    {
274
        $handle = Craft::$app->getRequest()->getParam('provider');
275
276
        // delete social user
277
        Plugin::getInstance()->getLoginAccounts()->deleteLoginAccountByProvider($handle);
278
279
        if (Craft::$app->getRequest()->getAcceptsJson()) {
280
            return $this->asJson([
281
                'success' => true
282
            ]);
283
        }
284
285
        $this->setNotice(Craft::t('social', 'Login account disconnected.'));
286
287
        // redirect
288
        $redirect = Craft::$app->getRequest()->referrer;
289
290
        return $this->redirect($redirect);
291
    }
292
293
    // Private Methods
294
    // =========================================================================
295
296
    /**
297
     * Connect (register, login, link) a user from token.
298
     *
299
     * @param Token $token
300
     *
301
     * @return null|\yii\web\Response
302
     * @throws \GuzzleHttp\Exception\GuzzleException
303
     * @throws \Throwable
304
     * @throws \craft\errors\ElementNotFoundException
305
     * @throws \craft\errors\ImageException
306
     * @throws \craft\errors\VolumeException
307
     * @throws \yii\base\Exception
308
     * @throws \yii\base\InvalidConfigException
309
     */
310
    private function connectUser(Token $token)
311
    {
312
        $craftUser = Craft::$app->getUser()->getIdentity();
313
314
        if ($craftUser) {
0 ignored issues
show
introduced by
$craftUser is of type yii\web\IdentityInterface, thus it always evaluated to true.
Loading history...
315
            // if the user is already linked to an account, stop there and redirect back to origin URL
316
317
            // otherwise continue to link the account
318
            return $this->linkAccountFromToken($token, $craftUser);
319
        }
320
321
        return $this->registerOrLoginFromToken($token);
322
    }
323
324
    /**
325
     * Link account from token.
326
     *
327
     * @param Token $token
328
     * @param       $craftUser
329
     *
330
     * @return Response
331
     * @throws \Throwable
332
     * @throws \craft\errors\ElementNotFoundException
333
     * @throws \yii\base\Exception
334
     * @throws \yii\base\InvalidConfigException
335
     */
336
    private function linkAccountFromToken(Token $token, $craftUser): Response
337
    {
338
        $socialLoginProvider = Plugin::getInstance()->getLoginProviders()->getLoginProvider($token->providerHandle);
0 ignored issues
show
Bug introduced by
It seems like $token->providerHandle can also be of type null; however, parameter $handle of dukt\social\services\Log...ers::getLoginProvider() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

338
        $socialLoginProvider = Plugin::getInstance()->getLoginProviders()->getLoginProvider(/** @scrutinizer ignore-type */ $token->providerHandle);
Loading history...
339
        $profile = $socialLoginProvider->getProfile($token);
0 ignored issues
show
Bug introduced by
The method getProfile() does not exist on dukt\social\base\LoginProviderInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to dukt\social\base\LoginProviderInterface. ( Ignorable by Annotation )

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

339
        /** @scrutinizer ignore-call */ 
340
        $profile = $socialLoginProvider->getProfile($token);
Loading history...
340
        $userFieldMapping = $socialLoginProvider->getUserFieldMapping();
0 ignored issues
show
Bug introduced by
The method getUserFieldMapping() does not exist on dukt\social\base\LoginProviderInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to dukt\social\base\LoginProviderInterface. ( Ignorable by Annotation )

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

340
        /** @scrutinizer ignore-call */ 
341
        $userFieldMapping = $socialLoginProvider->getUserFieldMapping();
Loading history...
341
        $socialUid = Craft::$app->getView()->renderString($userFieldMapping['id'], ['profile' => $profile]);
342
        $account = Plugin::getInstance()->getLoginAccounts()->getLoginAccountByUid($socialLoginProvider->getHandle(), $socialUid);
0 ignored issues
show
Bug introduced by
The method getHandle() does not exist on dukt\social\base\LoginProviderInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to dukt\social\base\LoginProviderInterface. ( Ignorable by Annotation )

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

342
        $account = Plugin::getInstance()->getLoginAccounts()->getLoginAccountByUid($socialLoginProvider->/** @scrutinizer ignore-call */ getHandle(), $socialUid);
Loading history...
343
344
345
        // Existing login account
346
347
        if ($account !== null) {
348
            if ($craftUser->id == $account->userId) {
349
                Craft::$app->elements->saveElement($account);
0 ignored issues
show
Bug introduced by
The method saveElement() does not exist on null. ( Ignorable by Annotation )

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

349
                Craft::$app->elements->/** @scrutinizer ignore-call */ 
350
                                       saveElement($account);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
350
351
                $this->setNotice(Craft::t('social', 'Logged in.'));
352
353
                return $this->redirect($this->redirectUrl);
354
            }
355
356
            throw new LoginException('This UID is already associated with another user. Disconnect from your current session and retry.');
357
        }
358
359
360
        // New login account
361
362
        $account = new LoginAccount;
363
        $account->userId = $craftUser->id;
364
        $account->providerHandle = $socialLoginProvider->getHandle();
365
        $account->socialUid = $socialUid;
366
367
        Craft::$app->getElements()->saveElement($account);
368
369
        $this->setNotice(Craft::t('social', 'Login account added.'));
370
371
        return $this->redirect($this->redirectUrl);
372
    }
373
374
    /**
375
     * Register or login user from an OAuth token.
376
     *
377
     * @param Token $token
378
     *
379
     * @return null
380
     * @throws \GuzzleHttp\Exception\GuzzleException
381
     * @throws \Throwable
382
     * @throws \craft\errors\ElementNotFoundException
383
     * @throws \craft\errors\ImageException
384
     * @throws \craft\errors\VolumeException
385
     * @throws \yii\base\Exception
386
     * @throws \yii\base\InvalidConfigException
387
     */
388
    private function registerOrLoginFromToken(Token $token)
389
    {
390
        $socialLoginProvider = Plugin::getInstance()->getLoginProviders()->getLoginProvider($token->providerHandle);
0 ignored issues
show
Bug introduced by
It seems like $token->providerHandle can also be of type null; however, parameter $handle of dukt\social\services\Log...ers::getLoginProvider() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

390
        $socialLoginProvider = Plugin::getInstance()->getLoginProviders()->getLoginProvider(/** @scrutinizer ignore-type */ $token->providerHandle);
Loading history...
391
        $profile = $socialLoginProvider->getProfile($token);
392
        $userFieldMapping = $socialLoginProvider->getUserFieldMapping();
393
        $socialUid = Craft::$app->getView()->renderString($userFieldMapping['id'], ['profile' => $profile]);
394
        $account = Plugin::getInstance()->getLoginAccounts()->getLoginAccountByUid($socialLoginProvider->getHandle(), $socialUid);
395
396
        // Existing user
397
        if ($account !== null) {
398
            $craftUser = Craft::$app->users->getUserById($account->userId);
399
400
            if (!$craftUser) {
401
                throw new LoginException('Social account exists but Craft user doesn’t.');
402
            }
403
404
            // Save existing login account
405
            Craft::$app->elements->saveElement($account);
406
407
            // Login
408
            return $this->login($craftUser, $account, $token);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->login($craftUser, $account, $token) returns the type craft\web\Response which is incompatible with the documented return type null.
Loading history...
409
        }
410
411
        // Register new user
412
        $craftUser = $this->registerUser($socialLoginProvider->getHandle(), $profile);
413
414
        if (!$craftUser) {
0 ignored issues
show
introduced by
$craftUser is of type craft\elements\User, thus it always evaluated to true.
Loading history...
415
            throw new RegistrationException('Craft user couldn’t be created.');
416
        }
417
418
        // Save new login account
419
        $account = new LoginAccount;
420
        $account->userId = $craftUser->getId();
421
        $account->providerHandle = $socialLoginProvider->getHandle();
422
        $account->socialUid = $socialUid;
423
424
        Craft::$app->elements->saveElement($account);
425
426
        // Login
427
        return $this->login($craftUser, $account, $token, true);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->login($cra...$account, $token, true) returns the type craft\web\Response which is incompatible with the documented return type null.
Loading history...
428
    }
429
430
    /**
431
     * Register a user.
432
     *
433
     * @param string $providerHandle
434
     * @param        $profile
435
     *
436
     * @return User
437
     * @throws RegistrationException
438
     * @throws \GuzzleHttp\Exception\GuzzleException
439
     * @throws \Throwable
440
     * @throws \craft\errors\ElementNotFoundException
441
     * @throws \craft\errors\ImageException
442
     * @throws \craft\errors\VolumeException
443
     * @throws \craft\errors\WrongEditionException
444
     * @throws \yii\base\Exception
445
     * @throws \yii\base\InvalidConfigException
446
     */
447
    private function registerUser(string $providerHandle, $profile): User
448
    {
449
        $loginProvider = Plugin::getInstance()->getLoginProviders()->getLoginProvider($providerHandle);
450
        $userFieldMapping = $loginProvider->getUserFieldMapping();
451
        $email = Craft::$app->getView()->renderString($userFieldMapping['email'], ['profile' => $profile]);
452
453
        if (empty($email)) {
454
            throw new RegistrationException('Email address not provided.');
455
        }
456
457
458
        // Registration of an existing user with a matching email
459
460
        $user = Craft::$app->users->getUserByUsernameOrEmail($email);
461
462
        if ($user) {
463
            if (Plugin::getInstance()->getSettings()->allowEmailMatch !== true) {
464
                throw new RegistrationException('An account already exists with this email: ' . $email);
465
            }
466
467
            return $user;
468
        }
469
470
471
        // Register a new user
472
473
        Craft::$app->requireEdition(Craft::Pro);
474
475
        $socialPlugin = Craft::$app->getPlugins()->getPlugin('social');
476
        $settings = $socialPlugin->getSettings();
477
478
        $this->checkRegistrationEnabled($settings);
479
        $this->checkLockedDomains($email);
480
481
        // Fire a 'beforeRegister' event
482
        if ($this->hasEventHandlers(self::EVENT_BEFORE_REGISTER)) {
483
            $this->trigger(self::EVENT_BEFORE_REGISTER, new LoginAccountEvent([
484
                'profile' => &$profile,
485
                'loginProvider' => $loginProvider,
486
            ]));
487
        }
488
489
        $newUser = new User();
490
491
        // Fill user
492
        $this->fillUser($providerHandle, $newUser, $profile);
493
494
        // Save user
495
        if (!Craft::$app->elements->saveElement($newUser)) {
496
            Craft::error('There was a problem creating the user:' . print_r($newUser->getErrors(), true), __METHOD__);
0 ignored issues
show
Bug introduced by
Are you sure print_r($newUser->getErrors(), true) of type string|true can be used in concatenation? ( Ignorable by Annotation )

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

496
            Craft::error('There was a problem creating the user:' . /** @scrutinizer ignore-type */ print_r($newUser->getErrors(), true), __METHOD__);
Loading history...
497
            throw new RegistrationException('Craft user couldn’t be created.');
498
        }
499
500
        // Save remote photo
501
        if ($settings['autoFillProfile']) {
502
            Plugin::getInstance()->getLoginAccounts()->saveRemotePhoto($providerHandle, $newUser, $profile);
503
        }
504
505
        // Assign user to default group
506
        if ($newUser->getId() !== null && !empty($settings['defaultGroup'])) {
507
            Craft::$app->users->assignUserToGroups($newUser->getId(), [$settings['defaultGroup']]);
508
        }
509
510
        Craft::$app->elements->saveElement($newUser);
511
512
        // Fire a 'afterRegister' event
513
        if ($this->hasEventHandlers(self::EVENT_AFTER_REGISTER)) {
514
            $this->trigger(self::EVENT_AFTER_REGISTER, new LoginAccountEvent([
515
                'profile' => &$profile,
516
                'loginProvider' => $loginProvider,
517
                'user' => $newUser
518
            ]));
519
        }
520
521
        return $newUser;
522
    }
523
524
    /**
525
     * @param string $providerHandle
526
     * @param User $newUser
527
     * @param        $profile
528
     *
529
     * @throws \yii\base\InvalidConfigException
530
     */
531
    private function fillUser(string $providerHandle, User $newUser, $profile)
532
    {
533
        $socialPlugin = Craft::$app->getPlugins()->getPlugin('social');
534
        $settings = $socialPlugin->getSettings();
535
        $loginProvider = Plugin::getInstance()->getLoginProviders()->getLoginProvider($providerHandle);
536
        $userFieldMapping = $loginProvider->getUserFieldMapping();
537
538
        $userModelAttributes = ['email', 'username', 'firstName', 'lastName', 'preferredLocale', 'weekStartDay'];
539
540
        foreach ($userFieldMapping as $attribute => $template) {
541
            // Only fill other fields than `email` and `username` when `autoFillProfile` is true
542
            if (!$settings['autoFillProfile'] && $attribute !== 'email' && $attribute !== 'username') {
543
                continue;
544
            }
545
546
            // Check whether they try to set an attribute or a custom field
547
            if (\in_array($attribute, $userModelAttributes, true)) {
548
                SocialHelper::fillUserAttribute($newUser, $attribute, $template, $profile);
549
            } else {
550
                SocialHelper::fillUserCustomFieldValue($newUser, $attribute, $template, $profile);
551
            }
552
        }
553
    }
554
555
    /**
556
     * Login user from login account.
557
     *
558
     *
559
     * @return Response
560
     * @throws \craft\errors\MissingComponentException
561
     * @throws \yii\base\InvalidConfigException
562
     */
563
    private function login(User $craftUser, LoginAccount $account, Token $token, bool $registrationMode = false): Response
564
    {
565
        if (!$account->authenticate($token)) {
566
            return $this->_handleLoginFailure();
567
        }
568
569
        if (!Craft::$app->getUser()->login($craftUser)) {
570
            return $this->_handleLoginFailure();
571
        }
572
573
        return $this->_handleSuccessfulLogin($registrationMode);
574
    }
575
576
    /**
577
     * Handles a failed login attempt.
578
     *
579
     * @return Response
580
     * @throws \craft\errors\MissingComponentException
581
     */
582
    private function _handleLoginFailure(): Response
583
    {
584
        $this->setError(Craft::t('social', 'Couldn’t authenticate.'));
585
586
        return $this->redirect($this->originUrl);
587
    }
588
589
    /**
590
     * Redirects the user after a successful login attempt.
591
     *
592
     * @param bool $registrationMode
593
     *
594
     * @return Response
595
     * @throws \craft\errors\MissingComponentException
596
     */
597
    private function _handleSuccessfulLogin(bool $registrationMode): Response
598
    {
599
        if ($registrationMode) {
600
            $this->setNotice(Craft::t('social', 'Account created.'));
601
        } else {
602
            $this->setNotice(Craft::t('social', 'Logged in.'));
603
        }
604
605
        return $this->redirect($this->redirectUrl);
606
    }
607
608
    /**
609
     * Stores a notice in the user’s flash data.
610
     *
611
     * The message will be stored on the session, and can be retrieved by calling
612
     * [[getFlash()|`getFlash('notice')`]] or [[getAllFlashes()]].
613
     * Only one flash notice can be stored at a time.
614
     *
615
     * @param string $message The message.
616
     */
617
    private function setNotice(string $message)
618
    {
619
        $session = Craft::$app->getSession();
620
        if ($session->get('social.isCpRequest')) {
621
            $session->setFlash('cp-notice', $message);
622
        } else {
623
            $session->setFlash('notice', $message);
624
        }
625
    }
626
627
    /**
628
     * Stores an error message in the user’s flash data.
629
     *
630
     * The message will be stored on the session, and can be retrieved by calling
631
     * [[getFlash()|`getFlash('error')`]] or [[getAllFlashes()]].
632
     * Only one flash error message can be stored at a time.
633
     *
634
     * @param string $message The message.
635
     */
636
    private function setError(string $message)
637
    {
638
        $session = Craft::$app->getSession();
639
640
        if ($session->get('social.isCpRequest')) {
641
            $session->setFlash('cp-error', $message);
642
        } else {
643
            $session->setFlash('error', $message);
644
        }
645
    }
646
}
647