/**
* 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);
}