Skip to content

Commit 94018dd

Browse files
committed
Symfony 6 compat
1 parent 672a2ca commit 94018dd

File tree

12 files changed

+237
-299
lines changed

12 files changed

+237
-299
lines changed

.github/workflows/run-tests.yml

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,29 +9,24 @@ jobs:
99
strategy:
1010
fail-fast: true
1111
matrix:
12-
php: ['7.4']
13-
symfony: ['4.4.*', '5.3.*', '5.4.*']
12+
php: ['7.4', '8.0', '8.1']
13+
symfony: ['4.4.*', '5.4.*', '6.0.*']
1414
composer-flags: ['--prefer-stable']
1515
can-fail: [false]
16-
extensions: ['amqp, curl, iconv, mbstring, pdo, pdo_sqlite, sqlite, zip']
16+
has-amqp: [false]
17+
extensions: ['curl, iconv, mbstring, pdo, pdo_sqlite, sqlite, zip']
1718
include:
1819
- php: '7.4'
1920
symfony: '4.4.*'
2021
composer-flags: '--prefer-stable --prefer-lowest'
2122
can-fail: false
23+
has-amqp: true
2224
extensions: 'amqp, curl, iconv, mbstring, pdo, pdo_sqlite, sqlite, zip'
23-
- php: '8.0'
24-
symfony: '5.4.*'
25-
composer-flags: '--prefer-stable'
26-
can-fail: false
27-
extensions: 'curl, iconv, mbstring, pdo, pdo_sqlite, sqlite, zip'
28-
- php: '8.1'
29-
symfony: '5.4.*'
30-
composer-flags: '--prefer-stable'
31-
can-fail: false
32-
extensions: 'curl, iconv, mbstring, pdo, pdo_sqlite, sqlite, zip'
25+
exclude:
26+
- php: '7.4'
27+
symfony: '6.0.*'
3328

34-
name: "PHP ${{ matrix.php }} - Symfony ${{ matrix.symfony }}${{ matrix.composer-flags != '' && format(' - Composer {0}', matrix.composer-flags) || '' }}"
29+
name: "PHP ${{ matrix.php }}${{ matrix.has-amqp == true && ' (with AMQP)' || '' }} - Symfony ${{ matrix.symfony }}${{ matrix.composer-flags != '' && format(' - Composer {0}', matrix.composer-flags) || '' }}"
3530

3631
steps:
3732
- name: Checkout code
@@ -52,7 +47,7 @@ jobs:
5247
coverage: none
5348

5449
- name: Install ReactAMQP package
55-
if: matrix.php == '7.4'
50+
if: matrix.has-amqp == true
5651
run: |
5752
composer require --dev --no-update gos/react-amqp:^0.3
5853

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# Changelog
22

3+
## 3.14.0 (????-??-??)
4+
5+
- Add support for Symfony 6.0
6+
- Drop support for Symfony 5.3
7+
38
## 3.13.0 (2021-11-30)
49

510
- Deprecated the unused `$router` argument of the `Gos\Bundle\WebSocketBundle\Server\App\Dispatcher\TopicDispatcher` constructor

composer.json

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -17,24 +17,24 @@
1717
],
1818
"require": {
1919
"php": "^7.4 || ^8.0",
20-
"cboden/ratchet": "^0.4.2",
20+
"cboden/ratchet": "^0.4.4",
2121
"gos/pubsub-router-bundle": "^2.2",
2222
"gos/websocket-client": "^1.1",
2323
"psr/log": "^1.1 || ^2.0 || ^3.0",
2424
"react/event-loop": "^1.2",
2525
"react/socket": "^1.9",
26-
"symfony/config": "^4.4 || ^5.3",
27-
"symfony/console": "^4.4 || ^5.3",
28-
"symfony/dependency-injection": "^4.4 || ^5.3",
26+
"symfony/config": "^4.4 || ^5.4 || ^6.0",
27+
"symfony/console": "^4.4 || ^5.4 || ^6.0",
28+
"symfony/dependency-injection": "^4.4 || ^5.4 || ^6.0",
2929
"symfony/deprecation-contracts": "^2.1 || ^3.0",
30-
"symfony/event-dispatcher": "^4.4 || ^5.3",
31-
"symfony/http-foundation": "^4.4 || ^5.3",
32-
"symfony/http-kernel": "^4.4 || ^5.3",
30+
"symfony/event-dispatcher": "^4.4 || ^5.4 || ^6.0",
31+
"symfony/http-foundation": "^4.4 || ^5.4 || ^6.0",
32+
"symfony/http-kernel": "^4.4 || ^5.4 || ^6.0",
3333
"symfony/polyfill-php80": "^1.15",
34-
"symfony/security-core": "^4.4 || ^5.3",
35-
"symfony/serializer": "^4.4 || ^5.3",
36-
"symfony/string": "^5.3",
37-
"symfony/yaml": "^4.4 || ^5.3"
34+
"symfony/security-core": "^4.4 || ^5.4 || ^6.0",
35+
"symfony/serializer": "^4.4 || ^5.4 || ^6.0",
36+
"symfony/string": "^5.4 || ^6.0",
37+
"symfony/yaml": "^4.4 || ^5.4 || ^6.0"
3838
},
3939
"require-dev": {
4040
"doctrine/cache": "^1.11 || ^2.0",
@@ -45,23 +45,23 @@
4545
"phpstan/phpstan-phpunit": "1.0.0",
4646
"phpstan/phpstan-symfony": "1.0.1",
4747
"phpunit/phpunit": "^9.5",
48-
"symfony/cache": "^4.4 || ^5.3",
49-
"symfony/options-resolver": "^4.4 || ^5.3",
50-
"symfony/phpunit-bridge": "^5.3",
51-
"symfony/stopwatch": "^4.4 || ^5.3",
52-
"symfony/twig-bundle": "^4.4 || ^5.3",
53-
"symfony/web-profiler-bundle": "^4.4 || ^5.3"
48+
"symfony/cache": "^4.4 || ^5.4 || ^6.0",
49+
"symfony/options-resolver": "^4.4 || ^5.4 || ^6.0",
50+
"symfony/phpunit-bridge": "^5.4 || ^6.0",
51+
"symfony/stopwatch": "^4.4 || ^5.4 || ^6.0",
52+
"symfony/twig-bundle": "^4.4 || ^5.4 || ^6.0",
53+
"symfony/web-profiler-bundle": "^4.4 || ^5.4 || ^6.0"
5454
},
5555
"conflict": {
5656
"doctrine/cache": "<1.11",
5757
"doctrine/dbal": "<2.13.1 || ~3.0.0",
5858
"gos/react-amqp": "<0.3",
59-
"symfony/cache": "<4.4 || >=5.0,<5.2",
59+
"symfony/cache": "<4.4 || >=5.0,<5.3",
6060
"symfony/monolog-bundle": "<3.0",
61-
"symfony/options-resolver": "<4.4 || >=5.0,<5.2",
62-
"symfony/stopwatch": "<4.4 || >=5.0,<5.2",
63-
"symfony/twig-bundle": "<4.4 || >=5.0,<5.2",
64-
"symfony/web-profiler-bundle": "<4.4 || >=5.0,<5.2",
61+
"symfony/options-resolver": "<4.4 || >=5.0,<5.3",
62+
"symfony/stopwatch": "<4.4 || >=5.0,<5.3",
63+
"symfony/twig-bundle": "<4.4 || >=5.0,<5.3",
64+
"symfony/web-profiler-bundle": "<4.4 || >=5.0,<5.3",
6565
"twig/twig": "<1.36 || >=2.0,<2.6"
6666
},
6767
"autoload": {

src/Authentication/ConnectionRepository.php

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
use Gos\Bundle\WebSocketBundle\Authentication\Storage\TokenStorageInterface;
77
use Ratchet\ConnectionInterface;
88
use Ratchet\Wamp\Topic;
9-
use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken;
109
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
1110
use Symfony\Component\Security\Core\User\UserInterface;
1211

@@ -34,7 +33,7 @@ public function findAll(Topic $topic, bool $anonymous = false): array
3433
foreach ($topic as $connection) {
3534
$client = $this->findTokenForConnection($connection);
3635

37-
if (true !== $anonymous && $client instanceof AnonymousToken) {
36+
if (!$anonymous && !($client->getUser() instanceof UserInterface)) {
3837
continue;
3938
}
4039

@@ -55,10 +54,6 @@ public function findAllByUsername(Topic $topic, string $username): array
5554
foreach ($topic as $connection) {
5655
$client = $this->findTokenForConnection($connection);
5756

58-
if ($client instanceof AnonymousToken) {
59-
continue;
60-
}
61-
6257
$clientUsername = method_exists($client, 'getUserIdentifier') ? $client->getUserIdentifier() : $client->getUsername();
6358

6459
if ($clientUsername === $username) {
@@ -80,11 +75,21 @@ public function findAllWithRoles(Topic $topic, array $roles): array
8075
foreach ($topic as $connection) {
8176
$client = $this->findTokenForConnection($connection);
8277

83-
foreach ($client->getRoleNames() as $role) {
84-
if (\in_array($role, $roles, true)) {
85-
$result[] = new TokenConnection($client, $connection);
78+
if (method_exists($client, 'getRoleNames')) {
79+
foreach ($client->getRoleNames() as $role) {
80+
if (\in_array($role, $roles)) {
81+
$result[] = new TokenConnection($client, $connection);
82+
83+
continue 2;
84+
}
85+
}
86+
} else {
87+
foreach ($client->getRoles() as $role) {
88+
if (\in_array($role->getRole(), $roles)) {
89+
$result[] = new TokenConnection($client, $connection);
8690

87-
continue 2;
91+
continue 2;
92+
}
8893
}
8994
}
9095
}
@@ -107,10 +112,18 @@ public function findTokenForConnection(ConnectionInterface $connection): TokenIn
107112
}
108113

109114
/**
110-
* @return string|\Stringable|UserInterface
115+
* @return string|\Stringable|UserInterface|null
116+
*
117+
* @note As of 4.0, the return type will change to `UserInterface|null`.
111118
*/
112119
public function getUser(ConnectionInterface $connection)
113120
{
114-
return $this->findTokenForConnection($connection)->getUser();
121+
$user = $this->findTokenForConnection($connection)->getUser();
122+
123+
if (null !== $user && !($user instanceof UserInterface)) {
124+
trigger_deprecation('gos/web-socket-bundle', '3.14', 'Retrieving a user that is not an instance of %s is deprecated in %s().', UserInterface::class, __METHOD__);
125+
}
126+
127+
return $user;
115128
}
116129
}

src/Client/Auth/WebsocketAuthenticationProvider.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use Psr\Log\LoggerAwareTrait;
88
use Ratchet\ConnectionInterface;
99
use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken;
10+
use Symfony\Component\Security\Core\Authentication\Token\NullToken;
1011
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
1112

1213
trigger_deprecation('gos/web-socket-bundle', '3.11', 'The "%s" class is deprecated and will be removed in 4.0, use the new websocket authentication API instead.', WebsocketAuthenticationProvider::class);
@@ -86,7 +87,11 @@ private function getToken(ConnectionInterface $connection): TokenInterface
8687
}
8788

8889
if (null === $token) {
89-
$token = new AnonymousToken($this->firewalls[0], 'anon-'.$connection->WAMP->sessionId);
90+
if (class_exists(NullToken::class)) {
91+
$token = new NullToken();
92+
} else {
93+
$token = new AnonymousToken($this->firewalls[0], 'anon-'.$connection->WAMP->sessionId);
94+
}
9095
}
9196

9297
return $token;

src/Client/ClientManipulator.php

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
use Gos\Bundle\WebSocketBundle\Client\Exception\ClientNotFoundException;
77
use Ratchet\ConnectionInterface;
88
use Ratchet\Wamp\Topic;
9-
use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken;
109
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
1110
use Symfony\Component\Security\Core\User\UserInterface;
1211

@@ -39,10 +38,6 @@ public function findAllByUsername(Topic $topic, string $username): array
3938
foreach ($topic as $connection) {
4039
$client = $this->getClient($connection);
4140

42-
if ($client instanceof AnonymousToken) {
43-
continue;
44-
}
45-
4641
$clientUsername = method_exists($client, 'getUserIdentifier') ? $client->getUserIdentifier() : $client->getUsername();
4742

4843
if ($clientUsername === $username) {
@@ -64,15 +59,21 @@ public function findByRoles(Topic $topic, array $roles): array
6459
foreach ($topic as $connection) {
6560
$client = $this->getClient($connection);
6661

67-
if ($client instanceof AnonymousToken) {
68-
continue;
69-
}
62+
if (method_exists($client, 'getRoleNames')) {
63+
foreach ($client->getRoleNames() as $role) {
64+
if (\in_array($role, $roles)) {
65+
$result[] = new ClientConnection($client, $connection);
7066

71-
foreach ($client->getRoleNames() as $role) {
72-
if (\in_array($role, $roles)) {
73-
$result[] = new ClientConnection($client, $connection);
67+
continue 2;
68+
}
69+
}
70+
} else {
71+
foreach ($client->getRoles() as $role) {
72+
if (\in_array($role->getRole(), $roles)) {
73+
$result[] = new ClientConnection($client, $connection);
7474

75-
continue 2;
75+
continue 2;
76+
}
7677
}
7778
}
7879
}
@@ -91,7 +92,7 @@ public function getAll(Topic $topic, bool $anonymous = false): array
9192
foreach ($topic as $connection) {
9293
$client = $this->getClient($connection);
9394

94-
if (true !== $anonymous && $client instanceof AnonymousToken) {
95+
if (!$anonymous && !($client->getUser() instanceof UserInterface)) {
9596
continue;
9697
}
9798

tests/Authentication/ConnectionRepositoryTest.php

Lines changed: 47 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@
1212
use Ratchet\ConnectionInterface;
1313
use Ratchet\Wamp\Topic;
1414
use Symfony\Component\Security\Core\Authentication\Token\AbstractToken;
15-
use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken;
16-
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
15+
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
16+
use Symfony\Component\Security\Core\Role\Role;
17+
use Symfony\Component\Security\Core\User\UserInterface;
1718

1819
final class ConnectionRepositoryTest extends TestCase
1920
{
@@ -185,11 +186,17 @@ public function testFetchingAllConnectionsByDefaultOnlyReturnsAuthenticatedUsers
185186
$storageId1 = 42;
186187
$storageId2 = 84;
187188

188-
/** @var MockObject&AbstractToken $authenticatedToken */
189-
$authenticatedToken = $this->createMock(AbstractToken::class);
189+
/** @var MockObject&TokenInterface $authenticatedToken */
190+
$authenticatedToken = $this->createMock(TokenInterface::class);
191+
$authenticatedToken->expects(self::once())
192+
->method('getUser')
193+
->willReturn($this->createMock(UserInterface::class));
190194

191-
/** @var MockObject&AnonymousToken $guestToken */
192-
$guestToken = $this->createMock(AnonymousToken::class);
195+
/** @var MockObject&TokenInterface $guestToken */
196+
$guestToken = $this->createMock(TokenInterface::class);
197+
$guestToken->expects(self::once())
198+
->method('getUser')
199+
->willReturn(null);
193200

194201
$this->tokenStorage->expects(self::exactly(2))
195202
->method('generateStorageId')
@@ -240,8 +247,8 @@ public function testFetchingAllConnectionsWithAnonymousFlagReturnsAllConnectedUs
240247
/** @var MockObject&AbstractToken $authenticatedToken */
241248
$authenticatedToken = $this->createMock(AbstractToken::class);
242249

243-
/** @var MockObject&AnonymousToken $guestToken */
244-
$guestToken = $this->createMock(AnonymousToken::class);
250+
/** @var MockObject&TokenInterface $guestToken */
251+
$guestToken = $this->createMock(TokenInterface::class);
245252

246253
$this->tokenStorage->expects(self::exactly(2))
247254
->method('generateStorageId')
@@ -295,20 +302,40 @@ public function testFetchingAllUsersWithDefinedRolesOnlyReturnsMatchingUsers():
295302
$storageId2 = 84;
296303
$storageId3 = 126;
297304

298-
/** @var MockObject&UsernamePasswordToken $authenticatedToken1 */
299-
$authenticatedToken1 = $this->createMock(UsernamePasswordToken::class);
300-
$authenticatedToken1->expects(self::once())
301-
->method('getRoleNames')
302-
->willReturn(['ROLE_USER', 'ROLE_STAFF']);
305+
/** @var MockObject&TokenInterface $authenticatedToken1 */
306+
$authenticatedToken1 = $this->createMock(TokenInterface::class);
307+
308+
/** @var MockObject&TokenInterface $authenticatedToken2 */
309+
$authenticatedToken2 = $this->createMock(TokenInterface::class);
310+
311+
/** @var MockObject&TokenInterface $guestToken */
312+
$guestToken = $this->createMock(TokenInterface::class);
313+
314+
if (method_exists(TokenInterface::class, 'getRoleNames')) {
315+
$authenticatedToken1->expects(self::once())
316+
->method('getRoleNames')
317+
->willReturn(['ROLE_USER', 'ROLE_STAFF']);
318+
319+
$authenticatedToken2->expects(self::once())
320+
->method('getRoleNames')
321+
->willReturn(['ROLE_USER']);
322+
323+
$guestToken->expects(self::once())
324+
->method('getRoleNames')
325+
->willReturn([]);
326+
} else {
327+
$authenticatedToken1->expects(self::once())
328+
->method('getRoles')
329+
->willReturn([new Role('ROLE_USER'), new Role('ROLE_STAFF')]);
303330

304-
/** @var MockObject&UsernamePasswordToken $authenticatedToken2 */
305-
$authenticatedToken2 = $this->createMock(UsernamePasswordToken::class);
306-
$authenticatedToken2->expects(self::once())
307-
->method('getRoleNames')
308-
->willReturn(['ROLE_USER']);
331+
$authenticatedToken2->expects(self::once())
332+
->method('getRoles')
333+
->willReturn([new Role('ROLE_USER')]);
309334

310-
/** @var MockObject&AnonymousToken $guestToken */
311-
$guestToken = $this->createMock(AnonymousToken::class);
335+
$guestToken->expects(self::once())
336+
->method('getRoles')
337+
->willReturn([]);
338+
}
312339

313340
$this->tokenStorage->expects(self::exactly(3))
314341
->method('generateStorageId')

0 commit comments

Comments
 (0)