UserManager::createOAuthUser()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 8
nc 1
nop 1
dl 0
loc 11
ccs 0
cts 9
cp 0
crap 2
rs 9.4285
c 0
b 0
f 0
1
<?php
2
namespace App\Manager;
3
4
use Doctrine\ORM\EntityManagerInterface;
5
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
6
use App\Entity\User\User;
7
use App\Entity\User\ProductOwner;
8
use App\Entity\User\Member;
9
use App\Entity\User\BetaTester;
10
use App\Entity\Organization;
11
use App\Manager\ActivationLinkManager;
12
use Symfony\Component\Translation\TranslatorInterface;
13
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
14
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
15
16
class UserManager
17
{
18
    /** @var EntityManagerInterface **/
19
    protected $em;
20
    /** @var UserPasswordEncoderInterface **/
21
    protected $encoder;
22
    /** @var TranslatorInterface **/
23
    protected $translator;
24
    /** @var ActivationLinkManager **/
25
    protected $activationLinkManager;
26
27
    /**
28
     * @param EntityManagerInterface $em
29
     * @param UserPasswordEncoderInterface $encoder
30
     * @param TranslatorInterface $translator
31
     * @param ActivationLinkManager
32
     */
33 26
    public function __construct(EntityManagerInterface $em, UserPasswordEncoderInterface $encoder, TranslatorInterface $translator, ActivationLinkManager $activationLinkManager)
34
    {
35 26
        $this->em = $em;
36 26
        $this->encoder = $encoder;
37 26
        $this->translator = $translator;
38 26
        $this->activationLinkManager = $activationLinkManager;
39 26
    }
40
41
    /**
42
     * @param string $identifier
43
     * @return \App\Entity\User\User
44
     */
45 12
    public function findUserByUsernameOrEmail($identifier) {
46
        return $this
47 12
            ->em
48 12
            ->getRepository(User::class)
49 12
            ->findOneByUsernameOrEmail($identifier)
50
        ;
51
    }
52
    
53
    public function findUserByServiceId(string $service, int $id)
54
    {
55
        return $this->em->getRepository(User::class)->{"findOneBy{$service}Id"}($id);
56
    }
57
58 5
    public function createUser(array $data, string $type, Organization $organization = null): User
59
	{
60 5
        if (empty($data['username']) || !$this->checkUsername($data['username'])) {
61 1
            throw new BadRequestHttpException('users.invalid_username');
62
        }
63 4
        if (empty($data['email']) || !$this->checkEmail($data['email'])) {
64
            throw new BadRequestHttpException('users.invalid_email');
65
        }
66 4
		if (empty($data['password']) || empty($data['password_confirmation'])) {
67
            throw new BadRequestHttpException('users.invalid_password');
68
		}
69 4
		if ($data['password'] !== $data['password_confirmation']) {
70 1
			throw new BadRequestHttpException('users.password_mismatch');
71
		}
72
		switch($type) {
73 3
			case User::TYPE_PRODUCT_OWNER: 
74 2
				$user = new ProductOwner();
75 2
				break;
76 1
			case User::TYPE_MEMBER:
77 1
				$user = new Member();
78 1
				break;
79
			case User::TYPE_BETA_TESTER:
80
				$user = new BetaTester();
81
				break;
82
			default:
83
				throw new BadRequestHttpException('users.invalid_type');
84
		}
85 3
		$user->setUsername($data['username']);
86 3
		$user->setEmail($data['email']);
87 3
        $user->setSalt(uniqid('', true));
88 3
        $password = $this->encoder->encodePassword($user, $data['password']);
89 3
        $user->setPassword($password);
90 3
        $user->addRole('ROLE_USER');
91 3
        $user->enable(false);
92 3
        $user->setIsLocked(false);
93
94 3
        if ($organization !== null) {
95 1
            $user->addOrganization($organization);
96
        }
97
98 3
        $this->em->persist($user);
99 3
        $this->em->flush();
100
101 3
        $this->activationLinkManager->createActivationLink($user);
102 3
        $this->activationLinkManager->sendValidationMail($user);
103
104 3
        return $user;
105
    }
106
    
107
    public function createOAuthUser(User $user)
108
    {
109
        $user->setPlainPassword(md5(uniqid(null, true)));
110
        $user->setSalt(md5(uniqid()));
111
        $user->setPassword($this->encoder->encodePassword($user, $user->getPlainPassword()));
112
        $user->addRole('ROLE_USER');
113
        $user->enable(true);
114
        $user->setIsLocked(false);
115
116
        $this->em->persist($user);
117
        $this->em->flush();
118
    }
119
120 2
    public function updateUser(User $user)
121
    {
122 2
        $this->em->persist($user);
123 2
        $this->em->flush();
124 2
    }
125
    
126
    /**
127
     * @param string $username
128
     * @param string $role
129
     * @throws UsernameNotFoundException
130
     * @throws \InvalidArgumentException
131
     * @return User
132
     */
133 3
    public function promoteUser(string $username, string $role)
134
    {
135 3
        if (($user = $this->em->getRepository(User::class)->findOneByUsername($username)) === null) {
0 ignored issues
show
Bug introduced by
The method findOneByUsername() does not exist on App\Repository\User\UserRepository. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

135
        if (($user = $this->em->getRepository(User::class)->/** @scrutinizer ignore-call */ findOneByUsername($username)) === null) {
Loading history...
136 1
            throw new UsernameNotFoundException();
137
        }
138
        $roles = [
139 2
            'lead' => 'ROLE_LEAD',
140
            'admin' => 'ROLE_ADMIN',
141
        ];
142 2
        if (!isset($roles[$role])) {
143 1
            throw new \InvalidArgumentException();
144
        }
145 1
        $user->setRoles([$roles[$role]]);
146 1
        $this->updateUser($user);
147 1
        return $user;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $user also could return the type integer|array which is incompatible with the documented return type App\Entity\User\User.
Loading history...
148
    }
149
150
    /**
151
     * @param string $activationHash
152
     * @throws \InvalidArgumentException
153
     * @return User
154
     */
155 1
    public function activateUserAccount(string $activationHash): User
156
    {
157 1
        $activationLink = $this->activationLinkManager->findOneByHash($activationHash);
158 1
        if($activationLink === null) {
159
            throw new \InvalidArgumentException('not_found');
160
        }
161 1
        $datetime = new \DateTime();
162 1
        $datetime->setTimestamp((time() - 86400));
163 1
        if($activationLink->getCreatedAt() < $datetime) {
164
            throw new \InvalidArgumentException('invalid');
165
        }
166 1
        $user = $this->em->getRepository(User::class)->findOneByActivationLink($activationLink);
0 ignored issues
show
Bug introduced by
The method findOneByActivationLink() does not exist on App\Repository\User\UserRepository. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

166
        $user = $this->em->getRepository(User::class)->/** @scrutinizer ignore-call */ findOneByActivationLink($activationLink);
Loading history...
167 1
        if($user === null) {
168
            $this->em->remove($activationLink);
169
            $this->em->flush();
170
            throw new \InvalidArgumentException('unrelated');
171
        }
172
173 1
        $user->enable(true);
174 1
        $this->em->persist($user);
175 1
        $this->em->remove($activationLink);
176 1
        $this->em->flush();
177
178 1
        return $user;
179
    }
180
181
    /**
182
     * @param string $email
183
     * @throws UsernameNotFoundException
184
     * @throws BadRequestHttpException
185
     * @return bool
186
     */
187 3
    public function sendNewActivationLink($email)
188
    {
189 3
        if(($user = $this->findUserByUsernameOrEmail($email)) === null) {
190 1
            throw new UsernameNotFoundException();
191
        }
192 2
        if($user->isEnabled()) {
193 1
            throw new BadRequestHttpException('users.activation_link.user_already_enabled');
194
        }
195 1
        if(($activationLink = $user->getActivationLink()) !== null) {
196
            $user->setActivationLink(null);
0 ignored issues
show
Bug introduced by
null of type null is incompatible with the type App\Model\User\ActivationLink expected by parameter $activationLink of App\Model\User\User::setActivationLink(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

196
            $user->setActivationLink(/** @scrutinizer ignore-type */ null);
Loading history...
197
            $this->em->persist($user);
198
            $this->em->remove($activationLink);
199
            $this->em->flush();
200
        }
201 1
        $this->activationLinkManager->createActivationLink($user);
202 1
        $this->activationLinkManager->sendValidationMail($user);
203 1
        return true;
204
    }
205
206
    /**
207
     * @param string $username
208
     * @return bool
209
     */
210 5
    public function checkUsername(string $username): bool
211
    {
212 5
        return $this->em->getRepository(User::class)->checkUsername($username);
213
    }
214
215
    /**
216
     * @param string $email
217
     * @return bool
218
     */
219 4
    public function checkEmail(string $email): bool
220
    {
221 4
        return $this->em->getRepository(User::class)->checkEmail($email);
222
    }
223
}
224