Completed
Pull Request — master (#2)
by Artem
01:20
created

PrivateChannelAuthenticator   A

Complexity

Total Complexity 17

Size/Duplication

Total Lines 99
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Importance

Changes 0
Metric Value
wmc 17
lcom 1
cbo 4
dl 0
loc 99
rs 10
c 0
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A authChannelsForUserFromRequest() 0 17 4
A authChannelForUser() 0 11 3
A findAppropriateChannelAuthenticator() 0 10 3
A processRequest() 0 16 6
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
    /** @var CredentialsGenerator */
27
    private $credentialsGenerator;
28
29
    /** @var ChannelAuthenticatorInterface[]|iterable */
30
    private $channelAuthenticators;
31
32
    /**
33
     * @param CredentialsGenerator                     $credentialsGenerator
34
     * @param ChannelAuthenticatorInterface[]|iterable $channelAuthenticators
35
     */
36
    public function __construct(CredentialsGenerator $credentialsGenerator, iterable $channelAuthenticators)
37
    {
38
        $this->credentialsGenerator = $credentialsGenerator;
39
        $this->channelAuthenticators = $channelAuthenticators;
40
    }
41
42
    /**
43
     * @param Request $request
44
     *
45
     * @return array
46
     */
47
    public function authChannelsForUserFromRequest(Request $request): array
48
    {
49
        $channelsAuth = [];
50
51
        [$client, $channels] = $this->processRequest($request);
0 ignored issues
show
Bug introduced by
The variable $client 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 $channels does not exist. Did you mean $channelsAuth?

This check looks for variables that are accessed but have not been defined. It raises an issue if it finds another variable that has a similar name.

The variable may have been renamed without also renaming all references.

Loading history...
52
53
        foreach ($channels as $channel) {
0 ignored issues
show
Bug introduced by
The variable $channels does not exist. Did you mean $channelsAuth?

This check looks for variables that are accessed but have not been defined. It raises an issue if it finds another variable that has a similar name.

The variable may have been renamed without also renaming all references.

Loading history...
54
            if (($token = $this->authChannelForUser($client, $channel)) && \is_string($token)) {
55
                $channelsAuth[] = [
56
                    'channel' => $channel,
57
                    'token' => $token,
58
                ];
59
            }
60
        }
61
62
        return ['channels' => $channelsAuth];
63
    }
64
65
    /**
66
     * @param string $client
67
     * @param string $channel
68
     *
69
     * @return string|null
70
     */
71
    private function authChannelForUser(string $client, string $channel): ?string
72
    {
73
        $token = null;
74
75
        $channelAuthenticator = $this->findAppropriateChannelAuthenticator($channel);
76
        if ($channelAuthenticator instanceof ChannelAuthenticatorInterface && $channelAuthenticator->hasAccessToChannel($channel)) {
77
            $token = $this->credentialsGenerator->generateJwtTokenForPrivateChannel($client, $channel);
78
        }
79
80
        return $token;
81
    }
82
83
    /**
84
     * @param string $channel
85
     *
86
     * @return ChannelAuthenticatorInterface|null
87
     */
88
    private function findAppropriateChannelAuthenticator(string $channel): ?ChannelAuthenticatorInterface
89
    {
90
        foreach ($this->channelAuthenticators as $channelAuthenticator) {
91
            if ($channelAuthenticator->supports($channel)) {
92
                return $channelAuthenticator;
93
            }
94
        }
95
96
        return null;
97
    }
98
99
    /**
100
     * @param Request $request
101
     *
102
     * @throws BadRequestHttpException
103
     *
104
     * @return array
105
     */
106
    private function processRequest(Request $request): array
107
    {
108
        $content = \json_decode((string) $request->getContent(), true, 512, \JSON_THROW_ON_ERROR);
109
110
        if (!isset($content['client']) || !\is_string($content['client'])) {
111
            throw new BadRequestHttpException('Client must be set in request');
112
        }
113
        $result[] = $content['client'];
0 ignored issues
show
Coding Style Comprehensibility introduced by
$result was never initialized. Although not strictly required by PHP, it is generally a good practice to add $result = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
114
115
        if (!isset($content['channels']) || empty($content['channels'] || !\is_array($content['channels']))) {
116
            throw new BadRequestHttpException('Channels must be set in request');
117
        }
118
        $result[] = $content['channels'];
119
120
        return $result;
121
    }
122
}
123