Extension::propertiesFromConfig()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
cc 3
eloc 6
nc 3
nop 1
dl 0
loc 10
ccs 0
cts 6
cp 0
crap 12
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace kalanis\OAuth2\DI;
4
5
6
use kalanis\OAuth2\Storage;
7
use Nette\Bootstrap\Configurator;
8
use Nette\DI\CompilerExtension;
9
use Nette\DI\ContainerBuilder;
10
use Nette\DI\Definitions\Definition;
11
12
13
/**
14
 * OAuth2 compiler extension
15
 * @package kalanis\OAuth2\DI
16
 */
17
class Extension extends CompilerExtension
18
{
19
20
    /**
21
     * @var array<string, array{
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<string, array{ at position 6 could not be parsed: the token is null at position 6.
Loading history...
22
     *     accessTokenStorage: class-string<Storage\AccessTokens\IAccessTokenStorage>,
23
     *     authorizationCodeStorage: class-string<Storage\AuthorizationCodes\IAuthorizationCodeStorage>,
24
     *     clientStorage: class-string<Storage\Clients\IClientStorage>,
25
     *     refreshTokenStorage: class-string<Storage\RefreshTokens\IRefreshTokenStorage>,
26
     * }>
27
     */
28
    protected array $storages = [
29
        'ndb' => [
30
            'accessTokenStorage' => Storage\NDB\AccessTokenStorage::class,
31
            'authorizationCodeStorage' => Storage\NDB\AuthorizationCodeStorage::class,
32
            'clientStorage' => Storage\NDB\ClientStorage::class,
33
            'refreshTokenStorage' => Storage\NDB\RefreshTokenStorage::class,
34
        ],
35
        'dibi' => [
36
            'accessTokenStorage' => Storage\Dibi\AccessTokenStorage::class,
37
            'authorizationCodeStorage' => Storage\Dibi\AuthorizationCodeStorage::class,
38
            'clientStorage' => Storage\Dibi\ClientStorage::class,
39
            'refreshTokenStorage' => Storage\Dibi\RefreshTokenStorage::class,
40
        ],
41
    ];
42
43
    /**
44
     * Default DI settings
45
     * @var array<string, string|int|null>
46
     */
47
    protected array $defaults = [
48
        'accessTokenStorage' => null,
49
        'authorizationCodeStorage' => null,
50
        'clientStorage' => null,
51
        'refreshTokenStorage' => null,
52
        'accessTokenLifetime' => 3600, // 1 hour
53
        'refreshTokenLifetime' => 36000, // 10 hours
54
        'authorizationCodeLifetime' => 360, // 6 minutes
55
        'storage' => null,
56
    ];
57
58
    /**
59
     * Register OAuth2 extension
60
     */
61
    public static function install(Configurator $configurator): void
62
    {
63
        $configurator->onCompile[] = function ($configurator, $compiler): void {
64
            $compiler->addExtension('oauth2', new Extension);
65
        };
66
    }
67
68
    /**
69
     * Load DI configuration
70
     */
71
    public function loadConfiguration(): void
72
    {
73 1
        $container = $this->getContainerBuilder();
74 1
        $passedConf = $this->getConfig();
75 1
        $passedConf = is_object($passedConf) ? $this->propertiesFromConfig($passedConf) : (array) $passedConf;
76 1
        $config = array_merge($this->defaults, $passedConf);
77
78
        // Library common
79 1
        $container->addDefinition($this->prefix('keyGenerator'))
80 1
            ->setType(\kalanis\OAuth2\KeyGenerator::class);
81
82 1
        $container->addDefinition($this->prefix('input'))
83 1
            ->setType(\kalanis\OAuth2\Http\Input::class);
84
85
        // Grant types
86 1
        $container->addDefinition($this->prefix('authorizationCodeGrant'))
87 1
            ->setType(\kalanis\OAuth2\Grant\AuthorizationCode::class);
88 1
        $container->addDefinition($this->prefix('refreshTokenGrant'))
89 1
            ->setType(\kalanis\OAuth2\Grant\RefreshToken::class);
90 1
        $container->addDefinition($this->prefix('passwordGrant'))
91 1
            ->setType(\kalanis\OAuth2\Grant\Password::class);
92 1
        $container->addDefinition($this->prefix('implicitGrant'))
93 1
            ->setType(\kalanis\OAuth2\Grant\Implicit::class);
94 1
        $container->addDefinition($this->prefix('clientCredentialsGrant'))
95 1
            ->setType(\kalanis\OAuth2\Grant\ClientCredentials::class);
96
97 1
        $container->addDefinition($this->prefix('grantContext'))
98 1
            ->setType(\kalanis\OAuth2\Grant\GrantContext::class)
99 1
            ->addSetup('$service->addGrantType(?)', [$this->prefix('@authorizationCodeGrant')])
100 1
            ->addSetup('$service->addGrantType(?)', [$this->prefix('@refreshTokenGrant')])
101 1
            ->addSetup('$service->addGrantType(?)', [$this->prefix('@passwordGrant')])
102 1
            ->addSetup('$service->addGrantType(?)', [$this->prefix('@implicitGrant')])
103 1
            ->addSetup('$service->addGrantType(?)', [$this->prefix('@clientCredentialsGrant')]);
104
105
        // Tokens
106 1
        $container->addDefinition($this->prefix('accessToken'))
107 1
            ->setType(\kalanis\OAuth2\Storage\AccessTokens\AccessTokenFacade::class)
108 1
            ->setArguments([$config['accessTokenLifetime']]);
109 1
        $container->addDefinition($this->prefix('refreshToken'))
110 1
            ->setType(\kalanis\OAuth2\Storage\RefreshTokens\RefreshTokenFacade::class)
111 1
            ->setArguments([$config['refreshTokenLifetime']]);
112 1
        $container->addDefinition($this->prefix('authorizationCode'))
113 1
            ->setType(\kalanis\OAuth2\Storage\AuthorizationCodes\AuthorizationCodeFacade::class)
114 1
            ->setArguments([$config['authorizationCodeLifetime']]);
115
116 1
        $container->addDefinition('tokenContext')
117 1
            ->setType(\kalanis\OAuth2\Storage\TokenContext::class)
118 1
            ->addSetup('$service->addToken(?)', [$this->prefix('@accessToken')])
119 1
            ->addSetup('$service->addToken(?)', [$this->prefix('@refreshToken')])
120 1
            ->addSetup('$service->addToken(?)', [$this->prefix('@authorizationCode')]);
121
122
        // Default fallback value
123 1
        $storageIndex = 'ndb';
124
125
        // Nette database Storage
126 1
        if ('DIBI' == strtoupper(strval($config['storage'])) || (is_null($config['storage']) && $this->getByType($container, 'DibiConnection'))) {
127
            $storageIndex = 'dibi';
128
        }
129
130
        // Nette database Storage
131 1
        $container->addDefinition($this->prefix('accessTokenStorage'))
132 1
            ->setType($config['accessTokenStorage'] ?: $this->storages[$storageIndex]['accessTokenStorage']);
133 1
        $container->addDefinition($this->prefix('refreshTokenStorage'))
134 1
            ->setType($config['refreshTokenStorage'] ?: $this->storages[$storageIndex]['refreshTokenStorage']);
135 1
        $container->addDefinition($this->prefix('authorizationCodeStorage'))
136 1
            ->setType($config['authorizationCodeStorage'] ?: $this->storages[$storageIndex]['authorizationCodeStorage']);
137 1
        $container->addDefinition($this->prefix('clientStorage'))
138 1
            ->setType($config['clientStorage'] ?: $this->storages[$storageIndex]['clientStorage']);
139 1
    }
140
141
    /**
142
     * @param object $config
143
     * @return array<string, mixed>
144
     */
145
    private function propertiesFromConfig(object $config): array
146
    {
147
        $result = [];
148
        $obj = new \ReflectionObject($config);
149
        foreach ($obj->getProperties() as $property) {
150
            if ($property->isPublic()) {
151
                $result[$property->getName()] = $property->getValue();
152
            }
153
        }
154
        return $result;
155
    }
156
157
    /**
158
     * @param ContainerBuilder $container
159
     * @param string $type
160
     * @return Definition|null
161
     */
162
    private function getByType(ContainerBuilder $container, string $type): ?Definition
163
    {
164 1
        $definitions = $container->getDefinitions();
165 1
        foreach ($definitions as $definition) {
166 1
            if (isset($definition->class) && $definition->class === $type) {
167
                return $definition;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $definition returns the type object which includes types incompatible with the type-hinted return Nette\DI\Definitions\Definition|null.
Loading history...
168
            }
169
        }
170 1
        return null;
171
    }
172
}
173