Authenticator::validateCredentials()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 21
rs 9.584
c 0
b 0
f 0
cc 3
nc 3
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace SixtyEightPublishers\User\Authentication\Authenticator;
6
7
use Nette\SmartObject;
8
use Nette\Security\IIdentity;
9
use Nette\Security\IAuthenticator;
10
use Doctrine\ORM\NonUniqueResultException;
11
use Nette\Security\AuthenticationException;
12
use Doctrine\DBAL\Exception as DBALException;
13
use SixtyEightPublishers\User\Authentication\Entity\UserInterface;
14
use SixtyEightPublishers\DoctrineQueryObjects\ExecutableQueryObjectFactoryInterface;
15
use SixtyEightPublishers\User\Authentication\Query\AuthenticatorQueryObjectFactoryInterface;
16
17
final class Authenticator implements IAuthenticator
18
{
19
	use SmartObject;
20
21
	/** @var \SixtyEightPublishers\DoctrineQueryObjects\ExecutableQueryObjectFactoryInterface  */
22
	private $executableQueryObjectFactory;
23
24
	/** @var \SixtyEightPublishers\User\Authentication\Query\AuthenticatorQueryObjectFactoryInterface  */
25
	private $authenticatorQueryFactory;
26
27
	/**
28
	 * @param \SixtyEightPublishers\DoctrineQueryObjects\ExecutableQueryObjectFactoryInterface         $executableQueryObjectFactory
29
	 * @param \SixtyEightPublishers\User\Authentication\Query\AuthenticatorQueryObjectFactoryInterface $authenticatorQueryFactory
30
	 */
31
	public function __construct(ExecutableQueryObjectFactoryInterface $executableQueryObjectFactory, AuthenticatorQueryObjectFactoryInterface $authenticatorQueryFactory)
32
	{
33
		$this->executableQueryObjectFactory = $executableQueryObjectFactory;
34
		$this->authenticatorQueryFactory = $authenticatorQueryFactory;
35
	}
36
37
	/**
38
	 * {@inheritdoc}
39
	 */
40
	public function authenticate(array $credentials): IIdentity
41
	{
42
		[ $username, $password ] = $this->validateCredentials($credentials);
0 ignored issues
show
Bug introduced by
The variable $username does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $password does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
43
		$user = $this->findUser($username);
44
45
		if (!$user->getPassword()->verify($password)) {
46
			throw new AuthenticationException(sprintf(
47
				'Invalid password for user "%s"',
48
				$username
49
			), self::INVALID_CREDENTIAL);
50
		}
51
52
		return $user;
53
	}
54
55
	/**
56
	 * @param array $credentials
57
	 *
58
	 * @return array
59
	 * @throws \Nette\Security\AuthenticationException
60
	 */
61
	private function validateCredentials(array $credentials): array
62
	{
63
		if (!isset($credentials[self::USERNAME])) {
64
			throw new AuthenticationException(sprintf(
65
				'Missing username field in credentials (key %s)',
66
				self::USERNAME
67
			), self::FAILURE);
68
		}
69
70
		if (!isset($credentials[self::PASSWORD])) {
71
			throw new AuthenticationException(sprintf(
72
				'Missing password field in credentials (key %s)',
73
				self::PASSWORD
74
			), self::FAILURE);
75
		}
76
77
		return [
78
			(string) $credentials[self::USERNAME],
79
			(string) $credentials[self::PASSWORD],
80
		];
81
	}
82
83
	/**
84
	 * @param string $username
85
	 *
86
	 * @return \SixtyEightPublishers\User\Authentication\Entity\UserInterface
87
	 * @throws \Nette\Security\AuthenticationException
88
	 */
89
	private function findUser(string $username): UserInterface
90
	{
91
		try {
92
			$user = $this->executableQueryObjectFactory->create($this->authenticatorQueryFactory->create($username))->fetchOne();
93
		} catch (NonUniqueResultException $e) {
0 ignored issues
show
Bug introduced by
The class Doctrine\ORM\NonUniqueResultException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
94
			$e = new AuthenticationException(sprintf(
95
				'User\'s username field is not unique! Value was "%s"',
96
				$username
97
			), self::FAILURE, $e);
98
		} catch (DBALException $e) {
0 ignored issues
show
Bug introduced by
The class Doctrine\DBAL\Exception does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
99
			$e = new AuthenticationException(sprintf(
100
				'DBAL throws unexpected exception, username value was "%s"',
101
				$username
102
			), self::FAILURE, $e);
103
		}
104
105
		if (isset($e)) {
106
			throw $e;
107
		}
108
109
		if (!isset($user)) {
110
			throw new AuthenticationException(sprintf(
111
				'User "%s" not found.',
112
				$username
113
			), self::IDENTITY_NOT_FOUND);
114
		}
115
116
		return $user;
117
	}
118
}
119