/** * TODO: допилить, разделить * @param \yii\authclient\BaseClient $client * @return bool */ public function successAuthclientCallback($client) { $attributes = $client->getUserAttributes(); //TODO: добавить обновление данных if (!Yii::$app->getUser()->isGuest) { $userAuthClient = \common\models\UserAuthclient::findOne(["user_id" => Yii::$app->user->getId(), "provider" => $client->getId(), "provider_identifier" => $attributes["id"]]); if (!$userAuthClient) { $userAuthClient = new \common\models\UserAuthclient(["user_id" => Yii::$app->user->getId(), "provider" => $client->getId(), "provider_identifier" => $attributes["id"], "provider_data" => serialize($attributes)]); $userAuthClient->save(); } } else { $userAuthClient = \common\models\UserAuthclient::findOne(["provider" => $client->getId(), "provider_identifier" => $attributes["id"]]); if ($userAuthClient) { $user = \common\models\User::findIdentity($userAuthClient->getUserId()); if ($user) { return Yii::$app->user->login($user, 0); } } } }
/** * @param \yii\authclient\BaseClient $client */ function __construct($client) { /** * 初始化模型参数 */ $this->attributes = $client->getUserAttributes(); $this->type = $client->getId(); switch ($this->type) { case 'tencent': $this->openId = $this->attributes['openid']; $this->avatar = $this->attributes['figureurl_2'] . '.png'; $this->username = $this->attributes['nickname']; $this->email = ''; break; case 'weibo': $this->openId = $this->attributes['id']; $this->avatar = strpos($this->attributes['avatar_hd'], '.jpg') ? $this->attributes['avatar_hd'] : $this->attributes['avatar_hd'] . '.jpg'; $this->username = $this->attributes['name']; $this->email = ''; break; case 'github': $this->openId = $this->attributes['id']; $this->avatar = $this->attributes['avatar_url'] . '.jpg'; $this->username = $this->attributes['name']; $this->email = $this->attributes['email']; break; case 'google': $this->openId = $this->attributes['id']; $this->avatar = str_replace("?sz=50", "", str_replace("https://", "http://", $this->attributes['image']['url'])); $this->username = $this->attributes['displayName']; $this->email = $this->attributes['emails'][0]['value']; break; default: $this->openId = ''; $this->avatar = ''; $this->username = ''; $this->email = ''; break; } /** * 检查模型的邮箱和名字是否存在 */ $this->checkEmail(); $this->checkUserName(); }
/** * 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); }