‪TYPO3CMS  ‪main
UserSessionManagerTest.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
19 
20 use PHPUnit\Framework\Attributes\DataProvider;
21 use PHPUnit\Framework\Attributes\Test;
22 use Psr\Http\Message\ServerRequestInterface;
23 use Psr\Log\NullLogger;
31 use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
32 
33 final class ‪UserSessionManagerTest extends UnitTestCase
34 {
35  use ‪JwtTrait;
36 
37  public static function ‪willExpireDataProvider(): array
38  {
39  return [
40  [
41  'sessionLifetime' => 120,
42  'gracePeriod' => 120,
43  'expectedResult' => true,
44  ],
45  [
46  'sessionLifetime' => 120,
47  'gracePeriod' => 60,
48  'expectedResult' => false,
49  ],
50  [
51  'sessionLifetime' => 120,
52  'gracePeriod' => 240,
53  'expectedResult' => true,
54  ],
55  ];
56  }
57 
58  #[DataProvider('willExpireDataProvider')]
59  #[Test]
60  public function ‪willExpireWillExpire(int $sessionLifetime, int $gracePeriod, bool $expectedResult): void
61  {
62  $sessionBackendMock = $this->createMock(SessionBackendInterface::class);
63  $subject = new ‪UserSessionManager(
64  $sessionBackendMock,
65  $sessionLifetime,
66  new ‪IpLocker(0, 0),
67  'FE'
68  );
69  $session = $subject->createAnonymousSession();
70  self::assertEquals($expectedResult, $subject->willExpire($session, $gracePeriod));
71  }
72 
73  public function ‪hasExpiredIsCalculatedCorrectly(): void
74  {
75  ‪$GLOBALS['EXEC_TIME'] = time();
76  $sessionBackendMock = $this->createMock(SessionBackendInterface::class);
77  $subject = new ‪UserSessionManager(
78  $sessionBackendMock,
79  60,
80  new ‪IpLocker(0, 0),
81  'FE'
82  );
83  $expiredSession = ‪UserSession::createFromRecord('random-string', ['ses_tstamp' => time() - 500]);
84  self::assertTrue($subject->hasExpired($expiredSession));
85  $newSession = ‪UserSession::createFromRecord('random-string', ['ses_tstamp' => time()]);
86  self::assertFalse($subject->hasExpired($newSession));
87  }
88 
89  #[Test]
91  {
92  ‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'] = 'secret-encryption-key-test';
93  $sessionBackendMock = $this->createMock(SessionBackendInterface::class);
94  $sessionBackendMock->method('get')->with('valid-session')->willReturn([
95  'ses_id' => 'valid-session',
96  'ses_userid' => 13,
97  'ses_data' => serialize(['propertyA' => 42, 'propertyB' => 'great']),
98  'ses_tstamp' => time(),
99  'ses_iplock' => '[DISABLED]',
100  ]);
101  $subject = new ‪UserSessionManager(
102  $sessionBackendMock,
103  50,
104  new ‪IpLocker(0, 0),
105  'FE'
106  );
107  $subject->setLogger(new NullLogger());
108  $cookieDomain = 'example.org';
109  $validSessionJwt = ‪self::encodeHashSignedJwt(
110  [
111  'identifier' => 'valid-session',
112  'time' => (new \DateTimeImmutable())->format(\DateTimeImmutable::RFC3339),
113  'scope' => [
114  'domain' => $cookieDomain,
115  'path' => '/',
116  ],
117  ],
118  self::createSigningKeyFromEncryptionKey(UserSession::class)
119  );
120 
121  $normalizedParams = $this->createMock(NormalizedParams::class);
122  $normalizedParams->method('getRequestHostOnly')->willReturn($cookieDomain);
123  $normalizedParams->method('getSitePath')->willReturn('/');
124  $request = $this->createMock(ServerRequestInterface::class);
125  $request->method('getAttribute')->willReturnCallback(static fn(string $name): mixed => match ($name) {
126  'normalizedParams' => $normalizedParams,
127  default => null,
128  });
129  $request->method('getCookieParams')->willReturn(['bar' => $validSessionJwt]);
130  $persistedSession = $subject->createFromRequestOrAnonymous($request, 'bar');
131  self::assertEquals(13, $persistedSession->getUserId());
132  self::assertFalse($persistedSession->isAnonymous());
133  self::assertFalse($persistedSession->isNew());
134  self::assertEquals(42, $persistedSession->get('propertyA'));
135  self::assertEquals('great', $persistedSession->get('propertyB'));
136  self::assertNull($persistedSession->get('propertyC'));
137  }
138 
139  #[Test]
141  {
142  ‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'] = 'secret-encryption-key-test';
143  $sessionBackendMock = $this->createMock(SessionBackendInterface::class);
144  $sessionBackendMock->method('get')->with('invalid-session')->willThrowException(
145  new ‪SessionNotFoundException('Session not found', 1669358326)
146  );
147  $subject = new ‪UserSessionManager(
148  $sessionBackendMock,
149  50,
150  new ‪IpLocker(0, 0),
151  'FE'
152  );
153  $subject->setLogger(new NullLogger());
154 
155  $cookieDomain = 'example.org';
156  $normalizedParams = $this->createMock(NormalizedParams::class);
157  $normalizedParams->method('getRequestHostOnly')->willReturn($cookieDomain);
158  $request = $this->createMock(ServerRequestInterface::class);
159  $request->method('getAttribute')->willReturnCallback(static fn(string $name): mixed => match ($name) {
160  'normalizedParams' => $normalizedParams,
161  default => null,
162  });
163  $request->method('getCookieParams')->willReturnOnConsecutiveCalls([], ['foo' => 'invalid-session']);
164  $anonymousSession = $subject->createFromRequestOrAnonymous($request, 'foo');
165  self::assertTrue($anonymousSession->isNew());
166  self::assertTrue($anonymousSession->isAnonymous());
167 
168  $anonymousSessionFromInvalidBackendRequest = $subject->createFromRequestOrAnonymous($request, 'foo');
169  self::assertTrue($anonymousSessionFromInvalidBackendRequest->isNew());
170  self::assertTrue($anonymousSessionFromInvalidBackendRequest->isAnonymous());
171  }
172 
173  #[Test]
174  public function ‪updateSessionWillSetLastUpdated(): void
175  {
176  $sessionBackendMock = $this->createMock(SessionBackendInterface::class);
177  $sessionBackendMock->method('update')->with(self::anything(), self::anything())->willReturn([
178  'ses_id' => 'valid-session',
179  'ses_userid' => 13,
180  'ses_data' => serialize(['propertyA' => 42, 'propertyB' => 'great']),
181  'ses_tstamp' => 7654321,
182  'ses_iplock' => '[DISABLED]',
183  ]);
184  $subject = new ‪UserSessionManager(
185  $sessionBackendMock,
186  60,
187  new ‪IpLocker(0, 0),
188  'FE'
189  );
190  $session = ‪UserSession::createFromRecord('random-string', ['ses_tstamp' => time() - 500]);
191  $session = $subject->updateSession($session);
192  self::assertSame(7654321, $session->getLastUpdated());
193  }
194 
195  #[Test]
197  {
198  $sessionBackendMock = $this->createMock(SessionBackendInterface::class);
199  $sessionBackendMock->method('set')->with(self::anything(), self::anything())->willReturn([
200  'ses_id' => 'valid-session',
201  'ses_userid' => 0,
202  'ses_data' => serialize(['propertyA' => 42, 'propertyB' => 'great']),
203  'ses_tstamp' => 7654321,
204  'ses_iplock' => ‪IpLocker::DISABLED_LOCK_VALUE,
205  ]);
206  $subject = new ‪UserSessionManager(
207  $sessionBackendMock,
208  60,
209  new ‪IpLocker(0, 0),
210  'FE'
211  );
212  $session = ‪UserSession::createFromRecord('random-string', ['ses_tstamp' => time() - 500]);
213  $session = $subject->fixateAnonymousSession($session);
214  self::assertSame(‪IpLocker::DISABLED_LOCK_VALUE, $session->getIpLock());
215  self::assertNull($session->getUserId());
216  self::assertSame(7654321, $session->getLastUpdated());
217  }
218 }
‪TYPO3\CMS\Core\Tests\Unit\Session\UserSessionManagerTest
Definition: UserSessionManagerTest.php:34
‪TYPO3\CMS\Core\Tests\Unit\Session
‪TYPO3\CMS\Core\Security\JwtTrait
Definition: JwtTrait.php:32
‪TYPO3\CMS\Core\Session\UserSession
Definition: UserSession.php:45
‪TYPO3\CMS\Core\Tests\Unit\Session\UserSessionManagerTest\willExpireDataProvider
‪static willExpireDataProvider()
Definition: UserSessionManagerTest.php:36
‪TYPO3\CMS\Core\Session\UserSession\createFromRecord
‪static createFromRecord(string $id, array $record, bool $markAsNew=false)
Definition: UserSession.php:223
‪TYPO3\CMS\Core\Tests\Unit\Session\UserSessionManagerTest\createFromRequestOrAnonymousCreatesProperSessionObjectForInvalidSession
‪createFromRequestOrAnonymousCreatesProperSessionObjectForInvalidSession()
Definition: UserSessionManagerTest.php:139
‪TYPO3\CMS\Core\Session\Backend\SessionBackendInterface
Definition: SessionBackendInterface.php:28
‪TYPO3\CMS\Core\Security\JwtTrait\encodeHashSignedJwt
‪static encodeHashSignedJwt(array $payload, Key $key, SecretIdentifier $identifier=null)
Definition: JwtTrait.php:57
‪TYPO3\CMS\Core\Tests\Unit\Session\UserSessionManagerTest\willExpireWillExpire
‪willExpireWillExpire(int $sessionLifetime, int $gracePeriod, bool $expectedResult)
Definition: UserSessionManagerTest.php:59
‪TYPO3\CMS\Core\Tests\Unit\Session\UserSessionManagerTest\fixateAnonymousSessionWillUpdateSessionObject
‪fixateAnonymousSessionWillUpdateSessionObject()
Definition: UserSessionManagerTest.php:195
‪TYPO3\CMS\Core\Tests\Unit\Session\UserSessionManagerTest\updateSessionWillSetLastUpdated
‪updateSessionWillSetLastUpdated()
Definition: UserSessionManagerTest.php:173
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Core\Tests\Unit\Session\UserSessionManagerTest\createFromRequestOrAnonymousCreatesProperSessionObjectForValidSessionJwt
‪createFromRequestOrAnonymousCreatesProperSessionObjectForValidSessionJwt()
Definition: UserSessionManagerTest.php:89
‪TYPO3\CMS\Core\Authentication\IpLocker
Definition: IpLocker.php:26
‪TYPO3\CMS\Core\Authentication\IpLocker\DISABLED_LOCK_VALUE
‪const DISABLED_LOCK_VALUE
Definition: IpLocker.php:27
‪TYPO3\CMS\Core\Session\Backend\Exception\SessionNotFoundException
Definition: SessionNotFoundException.php:23
‪TYPO3\CMS\Core\Session\UserSessionManager
Definition: UserSessionManager.php:46
‪TYPO3\CMS\Core\Http\NormalizedParams
Definition: NormalizedParams.php:38
‪TYPO3\CMS\Core\Tests\Unit\Session\UserSessionManagerTest\hasExpiredIsCalculatedCorrectly
‪hasExpiredIsCalculatedCorrectly()
Definition: UserSessionManagerTest.php:72