yii2-usuario
yii2-usuario copied to clipboard
Social Network Authenticate Service no longer creates a new user
The fix for #309 removed the feature that creates a New User from Social Network Logon if the user does not already exist.
Following Code was changed
https://github.com/2amigos/yii2-usuario/commit/dd407f50b482b472f290fdff741b85e8b52bacce#diff-527c5ba7064e8097f56bd9de2dac5f59
Social Network login already provides a validated email address and user name, there should be no need to complete the manual registration and verification process.
Fixed this by adding code for event:
Event::on(
SecurityController::class, SocialNetworkAuthEvent::EVENT_BEFORE_AUTHENTICATE, function (SocialNetworkAuthEvent $event) {
$client = $event->getClient();
$account = $event->getAccount();
if ($account->user === null || !$account->user instanceof User) {
/** @var User $user */
$user = $event->sender->make(
User::class,
[],
[
'scenario' => 'connect',
'username' => $account->username,
'email' => $account->email,
]
);
if (!$user->validate(['email'])) {
$user->email = null;
}
if (!$user->validate(['username'])) {
$user->username = null;
}
$mailService = MailFactory::makeWelcomeMailerService($user);
if ($event->sender->make(UserCreateService::class, [$user, $mailService])->run()) {
$account->user_id = $user->id;
$account->save(false);
}
}
});
I confirm. Registration through social networks does not work.
I'm undecided if adding a configuration parameter which will optionally restore the old behaviour or just add @drSun solution to docs. @tonydspaniard what are the motivations of your change?
+1. Need sign-up by social network functionality
I suggest to add parameter at class Module extends BaseModule
something like
public $allowSignUpBySocialNetwork = true;
you can pass it when make the service:
class SocialNetworkAuthenticateService implements ServiceInterface
{
protected $controller;
protected $authAction;
protected $client;
protected $socialNetworkAccountQuery;
protected $userQuery;
protected $allowSignUpBySocialNetwork;
public function __construct(
SecurityController $controller,
AuthAction $authAction,
AuthClientInterface $client,
SocialNetworkAccountQuery $socialNetworkAccountQuery,
UserQuery $userQuery,
$allowSignUpBySocialNetwork = true
) {
$this->controller = $controller;
$this->authAction = $authAction;
$this->client = $client;
$this->socialNetworkAccountQuery = $socialNetworkAccountQuery;
$this->userQuery = $userQuery;
$this->allowSignUpBySocialNetwork = $allowSignUpBySocialNetwork;
}
and at:
protected function createAccount()
{
$data = $this->client->getUserAttributes();
...
if (($user = $this->getUser($account)) instanceof User) {
$account->user_id = $user->id;
$account->save(false);
} elseif ($this->allowSignUpBySocialNetwork) {
$account->save(false);
}
return $account;
}
The previous suggestion will add flexibility if we want or not, to only allowed a user to connect to social network after form registration.
On the other hand, why we don't keep the social network account, even if the user will not connect to it. It can be used for future connection anyway.
So can we save the social account anyhow?
class SocialNetworkAuthenticateService implements ServiceInterface
...
protected function createAccount()
{
$data = $this->client->getUserAttributes();
...
if (($user = $this->getUser($account)) instanceof User) {
$account->user_id = $user->id;
}
$account->save(false);
return $account;
}
Fixed this by adding code for event:
Event::on( SecurityController::class, SocialNetworkAuthEvent::EVENT_BEFORE_AUTHENTICATE, function (SocialNetworkAuthEvent $event) { $client = $event->getClient(); $account = $event->getAccount(); if ($account->user === null || !$account->user instanceof User) { /** @var User $user */ $user = $event->sender->make( User::class, [], [ 'scenario' => 'connect', 'username' => $account->username, 'email' => $account->email, ] ); if (!$user->validate(['email'])) { $user->email = null; } if (!$user->validate(['username'])) { $user->username = null; } $mailService = MailFactory::makeWelcomeMailerService($user); if ($event->sender->make(UserCreateService::class, [$user, $mailService])->run()) { $account->user_id = $user->id; $account->save(false); } } });
@drSun where did u add this?