Completed
Pull Request — master (#14)
by Artem
06:19
created

PrivateChannelAuthenticator::authChannelsForClientFromRequest()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 19
rs 9.6333
c 0
b 0
f 0
cc 3
nc 3
nop 1
1
<?php
2
/*
3
 * This file is part of the FreshCentrifugoBundle.
4
 *
5
 * (c) Artem Henvald <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
declare(strict_types=1);
12
13
namespace Fresh\CentrifugoBundle\Service\ChannelAuthenticator;
14
15
use Fresh\CentrifugoBundle\Service\Credentials\CredentialsGenerator;
16
use Symfony\Component\HttpFoundation\Request;
17
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
18
19
/**
20
 * PrivateChannelAuthenticator.
21
 *
22
 * @author Artem Henvald <[email protected]>
23
 */
24
class PrivateChannelAuthenticator
25
{
26
    private CredentialsGenerator $credentialsGenerator;
0 ignored issues
show
Bug introduced by
This code did not parse for me. Apparently, there is an error somewhere around this line:

Syntax error, unexpected T_STRING, expecting T_FUNCTION or T_CONST
Loading history...
27
28
    /** @var ChannelAuthenticatorInterface[]|iterable */
29
    private iterable $channelAuthenticators;
30
31
    /**
32
     * @param CredentialsGenerator                     $credentialsGenerator
33
     * @param ChannelAuthenticatorInterface[]|iterable $channelAuthenticators
34
     */
35
    public function __construct(CredentialsGenerator $credentialsGenerator, iterable $channelAuthenticators)
36
    {
37
        $this->credentialsGenerator = $credentialsGenerator;
38
        $this->channelAuthenticators = $channelAuthenticators;
39
    }
40
41
    /**
42
     * @param Request $request
43
     *
44
     * @return array
45
     */
46
    public function authChannelsForClientFromRequest(Request $request): array
47
    {
48
        $authData = [];
49
50
        [$client, $channels] = $this->processRequest($request);
51
52
        foreach ($channels as $channel) {
53
            $token = $this->authChannelForClient($client, (string) $channel);
54
55
            if (\is_string($token)) {
56
                $authData[] = [
57
                    'channel' => (string) $channel,
58
                    'token' => $token,
59
                ];
60
            }
61
        }
62
63
        return ['channels' => $authData];
64
    }
65
66
    /**
67
     * @param string $client
68
     * @param string $channel
69
     *
70
     * @return string|null
71
     */
72
    private function authChannelForClient(string $client, string $channel): ?string
73
    {
74
        $token = null;
75
76
        $channelAuthenticator = $this->findAppropriateChannelAuthenticator($channel);
77
        if ($channelAuthenticator instanceof ChannelAuthenticatorInterface && $channelAuthenticator->hasAccessToChannel($channel)) {
78
            $token = $this->credentialsGenerator->generateJwtTokenForPrivateChannel($client, $channel);
79
        }
80
81
        return $token;
82
    }
83
84
    /**
85
     * @param string $channel
86
     *
87
     * @return ChannelAuthenticatorInterface|null
88
     */
89
    private function findAppropriateChannelAuthenticator(string $channel): ?ChannelAuthenticatorInterface
90
    {
91
        foreach ($this->channelAuthenticators as $channelAuthenticator) {
92
            if ($channelAuthenticator->supports($channel)) {
93
                return $channelAuthenticator;
94
            }
95
        }
96
97
        return null;
98
    }
99
100
    /**
101
     * @param Request $request
102
     *
103
     * @throws BadRequestHttpException
104
     * @throws \Exception
105
     *
106
     * @return array
107
     */
108
    private function processRequest(Request $request): array
109
    {
110
        try {
111
            $content = \json_decode((string) $request->getContent(), true, 512, \JSON_THROW_ON_ERROR);
112
        } catch (\JsonException $e) {
113
            throw new BadRequestHttpException('Invalid JSON.');
114
        } catch (\Exception $e) {
115
            throw $e;
116
        }
117
118
        $result = [];
119
120
        if (!isset($content['client']) || !\is_string($content['client'])) {
121
            throw new BadRequestHttpException('Client must be set in request.');
122
        }
123
        $result[] = $content['client'];
124
125
        if (!isset($content['channels']) || !\is_array($content['channels']) || empty($content['channels'])) {
126
            throw new BadRequestHttpException('Channels must be set in request.');
127
        }
128
129
        foreach ($content['channels'] as $channel) {
130
            if (!\is_string($channel)) {
131
                throw new BadRequestHttpException('Channel must be a string.');
132
            }
133
        }
134
135
        $result[] = $content['channels'];
136
137
        return $result;
138
    }
139
}
140