/** * Social client authorization callback * * @param \yii\authclient\BaseClient $client * * @return \yii\web\Response * @throws BadRequestHttpException */ public function onAuthSuccess($client) { /** * @var SocialProfile $socialClass * @var User $userClass * @var SocialProfile $auth * @var User $user * @var AuthEvent $event */ $socialClass = $this->fetchModel(Module::MODEL_SOCIAL_PROFILE); $userClass = $this->fetchModel(Module::MODEL_USER); $attributes = $client->getUserAttributes(); $clientId = $client->getId(); $clientTitle = $client->getTitle(); $sourceId = (string) $attributes['id']; $email = $client->getEmail(); $username = $client->getUsername(); // generate random username if username is empty, less than min length, or random usernames have been enabled $randomUsernameGenerator = $this->getConfig('registrationSettings', 'randomUsernameGenerator', ["delimiter" => "."]); if (empty($username) || $username < $this->getConfig('registrationSettings', 'minUsernameLength', 5) || $this->getConfig('registrationSettings', 'randomUsernames', false)) { $i = 0; do { if (is_callable($randomUsernameGenerator)) { $username = call_user_func($randomUsernameGenerator); } else { $username = Haikunator::haikunate($randomUsernameGenerator); } $i++; } while ($i < 10 && $userClass::find()->where(['username' => $username])->exists()); unset($i); } $event = new AuthEvent(); $event->client = $client; $event->userClass = $userClass; $event->socialClass = $socialClass; $auth = $socialClass::find()->where(['source' => $clientId, 'source_id' => $attributes['id']])->one(); $event->model = $auth; $this->_module->trigger(Module::EVENT_AUTH_BEGIN, $event); $transaction = static::tranInit($event); try { if (Yii::$app->user->isGuest) { if ($auth) { // login $user = $auth->user; Yii::$app->user->login($user); $event->flashType = 'success'; $event->message = Yii::t('user', 'Logged in successfully with your <b>{client}</b> account.', ['client' => $clientTitle]); $event->result = AuthEvent::RESULT_LOGGED_IN; } else { // signup if (!empty($email) && $userClass::find()->where(['email' => $email])->exists()) { $event->flashType = 'error'; $event->message = Yii::t('user', 'User with the same email as in <b>{client}</b> account already exists but is not linked to it. Login using email first to link it.', ['client' => $clientTitle]); $event->result = AuthEvent::RESULT_DUPLICATE_EMAIL; } else { $minPassLen = $this->getConfig('registrationSettings', 'randomPasswordMinLength', 10); $maxPassLen = $this->getConfig('registrationSettings', 'randomPasswordMaxLength', 14); $password = Yii::$app->security->generateRandomString(rand($minPassLen, $maxPassLen)); $user = new $userClass(['username' => $username, 'email' => $email, 'password' => $password]); $user->generateAuthKey(); $success = false; if ($user->save()) { $auth = new $socialClass(['user_id' => $user->id, 'source' => $clientId, 'source_id' => $sourceId]); if ($auth->save()) { $transaction->commit(); $success = true; Yii::$app->user->login($user); } } if (!$success) { $event->result = AuthEvent::RESULT_SIGNUP_ERROR; $event->flashType = 'error'; $event->message = Yii::t('user', 'Error while authenticating <b>{client}</b> account.<pre>{errors}</pre>', ['client' => $clientTitle, 'errors' => print_r($user->getErrors(), true)]); throw new Exception('Error authenticating social client'); } else { $event->result = AuthEvent::RESULT_SIGNUP_SUCCESS; $event->flashType = 'success'; $event->message = Yii::t('user', 'Logged in successfully with your <b>{client}</b> account.', ['client' => $clientTitle]); } } } } else { // user already logged in if (!$auth) { // add auth provider $user = Yii::$app->user; $id = $user->id; $auth = new $socialClass(['user_id' => $id, 'source' => $clientId, 'source_id' => $attributes['id']]); $event->model = $auth; if ($auth->save()) { $transaction->commit(); $event->result = AuthEvent::RESULT_LOGGED_IN; $event->flashType = 'success'; $event->message = Yii::t('user', 'Successfully authenticated <b>{client}</b> account for <b>{user}</b>.', ['client' => $clientTitle, 'user' => $user->username]); } else { $event->result = AuthEvent::RESULT_AUTH_ERROR; $event->flashType = 'error'; $event->message = Yii::t('user', 'Error while authenticating <b>{client}</b> account for <b>{user}</b>.<pre>{errors}</pre>', ['client' => $clientTitle, 'errors' => print_r($auth->getErrors(), true)]); throw new Exception('Error authenticating social client'); } } else { $event->result = AuthEvent::RESULT_LOGGED_IN; $event->flashType = 'success'; $event->message = Yii::t('user', 'You have already connected your <b>{client}</b> account previously. Logged in successfully.', ['client' => $clientTitle]); } } } catch (Exception $e) { static::tranRollback($transaction); $this->raise($e, $event); } $this->_module->trigger(Module::EVENT_AUTH_COMPLETE, $event); static::setFlash($event); if (!isset($event->redirectUrl)) { $event->redirectUrl = $this->fetchUrl('loginSettings', 'loginRedirectUrl'); } return $this->redirect($event->redirectUrl); }