-
Notifications
You must be signed in to change notification settings - Fork 0
/
OauthUserProvider.php
77 lines (65 loc) · 3.39 KB
/
OauthUserProvider.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
<?php
namespace App\Security;
use App\Entity\Eav\Attribute;
use App\Entity\User\User;
use App\Entity\User\UserAttributeValue;
use HWI\Bundle\OAuthBundle\OAuth\Response\UserResponseInterface;
use HWI\Bundle\OAuthBundle\Security\Core\User\OAuthAwareUserProviderInterface;
use MsgPhp\Domain\Factory\EntityAwareFactoryInterface;
use MsgPhp\Domain\Exception\EntityNotFoundException;
use MsgPhp\User\Command\{AddUserAttributeValueCommand, ConfirmUserCommand, CreateUserCommand};
use MsgPhp\User\Infra\Security\SecurityUserProvider;
use MsgPhp\User\Repository\{UserAttributeValueRepositoryInterface, UserRepositoryInterface};
use Symfony\Component\Messenger\MessageBusInterface;
use Symfony\Component\Security\Core\Exception\CustomUserMessageAuthenticationException;
use Symfony\Component\Security\Core\User\UserInterface;
final class OauthUserProvider implements OAuthAwareUserProviderInterface
{
private $userRepository;
private $userAttributeValueRepository;
private $securityUserProvider;
private $factory;
private $bus;
public function __construct(UserRepositoryInterface $userRepository, UserAttributeValueRepositoryInterface $userAttributeValueRepository, SecurityUserProvider $securityUserProvider, EntityAwareFactoryInterface $factory, MessageBusInterface $bus)
{
$this->userRepository = $userRepository;
$this->userAttributeValueRepository = $userAttributeValueRepository;
$this->securityUserProvider = $securityUserProvider;
$this->factory = $factory;
$this->bus = $bus;
}
public function loadUserByOAuthUserResponse(UserResponseInterface $response): UserInterface
{
$owner = $response->getResourceOwner()->getName();
$username = $response->getUsername();
if (!defined($const = Attribute::class.'::'.strtoupper($owner).'_OAUTH_ID')) {
throw new \LogicException(sprintf('Missing constant "%s" for OAuth resoure owner "%s"', $const, $owner));
}
$attributeId = $this->factory->identify(Attribute::class, constant($const));
$userAttributeValue = $this->userAttributeValueRepository->findAllByAttributeIdAndValue($attributeId, $username)->first();
if (!$userAttributeValue) {
if (null === $email = $response->getEmail()) {
throw new CustomUserMessageAuthenticationException(sprintf('Oauth resource owner "%s" requires e-mail availability and appropriate read-privilege.', $owner));
}
try {
$user = $this->userRepository->findByUsername($email);
$userId = $user->getId();
} catch (EntityNotFoundException $e) {
//@todo validate username/email availability
$userId = $this->factory->nextIdentifier(User::class);
$this->bus->handle(new CreateUserCommand([
'id' => $userId,
'email' => $email,
'password' => bin2hex(random_bytes(32)),
]));
$this->bus->dispatch(new ConfirmUserCommand($userId));
$user = $this->userRepository->find($userId);
}
$this->bus->dispatch(new AddUserAttributeValueCommand($userId, $attributeId, $username));
} else {
/** @var UserAttributeValue $userAttributeValue */
$user = $userAttributeValue->getUser();
}
return $this->securityUserProvider->fromUser($user);
}
}