GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — master ( 5ef788...8a0800 )
by Lukáš
09:29
created

loadConfiguration()   D

Complexity

Conditions 14
Paths 50

Size

Total Lines 122
Code Lines 89

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 122
rs 4.9516
c 0
b 0
f 0
cc 14
eloc 89
nc 50
nop 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
declare(strict_types=1);
3
4
namespace Lookyman\NetteOAuth2Server\Storage\Doctrine;
5
6
use Kdyby\Doctrine\DI\IEntityProvider;
7
use Kdyby\Events\DI\EventsExtension;
8
use League\OAuth2\Server\AuthorizationServer;
9
use League\OAuth2\Server\CryptKey;
10
use League\OAuth2\Server\Grant\AuthCodeGrant;
11
use League\OAuth2\Server\Grant\ClientCredentialsGrant;
12
use League\OAuth2\Server\Grant\ImplicitGrant;
13
use League\OAuth2\Server\Grant\PasswordGrant;
14
use League\OAuth2\Server\Grant\RefreshTokenGrant;
15
use League\OAuth2\Server\ResourceServer;
16
use Lookyman\NetteOAuth2Server\RedirectConfig;
17
use Lookyman\NetteOAuth2Server\Storage\Doctrine\AccessToken\AccessTokenRepository;
18
use Lookyman\NetteOAuth2Server\Storage\Doctrine\AuthCode\AuthCodeRepository;
19
use Lookyman\NetteOAuth2Server\Storage\Doctrine\Client\ClientRepository;
20
use Lookyman\NetteOAuth2Server\Storage\Doctrine\RefreshToken\RefreshTokenRepository;
21
use Lookyman\NetteOAuth2Server\Storage\Doctrine\Scope\ScopeRepository;
22
use Lookyman\NetteOAuth2Server\Storage\IAuthorizationRequestSerializer;
23
use Lookyman\NetteOAuth2Server\UI\ApproveControlFactory;
24
use Lookyman\NetteOAuth2Server\UI\OAuth2Presenter;
25
use Lookyman\NetteOAuth2Server\User\LoginSubscriber;
26
use Lookyman\NetteOAuth2Server\User\UserRepository;
27
use Nette\Application\IPresenterFactory;
28
use Nette\DI\CompilerExtension;
29
use Nette\DI\Statement;
30
use Nette\Utils\Validators;
31
32
class NetteOAuth2ServerDoctrineExtension extends CompilerExtension implements IEntityProvider
33
{
34
	/**
35
	 * @var array
36
	 */
37
	private $defaults = [
38
		'grants' => [
39
			'authCode' => false,
40
			'clientCredentials' => false,
41
			'implicit' => false,
42
			'password' => false,
43
			'refreshToken' => false,
44
		],
45
		'privateKey' => null,
46
		'publicKey' => null,
47
		'approveDestination' => null,
48
		'loginDestination' => null,
49
		'tablePrefix' => TablePrefixSubscriber::DEFAULT_PREFIX,
50
		'loginEventPriority' => 0,
51
	];
52
53
	public function loadConfiguration()
54
	{
55
		$builder = $this->getContainerBuilder();
56
		$config = $this->validateConfig($this->defaults);
57
58
		// Table mapping & Login redirection
59
		Validators::assertField($config, 'tablePrefix', 'string');
60
		$builder->addDefinition($this->prefix('tablePrefixSubscriber'))
61
			->setClass(TablePrefixSubscriber::class, [$config['tablePrefix']])
62
			->addTag(EventsExtension::TAG_SUBSCRIBER);
63
		Validators::assertField($config, 'loginEventPriority', 'integer');
64
		$builder->addDefinition($this->prefix('loginSubscriber'))
65
			->setClass(LoginSubscriber::class, ['priority' => $config['loginEventPriority']])
66
			->addTag(EventsExtension::TAG_SUBSCRIBER);
67
68
		// Common repositories
69
		$builder->addDefinition($this->prefix('repository.accessToken'))
70
			->setClass(AccessTokenRepository::class);
71
		$builder->addDefinition($this->prefix('repository.authCode'))
72
			->setClass(AuthCodeRepository::class);
73
		$builder->addDefinition($this->prefix('repository.client'))
74
			->setClass(ClientRepository::class);
75
		$builder->addDefinition($this->prefix('repository.refreshToken'))
76
			->setClass(RefreshTokenRepository::class);
77
		$builder->addDefinition($this->prefix('repository.scope'))
78
			->setClass(ScopeRepository::class);
79
		$builder->addDefinition($this->prefix('repository.user'))
80
			->setClass(UserRepository::class);
81
82
		// Encryption keys
83
		Validators::assertField($config, 'publicKey', 'string');
84
		Validators::assertField($config, 'privateKey', 'string|array');
85
		if (is_array($config['privateKey'])) {
86
			Validators::assertField($config['privateKey'], 'keyPath', 'string');
87
			Validators::assertField($config['privateKey'], 'passPhrase', 'string');
88
			$privateKey = new Statement(CryptKey::class, [$config['privateKey']['keyPath'], $config['privateKey']['passPhrase']]);
89
90
		} else {
91
			$privateKey = $config['privateKey'];
92
		}
93
94
		// Authorization & resource server
95
		$authorizationServer = $builder->addDefinition($this->prefix('authorizationServer'))
96
			->setClass(AuthorizationServer::class, [
97
				'privateKey' => $privateKey,
98
				'publicKey' => $config['publicKey'],
99
			]);
100
		$builder->addDefinition($this->prefix('resourceServer'))
101
			->setClass(ResourceServer::class, [
102
				'publicKey' => $config['publicKey'],
103
			]);
104
105
		// Grants
106
		Validators::assertField($config, 'grants', 'array');
107
		foreach ($config['grants'] as $grant => $options) {
108
			Validators::assert($options, 'boolean|array');
109
			if ($options === false) {
110
				continue;
111
112
			} else {
113
				$options = (array) $options;
114
			}
115
116
			$definition = $builder->addDefinition($this->prefix('grant.' . $grant));
117
118
			switch ($grant) {
119
				case 'authCode':
120
					if (!array_key_exists('authCodeTtl', $options)) {
121
						$options['authCodeTtl'] = 'PT10M';
122
					}
123
					$definition->setClass(AuthCodeGrant::class, ['authCodeTTL' => $this->createDateIntervalStatement($options['authCodeTtl'])]);
124
					if (array_key_exists('pkce', $options)) {
125
						Validators::assertField($options, 'pkce', 'boolean');
126
						if ($options['pkce']) {
127
							$definition->addSetup('enableCodeExchangeProof');
128
						}
129
					}
130
					break;
131
				case 'clientCredentials':
132
					$definition->setClass(ClientCredentialsGrant::class);
133
					break;
134
				case 'implicit':
135
					if (!array_key_exists('accessTokenTtl', $options)) {
136
						$options['accessTokenTtl'] = 'PT10M';
137
					}
138
					$definition->setClass(ImplicitGrant::class, ['accessTokenTTL' => $this->createDateIntervalStatement($options['accessTokenTtl'])]);
139
					break;
140
				case 'password':
141
					$definition->setClass(PasswordGrant::class);
142
					break;
143
				case 'refreshToken':
144
					$definition->setClass(RefreshTokenGrant::class);
145
					break;
146
				default:
147
					throw new \InvalidArgumentException(sprintf('Unknown grant %s', $grant));
148
			}
149
150
			$args = [$this->prefix('@grant.' . $grant)];
151
			if (array_key_exists('ttl', $options)) {
152
				$args[] = $this->createDateIntervalStatement($options['ttl']);
153
			}
154
			$authorizationServer->addSetup('enableGrantType', $args);
155
		}
156
157
		// Presenter, Control factory, Serializer
158
		$builder->addDefinition($this->prefix('presenter'))
159
			->setClass(OAuth2Presenter::class);
160
		$builder->addDefinition($this->prefix('approveControlFactory'))
161
			->setClass(ApproveControlFactory::class);
162
		$builder->addDefinition($this->prefix('serializer'))
163
			->setClass(IAuthorizationRequestSerializer::class)
164
			->setFactory(AuthorizationRequestSerializer::class);
165
166
		// Redirect config
167
		Validators::assertField($config, 'approveDestination', 'string|null');
168
		Validators::assertField($config, 'loginDestination', 'string|null');
169
		$builder->addDefinition($this->prefix('redirectConfig'))
170
			->setClass(RedirectConfig::class, [
171
				'approveDestination' => $config['approveDestination'],
172
				'loginDestination' => $config['loginDestination'],
173
			]);
174
	}
175
176
	public function beforeCompile()
177
	{
178
		$builder = $this->getContainerBuilder();
179
180
		// Mapping
181
		$presenterFactory = $builder->getDefinition($builder->getByType(IPresenterFactory::class));
182
		$presenterFactory->addSetup('if (!? instanceof \Nette\Application\PresenterFactory) { throw new \RuntimeException(\'Cannot set OAuth2Server mapping\'); } else { ?->setMapping(?); }', [
183
			'@self', '@self', ['NetteOAuth2Server' => 'Lookyman\NetteOAuth2Server\UI\*Presenter']
184
		]);
185
	}
186
187
	/**
188
	 * @return array
189
	 */
190
	public function getEntityMappings()
191
	{
192
		return ['Lookyman\NetteOAuth2Server\Storage\Doctrine' => __DIR__];
193
	}
194
195
	/**
196
	 * @param string $interval
197
	 * @return Statement
198
	 * @throws \Exception
199
	 */
200
	private function createDateIntervalStatement(string $interval): Statement
201
	{
202
		new \DateInterval($interval); // throw early
203
		return new Statement(\DateInterval::class, [$interval]);
204
	}
205
}
206