Completed
Push — master ( fe8029...f95222 )
by Michał
432:28 queued 418:44
created

UserProvider::loadUserByOAuthUserResponse()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 20
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 20
rs 9.2
cc 4
eloc 11
nc 4
nop 1
1
<?php
2
3
/*
4
 * This file is part of the Sylius package.
5
 *
6
 * (c) Paweł Jędrzejewski
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Sylius\Bundle\CoreBundle\OAuth;
13
14
use Doctrine\Common\Persistence\ObjectManager;
15
use HWI\Bundle\OAuthBundle\Connect\AccountConnectorInterface;
16
use HWI\Bundle\OAuthBundle\OAuth\Response\UserResponseInterface;
17
use HWI\Bundle\OAuthBundle\Security\Core\User\OAuthAwareUserProviderInterface;
18
use Sylius\Bundle\UserBundle\Provider\UsernameOrEmailProvider as BaseUserProvider;
19
use Sylius\Component\Resource\Factory\FactoryInterface;
20
use Sylius\Component\Resource\Repository\RepositoryInterface;
21
use Sylius\Component\User\Canonicalizer\CanonicalizerInterface;
22
use Sylius\Component\Core\Model\CustomerInterface;
23
use Sylius\Component\Core\Model\UserInterface as SyliusUserInterface;
24
use Sylius\Component\User\Model\UserOAuthInterface;
25
use Sylius\Component\User\Repository\UserRepositoryInterface;
26
use Symfony\Component\Security\Core\User\UserInterface;
27
28
/**
29
 * Loading and ad-hoc creation of a user by an OAuth sign-in provider account.
30
 *
31
 * @author Fabian Kiss <[email protected]>
32
 * @author Joseph Bielawski <[email protected]>
33
 * @author Łukasz Chruściel <[email protected]>
34
 */
35
class UserProvider extends BaseUserProvider implements AccountConnectorInterface, OAuthAwareUserProviderInterface
36
{
37
    /**
38
     * @var FactoryInterface
39
     */
40
    protected $oauthFactory;
41
42
    /**
43
     * @var RepositoryInterface
44
     */
45
    protected $oauthRepository;
46
47
    /**
48
     * @var FactoryInterface
49
     */
50
    protected $customerFactory;
51
    
52
    /**
53
     * @var FactoryInterface
54
     */
55
    protected $userFactory;
56
57
    /**
58
     * @var ObjectManager
59
     */
60
    protected $userManager;
61
62
    /**
63
     * @param FactoryInterface $customerFactory
64
     * @param FactoryInterface $userFactory
65
     * @param UserRepositoryInterface $userRepository
66
     * @param FactoryInterface $oauthFactory
67
     * @param RepositoryInterface $oauthRepository
68
     * @param ObjectManager $userManager
69
     * @param CanonicalizerInterface $canonicalizer
70
     */
71
    public function __construct(
72
        FactoryInterface $customerFactory,
73
        FactoryInterface $userFactory,
74
        UserRepositoryInterface $userRepository,
75
        FactoryInterface $oauthFactory,
76
        RepositoryInterface $oauthRepository,
77
        ObjectManager $userManager,
78
        CanonicalizerInterface $canonicalizer
79
    ) {
80
        parent::__construct($userRepository, $canonicalizer);
81
82
        $this->customerFactory = $customerFactory;
83
        $this->oauthFactory = $oauthFactory;
84
        $this->oauthRepository = $oauthRepository;
85
        $this->userFactory = $userFactory;
86
        $this->userManager = $userManager;
87
    }
88
89
    /**
90
     * {@inheritdoc}
91
     */
92
    public function loadUserByOAuthUserResponse(UserResponseInterface $response)
93
    {
94
        $oauth = $this->oauthRepository->findOneBy([
95
            'provider' => $response->getResourceOwner()->getName(),
96
            'identifier' => $response->getUsername(),
97
        ]);
98
99
        if ($oauth instanceof UserOAuthInterface) {
100
            return $oauth->getUser();
101
        }
102
103
        if (null !== $response->getEmail()) {
104
            $user = $this->userRepository->findOneByEmail($response->getEmail());
105
            if (null !== $user) {
106
                return $this->updateUserByOAuthUserResponse($user, $response);
107
            }
108
        }
109
110
        return $this->createUserByOAuthUserResponse($response);
111
    }
112
113
    /**
114
     * {@inheritdoc}
115
     */
116
    public function connect(UserInterface $user, UserResponseInterface $response)
117
    {
118
        /* @var $user SyliusUserInterface */
119
        $this->updateUserByOAuthUserResponse($user, $response);
120
    }
121
122
    /**
123
     * Ad-hoc creation of user.
124
     *
125
     * @param UserResponseInterface $response
126
     *
127
     * @return SyliusUserInterface
128
     */
129
    protected function createUserByOAuthUserResponse(UserResponseInterface $response)
130
    {
131
        /** @var \Sylius\Component\User\Model\UserInterface $user */
132
        $user = $this->userFactory->createNew();
133
        /** @var CustomerInterface $customer */
134
        $customer = $this->customerFactory->createNew();
135
        $user->setCustomer($customer);
136
137
        // set default values taken from OAuth sign-in provider account
138
        if (null !== $email = $response->getEmail()) {
139
            $customer->setEmail($email);
140
        }
141
142
        if (null !== $realName = $response->getRealName()) {
143
            $customer->setFirstName($realName);
144
        }
145
146
        if (!$user->getUsername()) {
147
            $user->setUsername($response->getEmail() ?: $response->getNickname());
148
        }
149
150
        // set random password to prevent issue with not nullable field & potential security hole
151
        $user->setPlainPassword(substr(sha1($response->getAccessToken()), 0, 10));
152
153
        $user->setEnabled(true);
154
155
        return $this->updateUserByOAuthUserResponse($user, $response);
156
    }
157
158
    /**
159
     * Attach OAuth sign-in provider account to existing user.
160
     *
161
     * @param UserInterface         $user
162
     * @param UserResponseInterface $response
163
     *
164
     * @return UserInterface
165
     */
166
    protected function updateUserByOAuthUserResponse(UserInterface $user, UserResponseInterface $response)
167
    {
168
        $oauth = $this->oauthFactory->createNew();
169
        $oauth->setIdentifier($response->getUsername());
170
        $oauth->setProvider($response->getResourceOwner()->getName());
171
        $oauth->setAccessToken($response->getAccessToken());
172
        $oauth->setRefreshToken($response->getRefreshToken());
173
174
        /* @var $user SyliusUserInterface */
175
        $user->addOAuthAccount($oauth);
176
177
        $this->userManager->persist($user);
178
        $this->userManager->flush();
179
180
        return $user;
181
    }
182
}
183