aboutsummaryrefslogtreecommitdiffstats
path: root/tests/lib/Security
diff options
context:
space:
mode:
Diffstat (limited to 'tests/lib/Security')
-rw-r--r--tests/lib/Security/Bruteforce/Backend/MemoryCacheBackendTest.php8
-rw-r--r--tests/lib/Security/Bruteforce/ThrottlerTest.php212
-rw-r--r--tests/lib/Security/CSP/AddContentSecurityPolicyEventTest.php2
-rw-r--r--tests/lib/Security/CSP/ContentSecurityPolicyManagerTest.php31
-rw-r--r--tests/lib/Security/CSP/ContentSecurityPolicyNonceManagerTest.php27
-rw-r--r--tests/lib/Security/CSRF/CsrfTokenGeneratorTest.php11
-rw-r--r--tests/lib/Security/CSRF/CsrfTokenManagerTest.php47
-rw-r--r--tests/lib/Security/CSRF/CsrfTokenTest.php14
-rw-r--r--tests/lib/Security/CSRF/TokenStorage/SessionStorageTest.php23
-rw-r--r--tests/lib/Security/CertificateManagerTest.php63
-rw-r--r--tests/lib/Security/CertificateTest.php31
-rw-r--r--tests/lib/Security/CredentialsManagerTest.php12
-rw-r--r--tests/lib/Security/CryptoTest.php39
-rw-r--r--tests/lib/Security/Events/GenerateSecurePasswordEventTest.php33
-rw-r--r--tests/lib/Security/Events/ValidatePasswordPolicyEventTest.php28
-rw-r--r--tests/lib/Security/FeaturePolicy/AddFeaturePolicyEventTest.php2
-rw-r--r--tests/lib/Security/FeaturePolicy/FeaturePolicyManagerTest.php13
-rw-r--r--tests/lib/Security/HasherTest.php70
-rw-r--r--tests/lib/Security/IdentityProof/KeyTest.php4
-rw-r--r--tests/lib/Security/IdentityProof/ManagerTest.php99
-rw-r--r--tests/lib/Security/IdentityProof/SignerTest.php8
-rw-r--r--tests/lib/Security/Ip/BruteforceAllowListTest.php161
-rw-r--r--tests/lib/Security/Ip/RemoteAddressTest.php79
-rw-r--r--tests/lib/Security/Normalizer/IpAddressTest.php18
-rw-r--r--tests/lib/Security/RateLimiting/Backend/MemoryCacheBackendTest.php8
-rw-r--r--tests/lib/Security/RateLimiting/LimiterTest.php36
-rw-r--r--tests/lib/Security/RemoteHostValidatorIntegrationTest.php16
-rw-r--r--tests/lib/Security/RemoteHostValidatorTest.php6
-rw-r--r--tests/lib/Security/SecureRandomTest.php40
-rw-r--r--tests/lib/Security/TrustedDomainHelperTest.php12
-rw-r--r--tests/lib/Security/VerificationToken/VerificationTokenTest.php20
31 files changed, 664 insertions, 509 deletions
diff --git a/tests/lib/Security/Bruteforce/Backend/MemoryCacheBackendTest.php b/tests/lib/Security/Bruteforce/Backend/MemoryCacheBackendTest.php
index 82bffb74e01..e0289fa7ca9 100644
--- a/tests/lib/Security/Bruteforce/Backend/MemoryCacheBackendTest.php
+++ b/tests/lib/Security/Bruteforce/Backend/MemoryCacheBackendTest.php
@@ -36,7 +36,7 @@ class MemoryCacheBackendTest extends TestCase {
$this->cacheFactory
->expects($this->once())
->method('createDistributed')
- ->with('OC\Security\Bruteforce\Backend\MemoryCacheBackend')
+ ->with(MemoryCacheBackend::class)
->willReturn($this->cache);
$this->backend = new MemoryCacheBackend(
@@ -55,7 +55,7 @@ class MemoryCacheBackendTest extends TestCase {
$this->assertSame(0, $this->backend->getAttempts('10.10.10.10/32', 0));
}
- public function dataGetAttempts(): array {
+ public static function dataGetAttempts(): array {
return [
[0, null, null, 4],
[100, null, null, 2],
@@ -67,9 +67,7 @@ class MemoryCacheBackendTest extends TestCase {
];
}
- /**
- * @dataProvider dataGetAttempts
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataGetAttempts')]
public function testGetAttempts(int $maxAge, ?string $action, ?array $metadata, int $expected): void {
$this->cache
->expects($this->once())
diff --git a/tests/lib/Security/Bruteforce/ThrottlerTest.php b/tests/lib/Security/Bruteforce/ThrottlerTest.php
deleted file mode 100644
index 69d20cccd3a..00000000000
--- a/tests/lib/Security/Bruteforce/ThrottlerTest.php
+++ /dev/null
@@ -1,212 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-/**
- * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
- * SPDX-License-Identifier: AGPL-3.0-or-later
- */
-
-namespace Test\Security\Bruteforce;
-
-use OC\Security\Bruteforce\Backend\DatabaseBackend;
-use OC\Security\Bruteforce\Throttler;
-use OCP\AppFramework\Utility\ITimeFactory;
-use OCP\IConfig;
-use OCP\IDBConnection;
-use Psr\Log\LoggerInterface;
-use Test\TestCase;
-
-/**
- * Based on the unit tests from Paragonie's Airship CMS
- * Ref: https://github.com/paragonie/airship/blob/7e5bad7e3c0fbbf324c11f963fd1f80e59762606/test/unit/Engine/Security/AirBrakeTest.php
- *
- * @package Test\Security\Bruteforce
- */
-class ThrottlerTest extends TestCase {
- /** @var Throttler */
- private $throttler;
- /** @var IDBConnection */
- private $dbConnection;
- /** @var ITimeFactory */
- private $timeFactory;
- /** @var LoggerInterface */
- private $logger;
- /** @var IConfig|\PHPUnit\Framework\MockObject\MockObject */
- private $config;
-
- protected function setUp(): void {
- $this->dbConnection = $this->createMock(IDBConnection::class);
- $this->timeFactory = $this->createMock(ITimeFactory::class);
- $this->logger = $this->createMock(LoggerInterface::class);
- $this->config = $this->createMock(IConfig::class);
-
- $this->throttler = new Throttler(
- $this->timeFactory,
- $this->logger,
- $this->config,
- new DatabaseBackend($this->dbConnection)
- );
- parent::setUp();
- }
-
- public function dataIsIPWhitelisted() {
- return [
- [
- '10.10.10.10',
- [
- 'whitelist_0' => '10.10.10.0/24',
- ],
- true,
- ],
- [
- '10.10.10.10',
- [
- 'whitelist_0' => '192.168.0.0/16',
- ],
- false,
- ],
- [
- '10.10.10.10',
- [
- 'whitelist_0' => '192.168.0.0/16',
- 'whitelist_1' => '10.10.10.0/24',
- ],
- true,
- ],
- [
- '10.10.10.10',
- [
- 'whitelist_0' => '10.10.10.11/31',
- ],
- true,
- ],
- [
- '10.10.10.10',
- [
- 'whitelist_0' => '10.10.10.9/31',
- ],
- false,
- ],
- [
- '10.10.10.10',
- [
- 'whitelist_0' => '10.10.10.15/29',
- ],
- true,
- ],
- [
- 'dead:beef:cafe::1',
- [
- 'whitelist_0' => '192.168.0.0/16',
- 'whitelist_1' => '10.10.10.0/24',
- 'whitelist_2' => 'deaf:beef:cafe:1234::/64'
- ],
- false,
- ],
- [
- 'dead:beef:cafe::1',
- [
- 'whitelist_0' => '192.168.0.0/16',
- 'whitelist_1' => '10.10.10.0/24',
- 'whitelist_2' => 'deaf:beef::/64'
- ],
- false,
- ],
- [
- 'dead:beef:cafe::1',
- [
- 'whitelist_0' => '192.168.0.0/16',
- 'whitelist_1' => '10.10.10.0/24',
- 'whitelist_2' => 'deaf:cafe::/8'
- ],
- true,
- ],
- [
- 'dead:beef:cafe::1111',
- [
- 'whitelist_0' => 'dead:beef:cafe::1100/123',
-
- ],
- true,
- ],
- [
- 'invalid',
- [],
- false,
- ],
- ];
- }
-
- /**
- * @param string $ip
- * @param string[] $whitelists
- * @param bool $isWhiteListed
- * @param bool $enabled
- */
- private function isIpWhiteListedHelper($ip,
- $whitelists,
- $isWhiteListed,
- $enabled) {
- $this->config->method('getAppKeys')
- ->with($this->equalTo('bruteForce'))
- ->willReturn(array_keys($whitelists));
- $this->config
- ->expects($this->once())
- ->method('getSystemValueBool')
- ->with('auth.bruteforce.protection.enabled', true)
- ->willReturn($enabled);
-
- $this->config->method('getAppValue')
- ->willReturnCallback(function ($app, $key, $default) use ($whitelists) {
- if ($app !== 'bruteForce') {
- return $default;
- }
- if (isset($whitelists[$key])) {
- return $whitelists[$key];
- }
- return $default;
- });
-
- $this->assertSame(
- ($enabled === false) ? true : $isWhiteListed,
- self::invokePrivate($this->throttler, 'isBypassListed', [$ip])
- );
- }
-
- /**
- * @dataProvider dataIsIPWhitelisted
- *
- * @param string $ip
- * @param string[] $whitelists
- * @param bool $isWhiteListed
- */
- public function testIsIpWhiteListedWithEnabledProtection($ip,
- $whitelists,
- $isWhiteListed) {
- $this->isIpWhiteListedHelper(
- $ip,
- $whitelists,
- $isWhiteListed,
- true
- );
- }
-
- /**
- * @dataProvider dataIsIPWhitelisted
- *
- * @param string $ip
- * @param string[] $whitelists
- * @param bool $isWhiteListed
- */
- public function testIsIpWhiteListedWithDisabledProtection($ip,
- $whitelists,
- $isWhiteListed) {
- $this->isIpWhiteListedHelper(
- $ip,
- $whitelists,
- $isWhiteListed,
- false
- );
- }
-}
diff --git a/tests/lib/Security/CSP/AddContentSecurityPolicyEventTest.php b/tests/lib/Security/CSP/AddContentSecurityPolicyEventTest.php
index edc0c613655..39dd7a95890 100644
--- a/tests/lib/Security/CSP/AddContentSecurityPolicyEventTest.php
+++ b/tests/lib/Security/CSP/AddContentSecurityPolicyEventTest.php
@@ -15,7 +15,7 @@ use OCP\Security\CSP\AddContentSecurityPolicyEvent;
use Test\TestCase;
class AddContentSecurityPolicyEventTest extends TestCase {
- public function testAddEvent() {
+ public function testAddEvent(): void {
$cspManager = $this->createMock(ContentSecurityPolicyManager::class);
$policy = $this->createMock(ContentSecurityPolicy::class);
$event = new AddContentSecurityPolicyEvent($cspManager);
diff --git a/tests/lib/Security/CSP/ContentSecurityPolicyManagerTest.php b/tests/lib/Security/CSP/ContentSecurityPolicyManagerTest.php
index dc0fe7c8340..a32a4132287 100644
--- a/tests/lib/Security/CSP/ContentSecurityPolicyManagerTest.php
+++ b/tests/lib/Security/CSP/ContentSecurityPolicyManagerTest.php
@@ -11,8 +11,11 @@ declare(strict_types=1);
namespace Test\Security\CSP;
use OC\Security\CSP\ContentSecurityPolicyManager;
+use OCP\AppFramework\Http\ContentSecurityPolicy;
+use OCP\AppFramework\Http\EmptyContentSecurityPolicy;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\Security\CSP\AddContentSecurityPolicyEvent;
+use OCP\Server;
use Test\TestCase;
class ContentSecurityPolicyManagerTest extends TestCase {
@@ -24,26 +27,26 @@ class ContentSecurityPolicyManagerTest extends TestCase {
protected function setUp(): void {
parent::setUp();
- $this->dispatcher = \OC::$server->query(IEventDispatcher::class);
+ $this->dispatcher = Server::get(IEventDispatcher::class);
$this->contentSecurityPolicyManager = new ContentSecurityPolicyManager($this->dispatcher);
}
- public function testAddDefaultPolicy() {
- $this->contentSecurityPolicyManager->addDefaultPolicy(new \OCP\AppFramework\Http\ContentSecurityPolicy());
+ public function testAddDefaultPolicy(): void {
+ $this->contentSecurityPolicyManager->addDefaultPolicy(new ContentSecurityPolicy());
$this->addToAssertionCount(1);
}
- public function testGetDefaultPolicyWithPolicies() {
- $policy = new \OCP\AppFramework\Http\ContentSecurityPolicy();
+ public function testGetDefaultPolicyWithPolicies(): void {
+ $policy = new ContentSecurityPolicy();
$policy->addAllowedFontDomain('mydomain.com');
$policy->addAllowedImageDomain('anotherdomain.de');
$this->contentSecurityPolicyManager->addDefaultPolicy($policy);
- $policy = new \OCP\AppFramework\Http\ContentSecurityPolicy();
+ $policy = new ContentSecurityPolicy();
$policy->addAllowedFontDomain('example.com');
$policy->addAllowedImageDomain('example.org');
$policy->allowEvalScript(true);
$this->contentSecurityPolicyManager->addDefaultPolicy($policy);
- $policy = new \OCP\AppFramework\Http\EmptyContentSecurityPolicy();
+ $policy = new EmptyContentSecurityPolicy();
$policy->addAllowedChildSrcDomain('childdomain');
$policy->addAllowedFontDomain('anotherFontDomain');
$policy->addAllowedFormActionDomain('thirdDomain');
@@ -64,9 +67,9 @@ class ContentSecurityPolicyManagerTest extends TestCase {
$this->assertSame($expectedStringPolicy, $this->contentSecurityPolicyManager->getDefaultPolicy()->buildPolicy());
}
- public function testGetDefaultPolicyWithPoliciesViaEvent() {
- $this->dispatcher->addListener(AddContentSecurityPolicyEvent::class, function (AddContentSecurityPolicyEvent $e) {
- $policy = new \OCP\AppFramework\Http\ContentSecurityPolicy();
+ public function testGetDefaultPolicyWithPoliciesViaEvent(): void {
+ $this->dispatcher->addListener(AddContentSecurityPolicyEvent::class, function (AddContentSecurityPolicyEvent $e): void {
+ $policy = new ContentSecurityPolicy();
$policy->addAllowedFontDomain('mydomain.com');
$policy->addAllowedImageDomain('anotherdomain.de');
$policy->useStrictDynamic(true);
@@ -75,16 +78,16 @@ class ContentSecurityPolicyManagerTest extends TestCase {
$e->addPolicy($policy);
});
- $this->dispatcher->addListener(AddContentSecurityPolicyEvent::class, function (AddContentSecurityPolicyEvent $e) {
- $policy = new \OCP\AppFramework\Http\ContentSecurityPolicy();
+ $this->dispatcher->addListener(AddContentSecurityPolicyEvent::class, function (AddContentSecurityPolicyEvent $e): void {
+ $policy = new ContentSecurityPolicy();
$policy->addAllowedFontDomain('example.com');
$policy->addAllowedImageDomain('example.org');
$policy->allowEvalScript(false);
$e->addPolicy($policy);
});
- $this->dispatcher->addListener(AddContentSecurityPolicyEvent::class, function (AddContentSecurityPolicyEvent $e) {
- $policy = new \OCP\AppFramework\Http\EmptyContentSecurityPolicy();
+ $this->dispatcher->addListener(AddContentSecurityPolicyEvent::class, function (AddContentSecurityPolicyEvent $e): void {
+ $policy = new EmptyContentSecurityPolicy();
$policy->addAllowedChildSrcDomain('childdomain');
$policy->addAllowedFontDomain('anotherFontDomain');
$policy->addAllowedFormActionDomain('thirdDomain');
diff --git a/tests/lib/Security/CSP/ContentSecurityPolicyNonceManagerTest.php b/tests/lib/Security/CSP/ContentSecurityPolicyNonceManagerTest.php
index f4281bd2b22..3765311155a 100644
--- a/tests/lib/Security/CSP/ContentSecurityPolicyNonceManagerTest.php
+++ b/tests/lib/Security/CSP/ContentSecurityPolicyNonceManagerTest.php
@@ -13,42 +13,46 @@ use OC\AppFramework\Http\Request;
use OC\Security\CSP\ContentSecurityPolicyNonceManager;
use OC\Security\CSRF\CsrfToken;
use OC\Security\CSRF\CsrfTokenManager;
+use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class ContentSecurityPolicyNonceManagerTest extends TestCase {
- /** @var CsrfTokenManager */
- private $csrfTokenManager;
- /** @var Request */
+ /** @var CsrfTokenManager&MockObject */
+ private $CSRFTokenManager;
+ /** @var Request&MockObject */
private $request;
/** @var ContentSecurityPolicyNonceManager */
private $nonceManager;
protected function setUp(): void {
- $this->csrfTokenManager = $this->createMock(CsrfTokenManager::class);
+ $this->CSRFTokenManager = $this->createMock(CsrfTokenManager::class);
$this->request = $this->createMock(Request::class);
$this->nonceManager = new ContentSecurityPolicyNonceManager(
- $this->csrfTokenManager,
+ $this->CSRFTokenManager,
$this->request
);
}
- public function testGetNonce() {
+ public function testGetNonce(): void {
+ $secret = base64_encode('secret');
+ $tokenValue = base64_encode('secret' ^ 'value_') . ':' . $secret;
$token = $this->createMock(CsrfToken::class);
$token
->expects($this->once())
->method('getEncryptedValue')
- ->willReturn('MyToken');
+ ->willReturn($tokenValue);
- $this->csrfTokenManager
+ $this->CSRFTokenManager
->expects($this->once())
->method('getToken')
->willReturn($token);
- $this->assertSame('TXlUb2tlbg==', $this->nonceManager->getNonce());
- $this->assertSame('TXlUb2tlbg==', $this->nonceManager->getNonce());
+ $this->assertSame($secret, $this->nonceManager->getNonce());
+ // call it twice but `getEncryptedValue` is expected to be called only once
+ $this->assertSame($secret, $this->nonceManager->getNonce());
}
- public function testGetNonceServerVar() {
+ public function testGetNonceServerVar(): void {
$token = 'SERVERNONCE';
$this->request
->method('__isset')
@@ -61,6 +65,7 @@ class ContentSecurityPolicyNonceManagerTest extends TestCase {
->willReturn(['CSP_NONCE' => $token]);
$this->assertSame($token, $this->nonceManager->getNonce());
+ // call it twice but `CSP_NONCE` variable is expected to be loaded only once
$this->assertSame($token, $this->nonceManager->getNonce());
}
}
diff --git a/tests/lib/Security/CSRF/CsrfTokenGeneratorTest.php b/tests/lib/Security/CSRF/CsrfTokenGeneratorTest.php
index 8b92848341c..86f458d8ea8 100644
--- a/tests/lib/Security/CSRF/CsrfTokenGeneratorTest.php
+++ b/tests/lib/Security/CSRF/CsrfTokenGeneratorTest.php
@@ -10,8 +10,11 @@ declare(strict_types=1);
namespace Test\Security\CSRF;
+use OC\Security\CSRF\CsrfTokenGenerator;
+use OCP\Security\ISecureRandom;
+
class CsrfTokenGeneratorTest extends \Test\TestCase {
- /** @var \OCP\Security\ISecureRandom */
+ /** @var ISecureRandom */
private $random;
/** @var \OC\Security\CSRF\CsrfTokenGenerator */
private $csrfTokenGenerator;
@@ -20,10 +23,10 @@ class CsrfTokenGeneratorTest extends \Test\TestCase {
parent::setUp();
$this->random = $this->getMockBuilder('\OCP\Security\ISecureRandom')
->disableOriginalConstructor()->getMock();
- $this->csrfTokenGenerator = new \OC\Security\CSRF\CsrfTokenGenerator($this->random);
+ $this->csrfTokenGenerator = new CsrfTokenGenerator($this->random);
}
- public function testGenerateTokenWithCustomNumber() {
+ public function testGenerateTokenWithCustomNumber(): void {
$this->random
->expects($this->once())
->method('generate')
@@ -32,7 +35,7 @@ class CsrfTokenGeneratorTest extends \Test\TestCase {
$this->assertSame('abc', $this->csrfTokenGenerator->generateToken(3));
}
- public function testGenerateTokenWithDefault() {
+ public function testGenerateTokenWithDefault(): void {
$this->random
->expects($this->once())
->method('generate')
diff --git a/tests/lib/Security/CSRF/CsrfTokenManagerTest.php b/tests/lib/Security/CSRF/CsrfTokenManagerTest.php
index c4fd480654d..66ee18475a4 100644
--- a/tests/lib/Security/CSRF/CsrfTokenManagerTest.php
+++ b/tests/lib/Security/CSRF/CsrfTokenManagerTest.php
@@ -10,6 +10,9 @@ declare(strict_types=1);
namespace Test\Security\CSRF;
+use OC\Security\CSRF\CsrfToken;
+use OC\Security\CSRF\CsrfTokenManager;
+
class CsrfTokenManagerTest extends \Test\TestCase {
/** @var \OC\Security\CSRF\CsrfTokenManager */
private $csrfTokenManager;
@@ -25,13 +28,13 @@ class CsrfTokenManagerTest extends \Test\TestCase {
$this->storageInterface = $this->getMockBuilder('\OC\Security\CSRF\TokenStorage\SessionStorage')
->disableOriginalConstructor()->getMock();
- $this->csrfTokenManager = new \OC\Security\CSRF\CsrfTokenManager(
+ $this->csrfTokenManager = new CsrfTokenManager(
$this->tokenGenerator,
$this->storageInterface
);
}
- public function testGetTokenWithExistingToken() {
+ public function testGetTokenWithExistingToken(): void {
$this->storageInterface
->expects($this->once())
->method('hasToken')
@@ -41,11 +44,11 @@ class CsrfTokenManagerTest extends \Test\TestCase {
->method('getToken')
->willReturn('MyExistingToken');
- $expected = new \OC\Security\CSRF\CsrfToken('MyExistingToken');
+ $expected = new CsrfToken('MyExistingToken');
$this->assertEquals($expected, $this->csrfTokenManager->getToken());
}
- public function testGetTokenWithExistingTokenKeepsOnSecondRequest() {
+ public function testGetTokenWithExistingTokenKeepsOnSecondRequest(): void {
$this->storageInterface
->expects($this->once())
->method('hasToken')
@@ -55,13 +58,13 @@ class CsrfTokenManagerTest extends \Test\TestCase {
->method('getToken')
->willReturn('MyExistingToken');
- $expected = new \OC\Security\CSRF\CsrfToken('MyExistingToken');
+ $expected = new CsrfToken('MyExistingToken');
$token = $this->csrfTokenManager->getToken();
$this->assertSame($token, $this->csrfTokenManager->getToken());
$this->assertSame($token, $this->csrfTokenManager->getToken());
}
- public function testGetTokenWithoutExistingToken() {
+ public function testGetTokenWithoutExistingToken(): void {
$this->storageInterface
->expects($this->once())
->method('hasToken')
@@ -75,11 +78,11 @@ class CsrfTokenManagerTest extends \Test\TestCase {
->method('setToken')
->with('MyNewToken');
- $expected = new \OC\Security\CSRF\CsrfToken('MyNewToken');
+ $expected = new CsrfToken('MyNewToken');
$this->assertEquals($expected, $this->csrfTokenManager->getToken());
}
- public function testRefreshToken() {
+ public function testRefreshToken(): void {
$this->tokenGenerator
->expects($this->once())
->method('generateToken')
@@ -89,11 +92,11 @@ class CsrfTokenManagerTest extends \Test\TestCase {
->method('setToken')
->with('MyNewToken');
- $expected = new \OC\Security\CSRF\CsrfToken('MyNewToken');
+ $expected = new CsrfToken('MyNewToken');
$this->assertEquals($expected, $this->csrfTokenManager->refreshToken());
}
- public function testRemoveToken() {
+ public function testRemoveToken(): void {
$this->storageInterface
->expects($this->once())
->method('removeToken');
@@ -101,22 +104,22 @@ class CsrfTokenManagerTest extends \Test\TestCase {
$this->csrfTokenManager->removeToken();
}
- public function testIsTokenValidWithoutToken() {
+ public function testIsTokenValidWithoutToken(): void {
$this->storageInterface
->expects($this->once())
->method('hasToken')
->willReturn(false);
- $token = new \OC\Security\CSRF\CsrfToken('Token');
+ $token = new CsrfToken('Token');
$this->assertSame(false, $this->csrfTokenManager->isTokenValid($token));
}
- public function testIsTokenValidWithWrongToken() {
+ public function testIsTokenValidWithWrongToken(): void {
$this->storageInterface
->expects($this->once())
->method('hasToken')
->willReturn(true);
- $token = new \OC\Security\CSRF\CsrfToken('Token');
+ $token = new CsrfToken('Token');
$this->storageInterface
->expects($this->once())
->method('getToken')
@@ -125,20 +128,20 @@ class CsrfTokenManagerTest extends \Test\TestCase {
$this->assertSame(false, $this->csrfTokenManager->isTokenValid($token));
}
- public function testIsTokenValidWithValidToken() {
+ public function testIsTokenValidWithValidToken(): void {
$a = 'abc';
$b = 'def';
$xorB64 = 'BQcF';
$tokenVal = sprintf('%s:%s', $xorB64, base64_encode($a));
$this->storageInterface
- ->expects($this->once())
- ->method('hasToken')
- ->willReturn(true);
- $token = new \OC\Security\CSRF\CsrfToken($tokenVal);
+ ->expects($this->once())
+ ->method('hasToken')
+ ->willReturn(true);
+ $token = new CsrfToken($tokenVal);
$this->storageInterface
- ->expects($this->once())
- ->method('getToken')
- ->willReturn($b);
+ ->expects($this->once())
+ ->method('getToken')
+ ->willReturn($b);
$this->assertSame(true, $this->csrfTokenManager->isTokenValid($token));
}
diff --git a/tests/lib/Security/CSRF/CsrfTokenTest.php b/tests/lib/Security/CSRF/CsrfTokenTest.php
index c6f9aaa5be7..5b5ba5ae54f 100644
--- a/tests/lib/Security/CSRF/CsrfTokenTest.php
+++ b/tests/lib/Security/CSRF/CsrfTokenTest.php
@@ -10,26 +10,28 @@ declare(strict_types=1);
namespace Test\Security\CSRF;
+use OC\Security\CSRF\CsrfToken;
+
class CsrfTokenTest extends \Test\TestCase {
- public function testGetEncryptedValue() {
- $csrfToken = new \OC\Security\CSRF\CsrfToken('MyCsrfToken');
+ public function testGetEncryptedValue(): void {
+ $csrfToken = new CsrfToken('MyCsrfToken');
$this->assertSame(33, strlen($csrfToken->getEncryptedValue()));
$this->assertSame(':', $csrfToken->getEncryptedValue()[16]);
}
- public function testGetEncryptedValueStaysSameOnSecondRequest() {
- $csrfToken = new \OC\Security\CSRF\CsrfToken('MyCsrfToken');
+ public function testGetEncryptedValueStaysSameOnSecondRequest(): void {
+ $csrfToken = new CsrfToken('MyCsrfToken');
$tokenValue = $csrfToken->getEncryptedValue();
$this->assertSame($tokenValue, $csrfToken->getEncryptedValue());
$this->assertSame($tokenValue, $csrfToken->getEncryptedValue());
}
- public function testGetDecryptedValue() {
+ public function testGetDecryptedValue(): void {
$a = 'abc';
$b = 'def';
$xorB64 = 'BQcF';
$tokenVal = sprintf('%s:%s', $xorB64, base64_encode($a));
- $csrfToken = new \OC\Security\CSRF\CsrfToken($tokenVal);
+ $csrfToken = new CsrfToken($tokenVal);
$this->assertSame($b, $csrfToken->getDecryptedValue());
}
}
diff --git a/tests/lib/Security/CSRF/TokenStorage/SessionStorageTest.php b/tests/lib/Security/CSRF/TokenStorage/SessionStorageTest.php
index 8e5c8b8e481..2b2c4af0444 100644
--- a/tests/lib/Security/CSRF/TokenStorage/SessionStorageTest.php
+++ b/tests/lib/Security/CSRF/TokenStorage/SessionStorageTest.php
@@ -10,10 +10,11 @@ declare(strict_types=1);
namespace Test\Security\CSRF\TokenStorage;
+use OC\Security\CSRF\TokenStorage\SessionStorage;
use OCP\ISession;
class SessionStorageTest extends \Test\TestCase {
- /** @var \OCP\ISession */
+ /** @var ISession */
private $session;
/** @var \OC\Security\CSRF\TokenStorage\SessionStorage */
private $sessionStorage;
@@ -22,13 +23,13 @@ class SessionStorageTest extends \Test\TestCase {
parent::setUp();
$this->session = $this->getMockBuilder(ISession::class)
->disableOriginalConstructor()->getMock();
- $this->sessionStorage = new \OC\Security\CSRF\TokenStorage\SessionStorage($this->session);
+ $this->sessionStorage = new SessionStorage($this->session);
}
/**
* @return array
*/
- public function getTokenDataProvider() {
+ public static function getTokenDataProvider(): array {
return [
[
'',
@@ -41,10 +42,10 @@ class SessionStorageTest extends \Test\TestCase {
/**
* @param string $token
- * @dataProvider getTokenDataProvider
*
*/
- public function testGetTokenWithEmptyToken($token) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('getTokenDataProvider')]
+ public function testGetTokenWithEmptyToken($token): void {
$this->expectException(\Exception::class);
$this->expectExceptionMessage('Session does not contain a requesttoken');
@@ -56,7 +57,7 @@ class SessionStorageTest extends \Test\TestCase {
$this->sessionStorage->getToken();
}
- public function testGetTokenWithValidToken() {
+ public function testGetTokenWithValidToken(): void {
$this->session
->expects($this->once())
->method('get')
@@ -65,7 +66,7 @@ class SessionStorageTest extends \Test\TestCase {
$this->assertSame('MyFancyCsrfToken', $this->sessionStorage->getToken());
}
- public function testSetToken() {
+ public function testSetToken(): void {
$this->session
->expects($this->once())
->method('set')
@@ -73,7 +74,7 @@ class SessionStorageTest extends \Test\TestCase {
$this->sessionStorage->setToken('TokenToSet');
}
- public function testRemoveToken() {
+ public function testRemoveToken(): void {
$this->session
->expects($this->once())
->method('remove')
@@ -81,7 +82,7 @@ class SessionStorageTest extends \Test\TestCase {
$this->sessionStorage->removeToken();
}
- public function testHasTokenWithExistingToken() {
+ public function testHasTokenWithExistingToken(): void {
$this->session
->expects($this->once())
->method('exists')
@@ -90,7 +91,7 @@ class SessionStorageTest extends \Test\TestCase {
$this->assertSame(true, $this->sessionStorage->hasToken());
}
- public function testHasTokenWithoutExistingToken() {
+ public function testHasTokenWithoutExistingToken(): void {
$this->session
->expects($this->once())
->method('exists')
@@ -99,7 +100,7 @@ class SessionStorageTest extends \Test\TestCase {
$this->assertSame(false, $this->sessionStorage->hasToken());
}
- public function testSetSession() {
+ public function testSetSession(): void {
$session = $this->createMock(ISession::class);
$session
->expects($this->once())
diff --git a/tests/lib/Security/CertificateManagerTest.php b/tests/lib/Security/CertificateManagerTest.php
index fc5ae1f03f2..4dadc824ef6 100644
--- a/tests/lib/Security/CertificateManagerTest.php
+++ b/tests/lib/Security/CertificateManagerTest.php
@@ -10,10 +10,17 @@ declare(strict_types=1);
namespace Test\Security;
+use OC\Files\Filesystem;
+use OC\Files\Storage\Temporary;
use OC\Files\View;
+use OC\Security\Certificate;
use OC\Security\CertificateManager;
+use OCP\Files\InvalidPathException;
use OCP\IConfig;
+use OCP\IUserManager;
use OCP\Security\ISecureRandom;
+use OCP\Server;
+use PHPUnit\Framework\MockObject\MockObject;
use Psr\Log\LoggerInterface;
/**
@@ -25,12 +32,9 @@ class CertificateManagerTest extends \Test\TestCase {
use \Test\Traits\UserTrait;
use \Test\Traits\MountProviderTrait;
- /** @var CertificateManager */
- private $certificateManager;
- /** @var String */
- private $username;
- /** @var ISecureRandom */
- private $random;
+ private CertificateManager $certificateManager;
+ private string $username;
+ private ISecureRandom&MockObject $random;
protected function setUp(): void {
parent::setUp();
@@ -38,12 +42,12 @@ class CertificateManagerTest extends \Test\TestCase {
$this->username = $this->getUniqueID('', 20);
$this->createUser($this->username, '');
- $storage = new \OC\Files\Storage\Temporary();
+ $storage = new Temporary();
$this->registerMount($this->username, $storage, '/' . $this->username . '/');
\OC_Util::tearDownFS();
- \OC_User::setUserId('');
- \OC\Files\Filesystem::tearDown();
+ \OC_User::setUserId($this->username);
+ Filesystem::tearDown();
\OC_Util::setupFS($this->username);
$config = $this->createMock(IConfig::class);
@@ -55,7 +59,7 @@ class CertificateManagerTest extends \Test\TestCase {
->willReturn('random');
$this->certificateManager = new CertificateManager(
- new \OC\Files\View(),
+ new View(),
$config,
$this->createMock(LoggerInterface::class),
$this->random
@@ -63,7 +67,7 @@ class CertificateManagerTest extends \Test\TestCase {
}
protected function tearDown(): void {
- $user = \OC::$server->getUserManager()->get($this->username);
+ $user = Server::get(IUserManager::class)->get($this->username);
if ($user !== null) {
$user->delete();
}
@@ -77,34 +81,31 @@ class CertificateManagerTest extends \Test\TestCase {
$this->assertEquals($expected, $actual);
}
- public function testListCertificates() {
+ public function testListCertificates(): void {
// Test empty certificate bundle
$this->assertSame([], $this->certificateManager->listCertificates());
// Add some certificates
$this->certificateManager->addCertificate(file_get_contents(__DIR__ . '/../../data/certificates/goodCertificate.crt'), 'GoodCertificate');
$certificateStore = [];
- $certificateStore[] = new \OC\Security\Certificate(file_get_contents(__DIR__ . '/../../data/certificates/goodCertificate.crt'), 'GoodCertificate');
+ $certificateStore[] = new Certificate(file_get_contents(__DIR__ . '/../../data/certificates/goodCertificate.crt'), 'GoodCertificate');
$this->assertEqualsArrays($certificateStore, $this->certificateManager->listCertificates());
// Add another certificates
$this->certificateManager->addCertificate(file_get_contents(__DIR__ . '/../../data/certificates/expiredCertificate.crt'), 'ExpiredCertificate');
- $certificateStore[] = new \OC\Security\Certificate(file_get_contents(__DIR__ . '/../../data/certificates/expiredCertificate.crt'), 'ExpiredCertificate');
+ $certificateStore[] = new Certificate(file_get_contents(__DIR__ . '/../../data/certificates/expiredCertificate.crt'), 'ExpiredCertificate');
$this->assertEqualsArrays($certificateStore, $this->certificateManager->listCertificates());
}
- public function testAddInvalidCertificate() {
+ public function testAddInvalidCertificate(): void {
$this->expectException(\Exception::class);
$this->expectExceptionMessage('Certificate could not get parsed.');
$this->certificateManager->addCertificate('InvalidCertificate', 'invalidCertificate');
}
- /**
- * @return array
- */
- public function dangerousFileProvider() {
+ public static function dangerousFileProvider(): array {
return [
['.htaccess'],
['../../foo.txt'],
@@ -113,42 +114,40 @@ class CertificateManagerTest extends \Test\TestCase {
}
/**
- * @dataProvider dangerousFileProvider
* @param string $filename
*/
- public function testAddDangerousFile($filename) {
- $this->expectException(\Exception::class);
- $this->expectExceptionMessage('Filename is not valid');
-
+ #[\PHPUnit\Framework\Attributes\DataProvider('dangerousFileProvider')]
+ public function testAddDangerousFile($filename): void {
+ $this->expectException(InvalidPathException::class);
$this->certificateManager->addCertificate(file_get_contents(__DIR__ . '/../../data/certificates/expiredCertificate.crt'), $filename);
}
- public function testRemoveDangerousFile() {
+ public function testRemoveDangerousFile(): void {
$this->assertFalse($this->certificateManager->removeCertificate('../../foo.txt'));
}
- public function testRemoveExistingFile() {
+ public function testRemoveExistingFile(): void {
$this->certificateManager->addCertificate(file_get_contents(__DIR__ . '/../../data/certificates/goodCertificate.crt'), 'GoodCertificate');
$this->assertTrue($this->certificateManager->removeCertificate('GoodCertificate'));
}
- public function testGetCertificateBundle() {
+ public function testGetCertificateBundle(): void {
$this->assertSame('/files_external/rootcerts.crt', $this->certificateManager->getCertificateBundle());
}
/**
- * @dataProvider dataTestNeedRebundling
*
* @param int $CaBundleMtime
* @param int $targetBundleMtime
* @param int $targetBundleExists
* @param bool $expected
*/
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataTestNeedRebundling')]
public function testNeedRebundling($CaBundleMtime,
$targetBundleMtime,
$targetBundleExists,
- $expected
- ) {
+ $expected,
+ ): void {
$view = $this->getMockBuilder(View::class)
->disableOriginalConstructor()->getMock();
$config = $this->createMock(IConfig::class);
@@ -156,7 +155,7 @@ class CertificateManagerTest extends \Test\TestCase {
/** @var CertificateManager | \PHPUnit\Framework\MockObject\MockObject $certificateManager */
$certificateManager = $this->getMockBuilder('OC\Security\CertificateManager')
->setConstructorArgs([$view, $config, $this->createMock(LoggerInterface::class), $this->random])
- ->setMethods(['getFilemtimeOfCaBundle', 'getCertificateBundle'])
+ ->onlyMethods(['getFilemtimeOfCaBundle', 'getCertificateBundle'])
->getMock();
$certificateManager->expects($this->any())->method('getFilemtimeOfCaBundle')
@@ -184,7 +183,7 @@ class CertificateManagerTest extends \Test\TestCase {
);
}
- public function dataTestNeedRebundling() {
+ public static function dataTestNeedRebundling(): array {
return [
//values: CaBundleMtime, targetBundleMtime, targetBundleExists, expected
diff --git a/tests/lib/Security/CertificateTest.php b/tests/lib/Security/CertificateTest.php
index 6f4e736263b..732b431d73e 100644
--- a/tests/lib/Security/CertificateTest.php
+++ b/tests/lib/Security/CertificateTest.php
@@ -31,8 +31,8 @@ class CertificateTest extends \Test\TestCase {
$this->expiredCertificate = new Certificate($expiredCertificate, 'ExpiredCertificate');
}
-
- public function testBogusData() {
+
+ public function testBogusData(): void {
$this->expectException(\Exception::class);
$this->expectExceptionMessage('Certificate could not get parsed.');
@@ -40,37 +40,42 @@ class CertificateTest extends \Test\TestCase {
$certificate->getIssueDate();
}
-
- public function testCertificateStartingWithFileReference() {
+ public function testOpenSslTrustedCertificateFormat(): void {
+ $trustedCertificate = file_get_contents(__DIR__ . '/../../data/certificates/openSslTrustedCertificate.crt');
+ $certificate = new Certificate($trustedCertificate, 'TrustedCertificate');
+ $this->assertSame('thawte, Inc.', $certificate->getOrganization());
+ }
+
+ public function testCertificateStartingWithFileReference(): void {
$this->expectException(\Exception::class);
$this->expectExceptionMessage('Certificate could not get parsed.');
- new Certificate('file://'.__DIR__ . '/../../data/certificates/goodCertificate.crt', 'bar');
+ new Certificate('file://' . __DIR__ . '/../../data/certificates/goodCertificate.crt', 'bar');
}
- public function testGetName() {
+ public function testGetName(): void {
$this->assertSame('GoodCertificate', $this->goodCertificate->getName());
$this->assertSame('BadCertificate', $this->invalidCertificate->getName());
}
- public function testGetCommonName() {
+ public function testGetCommonName(): void {
$this->assertSame('security.owncloud.com', $this->goodCertificate->getCommonName());
$this->assertSame(null, $this->invalidCertificate->getCommonName());
}
- public function testGetOrganization() {
+ public function testGetOrganization(): void {
$this->assertSame('ownCloud Security', $this->goodCertificate->getOrganization());
$this->assertSame('Internet Widgits Pty Ltd', $this->invalidCertificate->getOrganization());
}
- public function testGetIssueDate() {
+ public function testGetIssueDate(): void {
$expected = new \DateTime('2015-08-27 20:03:42 GMT');
$this->assertEquals($expected->getTimestamp(), $this->goodCertificate->getIssueDate()->getTimestamp());
$expected = new \DateTime('2015-08-27 20:19:13 GMT');
$this->assertEquals($expected->getTimestamp(), $this->invalidCertificate->getIssueDate()->getTimestamp());
}
- public function testGetExpireDate() {
+ public function testGetExpireDate(): void {
$expected = new \DateTime('2025-08-24 20:03:42 GMT');
$this->assertEquals($expected->getTimestamp(), $this->goodCertificate->getExpireDate()->getTimestamp());
$expected = new \DateTime('2025-08-24 20:19:13 GMT');
@@ -79,19 +84,19 @@ class CertificateTest extends \Test\TestCase {
$this->assertEquals($expected->getTimestamp(), $this->expiredCertificate->getExpireDate()->getTimestamp());
}
- public function testIsExpired() {
+ public function testIsExpired(): void {
$this->assertSame(false, $this->goodCertificate->isExpired());
$this->assertSame(false, $this->invalidCertificate->isExpired());
$this->assertSame(true, $this->expiredCertificate->isExpired());
}
- public function testGetIssuerName() {
+ public function testGetIssuerName(): void {
$this->assertSame('security.owncloud.com', $this->goodCertificate->getIssuerName());
$this->assertSame(null, $this->invalidCertificate->getIssuerName());
$this->assertSame(null, $this->expiredCertificate->getIssuerName());
}
- public function testGetIssuerOrganization() {
+ public function testGetIssuerOrganization(): void {
$this->assertSame('ownCloud Security', $this->goodCertificate->getIssuerOrganization());
$this->assertSame('Internet Widgits Pty Ltd', $this->invalidCertificate->getIssuerOrganization());
$this->assertSame('Internet Widgits Pty Ltd', $this->expiredCertificate->getIssuerOrganization());
diff --git a/tests/lib/Security/CredentialsManagerTest.php b/tests/lib/Security/CredentialsManagerTest.php
index d9272627e5b..4dfe8c5681d 100644
--- a/tests/lib/Security/CredentialsManagerTest.php
+++ b/tests/lib/Security/CredentialsManagerTest.php
@@ -17,10 +17,8 @@ use OCP\Server;
* @group DB
*/
class CredentialsManagerTest extends \Test\TestCase {
- /**
- * @dataProvider credentialsProvider
- */
- public function testWithDB($userId, $identifier) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('credentialsProvider')]
+ public function testWithDB($userId, $identifier): void {
$credentialsManager = Server::get(ICredentialsManager::class);
$secrets = 'Open Sesame';
@@ -34,9 +32,7 @@ class CredentialsManagerTest extends \Test\TestCase {
$this->assertSame(1, $removedRows);
}
- /**
- * @dataProvider credentialsProvider
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('credentialsProvider')]
public function testUpdate($userId, $identifier): void {
$credentialsManager = Server::get(ICredentialsManager::class);
@@ -50,7 +46,7 @@ class CredentialsManagerTest extends \Test\TestCase {
$this->assertSame($secretsRev, $received);
}
- public function credentialsProvider(): array {
+ public static function credentialsProvider(): array {
return [
[
'alice',
diff --git a/tests/lib/Security/CryptoTest.php b/tests/lib/Security/CryptoTest.php
index b65a9a36985..0f8575ab0b5 100644
--- a/tests/lib/Security/CryptoTest.php
+++ b/tests/lib/Security/CryptoTest.php
@@ -11,9 +11,11 @@ declare(strict_types=1);
namespace Test\Security;
use OC\Security\Crypto;
+use OCP\IConfig;
+use OCP\Server;
class CryptoTest extends \Test\TestCase {
- public function defaultEncryptionProvider() {
+ public static function defaultEncryptionProvider(): array {
return [
['Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt.'],
[''],
@@ -26,19 +28,17 @@ class CryptoTest extends \Test\TestCase {
protected function setUp(): void {
parent::setUp();
- $this->crypto = new Crypto(\OC::$server->getConfig());
+ $this->crypto = new Crypto(Server::get(IConfig::class));
}
- /**
- * @dataProvider defaultEncryptionProvider
- */
- public function testDefaultEncrypt($stringToEncrypt) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('defaultEncryptionProvider')]
+ public function testDefaultEncrypt($stringToEncrypt): void {
$ciphertext = $this->crypto->encrypt($stringToEncrypt);
$this->assertEquals($stringToEncrypt, $this->crypto->decrypt($ciphertext));
}
- public function testWrongPassword() {
+ public function testWrongPassword(): void {
$this->expectException(\Exception::class);
$this->expectExceptionMessage('HMAC does not match.');
@@ -47,14 +47,14 @@ class CryptoTest extends \Test\TestCase {
$this->crypto->decrypt($ciphertext, 'A wrong password!');
}
- public function testLaterDecryption() {
+ public function testLaterDecryption(): void {
$stringToEncrypt = 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt.';
$encryptedString = '44a35023cca2e7a6125e06c29fc4b2ad9d8a33d0873a8b45b0de4ef9284f260c6c46bf25dc62120644c59b8bafe4281ddc47a70c35ae6c29ef7a63d79eefacc297e60b13042ac582733598d0a6b4de37311556bb5c480fd2633de4e6ebafa868c2d1e2d80a5d24f9660360dba4d6e0c8|lhrFgK0zd9U160Wo|a75e57ab701f9124e1113543fd1dc596f21e20d456a0d1e813d5a8aaec9adcb11213788e96598b67fe9486a9f0b99642c18296d0175db44b1ae426e4e91080ee';
$this->assertEquals($stringToEncrypt, $this->crypto->decrypt($encryptedString, 'ThisIsAVeryS3cur3P4ssw0rd'));
}
- public function testWrongIV() {
+ public function testWrongIV(): void {
$this->expectException(\Exception::class);
$this->expectExceptionMessage('HMAC does not match.');
@@ -63,7 +63,7 @@ class CryptoTest extends \Test\TestCase {
}
- public function testWrongParameters() {
+ public function testWrongParameters(): void {
$this->expectException(\Exception::class);
$this->expectExceptionMessage('Authenticated ciphertext could not be decoded.');
@@ -71,14 +71,14 @@ class CryptoTest extends \Test\TestCase {
$this->crypto->decrypt($encryptedString, 'ThisIsAVeryS3cur3P4ssw0rd');
}
- public function testLegacy() {
+ public function testLegacy(): void {
$cipherText = 'e16599188e3d212f5c7f17fdc2abca46|M1WfLAxbcAmITeD6|509457885d6ca5e6c3bfd3741852687a7f2bffce197f8d5ae97b65818b15a1b7f616b68326ff312371540f4ca8ac55f8e2de4aa13aab3474bd3431e51214e3ee';
$password = 'mypass';
$this->assertSame('legacy test', $this->crypto->decrypt($cipherText, $password));
}
- public function testVersion2CiphertextDecryptsToCorrectPlaintext() {
+ public function testVersion2CiphertextDecryptsToCorrectPlaintext(): void {
$this->assertSame(
'This is a plaintext value that will be encrypted with version 2. Which addresses the reduced permutations on the IV.',
$this->crypto->decrypt(
@@ -88,7 +88,20 @@ class CryptoTest extends \Test\TestCase {
);
}
- public function testVersion3CiphertextDecryptsToCorrectPlaintext() {
+ /**
+ * Test data taken from https://github.com/owncloud/core/blob/9deb8196b20354c8de0cd720ad4d18d52ccc96d8/tests/lib/Security/CryptoTest.php#L56-L60
+ */
+ public function testOcVersion2CiphertextDecryptsToCorrectPlaintext(): void {
+ $this->assertSame(
+ 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt.',
+ $this->crypto->decrypt(
+ 'v2|d57dbe4d1317cdf19d4ddc2df807f6b5d63ab1e119c46590ce54bae56a9cd3969168c4ec1600ac9758dd7e7afb9c4c962dd23072c1463add1d9c77c467723b37bb768ef00e3c50898e59247cbb59ce56b74ce5990648ffe9e40d0e95076c27a785bdcf32c219ea4ad5c316b1f12f48c1|6bd21db258a5e406a2c288a444de195f|a19111a4cf1a11ee95fc1734699c20964eaa05bb007e1cecc4cc6872f827a4b7deedc977c13b138d728d68116aa3d82f9673e20c7e447a9788aa3be994b67cd6',
+ 'ThisIsAVeryS3cur3P4ssw0rd'
+ )
+ );
+ }
+
+ public function testVersion3CiphertextDecryptsToCorrectPlaintext(): void {
$this->assertSame(
'Another plaintext value that will be encrypted with version 3. It addresses the related key issue. Old ciphertexts should be decrypted properly, but only use the better version for encryption.',
$this->crypto->decrypt(
diff --git a/tests/lib/Security/Events/GenerateSecurePasswordEventTest.php b/tests/lib/Security/Events/GenerateSecurePasswordEventTest.php
new file mode 100644
index 00000000000..e589f20f62c
--- /dev/null
+++ b/tests/lib/Security/Events/GenerateSecurePasswordEventTest.php
@@ -0,0 +1,33 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace Test\Security\Events;
+
+use OCP\Security\Events\GenerateSecurePasswordEvent;
+use OCP\Security\PasswordContext;
+
+class GenerateSecurePasswordEventTest extends \Test\TestCase {
+
+ public function testDefaultProperties(): void {
+ $event = new GenerateSecurePasswordEvent();
+ $this->assertNull($event->getPassword());
+ $this->assertEquals(PasswordContext::ACCOUNT, $event->getContext());
+ }
+
+ public function testSettingPassword(): void {
+ $event = new GenerateSecurePasswordEvent();
+ $event->setPassword('example');
+ $this->assertEquals('example', $event->getPassword());
+ }
+
+ public function testSettingContext(): void {
+ $event = new GenerateSecurePasswordEvent(PasswordContext::SHARING);
+ $this->assertEquals(PasswordContext::SHARING, $event->getContext());
+ }
+}
diff --git a/tests/lib/Security/Events/ValidatePasswordPolicyEventTest.php b/tests/lib/Security/Events/ValidatePasswordPolicyEventTest.php
new file mode 100644
index 00000000000..272f34e31aa
--- /dev/null
+++ b/tests/lib/Security/Events/ValidatePasswordPolicyEventTest.php
@@ -0,0 +1,28 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace Test\Security\Events;
+
+use OCP\Security\Events\ValidatePasswordPolicyEvent;
+use OCP\Security\PasswordContext;
+
+class ValidatePasswordPolicyEventTest extends \Test\TestCase {
+
+ public function testDefaultProperties(): void {
+ $password = 'example';
+ $event = new ValidatePasswordPolicyEvent($password);
+ $this->assertEquals($password, $event->getPassword());
+ $this->assertEquals(PasswordContext::ACCOUNT, $event->getContext());
+ }
+
+ public function testSettingContext(): void {
+ $event = new ValidatePasswordPolicyEvent('example', PasswordContext::SHARING);
+ $this->assertEquals(PasswordContext::SHARING, $event->getContext());
+ }
+}
diff --git a/tests/lib/Security/FeaturePolicy/AddFeaturePolicyEventTest.php b/tests/lib/Security/FeaturePolicy/AddFeaturePolicyEventTest.php
index 3c964972238..1fe01e26280 100644
--- a/tests/lib/Security/FeaturePolicy/AddFeaturePolicyEventTest.php
+++ b/tests/lib/Security/FeaturePolicy/AddFeaturePolicyEventTest.php
@@ -14,7 +14,7 @@ use OCP\Security\FeaturePolicy\AddFeaturePolicyEvent;
use Test\TestCase;
class AddFeaturePolicyEventTest extends TestCase {
- public function testAddEvent() {
+ public function testAddEvent(): void {
$manager = $this->createMock(FeaturePolicyManager::class);
$policy = $this->createMock(FeaturePolicy::class);
$event = new AddFeaturePolicyEvent($manager);
diff --git a/tests/lib/Security/FeaturePolicy/FeaturePolicyManagerTest.php b/tests/lib/Security/FeaturePolicy/FeaturePolicyManagerTest.php
index 7110effb261..01624cb92d3 100644
--- a/tests/lib/Security/FeaturePolicy/FeaturePolicyManagerTest.php
+++ b/tests/lib/Security/FeaturePolicy/FeaturePolicyManagerTest.php
@@ -12,6 +12,7 @@ use OC\Security\FeaturePolicy\FeaturePolicyManager;
use OCP\AppFramework\Http\FeaturePolicy;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\Security\FeaturePolicy\AddFeaturePolicyEvent;
+use OCP\Server;
use Test\TestCase;
class FeaturePolicyManagerTest extends TestCase {
@@ -23,17 +24,17 @@ class FeaturePolicyManagerTest extends TestCase {
protected function setUp(): void {
parent::setUp();
- $this->dispatcher = \OC::$server->query(IEventDispatcher::class);
+ $this->dispatcher = Server::get(IEventDispatcher::class);
$this->manager = new FeaturePolicyManager($this->dispatcher);
}
- public function testAddDefaultPolicy() {
+ public function testAddDefaultPolicy(): void {
$this->manager->addDefaultPolicy(new FeaturePolicy());
$this->addToAssertionCount(1);
}
- public function testGetDefaultPolicyWithPoliciesViaEvent() {
- $this->dispatcher->addListener(AddFeaturePolicyEvent::class, function (AddFeaturePolicyEvent $e) {
+ public function testGetDefaultPolicyWithPoliciesViaEvent(): void {
+ $this->dispatcher->addListener(AddFeaturePolicyEvent::class, function (AddFeaturePolicyEvent $e): void {
$policy = new FeaturePolicy();
$policy->addAllowedMicrophoneDomain('mydomain.com');
$policy->addAllowedPaymentDomain('mypaymentdomain.com');
@@ -41,7 +42,7 @@ class FeaturePolicyManagerTest extends TestCase {
$e->addPolicy($policy);
});
- $this->dispatcher->addListener(AddFeaturePolicyEvent::class, function (AddFeaturePolicyEvent $e) {
+ $this->dispatcher->addListener(AddFeaturePolicyEvent::class, function (AddFeaturePolicyEvent $e): void {
$policy = new FeaturePolicy();
$policy->addAllowedPaymentDomain('mydomainother.com');
$policy->addAllowedGeoLocationDomain('mylocation.here');
@@ -49,7 +50,7 @@ class FeaturePolicyManagerTest extends TestCase {
$e->addPolicy($policy);
});
- $this->dispatcher->addListener(AddFeaturePolicyEvent::class, function (AddFeaturePolicyEvent $e) {
+ $this->dispatcher->addListener(AddFeaturePolicyEvent::class, function (AddFeaturePolicyEvent $e): void {
$policy = new FeaturePolicy();
$policy->addAllowedAutoplayDomain('youtube.com');
diff --git a/tests/lib/Security/HasherTest.php b/tests/lib/Security/HasherTest.php
index 0eb233de485..33130f86a73 100644
--- a/tests/lib/Security/HasherTest.php
+++ b/tests/lib/Security/HasherTest.php
@@ -17,10 +17,7 @@ use OCP\IConfig;
* Class HasherTest
*/
class HasherTest extends \Test\TestCase {
- /**
- * @return array
- */
- public function versionHashProvider() {
+ public static function versionHashProvider(): array {
return [
['asf32äà$$a.|3', null],
['asf32äà$$a.|3|5', null],
@@ -30,7 +27,7 @@ class HasherTest extends \Test\TestCase {
];
}
- public function hashProviders70_71(): array {
+ public static function hashProviders70_71(): array {
return [
// Valid SHA1 strings
['password', '5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8', true],
@@ -66,7 +63,7 @@ class HasherTest extends \Test\TestCase {
];
}
- public function hashProviders72(): array {
+ public static function hashProviders72(): array {
return [
// Valid ARGON2 hashes
['password', '2|$argon2i$v=19$m=1024,t=2,p=2$T3JGcEkxVFNOVktNSjZUcg$4/hyLtSejxNgAuzSFFV/HLM3qRQKBwEtKw61qPN4zWA', true],
@@ -83,7 +80,7 @@ class HasherTest extends \Test\TestCase {
];
}
- public function hashProviders73(): array {
+ public static function hashProviders73(): array {
return [
// Valid ARGON2ID hashes
['password', '2|$argon2id$v=19$m=65536,t=4,p=1$TEtIMnhUczliQzI0Y01WeA$BpMUDrApy25iagIogUAnlc0rNTPJmGs8lOEeVHujJ9Q', true],
@@ -122,24 +119,20 @@ class HasherTest extends \Test\TestCase {
$this->hasher = new Hasher($this->config);
}
- public function testHash() {
+ public function testHash(): void {
$hash = $this->hasher->hash('String To Hash');
$this->assertNotNull($hash);
}
- /**
- * @dataProvider versionHashProvider
- */
- public function testSplitHash($hash, $expected) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('versionHashProvider')]
+ public function testSplitHash($hash, $expected): void {
$relativePath = self::invokePrivate($this->hasher, 'splitHash', [$hash]);
$this->assertSame($expected, $relativePath);
}
- /**
- * @dataProvider hashProviders70_71
- */
- public function testVerify($password, $hash, $expected) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('hashProviders70_71')]
+ public function testVerify($password, $hash, $expected): void {
$this->config
->expects($this->any())
->method('getSystemValue')
@@ -154,10 +147,8 @@ class HasherTest extends \Test\TestCase {
$this->assertSame($expected, $result);
}
- /**
- * @dataProvider hashProviders72
- */
- public function testVerifyArgon2i($password, $hash, $expected) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('hashProviders72')]
+ public function testVerifyArgon2i($password, $hash, $expected): void {
if (!\defined('PASSWORD_ARGON2I')) {
$this->markTestSkipped('Need ARGON2 support to test ARGON2 hashes');
}
@@ -166,10 +157,8 @@ class HasherTest extends \Test\TestCase {
$this->assertSame($expected, $result);
}
- /**
- * @dataProvider hashProviders73
- */
- public function testVerifyArgon2id(string $password, string $hash, bool $expected) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('hashProviders73')]
+ public function testVerifyArgon2id(string $password, string $hash, bool $expected): void {
if (!\defined('PASSWORD_ARGON2ID')) {
$this->markTestSkipped('Need ARGON2ID support to test ARGON2ID hashes');
}
@@ -178,7 +167,7 @@ class HasherTest extends \Test\TestCase {
$this->assertSame($expected, $result);
}
- public function testUpgradeHashBlowFishToArgon2() {
+ public function testUpgradeHashBlowFishToArgon2(): void {
if (!\defined('PASSWORD_ARGON2I')) {
$this->markTestSkipped('Need ARGON2 support to test ARGON2 hashes');
}
@@ -203,7 +192,7 @@ class HasherTest extends \Test\TestCase {
$this->assertFalse(password_needs_rehash($relativePath['hash'], $newAlg, []));
}
- public function testUsePasswordDefaultArgon2iVerify() {
+ public function testUsePasswordDefaultArgon2iVerify(): void {
if (!\defined('PASSWORD_ARGON2I')) {
$this->markTestSkipped('Need ARGON2 support to test ARGON2 hashes');
}
@@ -227,7 +216,7 @@ class HasherTest extends \Test\TestCase {
$this->assertTrue(password_verify($message, $relativePath['hash']));
}
- public function testDoNotUsePasswordDefaultArgon2idVerify() {
+ public function testDoNotUsePasswordDefaultArgon2idVerify(): void {
if (!\defined('PASSWORD_ARGON2ID')) {
$this->markTestSkipped('Need ARGON2ID support to test ARGON2ID hashes');
}
@@ -245,7 +234,7 @@ class HasherTest extends \Test\TestCase {
$this->assertNull($newHash);
}
- public function testHashUsePasswordDefault() {
+ public function testHashUsePasswordDefault(): void {
if (!\defined('PASSWORD_ARGON2I')) {
$this->markTestSkipped('Need ARGON2 support to test ARGON2 hashes');
}
@@ -264,4 +253,29 @@ class HasherTest extends \Test\TestCase {
$info = password_get_info($relativePath['hash']);
$this->assertEquals(PASSWORD_BCRYPT, $info['algo']);
}
+
+ public function testValidHash(): void {
+ $hash = '3|$argon2id$v=19$m=65536,t=4,p=1$czFCSjk3LklVdXppZ2VCWA$li0NgdXe2/jwSRxgteGQPWlzJU0E0xdtfHbCbrpych0';
+
+ $isValid = $this->hasher->validate($hash);
+
+ $this->assertTrue($isValid);
+ }
+
+ public function testValidGeneratedHash(): void {
+ $message = 'secret';
+ $hash = $this->hasher->hash($message);
+
+ $isValid = $this->hasher->validate($hash);
+
+ $this->assertTrue($isValid);
+ }
+
+ public function testInvalidHash(): void {
+ $invalidHash = 'someInvalidHash';
+
+ $isValid = $this->hasher->validate($invalidHash);
+
+ $this->assertFalse($isValid);
+ }
}
diff --git a/tests/lib/Security/IdentityProof/KeyTest.php b/tests/lib/Security/IdentityProof/KeyTest.php
index 19dc02e2ad1..572bfbea619 100644
--- a/tests/lib/Security/IdentityProof/KeyTest.php
+++ b/tests/lib/Security/IdentityProof/KeyTest.php
@@ -22,11 +22,11 @@ class KeyTest extends TestCase {
$this->key = new Key('public', 'private');
}
- public function testGetPrivate() {
+ public function testGetPrivate(): void {
$this->assertSame('private', $this->key->getPrivate());
}
- public function testGetPublic() {
+ public function testGetPublic(): void {
$this->assertSame('public', $this->key->getPublic());
}
}
diff --git a/tests/lib/Security/IdentityProof/ManagerTest.php b/tests/lib/Security/IdentityProof/ManagerTest.php
index bb5b01d563c..921d72388a1 100644
--- a/tests/lib/Security/IdentityProof/ManagerTest.php
+++ b/tests/lib/Security/IdentityProof/ManagerTest.php
@@ -16,6 +16,8 @@ use OC\Security\IdentityProof\Manager;
use OCP\Files\IAppData;
use OCP\Files\SimpleFS\ISimpleFile;
use OCP\Files\SimpleFS\ISimpleFolder;
+use OCP\ICache;
+use OCP\ICacheFactory;
use OCP\IConfig;
use OCP\IUser;
use OCP\Security\ICrypto;
@@ -24,18 +26,14 @@ use Psr\Log\LoggerInterface;
use Test\TestCase;
class ManagerTest extends TestCase {
- /** @var Factory|MockObject */
- private $factory;
- /** @var IAppData|MockObject */
- private $appData;
- /** @var ICrypto|MockObject */
- private $crypto;
- /** @var Manager|MockObject */
- private $manager;
- /** @var IConfig|MockObject */
- private $config;
- /** @var LoggerInterface|MockObject */
- private $logger;
+ private Factory&MockObject $factory;
+ private IAppData&MockObject $appData;
+ private ICrypto&MockObject $crypto;
+ private Manager&MockObject $manager;
+ private IConfig&MockObject $config;
+ private LoggerInterface&MockObject $logger;
+ private ICacheFactory&MockObject $cacheFactory;
+ private ICache&MockObject $cache;
protected function setUp(): void {
parent::setUp();
@@ -49,6 +47,12 @@ class ManagerTest extends TestCase {
->with('identityproof')
->willReturn($this->appData);
$this->logger = $this->createMock(LoggerInterface::class);
+ $this->cacheFactory = $this->createMock(ICacheFactory::class);
+ $this->cache = $this->createMock(ICache::class);
+
+ $this->cacheFactory->expects($this->any())
+ ->method('createDistributed')
+ ->willReturn($this->cache);
$this->crypto = $this->createMock(ICrypto::class);
$this->manager = $this->getManager(['generateKeyPair']);
@@ -66,7 +70,8 @@ class ManagerTest extends TestCase {
$this->factory,
$this->crypto,
$this->config,
- $this->logger
+ $this->logger,
+ $this->cacheFactory,
);
} else {
return $this->getMockBuilder(Manager::class)
@@ -74,12 +79,15 @@ class ManagerTest extends TestCase {
$this->factory,
$this->crypto,
$this->config,
- $this->logger
- ])->setMethods($setMethods)->getMock();
+ $this->logger,
+ $this->cacheFactory,
+ ])
+ ->onlyMethods($setMethods)
+ ->getMock();
}
}
- public function testGetKeyWithExistingKey() {
+ public function testGetKeyWithExistingKey(): void {
$user = $this->createMock(IUser::class);
$user
->expects($this->once())
@@ -104,25 +112,48 @@ class ManagerTest extends TestCase {
$folder
->expects($this->exactly(2))
->method('getFile')
- ->withConsecutive(
- ['private'],
- ['public']
- )
- ->willReturnOnConsecutiveCalls(
- $privateFile,
- $publicFile
- );
+ ->willReturnMap([
+ ['private', $privateFile],
+ ['public', $publicFile],
+ ]);
$this->appData
->expects($this->once())
->method('getFolder')
->with('user-MyUid')
->willReturn($folder);
+ $this->cache
+ ->expects($this->exactly(2))
+ ->method('get')
+ ->willReturn(null);
+
+ $expected = new Key('MyPublicKey', 'MyPrivateKey');
+ $this->assertEquals($expected, $this->manager->getKey($user));
+ }
+
+ public function testGetKeyWithExistingKeyCached(): void {
+ $user = $this->createMock(IUser::class);
+ $user
+ ->expects($this->once())
+ ->method('getUID')
+ ->willReturn('MyUid');
+ $this->crypto
+ ->expects($this->once())
+ ->method('decrypt')
+ ->with('EncryptedPrivateKey')
+ ->willReturn('MyPrivateKey');
+ $this->cache
+ ->expects($this->exactly(2))
+ ->method('get')
+ ->willReturnMap([
+ ['user-MyUid-public', 'MyPublicKey'],
+ ['user-MyUid-private', 'EncryptedPrivateKey'],
+ ]);
$expected = new Key('MyPublicKey', 'MyPrivateKey');
$this->assertEquals($expected, $this->manager->getKey($user));
}
- public function testGetKeyWithNotExistingKey() {
+ public function testGetKeyWithNotExistingKey(): void {
$user = $this->createMock(IUser::class);
$user
->expects($this->once())
@@ -155,14 +186,10 @@ class ManagerTest extends TestCase {
$folder
->expects($this->exactly(2))
->method('newFile')
- ->withConsecutive(
- ['private'],
- ['public']
- )
- ->willReturnOnConsecutiveCalls(
- $privateFile,
- $publicFile
- );
+ ->willReturnMap([
+ ['private', null, $privateFile],
+ ['public', null, $publicFile],
+ ]);
$this->appData
->expects($this->exactly(2))
->method('getFolder')
@@ -177,7 +204,7 @@ class ManagerTest extends TestCase {
$this->assertEquals($expected, $this->manager->getKey($user));
}
- public function testGenerateKeyPair() {
+ public function testGenerateKeyPair(): void {
$manager = $this->getManager();
$data = 'MyTestData';
@@ -189,7 +216,7 @@ class ManagerTest extends TestCase {
$this->assertSame(2048, $details['bits']);
}
- public function testGetSystemKey() {
+ public function testGetSystemKey(): void {
$manager = $this->getManager(['retrieveKey']);
/** @var Key|\PHPUnit\Framework\MockObject\MockObject $key */
@@ -206,7 +233,7 @@ class ManagerTest extends TestCase {
- public function testGetSystemKeyFailure() {
+ public function testGetSystemKeyFailure(): void {
$this->expectException(\RuntimeException::class);
$manager = $this->getManager(['retrieveKey']);
diff --git a/tests/lib/Security/IdentityProof/SignerTest.php b/tests/lib/Security/IdentityProof/SignerTest.php
index 8b8d93e6b9a..6dc73c072e4 100644
--- a/tests/lib/Security/IdentityProof/SignerTest.php
+++ b/tests/lib/Security/IdentityProof/SignerTest.php
@@ -90,7 +90,7 @@ gQIDAQAB
);
}
- public function testSign() {
+ public function testSign(): void {
$user = $this->createMock(IUser::class);
$user->method('getCloudId')
->willReturn('foo@example.com');
@@ -123,7 +123,7 @@ gQIDAQAB
$this->assertEquals($expects, $result);
}
- public function testVerifyValid() {
+ public function testVerifyValid(): void {
$data = [
'message' => [
'data' => [
@@ -151,7 +151,7 @@ gQIDAQAB
$this->assertTrue($this->signer->verify($data));
}
- public function testVerifyInvalid() {
+ public function testVerifyInvalid(): void {
$data = [
'message' => [
'data' => [
@@ -179,7 +179,7 @@ gQIDAQAB
$this->assertFalse($this->signer->verify($data));
}
- public function testVerifyInvalidData() {
+ public function testVerifyInvalidData(): void {
$data = [
];
diff --git a/tests/lib/Security/Ip/BruteforceAllowListTest.php b/tests/lib/Security/Ip/BruteforceAllowListTest.php
new file mode 100644
index 00000000000..1454b779c1b
--- /dev/null
+++ b/tests/lib/Security/Ip/BruteforceAllowListTest.php
@@ -0,0 +1,161 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace Test\Security\Ip;
+
+use OC\Security\Ip\BruteforceAllowList;
+use OC\Security\Ip\Factory;
+use OCP\IAppConfig;
+use OCP\Security\Ip\IFactory;
+use PHPUnit\Framework\MockObject\MockObject;
+use Test\TestCase;
+
+/**
+ * Based on the unit tests from Paragonie's Airship CMS
+ * Ref: https://github.com/paragonie/airship/blob/7e5bad7e3c0fbbf324c11f963fd1f80e59762606/test/unit/Engine/Security/AirBrakeTest.php
+ *
+ * @package Test\Security\Bruteforce
+ */
+class BruteforceAllowListTest extends TestCase {
+ /** @var IAppConfig|MockObject */
+ private $appConfig;
+ /** @var IFactory|MockObject */
+ private $factory;
+ /** @var BruteforceAllowList */
+ private $allowList;
+
+ protected function setUp(): void {
+ parent::setUp();
+
+ $this->appConfig = $this->createMock(IAppConfig::class);
+ $this->factory = new Factory();
+
+ $this->allowList = new BruteforceAllowList(
+ $this->appConfig,
+ $this->factory,
+ );
+ }
+
+ public static function dataIsBypassListed(): array {
+ return [
+ [
+ '10.10.10.10',
+ [
+ 'whitelist_0' => '10.10.10.0/24',
+ ],
+ true,
+ ],
+ [
+ '10.10.10.10',
+ [
+ 'whitelist_0' => '192.168.0.0/16',
+ ],
+ false,
+ ],
+ [
+ '10.10.10.10',
+ [
+ 'whitelist_0' => '192.168.0.0/16',
+ 'whitelist_1' => '10.10.10.0/24',
+ ],
+ true,
+ ],
+ [
+ '10.10.10.10',
+ [
+ 'whitelist_0' => '10.10.10.11/31',
+ ],
+ true,
+ ],
+ [
+ '10.10.10.10',
+ [
+ 'whitelist_0' => '10.10.10.9/31',
+ ],
+ false,
+ ],
+ [
+ '10.10.10.10',
+ [
+ 'whitelist_0' => '10.10.10.15/29',
+ ],
+ true,
+ ],
+ [
+ 'dead:beef:cafe::1',
+ [
+ 'whitelist_0' => '192.168.0.0/16',
+ 'whitelist_1' => '10.10.10.0/24',
+ 'whitelist_2' => 'deaf:beef:cafe:1234::/64'
+ ],
+ false,
+ ],
+ [
+ 'dead:beef:cafe::1',
+ [
+ 'whitelist_0' => '192.168.0.0/16',
+ 'whitelist_1' => '10.10.10.0/24',
+ 'whitelist_2' => 'deaf:beef::/64'
+ ],
+ false,
+ ],
+ [
+ 'dead:beef:cafe::1',
+ [
+ 'whitelist_0' => '192.168.0.0/16',
+ 'whitelist_1' => '10.10.10.0/24',
+ 'whitelist_2' => 'deaf:cafe::/8'
+ ],
+ true,
+ ],
+ [
+ 'dead:beef:cafe::1111',
+ [
+ 'whitelist_0' => 'dead:beef:cafe::1100/123',
+ ],
+ true,
+ ],
+ [
+ 'invalid',
+ [],
+ false,
+ ],
+ ];
+ }
+
+ /**
+ * @param string[] $allowList
+ */
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataIsBypassListed')]
+ public function testIsBypassListed(
+ string $ip,
+ array $allowList,
+ bool $isAllowListed,
+ ): void {
+ $this->appConfig->method('searchKeys')
+ ->with($this->equalTo('bruteForce'), $this->equalTo('whitelist_'))
+ ->willReturn(array_keys($allowList));
+
+ $this->appConfig->method('getValueString')
+ ->willReturnCallback(function ($app, $key, $default) use ($allowList) {
+ if ($app !== 'bruteForce') {
+ return $default;
+ }
+ if (isset($allowList[$key])) {
+ return $allowList[$key];
+ }
+ return $default;
+ });
+
+ $this->assertSame(
+ $isAllowListed,
+ $this->allowList->isBypassListed($ip)
+ );
+ }
+}
diff --git a/tests/lib/Security/Ip/RemoteAddressTest.php b/tests/lib/Security/Ip/RemoteAddressTest.php
new file mode 100644
index 00000000000..a6619cffe8e
--- /dev/null
+++ b/tests/lib/Security/Ip/RemoteAddressTest.php
@@ -0,0 +1,79 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace Test\Security\Ip;
+
+use OC\Security\Ip\RemoteAddress;
+use OCP\IConfig;
+use OCP\IRequest;
+
+class RemoteAddressTest extends \Test\TestCase {
+ private IConfig $config;
+ private IRequest $request;
+
+ protected function setUp(): void {
+ parent::setUp();
+ $this->config = $this->createMock(IConfig::class);
+ $this->request = $this->createMock(IRequest::class);
+ }
+
+ /**
+ * @param mixed $allowedRanges
+ */
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataProvider')]
+ public function testAllowedIps(string $remoteIp, $allowedRanges, bool $expected): void {
+ $this->request
+ ->method('getRemoteAddress')
+ ->willReturn($remoteIp);
+ $this->config
+ ->method('getSystemValue')
+ ->with('allowed_admin_ranges', false)
+ ->willReturn($allowedRanges);
+
+ $remoteAddress = new RemoteAddress($this->config, $this->request);
+
+ $this->assertEquals($expected, $remoteAddress->allowsAdminActions());
+ }
+
+ /**
+ * @return array<string, mixed, bool>
+ */
+ public static function dataProvider(): array {
+ return [
+ // No IP (ie. CLI)
+ ['', ['192.168.1.2/24'], true],
+ ['', ['fe80/8'], true],
+ // No configuration
+ ['1.2.3.4', false, true],
+ ['1234:4567:8910::', false, true],
+ // v6 Zone ID
+ ['fe80::1fc4:15d8:78db:2319%enp4s0', false, true],
+ // Empty configuration
+ ['1.2.3.4', [], true],
+ ['1234:4567:8910::', [], true],
+ // Invalid configuration
+ ['1.2.3.4', 'hello', true],
+ ['1234:4567:8910::', 'world', true],
+ // Mixed configuration
+ ['192.168.1.5', ['1.2.3.*', '1234::/8'], false],
+ ['::1', ['127.0.0.1', '1234::/8'], false],
+ ['192.168.1.5', ['192.168.1.0/24', '1234::/8'], true],
+ // Allowed IP
+ ['1.2.3.4', ['1.2.3.*'], true],
+ ['fc00:1:2:3::1', ['fc00::/7'], true],
+ ['1.2.3.4', ['192.168.1.2/24', '1.2.3.0/24'], true],
+ ['1234:4567:8910::1', ['fe80::/8','1234:4567::/16'], true],
+ // Blocked IP
+ ['192.168.1.5', ['1.2.3.*'], false],
+ ['9234:4567:8910::', ['1234:4567::1'], false],
+ ['192.168.2.1', ['192.168.1.2/24', '1.2.3.0/24'], false],
+ ['9234:4567:8910::', ['fe80::/8','1234:4567::/16'], false],
+ ];
+ }
+}
diff --git a/tests/lib/Security/Normalizer/IpAddressTest.php b/tests/lib/Security/Normalizer/IpAddressTest.php
index ae6b5cbc9ca..f7adfb4a0dd 100644
--- a/tests/lib/Security/Normalizer/IpAddressTest.php
+++ b/tests/lib/Security/Normalizer/IpAddressTest.php
@@ -13,7 +13,7 @@ use OC\Security\Normalizer\IpAddress;
use Test\TestCase;
class IpAddressTest extends TestCase {
- public function subnetDataProvider() {
+ public static function subnetDataProvider(): array {
return [
[
'64.233.191.254',
@@ -36,35 +36,35 @@ class IpAddressTest extends TestCase {
'192.168.0.123/32',
],
[
- '2001:0db8:85a3:0000:0000:8a2e:0370:7334',
- '2001:db8:85a3::/64',
+ '2001:0db8:0000:0000:0000:8a2e:0370:7334',
+ '2001:db8::/56',
],
[
'2001:db8:3333:4444:5555:6666:7777:8888',
- '2001:db8:3333:4444::/64',
+ '2001:db8:3333:4400::/56',
],
[
'::1234:5678',
- '::/64',
+ '::/56',
],
[
'[::1]',
- '::/64',
+ '::/56',
],
];
}
/**
- * @dataProvider subnetDataProvider
*
* @param string $input
* @param string $expected
*/
- public function testGetSubnet($input, $expected) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('subnetDataProvider')]
+ public function testGetSubnet($input, $expected): void {
$this->assertSame($expected, (new IpAddress($input))->getSubnet());
}
- public function testToString() {
+ public function testToString(): void {
$this->assertSame('127.0.0.1', (string)(new IpAddress('127.0.0.1')));
}
}
diff --git a/tests/lib/Security/RateLimiting/Backend/MemoryCacheBackendTest.php b/tests/lib/Security/RateLimiting/Backend/MemoryCacheBackendTest.php
index 27799ce4af5..24e3ab1a209 100644
--- a/tests/lib/Security/RateLimiting/Backend/MemoryCacheBackendTest.php
+++ b/tests/lib/Security/RateLimiting/Backend/MemoryCacheBackendTest.php
@@ -53,7 +53,7 @@ class MemoryCacheBackendTest extends TestCase {
);
}
- public function testGetAttemptsWithNoAttemptsBefore() {
+ public function testGetAttemptsWithNoAttemptsBefore(): void {
$this->cache
->expects($this->once())
->method('get')
@@ -63,7 +63,7 @@ class MemoryCacheBackendTest extends TestCase {
$this->assertSame(0, $this->memoryCache->getAttempts('Method', 'User'));
}
- public function testGetAttempts() {
+ public function testGetAttempts(): void {
$this->timeFactory
->expects($this->once())
->method('getTime')
@@ -84,7 +84,7 @@ class MemoryCacheBackendTest extends TestCase {
$this->assertSame(3, $this->memoryCache->getAttempts('Method', 'User'));
}
- public function testRegisterAttemptWithNoAttemptsBefore() {
+ public function testRegisterAttemptWithNoAttemptsBefore(): void {
$this->timeFactory
->expects($this->once())
->method('getTime')
@@ -106,7 +106,7 @@ class MemoryCacheBackendTest extends TestCase {
$this->memoryCache->registerAttempt('Method', 'User', 100);
}
- public function testRegisterAttempt() {
+ public function testRegisterAttempt(): void {
$this->timeFactory
->expects($this->once())
->method('getTime')
diff --git a/tests/lib/Security/RateLimiting/LimiterTest.php b/tests/lib/Security/RateLimiting/LimiterTest.php
index 332f26b81d0..b19d5c6feba 100644
--- a/tests/lib/Security/RateLimiting/LimiterTest.php
+++ b/tests/lib/Security/RateLimiting/LimiterTest.php
@@ -10,29 +10,35 @@ declare(strict_types=1);
namespace Test\Security\RateLimiting;
use OC\Security\RateLimiting\Backend\IBackend;
+use OC\Security\RateLimiting\Exception\RateLimitExceededException;
use OC\Security\RateLimiting\Limiter;
use OCP\IUser;
+use OCP\Security\RateLimiting\ILimiter;
+use PHPUnit\Framework\MockObject\MockObject;
+use Psr\Log\LoggerInterface;
use Test\TestCase;
class LimiterTest extends TestCase {
- /** @var IBackend|\PHPUnit\Framework\MockObject\MockObject */
- private $backend;
- /** @var Limiter */
- private $limiter;
+
+ private IBackend&MockObject $backend;
+ private ILimiter $limiter;
+ private LoggerInterface $logger;
protected function setUp(): void {
parent::setUp();
$this->backend = $this->createMock(IBackend::class);
+ $this->logger = $this->createMock(LoggerInterface::class);
$this->limiter = new Limiter(
- $this->backend
+ $this->backend,
+ $this->logger,
);
}
- public function testRegisterAnonRequestExceeded() {
- $this->expectException(\OC\Security\RateLimiting\Exception\RateLimitExceededException::class);
+ public function testRegisterAnonRequestExceeded(): void {
+ $this->expectException(RateLimitExceededException::class);
$this->expectExceptionMessage('Rate limit exceeded');
$this->backend
@@ -43,11 +49,13 @@ class LimiterTest extends TestCase {
'4664f0d9c88dcb7552be47b37bb52ce35977b2e60e1ac13757cf625f31f87050a41f3da064887fa87d49fd042e4c8eb20de8f10464877d3959677ab011b73a47'
)
->willReturn(101);
+ $this->logger->expects($this->once())
+ ->method('info');
$this->limiter->registerAnonRequest('MyIdentifier', 100, 100, '127.0.0.1');
}
- public function testRegisterAnonRequestSuccess() {
+ public function testRegisterAnonRequestSuccess(): void {
$this->backend
->expects($this->once())
->method('getAttempts')
@@ -64,13 +72,15 @@ class LimiterTest extends TestCase {
'4664f0d9c88dcb7552be47b37bb52ce35977b2e60e1ac13757cf625f31f87050a41f3da064887fa87d49fd042e4c8eb20de8f10464877d3959677ab011b73a47',
100
);
+ $this->logger->expects($this->never())
+ ->method('info');
$this->limiter->registerAnonRequest('MyIdentifier', 100, 100, '127.0.0.1');
}
- public function testRegisterUserRequestExceeded() {
- $this->expectException(\OC\Security\RateLimiting\Exception\RateLimitExceededException::class);
+ public function testRegisterUserRequestExceeded(): void {
+ $this->expectException(RateLimitExceededException::class);
$this->expectExceptionMessage('Rate limit exceeded');
/** @var IUser|\PHPUnit\Framework\MockObject\MockObject $user */
@@ -87,11 +97,13 @@ class LimiterTest extends TestCase {
'ddb2ec50fa973fd49ecf3d816f677c8095143e944ad10485f30fb3dac85c13a346dace4dae2d0a15af91867320957bfd38a43d9eefbb74fe6919e15119b6d805'
)
->willReturn(101);
+ $this->logger->expects($this->once())
+ ->method('info');
$this->limiter->registerUserRequest('MyIdentifier', 100, 100, $user);
}
- public function testRegisterUserRequestSuccess() {
+ public function testRegisterUserRequestSuccess(): void {
/** @var IUser|\PHPUnit\Framework\MockObject\MockObject $user */
$user = $this->createMock(IUser::class);
$user
@@ -115,6 +127,8 @@ class LimiterTest extends TestCase {
'ddb2ec50fa973fd49ecf3d816f677c8095143e944ad10485f30fb3dac85c13a346dace4dae2d0a15af91867320957bfd38a43d9eefbb74fe6919e15119b6d805',
100
);
+ $this->logger->expects($this->never())
+ ->method('info');
$this->limiter->registerUserRequest('MyIdentifier', 100, 100, $user);
}
diff --git a/tests/lib/Security/RemoteHostValidatorIntegrationTest.php b/tests/lib/Security/RemoteHostValidatorIntegrationTest.php
index 6cddb8b4ce9..913acfa054d 100644
--- a/tests/lib/Security/RemoteHostValidatorIntegrationTest.php
+++ b/tests/lib/Security/RemoteHostValidatorIntegrationTest.php
@@ -37,7 +37,7 @@ class RemoteHostValidatorIntegrationTest extends TestCase {
);
}
- public function localHostsData(): array {
+ public static function localHostsData(): array {
return [
['[::1]'],
['[::]'],
@@ -73,9 +73,7 @@ class RemoteHostValidatorIntegrationTest extends TestCase {
];
}
- /**
- * @dataProvider localHostsData
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('localHostsData')]
public function testLocalHostsWhenNotAllowed(string $host): void {
$this->config
->method('getSystemValueBool')
@@ -87,9 +85,7 @@ class RemoteHostValidatorIntegrationTest extends TestCase {
self::assertFalse($isValid);
}
- /**
- * @dataProvider localHostsData
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('localHostsData')]
public function testLocalHostsWhenAllowed(string $host): void {
$this->config
->method('getSystemValueBool')
@@ -101,7 +97,7 @@ class RemoteHostValidatorIntegrationTest extends TestCase {
self::assertTrue($isValid);
}
- public function externalAddressesData():array {
+ public static function externalAddressesData():array {
return [
['8.8.8.8'],
['8.8.4.4'],
@@ -111,9 +107,7 @@ class RemoteHostValidatorIntegrationTest extends TestCase {
];
}
- /**
- * @dataProvider externalAddressesData
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('externalAddressesData')]
public function testExternalHost(string $host): void {
$this->config
->method('getSystemValueBool')
diff --git a/tests/lib/Security/RemoteHostValidatorTest.php b/tests/lib/Security/RemoteHostValidatorTest.php
index c698ebbc3c6..b048b9dafd1 100644
--- a/tests/lib/Security/RemoteHostValidatorTest.php
+++ b/tests/lib/Security/RemoteHostValidatorTest.php
@@ -44,16 +44,14 @@ class RemoteHostValidatorTest extends TestCase {
);
}
- public function dataValid(): array {
+ public static function dataValid(): array {
return [
['nextcloud.com', true],
['com.one-.nextcloud-one.com', false],
];
}
- /**
- * @dataProvider dataValid
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataValid')]
public function testValid(string $host, bool $expected): void {
$this->hostnameClassifier
->method('isLocalHostname')
diff --git a/tests/lib/Security/SecureRandomTest.php b/tests/lib/Security/SecureRandomTest.php
index 6e5f3587630..954fd85eaf1 100644
--- a/tests/lib/Security/SecureRandomTest.php
+++ b/tests/lib/Security/SecureRandomTest.php
@@ -13,7 +13,7 @@ namespace Test\Security;
use OC\Security\SecureRandom;
class SecureRandomTest extends \Test\TestCase {
- public function stringGenerationProvider() {
+ public static function stringGenerationProvider(): array {
return [
[1, 1],
[128, 128],
@@ -24,7 +24,7 @@ class SecureRandomTest extends \Test\TestCase {
];
}
- public static function charCombinations() {
+ public static function charCombinations(): array {
return [
['CHAR_LOWER', '[a-z]'],
['CHAR_UPPER', '[A-Z]'],
@@ -37,56 +37,46 @@ class SecureRandomTest extends \Test\TestCase {
protected function setUp(): void {
parent::setUp();
- $this->rng = new \OC\Security\SecureRandom();
+ $this->rng = new SecureRandom();
}
- /**
- * @dataProvider stringGenerationProvider
- */
- public function testGetLowStrengthGeneratorLength($length, $expectedLength) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('stringGenerationProvider')]
+ public function testGetLowStrengthGeneratorLength($length, $expectedLength): void {
$generator = $this->rng;
$this->assertEquals($expectedLength, strlen($generator->generate($length)));
}
- /**
- * @dataProvider stringGenerationProvider
- */
- public function testMediumLowStrengthGeneratorLength($length, $expectedLength) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('stringGenerationProvider')]
+ public function testMediumLowStrengthGeneratorLength($length, $expectedLength): void {
$generator = $this->rng;
$this->assertEquals($expectedLength, strlen($generator->generate($length)));
}
- /**
- * @dataProvider stringGenerationProvider
- */
- public function testUninitializedGenerate($length, $expectedLength) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('stringGenerationProvider')]
+ public function testUninitializedGenerate($length, $expectedLength): void {
$this->assertEquals($expectedLength, strlen($this->rng->generate($length)));
}
- /**
- * @dataProvider charCombinations
- */
- public function testScheme($charName, $chars) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('charCombinations')]
+ public function testScheme($charName, $chars): void {
$generator = $this->rng;
$scheme = constant('OCP\Security\ISecureRandom::' . $charName);
$randomString = $generator->generate(100, $scheme);
- $matchesRegex = preg_match('/^'.$chars.'+$/', $randomString);
+ $matchesRegex = preg_match('/^' . $chars . '+$/', $randomString);
$this->assertSame(1, $matchesRegex);
}
- public static function invalidLengths() {
+ public static function invalidLengths(): array {
return [
[0],
[-1],
];
}
- /**
- * @dataProvider invalidLengths
- */
- public function testInvalidLengths($length) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('invalidLengths')]
+ public function testInvalidLengths($length): void {
$this->expectException(\LengthException::class);
$generator = $this->rng;
$generator->generate($length);
diff --git a/tests/lib/Security/TrustedDomainHelperTest.php b/tests/lib/Security/TrustedDomainHelperTest.php
index 3dbaf376b52..8b671a93d06 100644
--- a/tests/lib/Security/TrustedDomainHelperTest.php
+++ b/tests/lib/Security/TrustedDomainHelperTest.php
@@ -27,12 +27,12 @@ class TrustedDomainHelperTest extends \Test\TestCase {
}
/**
- * @dataProvider trustedDomainDataProvider
* @param string $trustedDomains
* @param string $testDomain
* @param bool $result
*/
- public function testIsTrustedUrl($trustedDomains, $testDomain, $result) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('trustedDomainDataProvider')]
+ public function testIsTrustedUrl($trustedDomains, $testDomain, $result): void {
$this->config->method('getSystemValue')
->willReturnMap([
['overwritehost', '', ''],
@@ -44,12 +44,12 @@ class TrustedDomainHelperTest extends \Test\TestCase {
}
/**
- * @dataProvider trustedDomainDataProvider
* @param string $trustedDomains
* @param string $testDomain
* @param bool $result
*/
- public function testIsTrustedDomain($trustedDomains, $testDomain, $result) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('trustedDomainDataProvider')]
+ public function testIsTrustedDomain($trustedDomains, $testDomain, $result): void {
$this->config->method('getSystemValue')
->willReturnMap([
['overwritehost', '', ''],
@@ -63,7 +63,7 @@ class TrustedDomainHelperTest extends \Test\TestCase {
/**
* @return array
*/
- public function trustedDomainDataProvider() {
+ public static function trustedDomainDataProvider(): array {
$trustedHostTestList = [
'host.one.test',
'host.two.test',
@@ -134,7 +134,7 @@ class TrustedDomainHelperTest extends \Test\TestCase {
];
}
- public function testIsTrustedDomainOverwriteHost() {
+ public function testIsTrustedDomainOverwriteHost(): void {
$this->config->method('getSystemValue')
->with('overwritehost')
->willReturn('myproxyhost');
diff --git a/tests/lib/Security/VerificationToken/VerificationTokenTest.php b/tests/lib/Security/VerificationToken/VerificationTokenTest.php
index f8573478fa5..7123cc8b013 100644
--- a/tests/lib/Security/VerificationToken/VerificationTokenTest.php
+++ b/tests/lib/Security/VerificationToken/VerificationTokenTest.php
@@ -52,13 +52,13 @@ class VerificationTokenTest extends TestCase {
);
}
- public function testTokenUserUnknown() {
+ public function testTokenUserUnknown(): void {
$this->expectException(InvalidTokenException::class);
$this->expectExceptionCode(InvalidTokenException::USER_UNKNOWN);
$this->token->check('encryptedToken', null, 'fingerprintToken', 'foobar');
}
- public function testTokenUserUnknown2() {
+ public function testTokenUserUnknown2(): void {
$user = $this->createMock(IUser::class);
$user->expects($this->atLeastOnce())
->method('isEnabled')
@@ -69,7 +69,7 @@ class VerificationTokenTest extends TestCase {
$this->token->check('encryptedToken', $user, 'fingerprintToken', 'foobar');
}
- public function testTokenNotFound() {
+ public function testTokenNotFound(): void {
$user = $this->createMock(IUser::class);
$user->expects($this->atLeastOnce())
->method('isEnabled')
@@ -85,7 +85,7 @@ class VerificationTokenTest extends TestCase {
$this->token->check('encryptedToken', $user, 'fingerprintToken', 'foobar');
}
- public function testTokenDecryptionError() {
+ public function testTokenDecryptionError(): void {
$user = $this->createMock(IUser::class);
$user->expects($this->atLeastOnce())
->method('isEnabled')
@@ -112,7 +112,7 @@ class VerificationTokenTest extends TestCase {
$this->token->check('encryptedToken', $user, 'fingerprintToken', 'foobar');
}
- public function testTokenInvalidFormat() {
+ public function testTokenInvalidFormat(): void {
$user = $this->createMock(IUser::class);
$user->expects($this->atLeastOnce())
->method('isEnabled')
@@ -139,7 +139,7 @@ class VerificationTokenTest extends TestCase {
$this->token->check('encryptedToken', $user, 'fingerprintToken', 'foobar');
}
- public function testTokenExpired() {
+ public function testTokenExpired(): void {
$user = $this->createMock(IUser::class);
$user->expects($this->atLeastOnce())
->method('isEnabled')
@@ -173,7 +173,7 @@ class VerificationTokenTest extends TestCase {
$this->token->check('encryptedToken', $user, 'fingerprintToken', 'foobar');
}
- public function testTokenExpiredByLogin() {
+ public function testTokenExpiredByLogin(): void {
$user = $this->createMock(IUser::class);
$user->expects($this->atLeastOnce())
->method('isEnabled')
@@ -207,7 +207,7 @@ class VerificationTokenTest extends TestCase {
$this->token->check('encryptedToken', $user, 'fingerprintToken', 'foobar', true);
}
- public function testTokenMismatch() {
+ public function testTokenMismatch(): void {
$user = $this->createMock(IUser::class);
$user->expects($this->atLeastOnce())
->method('isEnabled')
@@ -241,7 +241,7 @@ class VerificationTokenTest extends TestCase {
$this->token->check('encryptedToken', $user, 'fingerprintToken', 'foobar');
}
- public function testTokenSuccess() {
+ public function testTokenSuccess(): void {
$user = $this->createMock(IUser::class);
$user->expects($this->atLeastOnce())
->method('isEnabled')
@@ -273,7 +273,7 @@ class VerificationTokenTest extends TestCase {
$this->token->check('barfoo', $user, 'fingerprintToken', 'foobar');
}
- public function testCreate() {
+ public function testCreate(): void {
$user = $this->createMock(IUser::class);
$user->expects($this->any())
->method('getUID')