aboutsummaryrefslogtreecommitdiffstats
path: root/tests/lib/AppFramework/Middleware/Security
diff options
context:
space:
mode:
Diffstat (limited to 'tests/lib/AppFramework/Middleware/Security')
-rw-r--r--tests/lib/AppFramework/Middleware/Security/BruteForceMiddlewareTest.php62
-rw-r--r--tests/lib/AppFramework/Middleware/Security/CORSMiddlewareTest.php102
-rw-r--r--tests/lib/AppFramework/Middleware/Security/CSPMiddlewareTest.php51
-rw-r--r--tests/lib/AppFramework/Middleware/Security/FeaturePolicyMiddlewareTest.php25
-rw-r--r--tests/lib/AppFramework/Middleware/Security/Mock/CORSMiddlewareController.php23
-rw-r--r--tests/lib/AppFramework/Middleware/Security/Mock/NormalController.php24
-rw-r--r--tests/lib/AppFramework/Middleware/Security/Mock/OCSController.php20
-rw-r--r--tests/lib/AppFramework/Middleware/Security/Mock/PasswordConfirmationMiddlewareController.php27
-rw-r--r--tests/lib/AppFramework/Middleware/Security/Mock/SecurityMiddlewareController.php34
-rw-r--r--tests/lib/AppFramework/Middleware/Security/PasswordConfirmationMiddlewareTest.php121
-rw-r--r--tests/lib/AppFramework/Middleware/Security/RateLimitingMiddlewareTest.php32
-rw-r--r--tests/lib/AppFramework/Middleware/Security/SameSiteCookieMiddlewareTest.php36
-rw-r--r--tests/lib/AppFramework/Middleware/Security/SecurityMiddlewareTest.php225
13 files changed, 345 insertions, 437 deletions
diff --git a/tests/lib/AppFramework/Middleware/Security/BruteForceMiddlewareTest.php b/tests/lib/AppFramework/Middleware/Security/BruteForceMiddlewareTest.php
index 0492d5f7fcf..3fd2cb38a33 100644
--- a/tests/lib/AppFramework/Middleware/Security/BruteForceMiddlewareTest.php
+++ b/tests/lib/AppFramework/Middleware/Security/BruteForceMiddlewareTest.php
@@ -1,23 +1,8 @@
<?php
+
/**
- * @copyright Copyright (c) 2023 Joas Schilling <coding@schilljs.com>
- * @copyright Copyright (c) 2017 Lukas Reschke <lukas@statuscode.ch>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace Test\AppFramework\Middleware\Security;
@@ -114,13 +99,19 @@ class BruteForceMiddlewareTest extends TestCase {
->expects($this->once())
->method('getRemoteAddress')
->willReturn('::1');
+
+ $calls = [
+ ['::1', 'first'],
+ ['::1', 'second'],
+ ];
$this->throttler
->expects($this->exactly(2))
->method('sleepDelayOrThrowOnMax')
- ->withConsecutive(
- ['::1', 'first'],
- ['::1', 'second'],
- );
+ ->willReturnCallback(function () use (&$calls) {
+ $expected = array_shift($calls);
+ $this->assertEquals($expected, func_get_args());
+ return 0;
+ });
$controller = new TestController('test', $this->request);
$this->reflector->reflect($controller, 'multipleAttributes');
@@ -237,20 +228,31 @@ class BruteForceMiddlewareTest extends TestCase {
->expects($this->once())
->method('getRemoteAddress')
->willReturn('::1');
+
+ $sleepCalls = [
+ ['::1', 'first'],
+ ['::1', 'second'],
+ ];
$this->throttler
->expects($this->exactly(2))
->method('sleepDelayOrThrowOnMax')
- ->withConsecutive(
- ['::1', 'first'],
- ['::1', 'second'],
- );
+ ->willReturnCallback(function () use (&$sleepCalls) {
+ $expected = array_shift($sleepCalls);
+ $this->assertEquals($expected, func_get_args());
+ return 0;
+ });
+
+ $attemptCalls = [
+ ['first', '::1', []],
+ ['second', '::1', []],
+ ];
$this->throttler
->expects($this->exactly(2))
->method('registerAttempt')
- ->withConsecutive(
- ['first', '::1'],
- ['second', '::1'],
- );
+ ->willReturnCallback(function () use (&$attemptCalls): void {
+ $expected = array_shift($attemptCalls);
+ $this->assertEquals($expected, func_get_args());
+ });
$controller = new TestController('test', $this->request);
$this->reflector->reflect($controller, 'multipleAttributes');
diff --git a/tests/lib/AppFramework/Middleware/Security/CORSMiddlewareTest.php b/tests/lib/AppFramework/Middleware/Security/CORSMiddlewareTest.php
index 80c2ed84451..c325ae638fb 100644
--- a/tests/lib/AppFramework/Middleware/Security/CORSMiddlewareTest.php
+++ b/tests/lib/AppFramework/Middleware/Security/CORSMiddlewareTest.php
@@ -1,20 +1,17 @@
<?php
+
/**
- * ownCloud - App Framework
- *
- * This file is licensed under the Affero General Public License version 3 or
- * later. See the COPYING file.
- *
- * @author Bernhard Posselt <dev@bernhard-posselt.com>
- * @copyright Bernhard Posselt 2014
+ * SPDX-FileCopyrightText: 2016-2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2014-2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
-
namespace Test\AppFramework\Middleware\Security;
use OC\AppFramework\Http\Request;
use OC\AppFramework\Middleware\Security\CORSMiddleware;
use OC\AppFramework\Middleware\Security\Exceptions\SecurityException;
use OC\AppFramework\Utility\ControllerMethodReflector;
+use OC\Authentication\Exceptions\PasswordLoginForbiddenException;
use OC\User\Session;
use OCP\AppFramework\Http\JSONResponse;
use OCP\AppFramework\Http\Response;
@@ -23,6 +20,7 @@ use OCP\IRequest;
use OCP\IRequestId;
use OCP\Security\Bruteforce\IThrottler;
use PHPUnit\Framework\MockObject\MockObject;
+use Psr\Log\LoggerInterface;
use Test\AppFramework\Middleware\Security\Mock\CORSMiddlewareController;
class CORSMiddlewareTest extends \Test\TestCase {
@@ -34,28 +32,28 @@ class CORSMiddlewareTest extends \Test\TestCase {
private $throttler;
/** @var CORSMiddlewareController */
private $controller;
+ private LoggerInterface $logger;
protected function setUp(): void {
parent::setUp();
$this->reflector = new ControllerMethodReflector();
$this->session = $this->createMock(Session::class);
$this->throttler = $this->createMock(IThrottler::class);
+ $this->logger = $this->createMock(LoggerInterface::class);
$this->controller = new CORSMiddlewareController(
'test',
$this->createMock(IRequest::class)
);
}
- public function dataSetCORSAPIHeader(): array {
+ public static function dataSetCORSAPIHeader(): array {
return [
['testSetCORSAPIHeader'],
['testSetCORSAPIHeaderAttribute'],
];
}
- /**
- * @dataProvider dataSetCORSAPIHeader
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataSetCORSAPIHeader')]
public function testSetCORSAPIHeader(string $method): void {
$request = new Request(
[
@@ -67,7 +65,7 @@ class CORSMiddlewareTest extends \Test\TestCase {
$this->createMock(IConfig::class)
);
$this->reflector->reflect($this->controller, $method);
- $middleware = new CORSMiddleware($request, $this->reflector, $this->session, $this->throttler);
+ $middleware = new CORSMiddleware($request, $this->reflector, $this->session, $this->throttler, $this->logger);
$response = $middleware->afterController($this->controller, $method, new Response());
$headers = $response->getHeaders();
@@ -84,23 +82,21 @@ class CORSMiddlewareTest extends \Test\TestCase {
$this->createMock(IRequestId::class),
$this->createMock(IConfig::class)
);
- $middleware = new CORSMiddleware($request, $this->reflector, $this->session, $this->throttler);
+ $middleware = new CORSMiddleware($request, $this->reflector, $this->session, $this->throttler, $this->logger);
$response = $middleware->afterController($this->controller, __FUNCTION__, new Response());
$headers = $response->getHeaders();
$this->assertFalse(array_key_exists('Access-Control-Allow-Origin', $headers));
}
- public function dataNoOriginHeaderNoCORSHEADER(): array {
+ public static function dataNoOriginHeaderNoCORSHEADER(): array {
return [
['testNoOriginHeaderNoCORSHEADER'],
['testNoOriginHeaderNoCORSHEADERAttribute'],
];
}
- /**
- * @dataProvider dataNoOriginHeaderNoCORSHEADER
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataNoOriginHeaderNoCORSHEADER')]
public function testNoOriginHeaderNoCORSHEADER(string $method): void {
$request = new Request(
[],
@@ -108,25 +104,23 @@ class CORSMiddlewareTest extends \Test\TestCase {
$this->createMock(IConfig::class)
);
$this->reflector->reflect($this->controller, $method);
- $middleware = new CORSMiddleware($request, $this->reflector, $this->session, $this->throttler);
+ $middleware = new CORSMiddleware($request, $this->reflector, $this->session, $this->throttler, $this->logger);
$response = $middleware->afterController($this->controller, $method, new Response());
$headers = $response->getHeaders();
$this->assertFalse(array_key_exists('Access-Control-Allow-Origin', $headers));
}
- public function dataCorsIgnoredIfWithCredentialsHeaderPresent(): array {
+ public static function dataCorsIgnoredIfWithCredentialsHeaderPresent(): array {
return [
['testCorsIgnoredIfWithCredentialsHeaderPresent'],
['testCorsAttributeIgnoredIfWithCredentialsHeaderPresent'],
];
}
- /**
- * @dataProvider dataCorsIgnoredIfWithCredentialsHeaderPresent
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataCorsIgnoredIfWithCredentialsHeaderPresent')]
public function testCorsIgnoredIfWithCredentialsHeaderPresent(string $method): void {
- $this->expectException(\OC\AppFramework\Middleware\Security\Exceptions\SecurityException::class);
+ $this->expectException(SecurityException::class);
$request = new Request(
[
@@ -138,14 +132,14 @@ class CORSMiddlewareTest extends \Test\TestCase {
$this->createMock(IConfig::class)
);
$this->reflector->reflect($this->controller, $method);
- $middleware = new CORSMiddleware($request, $this->reflector, $this->session, $this->throttler);
+ $middleware = new CORSMiddleware($request, $this->reflector, $this->session, $this->throttler, $this->logger);
$response = new Response();
$response->addHeader('AcCess-control-Allow-Credentials ', 'TRUE');
$middleware->afterController($this->controller, $method, $response);
}
- public function dataNoCORSOnAnonymousPublicPage(): array {
+ public static function dataNoCORSOnAnonymousPublicPage(): array {
return [
['testNoCORSOnAnonymousPublicPage'],
['testNoCORSOnAnonymousPublicPageAttribute'],
@@ -154,9 +148,7 @@ class CORSMiddlewareTest extends \Test\TestCase {
];
}
- /**
- * @dataProvider dataNoCORSOnAnonymousPublicPage
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataNoCORSOnAnonymousPublicPage')]
public function testNoCORSOnAnonymousPublicPage(string $method): void {
$request = new Request(
[],
@@ -164,7 +156,7 @@ class CORSMiddlewareTest extends \Test\TestCase {
$this->createMock(IConfig::class)
);
$this->reflector->reflect($this->controller, $method);
- $middleware = new CORSMiddleware($request, $this->reflector, $this->session, $this->throttler);
+ $middleware = new CORSMiddleware($request, $this->reflector, $this->session, $this->throttler, $this->logger);
$this->session->expects($this->once())
->method('isLoggedIn')
->willReturn(false);
@@ -179,7 +171,7 @@ class CORSMiddlewareTest extends \Test\TestCase {
$middleware->beforeController($this->controller, $method);
}
- public function dataCORSShouldNeverAllowCookieAuth(): array {
+ public static function dataCORSShouldNeverAllowCookieAuth(): array {
return [
['testCORSShouldNeverAllowCookieAuth'],
['testCORSShouldNeverAllowCookieAuthAttribute'],
@@ -188,9 +180,7 @@ class CORSMiddlewareTest extends \Test\TestCase {
];
}
- /**
- * @dataProvider dataCORSShouldNeverAllowCookieAuth
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataCORSShouldNeverAllowCookieAuth')]
public function testCORSShouldNeverAllowCookieAuth(string $method): void {
$request = new Request(
[],
@@ -198,7 +188,7 @@ class CORSMiddlewareTest extends \Test\TestCase {
$this->createMock(IConfig::class)
);
$this->reflector->reflect($this->controller, $method);
- $middleware = new CORSMiddleware($request, $this->reflector, $this->session, $this->throttler);
+ $middleware = new CORSMiddleware($request, $this->reflector, $this->session, $this->throttler, $this->logger);
$this->session->expects($this->once())
->method('isLoggedIn')
->willReturn(true);
@@ -213,16 +203,14 @@ class CORSMiddlewareTest extends \Test\TestCase {
$middleware->beforeController($this->controller, $method);
}
- public function dataCORSShouldRelogin(): array {
+ public static function dataCORSShouldRelogin(): array {
return [
['testCORSShouldRelogin'],
['testCORSAttributeShouldRelogin'],
];
}
- /**
- * @dataProvider dataCORSShouldRelogin
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataCORSShouldRelogin')]
public function testCORSShouldRelogin(string $method): void {
$request = new Request(
['server' => [
@@ -239,23 +227,21 @@ class CORSMiddlewareTest extends \Test\TestCase {
->with($this->equalTo('user'), $this->equalTo('pass'))
->willReturn(true);
$this->reflector->reflect($this->controller, $method);
- $middleware = new CORSMiddleware($request, $this->reflector, $this->session, $this->throttler);
+ $middleware = new CORSMiddleware($request, $this->reflector, $this->session, $this->throttler, $this->logger);
$middleware->beforeController($this->controller, $method);
}
- public function dataCORSShouldFailIfPasswordLoginIsForbidden(): array {
+ public static function dataCORSShouldFailIfPasswordLoginIsForbidden(): array {
return [
['testCORSShouldFailIfPasswordLoginIsForbidden'],
['testCORSAttributeShouldFailIfPasswordLoginIsForbidden'],
];
}
- /**
- * @dataProvider dataCORSShouldFailIfPasswordLoginIsForbidden
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataCORSShouldFailIfPasswordLoginIsForbidden')]
public function testCORSShouldFailIfPasswordLoginIsForbidden(string $method): void {
- $this->expectException(\OC\AppFramework\Middleware\Security\Exceptions\SecurityException::class);
+ $this->expectException(SecurityException::class);
$request = new Request(
['server' => [
@@ -270,25 +256,23 @@ class CORSMiddlewareTest extends \Test\TestCase {
$this->session->expects($this->once())
->method('logClientIn')
->with($this->equalTo('user'), $this->equalTo('pass'))
- ->will($this->throwException(new \OC\Authentication\Exceptions\PasswordLoginForbiddenException));
+ ->willThrowException(new PasswordLoginForbiddenException);
$this->reflector->reflect($this->controller, $method);
- $middleware = new CORSMiddleware($request, $this->reflector, $this->session, $this->throttler);
+ $middleware = new CORSMiddleware($request, $this->reflector, $this->session, $this->throttler, $this->logger);
$middleware->beforeController($this->controller, $method);
}
- public function dataCORSShouldNotAllowCookieAuth(): array {
+ public static function dataCORSShouldNotAllowCookieAuth(): array {
return [
['testCORSShouldNotAllowCookieAuth'],
['testCORSAttributeShouldNotAllowCookieAuth'],
];
}
- /**
- * @dataProvider dataCORSShouldNotAllowCookieAuth
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataCORSShouldNotAllowCookieAuth')]
public function testCORSShouldNotAllowCookieAuth(string $method): void {
- $this->expectException(\OC\AppFramework\Middleware\Security\Exceptions\SecurityException::class);
+ $this->expectException(SecurityException::class);
$request = new Request(
['server' => [
@@ -305,12 +289,12 @@ class CORSMiddlewareTest extends \Test\TestCase {
->with($this->equalTo('user'), $this->equalTo('pass'))
->willReturn(false);
$this->reflector->reflect($this->controller, $method);
- $middleware = new CORSMiddleware($request, $this->reflector, $this->session, $this->throttler);
+ $middleware = new CORSMiddleware($request, $this->reflector, $this->session, $this->throttler, $this->logger);
$middleware->beforeController($this->controller, $method);
}
- public function testAfterExceptionWithSecurityExceptionNoStatus() {
+ public function testAfterExceptionWithSecurityExceptionNoStatus(): void {
$request = new Request(
['server' => [
'PHP_AUTH_USER' => 'user',
@@ -319,14 +303,14 @@ class CORSMiddlewareTest extends \Test\TestCase {
$this->createMock(IRequestId::class),
$this->createMock(IConfig::class)
);
- $middleware = new CORSMiddleware($request, $this->reflector, $this->session, $this->throttler);
+ $middleware = new CORSMiddleware($request, $this->reflector, $this->session, $this->throttler, $this->logger);
$response = $middleware->afterException($this->controller, __FUNCTION__, new SecurityException('A security exception'));
$expected = new JSONResponse(['message' => 'A security exception'], 500);
$this->assertEquals($expected, $response);
}
- public function testAfterExceptionWithSecurityExceptionWithStatus() {
+ public function testAfterExceptionWithSecurityExceptionWithStatus(): void {
$request = new Request(
['server' => [
'PHP_AUTH_USER' => 'user',
@@ -335,14 +319,14 @@ class CORSMiddlewareTest extends \Test\TestCase {
$this->createMock(IRequestId::class),
$this->createMock(IConfig::class)
);
- $middleware = new CORSMiddleware($request, $this->reflector, $this->session, $this->throttler);
+ $middleware = new CORSMiddleware($request, $this->reflector, $this->session, $this->throttler, $this->logger);
$response = $middleware->afterException($this->controller, __FUNCTION__, new SecurityException('A security exception', 501));
$expected = new JSONResponse(['message' => 'A security exception'], 501);
$this->assertEquals($expected, $response);
}
- public function testAfterExceptionWithRegularException() {
+ public function testAfterExceptionWithRegularException(): void {
$this->expectException(\Exception::class);
$this->expectExceptionMessage('A regular exception');
@@ -354,7 +338,7 @@ class CORSMiddlewareTest extends \Test\TestCase {
$this->createMock(IRequestId::class),
$this->createMock(IConfig::class)
);
- $middleware = new CORSMiddleware($request, $this->reflector, $this->session, $this->throttler);
+ $middleware = new CORSMiddleware($request, $this->reflector, $this->session, $this->throttler, $this->logger);
$middleware->afterException($this->controller, __FUNCTION__, new \Exception('A regular exception'));
}
}
diff --git a/tests/lib/AppFramework/Middleware/Security/CSPMiddlewareTest.php b/tests/lib/AppFramework/Middleware/Security/CSPMiddlewareTest.php
index 284634f7db2..b0b41b27cb9 100644
--- a/tests/lib/AppFramework/Middleware/Security/CSPMiddlewareTest.php
+++ b/tests/lib/AppFramework/Middleware/Security/CSPMiddlewareTest.php
@@ -2,25 +2,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2019, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace Test\AppFramework\Middleware\Security;
@@ -29,23 +12,19 @@ use OC\AppFramework\Middleware\Security\CSPMiddleware;
use OC\Security\CSP\ContentSecurityPolicy;
use OC\Security\CSP\ContentSecurityPolicyManager;
use OC\Security\CSP\ContentSecurityPolicyNonceManager;
-use OC\Security\CSRF\CsrfToken;
-use OC\Security\CSRF\CsrfTokenManager;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http\EmptyContentSecurityPolicy;
use OCP\AppFramework\Http\Response;
use PHPUnit\Framework\MockObject\MockObject;
class CSPMiddlewareTest extends \Test\TestCase {
- /** @var CSPMiddleware|MockObject */
+ /** @var CSPMiddleware&MockObject */
private $middleware;
- /** @var Controller|MockObject */
+ /** @var Controller&MockObject */
private $controller;
- /** @var ContentSecurityPolicyManager|MockObject */
+ /** @var ContentSecurityPolicyManager&MockObject */
private $contentSecurityPolicyManager;
- /** @var CsrfTokenManager|MockObject */
- private $csrfTokenManager;
- /** @var ContentSecurityPolicyNonceManager|MockObject */
+ /** @var ContentSecurityPolicyNonceManager&MockObject */
private $cspNonceManager;
protected function setUp(): void {
@@ -53,16 +32,14 @@ class CSPMiddlewareTest extends \Test\TestCase {
$this->controller = $this->createMock(Controller::class);
$this->contentSecurityPolicyManager = $this->createMock(ContentSecurityPolicyManager::class);
- $this->csrfTokenManager = $this->createMock(CsrfTokenManager::class);
$this->cspNonceManager = $this->createMock(ContentSecurityPolicyNonceManager::class);
$this->middleware = new CSPMiddleware(
$this->contentSecurityPolicyManager,
$this->cspNonceManager,
- $this->csrfTokenManager
);
}
- public function testAfterController() {
+ public function testAfterController(): void {
$this->cspNonceManager
->expects($this->once())
->method('browserSupportsCspV3')
@@ -94,7 +71,7 @@ class CSPMiddlewareTest extends \Test\TestCase {
$this->middleware->afterController($this->controller, 'test', $response);
}
- public function testAfterControllerEmptyCSP() {
+ public function testAfterControllerEmptyCSP(): void {
$response = $this->createMock(Response::class);
$emptyPolicy = new EmptyContentSecurityPolicy();
$response->expects($this->any())
@@ -106,19 +83,15 @@ class CSPMiddlewareTest extends \Test\TestCase {
$this->middleware->afterController($this->controller, 'test', $response);
}
- public function testAfterControllerWithContentSecurityPolicy3Support() {
+ public function testAfterControllerWithContentSecurityPolicy3Support(): void {
$this->cspNonceManager
->expects($this->once())
->method('browserSupportsCspV3')
->willReturn(true);
- $token = $this->createMock(CsrfToken::class);
- $token
- ->expects($this->once())
- ->method('getEncryptedValue')
- ->willReturn('MyEncryptedToken');
- $this->csrfTokenManager
+ $token = base64_encode('the-nonce');
+ $this->cspNonceManager
->expects($this->once())
- ->method('getToken')
+ ->method('getNonce')
->willReturn($token);
$response = $this->createMock(Response::class);
$defaultPolicy = new ContentSecurityPolicy();
diff --git a/tests/lib/AppFramework/Middleware/Security/FeaturePolicyMiddlewareTest.php b/tests/lib/AppFramework/Middleware/Security/FeaturePolicyMiddlewareTest.php
index 154b43f69a5..55a70d4c040 100644
--- a/tests/lib/AppFramework/Middleware/Security/FeaturePolicyMiddlewareTest.php
+++ b/tests/lib/AppFramework/Middleware/Security/FeaturePolicyMiddlewareTest.php
@@ -2,25 +2,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2019, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace Test\AppFramework\Middleware\Security;
@@ -51,7 +34,7 @@ class FeaturePolicyMiddlewareTest extends \Test\TestCase {
);
}
- public function testAfterController() {
+ public function testAfterController(): void {
$response = $this->createMock(Response::class);
$defaultPolicy = new FeaturePolicy();
$defaultPolicy->addAllowedCameraDomain('defaultpolicy');
@@ -73,7 +56,7 @@ class FeaturePolicyMiddlewareTest extends \Test\TestCase {
$this->middleware->afterController($this->controller, 'test', $response);
}
- public function testAfterControllerEmptyCSP() {
+ public function testAfterControllerEmptyCSP(): void {
$response = $this->createMock(Response::class);
$emptyPolicy = new EmptyFeaturePolicy();
$response->method('getFeaturePolicy')
diff --git a/tests/lib/AppFramework/Middleware/Security/Mock/CORSMiddlewareController.php b/tests/lib/AppFramework/Middleware/Security/Mock/CORSMiddlewareController.php
index 44e6c7a588b..8ab3a48b62e 100644
--- a/tests/lib/AppFramework/Middleware/Security/Mock/CORSMiddlewareController.php
+++ b/tests/lib/AppFramework/Middleware/Security/Mock/CORSMiddlewareController.php
@@ -3,32 +3,17 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2023 Joas Schilling <coding@schilljs.com>
- *
- * @author Joas Schilling <coding@schilljs.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace Test\AppFramework\Middleware\Security\Mock;
+use OCP\AppFramework\Controller;
use OCP\AppFramework\Http\Attribute\CORS;
use OCP\AppFramework\Http\Attribute\PublicPage;
-class CORSMiddlewareController extends \OCP\AppFramework\Controller {
+class CORSMiddlewareController extends Controller {
/**
* @CORS
*/
diff --git a/tests/lib/AppFramework/Middleware/Security/Mock/NormalController.php b/tests/lib/AppFramework/Middleware/Security/Mock/NormalController.php
index e732b89e308..4d6778e98b9 100644
--- a/tests/lib/AppFramework/Middleware/Security/Mock/NormalController.php
+++ b/tests/lib/AppFramework/Middleware/Security/Mock/NormalController.php
@@ -3,29 +3,15 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2023 Joas Schilling <coding@schilljs.com>
- *
- * @author Joas Schilling <coding@schilljs.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace Test\AppFramework\Middleware\Security\Mock;
-class NormalController extends \OCP\AppFramework\Controller {
+use OCP\AppFramework\Controller;
+
+class NormalController extends Controller {
public function foo() {
}
}
diff --git a/tests/lib/AppFramework/Middleware/Security/Mock/OCSController.php b/tests/lib/AppFramework/Middleware/Security/Mock/OCSController.php
index d053124fe19..93e793ecca9 100644
--- a/tests/lib/AppFramework/Middleware/Security/Mock/OCSController.php
+++ b/tests/lib/AppFramework/Middleware/Security/Mock/OCSController.php
@@ -3,24 +3,8 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2023 Joas Schilling <coding@schilljs.com>
- *
- * @author Joas Schilling <coding@schilljs.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace Test\AppFramework\Middleware\Security\Mock;
diff --git a/tests/lib/AppFramework/Middleware/Security/Mock/PasswordConfirmationMiddlewareController.php b/tests/lib/AppFramework/Middleware/Security/Mock/PasswordConfirmationMiddlewareController.php
index 5b83575f711..cd1cdaa49ca 100644
--- a/tests/lib/AppFramework/Middleware/Security/Mock/PasswordConfirmationMiddlewareController.php
+++ b/tests/lib/AppFramework/Middleware/Security/Mock/PasswordConfirmationMiddlewareController.php
@@ -3,31 +3,16 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2023 Joas Schilling <coding@schilljs.com>
- *
- * @author Joas Schilling <coding@schilljs.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace Test\AppFramework\Middleware\Security\Mock;
+use OCP\AppFramework\Controller;
use OCP\AppFramework\Http\Attribute\PasswordConfirmationRequired;
-class PasswordConfirmationMiddlewareController extends \OCP\AppFramework\Controller {
+class PasswordConfirmationMiddlewareController extends Controller {
public function testNoAnnotationNorAttribute() {
}
@@ -46,4 +31,8 @@ class PasswordConfirmationMiddlewareController extends \OCP\AppFramework\Control
#[PasswordConfirmationRequired]
public function testAttribute() {
}
+
+ #[PasswordConfirmationRequired]
+ public function testSSO() {
+ }
}
diff --git a/tests/lib/AppFramework/Middleware/Security/Mock/SecurityMiddlewareController.php b/tests/lib/AppFramework/Middleware/Security/Mock/SecurityMiddlewareController.php
index b0a59faba78..c8f9878b0c1 100644
--- a/tests/lib/AppFramework/Middleware/Security/Mock/SecurityMiddlewareController.php
+++ b/tests/lib/AppFramework/Middleware/Security/Mock/SecurityMiddlewareController.php
@@ -3,35 +3,21 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2023 Joas Schilling <coding@schilljs.com>
- *
- * @author Joas Schilling <coding@schilljs.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace Test\AppFramework\Middleware\Security\Mock;
+use OCP\AppFramework\Controller;
+use OCP\AppFramework\Http\Attribute\ExAppRequired;
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
use OCP\AppFramework\Http\Attribute\NoCSRFRequired;
use OCP\AppFramework\Http\Attribute\PublicPage;
use OCP\AppFramework\Http\Attribute\StrictCookiesRequired;
use OCP\AppFramework\Http\Attribute\SubAdminRequired;
-class SecurityMiddlewareController extends \OCP\AppFramework\Controller {
+class SecurityMiddlewareController extends Controller {
/**
* @PublicPage
* @NoCSRFRequired
@@ -172,4 +158,14 @@ class SecurityMiddlewareController extends \OCP\AppFramework\Controller {
#[PublicPage]
public function testAttributeNoAdminRequiredNoCSRFRequiredPublicPage() {
}
+
+ /**
+ * @ExAppRequired
+ */
+ public function testAnnotationExAppRequired() {
+ }
+
+ #[ExAppRequired]
+ public function testAttributeExAppRequired() {
+ }
}
diff --git a/tests/lib/AppFramework/Middleware/Security/PasswordConfirmationMiddlewareTest.php b/tests/lib/AppFramework/Middleware/Security/PasswordConfirmationMiddlewareTest.php
index 3752259c61b..90e801ca471 100644
--- a/tests/lib/AppFramework/Middleware/Security/PasswordConfirmationMiddlewareTest.php
+++ b/tests/lib/AppFramework/Middleware/Security/PasswordConfirmationMiddlewareTest.php
@@ -1,24 +1,8 @@
<?php
+
/**
- * @copyright 2018, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace Test\AppFramework\Middleware\Security;
@@ -26,29 +10,39 @@ namespace Test\AppFramework\Middleware\Security;
use OC\AppFramework\Middleware\Security\Exceptions\NotConfirmedException;
use OC\AppFramework\Middleware\Security\PasswordConfirmationMiddleware;
use OC\AppFramework\Utility\ControllerMethodReflector;
+use OC\Authentication\Token\IProvider;
+use OC\User\Manager;
use OCP\AppFramework\Utility\ITimeFactory;
+use OCP\Authentication\Token\IToken;
use OCP\IRequest;
use OCP\ISession;
use OCP\IUser;
use OCP\IUserSession;
+use Psr\Log\LoggerInterface;
use Test\AppFramework\Middleware\Security\Mock\PasswordConfirmationMiddlewareController;
use Test\TestCase;
class PasswordConfirmationMiddlewareTest extends TestCase {
/** @var ControllerMethodReflector */
private $reflector;
- /** @var ISession|\PHPUnit\Framework\MockObject\MockObject */
+ /** @var ISession&\PHPUnit\Framework\MockObject\MockObject */
private $session;
- /** @var IUserSession|\PHPUnit\Framework\MockObject\MockObject */
+ /** @var IUserSession&\PHPUnit\Framework\MockObject\MockObject */
private $userSession;
- /** @var IUser|\PHPUnit\Framework\MockObject\MockObject */
+ /** @var IUser&\PHPUnit\Framework\MockObject\MockObject */
private $user;
/** @var PasswordConfirmationMiddleware */
private $middleware;
/** @var PasswordConfirmationMiddlewareController */
private $controller;
- /** @var ITimeFactory|\PHPUnit\Framework\MockObject\MockObject */
+ /** @var ITimeFactory&\PHPUnit\Framework\MockObject\MockObject */
private $timeFactory;
+ private IProvider&\PHPUnit\Framework\MockObject\MockObject $tokenProvider;
+ private LoggerInterface $logger;
+ /** @var IRequest&\PHPUnit\Framework\MockObject\MockObject */
+ private IRequest $request;
+ /** @var Manager&\PHPUnit\Framework\MockObject\MockObject */
+ private Manager $userManager;
protected function setUp(): void {
$this->reflector = new ControllerMethodReflector();
@@ -56,6 +50,10 @@ class PasswordConfirmationMiddlewareTest extends TestCase {
$this->userSession = $this->createMock(IUserSession::class);
$this->user = $this->createMock(IUser::class);
$this->timeFactory = $this->createMock(ITimeFactory::class);
+ $this->tokenProvider = $this->createMock(IProvider::class);
+ $this->logger = $this->createMock(LoggerInterface::class);
+ $this->request = $this->createMock(IRequest::class);
+ $this->userManager = $this->createMock(Manager::class);
$this->controller = new PasswordConfirmationMiddlewareController(
'test',
$this->createMock(IRequest::class)
@@ -65,11 +63,15 @@ class PasswordConfirmationMiddlewareTest extends TestCase {
$this->reflector,
$this->session,
$this->userSession,
- $this->timeFactory
+ $this->timeFactory,
+ $this->tokenProvider,
+ $this->logger,
+ $this->request,
+ $this->userManager,
);
}
- public function testNoAnnotationNorAttribute() {
+ public function testNoAnnotationNorAttribute(): void {
$this->reflector->reflect($this->controller, __FUNCTION__);
$this->session->expects($this->never())
->method($this->anything());
@@ -79,7 +81,7 @@ class PasswordConfirmationMiddlewareTest extends TestCase {
$this->middleware->beforeController($this->controller, __FUNCTION__);
}
- public function testDifferentAnnotation() {
+ public function testDifferentAnnotation(): void {
$this->reflector->reflect($this->controller, __FUNCTION__);
$this->session->expects($this->never())
->method($this->anything());
@@ -89,10 +91,8 @@ class PasswordConfirmationMiddlewareTest extends TestCase {
$this->middleware->beforeController($this->controller, __FUNCTION__);
}
- /**
- * @dataProvider dataProvider
- */
- public function testAnnotation($backend, $lastConfirm, $currentTime, $exception) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataProvider')]
+ public function testAnnotation($backend, $lastConfirm, $currentTime, $exception): void {
$this->reflector->reflect($this->controller, __FUNCTION__);
$this->user->method('getBackendClassName')
@@ -107,6 +107,13 @@ class PasswordConfirmationMiddlewareTest extends TestCase {
$this->timeFactory->method('getTime')
->willReturn($currentTime);
+ $token = $this->createMock(IToken::class);
+ $token->method('getScopeAsArray')
+ ->willReturn([]);
+ $this->tokenProvider->expects($this->once())
+ ->method('getToken')
+ ->willReturn($token);
+
$thrown = false;
try {
$this->middleware->beforeController($this->controller, __FUNCTION__);
@@ -117,10 +124,8 @@ class PasswordConfirmationMiddlewareTest extends TestCase {
$this->assertSame($exception, $thrown);
}
- /**
- * @dataProvider dataProvider
- */
- public function testAttribute($backend, $lastConfirm, $currentTime, $exception) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataProvider')]
+ public function testAttribute($backend, $lastConfirm, $currentTime, $exception): void {
$this->reflector->reflect($this->controller, __FUNCTION__);
$this->user->method('getBackendClassName')
@@ -135,6 +140,13 @@ class PasswordConfirmationMiddlewareTest extends TestCase {
$this->timeFactory->method('getTime')
->willReturn($currentTime);
+ $token = $this->createMock(IToken::class);
+ $token->method('getScopeAsArray')
+ ->willReturn([]);
+ $this->tokenProvider->expects($this->once())
+ ->method('getToken')
+ ->willReturn($token);
+
$thrown = false;
try {
$this->middleware->beforeController($this->controller, __FUNCTION__);
@@ -145,7 +157,9 @@ class PasswordConfirmationMiddlewareTest extends TestCase {
$this->assertSame($exception, $thrown);
}
- public function dataProvider() {
+
+
+ public static function dataProvider(): array {
return [
['foo', 2000, 4000, true],
['foo', 2000, 3000, false],
@@ -155,4 +169,41 @@ class PasswordConfirmationMiddlewareTest extends TestCase {
['foo', 2000, 3816, true],
];
}
+
+ public function testSSO(): void {
+ static $sessionId = 'mySession1d';
+
+ $this->reflector->reflect($this->controller, __FUNCTION__);
+
+ $this->user->method('getBackendClassName')
+ ->willReturn('fictional_backend');
+ $this->userSession->method('getUser')
+ ->willReturn($this->user);
+
+ $this->session->method('get')
+ ->with('last-password-confirm')
+ ->willReturn(0);
+ $this->session->method('getId')
+ ->willReturn($sessionId);
+
+ $this->timeFactory->method('getTime')
+ ->willReturn(9876);
+
+ $token = $this->createMock(IToken::class);
+ $token->method('getScopeAsArray')
+ ->willReturn([IToken::SCOPE_SKIP_PASSWORD_VALIDATION => true]);
+ $this->tokenProvider->expects($this->once())
+ ->method('getToken')
+ ->with($sessionId)
+ ->willReturn($token);
+
+ $thrown = false;
+ try {
+ $this->middleware->beforeController($this->controller, __FUNCTION__);
+ } catch (NotConfirmedException) {
+ $thrown = true;
+ }
+
+ $this->assertSame(false, $thrown);
+ }
}
diff --git a/tests/lib/AppFramework/Middleware/Security/RateLimitingMiddlewareTest.php b/tests/lib/AppFramework/Middleware/Security/RateLimitingMiddlewareTest.php
index c0988ff5a11..c42baadcb1c 100644
--- a/tests/lib/AppFramework/Middleware/Security/RateLimitingMiddlewareTest.php
+++ b/tests/lib/AppFramework/Middleware/Security/RateLimitingMiddlewareTest.php
@@ -3,32 +3,15 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2023 Joas Schilling <coding@schilljs.com>
- * @copyright Copyright (c) 2017 Lukas Reschke <lukas@statuscode.ch>
- *
- * @author Joas Schilling <coding@schilljs.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace Test\AppFramework\Middleware\Security;
use OC\AppFramework\Middleware\Security\RateLimitingMiddleware;
use OC\AppFramework\Utility\ControllerMethodReflector;
+use OC\Security\Ip\BruteforceAllowList;
use OC\Security\RateLimiting\Exception\RateLimitExceededException;
use OC\Security\RateLimiting\Limiter;
use OCP\AppFramework\Controller;
@@ -36,6 +19,7 @@ use OCP\AppFramework\Http\Attribute\AnonRateLimit;
use OCP\AppFramework\Http\Attribute\UserRateLimit;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\Http\TemplateResponse;
+use OCP\IAppConfig;
use OCP\IRequest;
use OCP\ISession;
use OCP\IUser;
@@ -79,6 +63,8 @@ class RateLimitingMiddlewareTest extends TestCase {
private ControllerMethodReflector $reflector;
private Limiter|MockObject $limiter;
private ISession|MockObject $session;
+ private IAppConfig|MockObject $appConfig;
+ private BruteforceAllowList|MockObject $bruteForceAllowList;
private RateLimitingMiddleware $rateLimitingMiddleware;
protected function setUp(): void {
@@ -89,13 +75,17 @@ class RateLimitingMiddlewareTest extends TestCase {
$this->reflector = new ControllerMethodReflector();
$this->limiter = $this->createMock(Limiter::class);
$this->session = $this->createMock(ISession::class);
+ $this->appConfig = $this->createMock(IAppConfig::class);
+ $this->bruteForceAllowList = $this->createMock(BruteforceAllowList::class);
$this->rateLimitingMiddleware = new RateLimitingMiddleware(
$this->request,
$this->userSession,
$this->reflector,
$this->limiter,
- $this->session
+ $this->session,
+ $this->appConfig,
+ $this->bruteForceAllowList,
);
}
diff --git a/tests/lib/AppFramework/Middleware/Security/SameSiteCookieMiddlewareTest.php b/tests/lib/AppFramework/Middleware/Security/SameSiteCookieMiddlewareTest.php
index 787f5c92fd7..7800371f68f 100644
--- a/tests/lib/AppFramework/Middleware/Security/SameSiteCookieMiddlewareTest.php
+++ b/tests/lib/AppFramework/Middleware/Security/SameSiteCookieMiddlewareTest.php
@@ -1,24 +1,8 @@
<?php
+
/**
- * @copyright 2017, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace Test\AppFramework\Middleware\Security;
@@ -50,7 +34,7 @@ class SameSiteCookieMiddlewareTest extends TestCase {
$this->middleware = new SameSiteCookieMiddleware($this->request, $this->reflector);
}
- public function testBeforeControllerNoIndex() {
+ public function testBeforeControllerNoIndex(): void {
$this->request->method('getScriptName')
->willReturn('/ocs/v2.php');
@@ -58,7 +42,7 @@ class SameSiteCookieMiddlewareTest extends TestCase {
$this->addToAssertionCount(1);
}
- public function testBeforeControllerIndexHasAnnotation() {
+ public function testBeforeControllerIndexHasAnnotation(): void {
$this->request->method('getScriptName')
->willReturn('/index.php');
@@ -70,7 +54,7 @@ class SameSiteCookieMiddlewareTest extends TestCase {
$this->addToAssertionCount(1);
}
- public function testBeforeControllerIndexNoAnnotationPassingCheck() {
+ public function testBeforeControllerIndexNoAnnotationPassingCheck(): void {
$this->request->method('getScriptName')
->willReturn('/index.php');
@@ -85,7 +69,7 @@ class SameSiteCookieMiddlewareTest extends TestCase {
$this->addToAssertionCount(1);
}
- public function testBeforeControllerIndexNoAnnotationFailingCheck() {
+ public function testBeforeControllerIndexNoAnnotationFailingCheck(): void {
$this->expectException(LaxSameSiteCookieFailedException::class);
$this->request->method('getScriptName')
@@ -101,7 +85,7 @@ class SameSiteCookieMiddlewareTest extends TestCase {
$this->middleware->beforeController($this->createMock(Controller::class), 'foo');
}
- public function testAfterExceptionNoLaxCookie() {
+ public function testAfterExceptionNoLaxCookie(): void {
$ex = new SecurityException();
try {
@@ -112,7 +96,7 @@ class SameSiteCookieMiddlewareTest extends TestCase {
}
}
- public function testAfterExceptionLaxCookie() {
+ public function testAfterExceptionLaxCookie(): void {
$ex = new LaxSameSiteCookieFailedException();
$this->request->method('getRequestUri')
@@ -120,7 +104,7 @@ class SameSiteCookieMiddlewareTest extends TestCase {
$middleware = $this->getMockBuilder(SameSiteCookieMiddleware::class)
->setConstructorArgs([$this->request, $this->reflector])
- ->setMethods(['setSameSiteCookie'])
+ ->onlyMethods(['setSameSiteCookie'])
->getMock();
$middleware->expects($this->once())
diff --git a/tests/lib/AppFramework/Middleware/Security/SecurityMiddlewareTest.php b/tests/lib/AppFramework/Middleware/Security/SecurityMiddlewareTest.php
index 7c59a8c1452..0c6fc21357d 100644
--- a/tests/lib/AppFramework/Middleware/Security/SecurityMiddlewareTest.php
+++ b/tests/lib/AppFramework/Middleware/Security/SecurityMiddlewareTest.php
@@ -1,23 +1,9 @@
<?php
+
/**
- * @author Bernhard Posselt <dev@bernhard-posselt.com>
- * @author Lukas Reschke <lukas@owncloud.com>
- *
- * @copyright Copyright (c) 2015, ownCloud, Inc.
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace Test\AppFramework\Middleware\Security;
@@ -26,6 +12,7 @@ use OC\AppFramework\Http;
use OC\AppFramework\Http\Request;
use OC\AppFramework\Middleware\Security\Exceptions\AppNotEnabledException;
use OC\AppFramework\Middleware\Security\Exceptions\CrossSiteRequestForgeryException;
+use OC\AppFramework\Middleware\Security\Exceptions\ExAppRequiredException;
use OC\AppFramework\Middleware\Security\Exceptions\NotAdminException;
use OC\AppFramework\Middleware\Security\Exceptions\NotLoggedInException;
use OC\AppFramework\Middleware\Security\Exceptions\SecurityException;
@@ -33,17 +20,23 @@ use OC\Appframework\Middleware\Security\Exceptions\StrictCookieMissingException;
use OC\AppFramework\Middleware\Security\SecurityMiddleware;
use OC\AppFramework\Utility\ControllerMethodReflector;
use OC\Settings\AuthorizedGroupMapper;
+use OC\User\Session;
use OCP\App\IAppManager;
use OCP\AppFramework\Http\JSONResponse;
use OCP\AppFramework\Http\RedirectResponse;
use OCP\AppFramework\Http\TemplateResponse;
+use OCP\Group\ISubAdmin;
use OCP\IConfig;
+use OCP\IGroupManager;
use OCP\IL10N;
use OCP\INavigationManager;
use OCP\IRequest;
use OCP\IRequestId;
+use OCP\ISession;
use OCP\IURLGenerator;
+use OCP\IUser;
use OCP\IUserSession;
+use OCP\Security\Ip\IRemoteAddress;
use Psr\Log\LoggerInterface;
use Test\AppFramework\Middleware\Security\Mock\NormalController;
use Test\AppFramework\Middleware\Security\Mock\OCSController;
@@ -81,7 +74,10 @@ class SecurityMiddlewareTest extends \Test\TestCase {
parent::setUp();
$this->authorizedGroupMapper = $this->createMock(AuthorizedGroupMapper::class);
- $this->userSession = $this->createMock(IUserSession::class);
+ $this->userSession = $this->createMock(Session::class);
+ $user = $this->createMock(IUser::class);
+ $user->method('getUID')->willReturn('test');
+ $this->userSession->method('getUser')->willReturn($user);
$this->request = $this->createMock(IRequest::class);
$this->controller = new SecurityMiddlewareController(
'test',
@@ -102,6 +98,15 @@ class SecurityMiddlewareTest extends \Test\TestCase {
$this->appManager->expects($this->any())
->method('isEnabledForUser')
->willReturn($isAppEnabledForUser);
+ $remoteIpAddress = $this->createMock(IRemoteAddress::class);
+ $remoteIpAddress->method('allowsAdminActions')->willReturn(true);
+
+ $groupManager = $this->createMock(IGroupManager::class);
+ $groupManager->method('isAdmin')
+ ->willReturn($isAdminUser);
+ $subAdminManager = $this->createMock(ISubAdmin::class);
+ $subAdminManager->method('isSubAdmin')
+ ->willReturn($isSubAdmin);
return new SecurityMiddleware(
$this->request,
@@ -111,16 +116,17 @@ class SecurityMiddlewareTest extends \Test\TestCase {
$this->logger,
'files',
$isLoggedIn,
- $isAdminUser,
- $isSubAdmin,
+ $groupManager,
+ $subAdminManager,
$this->appManager,
$this->l10n,
$this->authorizedGroupMapper,
- $this->userSession
+ $this->userSession,
+ $remoteIpAddress
);
}
- public function dataNoCSRFRequiredPublicPage(): array {
+ public static function dataNoCSRFRequiredPublicPage(): array {
return [
['testAnnotationNoCSRFRequiredPublicPage'],
['testAnnotationNoCSRFRequiredAttributePublicPage'],
@@ -129,21 +135,21 @@ class SecurityMiddlewareTest extends \Test\TestCase {
];
}
- public function dataPublicPage(): array {
+ public static function dataPublicPage(): array {
return [
['testAnnotationPublicPage'],
['testAttributePublicPage'],
];
}
- public function dataNoCSRFRequired(): array {
+ public static function dataNoCSRFRequired(): array {
return [
['testAnnotationNoCSRFRequired'],
['testAttributeNoCSRFRequired'],
];
}
- public function dataPublicPageStrictCookieRequired(): array {
+ public static function dataPublicPageStrictCookieRequired(): array {
return [
['testAnnotationPublicPageStrictCookieRequired'],
['testAnnotationStrictCookieRequiredAttributePublicPage'],
@@ -152,28 +158,28 @@ class SecurityMiddlewareTest extends \Test\TestCase {
];
}
- public function dataNoCSRFRequiredPublicPageStrictCookieRequired(): array {
+ public static function dataNoCSRFRequiredPublicPageStrictCookieRequired(): array {
return [
['testAnnotationNoCSRFRequiredPublicPageStrictCookieRequired'],
['testAttributeNoCSRFRequiredPublicPageStrictCookiesRequired'],
];
}
- public function dataNoAdminRequiredNoCSRFRequired(): array {
+ public static function dataNoAdminRequiredNoCSRFRequired(): array {
return [
['testAnnotationNoAdminRequiredNoCSRFRequired'],
['testAttributeNoAdminRequiredNoCSRFRequired'],
];
}
- public function dataNoAdminRequiredNoCSRFRequiredPublicPage(): array {
+ public static function dataNoAdminRequiredNoCSRFRequiredPublicPage(): array {
return [
['testAnnotationNoAdminRequiredNoCSRFRequiredPublicPage'],
['testAttributeNoAdminRequiredNoCSRFRequiredPublicPage'],
];
}
- public function dataNoCSRFRequiredSubAdminRequired(): array {
+ public static function dataNoCSRFRequiredSubAdminRequired(): array {
return [
['testAnnotationNoCSRFRequiredSubAdminRequired'],
['testAnnotationNoCSRFRequiredAttributeSubAdminRequired'],
@@ -182,9 +188,14 @@ class SecurityMiddlewareTest extends \Test\TestCase {
];
}
- /**
- * @dataProvider dataNoCSRFRequiredPublicPage
- */
+ public static function dataExAppRequired(): array {
+ return [
+ ['testAnnotationExAppRequired'],
+ ['testAttributeExAppRequired'],
+ ];
+ }
+
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataNoCSRFRequiredPublicPage')]
public function testSetNavigationEntry(string $method): void {
$this->navigationManager->expects($this->once())
->method('setActiveEntry')
@@ -232,9 +243,7 @@ class SecurityMiddlewareTest extends \Test\TestCase {
);
}
- /**
- * @dataProvider dataNoCSRFRequired
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataNoCSRFRequired')]
public function testAjaxNotAdminCheck(string $method): void {
$this->ajaxExceptionStatus(
$method,
@@ -243,9 +252,7 @@ class SecurityMiddlewareTest extends \Test\TestCase {
);
}
- /**
- * @dataProvider dataPublicPage
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataPublicPage')]
public function testAjaxStatusCSRFCheck(string $method): void {
$this->ajaxExceptionStatus(
$method,
@@ -254,9 +261,7 @@ class SecurityMiddlewareTest extends \Test\TestCase {
);
}
- /**
- * @dataProvider dataNoCSRFRequiredPublicPage
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataNoCSRFRequiredPublicPage')]
public function testAjaxStatusAllGood(string $method): void {
$this->ajaxExceptionStatus(
$method,
@@ -275,9 +280,7 @@ class SecurityMiddlewareTest extends \Test\TestCase {
);
}
- /**
- * @dataProvider dataNoCSRFRequiredPublicPage
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataNoCSRFRequiredPublicPage')]
public function testNoChecks(string $method): void {
$this->request->expects($this->never())
->method('passesCSRFCheck')
@@ -316,11 +319,9 @@ class SecurityMiddlewareTest extends \Test\TestCase {
}
- /**
- * @dataProvider dataPublicPage
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataPublicPage')]
public function testCsrfCheck(string $method): void {
- $this->expectException(\OC\AppFramework\Middleware\Security\Exceptions\CrossSiteRequestForgeryException::class);
+ $this->expectException(CrossSiteRequestForgeryException::class);
$this->request->expects($this->once())
->method('passesCSRFCheck')
@@ -332,10 +333,8 @@ class SecurityMiddlewareTest extends \Test\TestCase {
$this->middleware->beforeController($this->controller, $method);
}
- /**
- * @dataProvider dataNoCSRFRequiredPublicPage
- */
- public function testNoCsrfCheck(string $method) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataNoCSRFRequiredPublicPage')]
+ public function testNoCsrfCheck(string $method): void {
$this->request->expects($this->never())
->method('passesCSRFCheck')
->willReturn(false);
@@ -344,9 +343,7 @@ class SecurityMiddlewareTest extends \Test\TestCase {
$this->middleware->beforeController($this->controller, $method);
}
- /**
- * @dataProvider dataPublicPage
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataPublicPage')]
public function testPassesCsrfCheck(string $method): void {
$this->request->expects($this->once())
->method('passesCSRFCheck')
@@ -359,11 +356,9 @@ class SecurityMiddlewareTest extends \Test\TestCase {
$this->middleware->beforeController($this->controller, $method);
}
- /**
- * @dataProvider dataPublicPage
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataPublicPage')]
public function testFailCsrfCheck(string $method): void {
- $this->expectException(\OC\AppFramework\Middleware\Security\Exceptions\CrossSiteRequestForgeryException::class);
+ $this->expectException(CrossSiteRequestForgeryException::class);
$this->request->expects($this->once())
->method('passesCSRFCheck')
@@ -376,9 +371,7 @@ class SecurityMiddlewareTest extends \Test\TestCase {
$this->middleware->beforeController($this->controller, $method);
}
- /**
- * @dataProvider dataPublicPageStrictCookieRequired
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataPublicPageStrictCookieRequired')]
public function testStrictCookieRequiredCheck(string $method): void {
$this->expectException(\OC\AppFramework\Middleware\Security\Exceptions\StrictCookieMissingException::class);
@@ -392,9 +385,7 @@ class SecurityMiddlewareTest extends \Test\TestCase {
$this->middleware->beforeController($this->controller, $method);
}
- /**
- * @dataProvider dataNoCSRFRequiredPublicPage
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataNoCSRFRequiredPublicPage')]
public function testNoStrictCookieRequiredCheck(string $method): void {
$this->request->expects($this->never())
->method('passesStrictCookieCheck')
@@ -404,9 +395,7 @@ class SecurityMiddlewareTest extends \Test\TestCase {
$this->middleware->beforeController($this->controller, $method);
}
- /**
- * @dataProvider dataNoCSRFRequiredPublicPageStrictCookieRequired
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataNoCSRFRequiredPublicPageStrictCookieRequired')]
public function testPassesStrictCookieRequiredCheck(string $method): void {
$this->request
->expects($this->once())
@@ -417,7 +406,7 @@ class SecurityMiddlewareTest extends \Test\TestCase {
$this->middleware->beforeController($this->controller, $method);
}
- public function dataCsrfOcsController(): array {
+ public static function dataCsrfOcsController(): array {
return [
[NormalController::class, false, false, true],
[NormalController::class, false, true, true],
@@ -432,12 +421,12 @@ class SecurityMiddlewareTest extends \Test\TestCase {
}
/**
- * @dataProvider dataCsrfOcsController
* @param string $controllerClass
* @param bool $hasOcsApiHeader
* @param bool $hasBearerAuth
* @param bool $exception
*/
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataCsrfOcsController')]
public function testCsrfOcsController(string $controllerClass, bool $hasOcsApiHeader, bool $hasBearerAuth, bool $exception): void {
$this->request
->method('getHeader')
@@ -464,30 +453,22 @@ class SecurityMiddlewareTest extends \Test\TestCase {
}
}
- /**
- * @dataProvider dataNoAdminRequiredNoCSRFRequired
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataNoAdminRequiredNoCSRFRequired')]
public function testLoggedInCheck(string $method): void {
$this->securityCheck($method, 'isLoggedIn');
}
- /**
- * @dataProvider dataNoAdminRequiredNoCSRFRequired
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataNoAdminRequiredNoCSRFRequired')]
public function testFailLoggedInCheck(string $method): void {
$this->securityCheck($method, 'isLoggedIn', true);
}
- /**
- * @dataProvider dataNoCSRFRequired
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataNoCSRFRequired')]
public function testIsAdminCheck(string $method): void {
$this->securityCheck($method, 'isAdminUser');
}
- /**
- * @dataProvider dataNoCSRFRequiredSubAdminRequired
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataNoCSRFRequiredSubAdminRequired')]
public function testIsNotSubAdminCheck(string $method): void {
$this->reader->reflect($this->controller, $method);
$sec = $this->getMiddleware(true, false, false);
@@ -496,9 +477,7 @@ class SecurityMiddlewareTest extends \Test\TestCase {
$sec->beforeController($this->controller, $method);
}
- /**
- * @dataProvider dataNoCSRFRequiredSubAdminRequired
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataNoCSRFRequiredSubAdminRequired')]
public function testIsSubAdminCheck(string $method): void {
$this->reader->reflect($this->controller, $method);
$sec = $this->getMiddleware(true, false, true);
@@ -507,9 +486,7 @@ class SecurityMiddlewareTest extends \Test\TestCase {
$this->addToAssertionCount(1);
}
- /**
- * @dataProvider dataNoCSRFRequiredSubAdminRequired
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataNoCSRFRequiredSubAdminRequired')]
public function testIsSubAdminAndAdminCheck(string $method): void {
$this->reader->reflect($this->controller, $method);
$sec = $this->getMiddleware(true, true, true);
@@ -518,16 +495,12 @@ class SecurityMiddlewareTest extends \Test\TestCase {
$this->addToAssertionCount(1);
}
- /**
- * @dataProvider dataNoCSRFRequired
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataNoCSRFRequired')]
public function testFailIsAdminCheck(string $method): void {
$this->securityCheck($method, 'isAdminUser', true);
}
- /**
- * @dataProvider dataNoAdminRequiredNoCSRFRequiredPublicPage
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataNoAdminRequiredNoCSRFRequiredPublicPage')]
public function testRestrictedAppLoggedInPublicPage(string $method): void {
$middleware = $this->getMiddleware(true, false, false);
$this->reader->reflect($this->controller, $method);
@@ -544,9 +517,7 @@ class SecurityMiddlewareTest extends \Test\TestCase {
$this->addToAssertionCount(1);
}
- /**
- * @dataProvider dataNoAdminRequiredNoCSRFRequiredPublicPage
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataNoAdminRequiredNoCSRFRequiredPublicPage')]
public function testRestrictedAppNotLoggedInPublicPage(string $method): void {
$middleware = $this->getMiddleware(false, false, false);
$this->reader->reflect($this->controller, $method);
@@ -563,9 +534,7 @@ class SecurityMiddlewareTest extends \Test\TestCase {
$this->addToAssertionCount(1);
}
- /**
- * @dataProvider dataNoAdminRequiredNoCSRFRequired
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataNoAdminRequiredNoCSRFRequired')]
public function testRestrictedAppLoggedIn(string $method): void {
$middleware = $this->getMiddleware(true, false, false, false);
$this->reader->reflect($this->controller, $method);
@@ -579,17 +548,17 @@ class SecurityMiddlewareTest extends \Test\TestCase {
}
- public function testAfterExceptionNotCaughtThrowsItAgain() {
+ public function testAfterExceptionNotCaughtThrowsItAgain(): void {
$ex = new \Exception();
$this->expectException(\Exception::class);
$this->middleware->afterException($this->controller, 'test', $ex);
}
- public function testAfterExceptionReturnsRedirectForNotLoggedInUser() {
+ public function testAfterExceptionReturnsRedirectForNotLoggedInUser(): void {
$this->request = new Request(
[
- 'server' =>
- [
+ 'server'
+ => [
'HTTP_ACCEPT' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'REQUEST_URI' => 'nextcloud/index.php/apps/specialapp'
]
@@ -620,7 +589,7 @@ class SecurityMiddlewareTest extends \Test\TestCase {
$this->assertEquals($expected, $response);
}
- public function testAfterExceptionRedirectsToWebRootAfterStrictCookieFail() {
+ public function testAfterExceptionRedirectsToWebRootAfterStrictCookieFail(): void {
$this->request = new Request(
[
'server' => [
@@ -647,7 +616,7 @@ class SecurityMiddlewareTest extends \Test\TestCase {
/**
* @return array
*/
- public function exceptionProvider() {
+ public static function exceptionProvider(): array {
return [
[
new AppNotEnabledException(),
@@ -662,14 +631,14 @@ class SecurityMiddlewareTest extends \Test\TestCase {
}
/**
- * @dataProvider exceptionProvider
* @param SecurityException $exception
*/
- public function testAfterExceptionReturnsTemplateResponse(SecurityException $exception) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('exceptionProvider')]
+ public function testAfterExceptionReturnsTemplateResponse(SecurityException $exception): void {
$this->request = new Request(
[
- 'server' =>
- [
+ 'server'
+ => [
'HTTP_ACCEPT' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'REQUEST_URI' => 'nextcloud/index.php/apps/specialapp'
]
@@ -691,10 +660,42 @@ class SecurityMiddlewareTest extends \Test\TestCase {
$this->assertEquals($expected, $response);
}
- public function testAfterAjaxExceptionReturnsJSONError() {
+ public function testAfterAjaxExceptionReturnsJSONError(): void {
$response = $this->middleware->afterException($this->controller, 'test',
$this->secAjaxException);
$this->assertTrue($response instanceof JSONResponse);
}
+
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataExAppRequired')]
+ public function testExAppRequired(string $method): void {
+ $middleware = $this->getMiddleware(true, false, false);
+ $this->reader->reflect($this->controller, $method);
+
+ $session = $this->createMock(ISession::class);
+ $session->method('get')->with('app_api')->willReturn(true);
+ $this->userSession->method('getSession')->willReturn($session);
+
+ $this->request->expects($this->once())
+ ->method('passesStrictCookieCheck')
+ ->willReturn(true);
+ $this->request->expects($this->once())
+ ->method('passesCSRFCheck')
+ ->willReturn(true);
+
+ $middleware->beforeController($this->controller, $method);
+ }
+
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataExAppRequired')]
+ public function testExAppRequiredError(string $method): void {
+ $middleware = $this->getMiddleware(true, false, false, false);
+ $this->reader->reflect($this->controller, $method);
+
+ $session = $this->createMock(ISession::class);
+ $session->method('get')->with('app_api')->willReturn(false);
+ $this->userSession->method('getSession')->willReturn($session);
+
+ $this->expectException(ExAppRequiredException::class);
+ $middleware->beforeController($this->controller, $method);
+ }
}