Completed
Push — master ( 17598f...abee1f )
by Kirill
13s queued 11s
created

WebsocketsTest::testNonAuthorized()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 37
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 25
c 0
b 0
f 0
dl 0
loc 37
rs 9.52
cc 1
nc 1
nop 0
1
<?php
2
3
/**
4
 * Spiral Framework.
5
 *
6
 * @license   MIT
7
 * @author    Anton Titov (Wolfy-J)
8
 */
9
10
declare(strict_types=1);
11
12
namespace Spiral\Tests\Framework\Http;
13
14
use Psr\Http\Message\ServerRequestInterface;
15
use Spiral\Auth\AuthContextInterface;
16
use Spiral\Encrypter\Encrypter;
17
use Spiral\Encrypter\EncrypterFactory;
18
use Spiral\Http\Http;
19
use Spiral\Tests\Framework\HttpTest;
20
21
class WebsocketsTest extends HttpTest
22
{
23
    public function testBypass(): void
24
    {
25
        $this->init();
26
        $this->assertSame('Hello, Dave.', (string)$this->get('/index')->getBody());
27
    }
28
29
    public function testEmptyServerOK(): void
30
    {
31
        $this->init();
32
33
        $this->assertSame(403, $this->get('/ws/')->getStatusCode());
34
        $this->assertSame(200, $this->getWithAttributes('/ws/', [
35
            'ws:joinServer' => true
36
        ])->getStatusCode());
37
    }
38
39
    public function testAllowServerAccess(): void
40
    {
41
        $this->init(static function () {
42
            return true;
43
        });
44
45
        $this->assertSame(403, $this->get('/ws/')->getStatusCode());
46
        $this->assertSame(200, $this->getWithAttributes('/ws/', [
47
            'ws:joinServer' => true
48
        ])->getStatusCode());
49
    }
50
51
    public function testDenyServerAccess(): void
52
    {
53
        $this->init(static function () {
54
            return false;
55
        });
56
57
        $this->assertSame(403, $this->get('/ws/')->getStatusCode());
58
        $this->assertSame(403, $this->getWithAttributes('/ws/', [
59
            'ws:joinServer' => true
60
        ])->getStatusCode());
61
    }
62
63
    public function testServerAccessWithDependency(): void
64
    {
65
        $this->init(static function (ServerRequestInterface $request) {
66
            return $request instanceof ServerRequestInterface;
67
        });
68
69
        $this->assertSame(403, $this->get('/ws/')->getStatusCode());
70
        $this->assertSame(200, $this->getWithAttributes('/ws/', [
71
            'ws:joinServer' => true
72
        ])->getStatusCode());
73
    }
74
75
    public function testServerAccessFunction(): void
76
    {
77
        $this->init('closelog');
78
79
        $this->assertSame(403, $this->get('/ws/')->getStatusCode());
80
        $this->assertSame(200, $this->getWithAttributes('/ws/', [
81
            'ws:joinServer' => true
82
        ])->getStatusCode());
83
    }
84
85
    public function testServerAccessCallback(): void
86
    {
87
        $this->init([$this, 'ok']);
88
89
        $this->assertSame(403, $this->get('/ws/')->getStatusCode());
90
        $this->assertSame(200, $this->getWithAttributes('/ws/', [
91
            'ws:joinServer' => true
92
        ])->getStatusCode());
93
    }
94
95
    public function ok(ServerRequestInterface $request)
96
    {
97
        return $request instanceof ServerRequestInterface;
98
    }
99
100
    public function testServerAccessStaticCallback(): void
101
    {
102
        $this->init([self::class, 'ok2']);
103
104
        $this->assertSame(403, $this->get('/ws/')->getStatusCode());
105
        $this->assertSame(200, $this->getWithAttributes('/ws/', [
106
            'ws:joinServer' => true
107
        ])->getStatusCode());
108
    }
109
110
    public static function ok2(ServerRequestInterface $request)
111
    {
112
        return $request instanceof ServerRequestInterface;
113
    }
114
115
    public function testTopicAccessUndefined(): void
116
    {
117
        $this->init(null);
118
119
        $this->assertSame(403, $this->get('/ws/')->getStatusCode());
120
        $this->assertSame(403, $this->getWithAttributes('/ws/', [
121
            'ws:joinTopics' => 'topic'
122
        ])->getStatusCode());
123
    }
124
125
    public function testTopicAccessOK(): void
126
    {
127
        $this->init(null, function () {
128
            return true;
129
        });
130
131
        $this->assertSame(403, $this->get('/ws/')->getStatusCode());
132
        $this->assertSame(200, $this->getWithAttributes('/ws/', [
133
            'ws:joinTopics' => 'topic'
134
        ])->getStatusCode());
135
    }
136
137
    public function testTopicWildcardAccessFail(): void
138
    {
139
        $this->init(null, function () {
140
            return true;
141
        });
142
143
        $this->assertSame(403, $this->get('/ws/')->getStatusCode());
144
        $this->assertSame(403, $this->getWithAttributes('/ws/', [
145
            'ws:joinTopics' => 'wildcard.1,topic'
146
        ])->getStatusCode());
147
    }
148
149
    public function testTopicWildcardAccessOK(): void
150
    {
151
        $this->init(
152
            null,
153
            null,
154
            function () {
155
                return true;
156
            }
157
        );
158
159
        $this->assertSame(403, $this->get('/ws/')->getStatusCode());
160
        $this->assertSame(200, $this->getWithAttributes('/ws/', [
161
            'ws:joinTopics' => 'wildcard.1'
162
        ])->getStatusCode());
163
    }
164
165
    public function testTopicWildcardAccessOK1(): void
166
    {
167
        $this->init(
168
            null,
169
            null,
170
            function ($id) {
171
                return $id === '1';
172
            }
173
        );
174
175
        $this->assertSame(403, $this->get('/ws/')->getStatusCode());
176
        $this->assertSame(200, $this->getWithAttributes('/ws/', [
177
            'ws:joinTopics' => 'wildcard.1'
178
        ])->getStatusCode());
179
    }
180
181
    public function testTopicWildcardAccessFail2(): void
182
    {
183
        $this->init(
184
            null,
185
            null,
186
            function ($id) {
187
                return $id === '1';
188
            }
189
        );
190
191
        $this->assertSame(403, $this->get('/ws/')->getStatusCode());
192
        $this->assertSame(403, $this->getWithAttributes('/ws/', [
193
            'ws:joinTopics' => 'wildcard.2'
194
        ])->getStatusCode());
195
    }
196
197
    public function testNonAuthorized(): void
198
    {
199
        $this->app = $this->makeApp();
200
        $key = $this->app->get(EncrypterFactory::class)->generateKey();
201
202
        $this->app = $this->makeApp([
203
            'ENCRYPTER_KEY'              => $key,
204
            'CYCLE_AUTH'                 => true,
205
            'RR_BROADCAST_PATH'          => '/ws/',
206
            'WS_SERVER_CALLBACK'         => null,
207
            'WS_TOPIC_CALLBACK'          => function (AuthContextInterface $authContext) {
208
                return $authContext->getToken() !== null;
209
            },
210
            'WS_TOPIC_WILDCARD_CALLBACK' => null,
211
        ]);
212
213
        $this->app->console()->run('cycle:sync');
214
        $this->http = $this->app->get(Http::class);
215
216
        $result = $this->get('/auth/login');
217
        $this->assertSame('OK', (string)$result->getBody());
218
219
        $cookies = $this->fetchCookies($result->getHeader('Set-Cookie'));
220
        $this->assertTrue(isset($cookies['token']));
221
222
        $token = $this->app->get(Encrypter::class)->decrypt($cookies['token']);
223
224
        $this->assertSame(403, $this->get('/ws/')->getStatusCode());
225
        $this->assertSame(403, $this->getWithAttributes('/ws/', [
226
            'ws:joinTopics' => 'topic'
227
        ])->getStatusCode());
228
229
        $this->assertSame(200, $this->getWithAttributes('/ws/', [
230
            'ws:joinTopics' => 'topic'
231
        ], [
232
            'x-auth-token' => $token
233
        ])->getStatusCode());
234
    }
235
236
    private function init(callable $server = null, callable $topic = null, callable $topicWildcard = null): void
237
    {
238
        $this->app = $this->makeApp([
239
            'RR_BROADCAST_PATH'          => '/ws/',
240
            'WS_SERVER_CALLBACK'         => $server,
241
            'WS_TOPIC_CALLBACK'          => $topic,
242
            'WS_TOPIC_WILDCARD_CALLBACK' => $topicWildcard,
243
        ]);
244
245
        $this->http = $this->app->get(Http::class);
246
    }
247
}
248