Passed
Push — master ( a6d59a...971523 )
by butschster
16:28 queued 13s
created

HttpAuthBootloader::addTokenStorage()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 1
c 0
b 0
f 0
dl 0
loc 3
ccs 2
cts 2
cp 1
rs 10
cc 1
nc 1
nop 2
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Spiral\Bootloader\Auth;
6
7
use Spiral\Auth\Config\AuthConfig;
8
use Spiral\Auth\HttpTransportInterface;
9
use Spiral\Auth\Session\TokenStorage as SessionTokenStorage;
10
use Spiral\Auth\TokenStorageInterface;
11
use Spiral\Auth\TokenStorageProvider;
12
use Spiral\Auth\TokenStorageProviderInterface;
13
use Spiral\Auth\Transport\CookieTransport;
14
use Spiral\Auth\Transport\HeaderTransport;
15
use Spiral\Auth\TransportRegistry;
16
use Spiral\Boot\AbstractKernel;
17
use Spiral\Boot\Bootloader\Bootloader;
18
use Spiral\Boot\EnvironmentInterface;
19
use Spiral\Bootloader\Http\HttpBootloader;
20
use Spiral\Config\ConfiguratorInterface;
21
use Spiral\Config\Patch\Append;
22
use Spiral\Core\Container\Autowire;
23
use Spiral\Core\Container\SingletonInterface;
24
use Spiral\Core\FactoryInterface;
25
use Spiral\Http\Config\HttpConfig;
26
27
/**
28
 * Enables Auth middleware and http transports to read and write tokens in PSR-7 request/response.
29
 */
30
final class HttpAuthBootloader extends Bootloader implements SingletonInterface
31
{
32
    protected const DEPENDENCIES = [
33
        AuthBootloader::class,
34
        HttpBootloader::class,
35
    ];
36
37
    protected const SINGLETONS = [
38
        TransportRegistry::class => [self::class, 'transportRegistry'],
39
        TokenStorageInterface::class => [self::class, 'getDefaultTokenStorage'],
40
        TokenStorageProviderInterface::class => TokenStorageProvider::class,
41
    ];
42
43 266
    public function __construct(
44
        private readonly ConfiguratorInterface $config
45
    ) {
46
    }
47
48 266
    public function init(AbstractKernel $kernel, EnvironmentInterface $env): void
49
    {
50 266
        $this->config->setDefaults(
51
            AuthConfig::CONFIG,
52
            [
53 266
                'defaultTransport' => $env->get('AUTH_TOKEN_TRANSPORT', 'cookie'),
54 266
                'defaultStorage' => $env->get('AUTH_TOKEN_STORAGE', 'session'),
55
                'transports' => [],
56
                'storages' => [],
57
            ]
58
        );
59
60 266
        $kernel->booting(function () {
61 266
            $this->addTransport('cookie', $this->createDefaultCookieTransport());
62 266
            $this->addTransport('header', new HeaderTransport('X-Auth-Token'));
63 266
            $this->addTokenStorage('session', SessionTokenStorage::class);
64
        });
65
    }
66
67
    /**
68
     * Add new Http token transport.
69
     *
70
     * @param non-empty-string $name
0 ignored issues
show
Documentation Bug introduced by
The doc comment non-empty-string at position 0 could not be parsed: Unknown type name 'non-empty-string' at position 0 in non-empty-string.
Loading history...
71
     * @param Autowire|HttpTransportInterface|class-string<HttpTransportInterface> $transport
72
     */
73 266
    public function addTransport(string $name, Autowire|HttpTransportInterface|string $transport): void
74
    {
75 266
        $this->config->modify(AuthConfig::CONFIG, new Append('transports', $name, $transport));
76
    }
77
78
    /**
79
     * Add new Http token storage.
80
     *
81
     * @param non-empty-string $name
0 ignored issues
show
Documentation Bug introduced by
The doc comment non-empty-string at position 0 could not be parsed: Unknown type name 'non-empty-string' at position 0 in non-empty-string.
Loading history...
82
     * @param Autowire|TokenStorageInterface|class-string<TokenStorageInterface> $storage
83
     */
84 266
    public function addTokenStorage(string $name, Autowire|TokenStorageInterface|string $storage): void
85
    {
86 266
        $this->config->modify(AuthConfig::CONFIG, new Append('storages', $name, $storage));
87
    }
88
89
    /**
90
     * Creates default cookie transport when "transports" section is empty.
91
     */
92 266
    private function createDefaultCookieTransport(): CookieTransport
93
    {
94 266
        $config = $this->config->getConfig(HttpConfig::CONFIG);
95
96 266
        return new CookieTransport('token', $config['basePath'] ?? '/');
97
    }
98
99
    /**
100
     * @noRector RemoveUnusedPrivateMethodRector
101
     */
102 266
    private function transportRegistry(AuthConfig $config, FactoryInterface $factory): TransportRegistry
103
    {
104 266
        $registry = new TransportRegistry();
105 266
        $registry->setDefaultTransport($config->getDefaultTransport());
106
107 266
        foreach ($config->getTransports() as $name => $transport) {
108 266
            if ($transport instanceof Autowire) {
109 266
                $transport = $transport->resolve($factory);
110
            }
111
112 266
            $registry->setTransport($name, $transport);
113
        }
114
115 266
        return $registry;
116
    }
117
118
    /**
119
     * Get default token storage from provider
120
     */
121 266
    private function getDefaultTokenStorage(TokenStorageProviderInterface $provider): TokenStorageInterface
122
    {
123 266
        return $provider->getStorage();
124
    }
125
}
126