diff options
Diffstat (limited to 'tests/lib/AppFramework/Middleware')
21 files changed, 494 insertions, 739 deletions
diff --git a/tests/lib/AppFramework/Middleware/AdditionalScriptsMiddlewareTest.php b/tests/lib/AppFramework/Middleware/AdditionalScriptsMiddlewareTest.php index d37c1c47609..4fa5de62b0b 100644 --- a/tests/lib/AppFramework/Middleware/AdditionalScriptsMiddlewareTest.php +++ b/tests/lib/AppFramework/Middleware/AdditionalScriptsMiddlewareTest.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; @@ -61,7 +44,7 @@ class AdditionalScriptsMiddlewareTest extends \Test\TestCase { $this->controller = $this->createMock(Controller::class); } - public function testNoTemplateResponse() { + public function testNoTemplateResponse(): void { $this->userSession->expects($this->never()) ->method($this->anything()); $this->dispatcher->expects($this->never()) @@ -70,7 +53,7 @@ class AdditionalScriptsMiddlewareTest extends \Test\TestCase { $this->middleWare->afterController($this->controller, 'myMethod', $this->createMock(Response::class)); } - public function testPublicShareController() { + public function testPublicShareController(): void { $this->userSession->expects($this->never()) ->method($this->anything()); $this->dispatcher->expects($this->never()) @@ -79,12 +62,12 @@ class AdditionalScriptsMiddlewareTest extends \Test\TestCase { $this->middleWare->afterController($this->createMock(PublicShareController::class), 'myMethod', $this->createMock(Response::class)); } - public function testStandaloneTemplateResponse() { + public function testStandaloneTemplateResponse(): void { $this->userSession->expects($this->never()) ->method($this->anything()); $this->dispatcher->expects($this->once()) ->method('dispatchTyped') - ->willReturnCallback(function ($event) { + ->willReturnCallback(function ($event): void { if ($event instanceof BeforeTemplateRenderedEvent && $event->isLoggedIn() === false) { return; } @@ -95,12 +78,12 @@ class AdditionalScriptsMiddlewareTest extends \Test\TestCase { $this->middleWare->afterController($this->controller, 'myMethod', $this->createMock(StandaloneTemplateResponse::class)); } - public function testTemplateResponseNotLoggedIn() { + public function testTemplateResponseNotLoggedIn(): void { $this->userSession->method('isLoggedIn') ->willReturn(false); $this->dispatcher->expects($this->once()) ->method('dispatchTyped') - ->willReturnCallback(function ($event) { + ->willReturnCallback(function ($event): void { if ($event instanceof BeforeTemplateRenderedEvent && $event->isLoggedIn() === false) { return; } @@ -111,14 +94,14 @@ class AdditionalScriptsMiddlewareTest extends \Test\TestCase { $this->middleWare->afterController($this->controller, 'myMethod', $this->createMock(TemplateResponse::class)); } - public function testTemplateResponseLoggedIn() { + public function testTemplateResponseLoggedIn(): void { $events = []; $this->userSession->method('isLoggedIn') ->willReturn(true); $this->dispatcher->expects($this->once()) ->method('dispatchTyped') - ->willReturnCallback(function ($event) { + ->willReturnCallback(function ($event): void { if ($event instanceof BeforeTemplateRenderedEvent && $event->isLoggedIn() === true) { return; } diff --git a/tests/lib/AppFramework/Middleware/CompressionMiddlewareTest.php b/tests/lib/AppFramework/Middleware/CompressionMiddlewareTest.php index 79e07ac6686..010ce3fff6d 100644 --- a/tests/lib/AppFramework/Middleware/CompressionMiddlewareTest.php +++ b/tests/lib/AppFramework/Middleware/CompressionMiddlewareTest.php @@ -2,25 +2,8 @@ declare(strict_types=1); /** - * @copyright Copyright (c) 2020, 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: 2020 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace Test\AppFramework\Middleware; @@ -53,7 +36,7 @@ class CompressionMiddlewareTest extends \Test\TestCase { $this->controller = $this->createMock(Controller::class); } - public function testGzipOCSV1() { + public function testGzipOCSV1(): void { $this->request->method('getHeader') ->with('Accept-Encoding') ->willReturn('gzip'); @@ -75,7 +58,7 @@ class CompressionMiddlewareTest extends \Test\TestCase { $this->assertSame($output, gzdecode($result)); } - public function testGzipOCSV2() { + public function testGzipOCSV2(): void { $this->request->method('getHeader') ->with('Accept-Encoding') ->willReturn('gzip'); @@ -97,7 +80,7 @@ class CompressionMiddlewareTest extends \Test\TestCase { $this->assertSame($output, gzdecode($result)); } - public function testGzipJSONResponse() { + public function testGzipJSONResponse(): void { $this->request->method('getHeader') ->with('Accept-Encoding') ->willReturn('gzip'); @@ -119,7 +102,7 @@ class CompressionMiddlewareTest extends \Test\TestCase { $this->assertSame($output, gzdecode($result)); } - public function testNoGzipDataResponse() { + public function testNoGzipDataResponse(): void { $this->request->method('getHeader') ->with('Accept-Encoding') ->willReturn('gzip'); @@ -139,7 +122,7 @@ class CompressionMiddlewareTest extends \Test\TestCase { $this->assertSame($output, $result); } - public function testNoGzipNo200() { + public function testNoGzipNo200(): void { $this->request->method('getHeader') ->with('Accept-Encoding') ->willReturn('gzip'); diff --git a/tests/lib/AppFramework/Middleware/MiddlewareDispatcherTest.php b/tests/lib/AppFramework/Middleware/MiddlewareDispatcherTest.php index f408320971d..aae1c53456b 100644 --- a/tests/lib/AppFramework/Middleware/MiddlewareDispatcherTest.php +++ b/tests/lib/AppFramework/Middleware/MiddlewareDispatcherTest.php @@ -1,30 +1,16 @@ <?php /** - * ownCloud - App Framework - * - * @author Bernhard Posselt - * @copyright 2012 Bernhard Posselt <dev@bernhard-posselt.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE - * License as published by the Free Software Foundation; either - * version 3 of the License, or any later version. - * - * This library 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 library. 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-or-later */ namespace Test\AppFramework\Middleware; use OC\AppFramework\Http\Request; use OC\AppFramework\Middleware\MiddlewareDispatcher; +use OCP\AppFramework\Controller; use OCP\AppFramework\Http\Response; use OCP\AppFramework\Middleware; use OCP\IConfig; @@ -48,17 +34,16 @@ class TestMiddleware extends Middleware { public $response; public $output; - private $beforeControllerThrowsEx; - /** * @param boolean $beforeControllerThrowsEx */ - public function __construct($beforeControllerThrowsEx) { + public function __construct( + private $beforeControllerThrowsEx, + ) { self::$beforeControllerCalled = 0; self::$afterControllerCalled = 0; self::$afterExceptionCalled = 0; self::$beforeOutputCalled = 0; - $this->beforeControllerThrowsEx = $beforeControllerThrowsEx; } public function beforeController($controller, $methodName) { @@ -99,6 +84,10 @@ class TestMiddleware extends Middleware { } } +class TestController extends Controller { + public function method(): void { + } +} class MiddlewareDispatcherTest extends \Test\TestCase { public $exception; @@ -125,8 +114,8 @@ class MiddlewareDispatcherTest extends \Test\TestCase { private function getControllerMock() { - return $this->getMockBuilder('OCP\AppFramework\Controller') - ->setMethods(['method']) + return $this->getMockBuilder(TestController::class) + ->onlyMethods(['method']) ->setConstructorArgs(['app', new Request( ['method' => 'GET'], @@ -144,20 +133,20 @@ class MiddlewareDispatcherTest extends \Test\TestCase { } - public function testAfterExceptionShouldReturnResponseOfMiddleware() { + public function testAfterExceptionShouldReturnResponseOfMiddleware(): void { $response = new Response(); - $m1 = $this->getMockBuilder('\OCP\AppFramework\Middleware') - ->setMethods(['afterException', 'beforeController']) + $m1 = $this->getMockBuilder(Middleware::class) + ->onlyMethods(['afterException', 'beforeController']) ->getMock(); $m1->expects($this->never()) - ->method('afterException'); + ->method('afterException'); - $m2 = $this->getMockBuilder('OCP\AppFramework\Middleware') - ->setMethods(['afterException', 'beforeController']) + $m2 = $this->getMockBuilder(Middleware::class) + ->onlyMethods(['afterException', 'beforeController']) ->getMock(); $m2->expects($this->once()) - ->method('afterException') - ->willReturn($response); + ->method('afterException') + ->willReturn($response); $this->dispatcher->registerMiddleware($m1); $this->dispatcher->registerMiddleware($m2); @@ -167,7 +156,7 @@ class MiddlewareDispatcherTest extends \Test\TestCase { } - public function testAfterExceptionShouldThrowAgainWhenNotHandled() { + public function testAfterExceptionShouldThrowAgainWhenNotHandled(): void { $m1 = new TestMiddleware(false); $m2 = new TestMiddleware(true); @@ -180,7 +169,7 @@ class MiddlewareDispatcherTest extends \Test\TestCase { } - public function testBeforeControllerCorrectArguments() { + public function testBeforeControllerCorrectArguments(): void { $m1 = $this->getMiddleware(); $this->dispatcher->beforeController($this->controller, $this->method); @@ -189,7 +178,7 @@ class MiddlewareDispatcherTest extends \Test\TestCase { } - public function testAfterControllerCorrectArguments() { + public function testAfterControllerCorrectArguments(): void { $m1 = $this->getMiddleware(); $this->dispatcher->afterController($this->controller, $this->method, $this->response); @@ -200,7 +189,7 @@ class MiddlewareDispatcherTest extends \Test\TestCase { } - public function testAfterExceptionCorrectArguments() { + public function testAfterExceptionCorrectArguments(): void { $m1 = $this->getMiddleware(); $this->expectException(\Exception::class); @@ -214,7 +203,7 @@ class MiddlewareDispatcherTest extends \Test\TestCase { } - public function testBeforeOutputCorrectArguments() { + public function testBeforeOutputCorrectArguments(): void { $m1 = $this->getMiddleware(); $this->dispatcher->beforeOutput($this->controller, $this->method, $this->out); @@ -225,7 +214,7 @@ class MiddlewareDispatcherTest extends \Test\TestCase { } - public function testBeforeControllerOrder() { + public function testBeforeControllerOrder(): void { $m1 = $this->getMiddleware(); $m2 = $this->getMiddleware(); @@ -235,7 +224,7 @@ class MiddlewareDispatcherTest extends \Test\TestCase { $this->assertEquals(2, $m2->beforeControllerOrder); } - public function testAfterControllerOrder() { + public function testAfterControllerOrder(): void { $m1 = $this->getMiddleware(); $m2 = $this->getMiddleware(); @@ -246,7 +235,7 @@ class MiddlewareDispatcherTest extends \Test\TestCase { } - public function testAfterExceptionOrder() { + public function testAfterExceptionOrder(): void { $m1 = $this->getMiddleware(); $m2 = $this->getMiddleware(); @@ -259,7 +248,7 @@ class MiddlewareDispatcherTest extends \Test\TestCase { } - public function testBeforeOutputOrder() { + public function testBeforeOutputOrder(): void { $m1 = $this->getMiddleware(); $m2 = $this->getMiddleware(); @@ -270,16 +259,16 @@ class MiddlewareDispatcherTest extends \Test\TestCase { } - public function testExceptionShouldRunAfterExceptionOfOnlyPreviouslyExecutedMiddlewares() { + public function testExceptionShouldRunAfterExceptionOfOnlyPreviouslyExecutedMiddlewares(): void { $m1 = $this->getMiddleware(); $m2 = $this->getMiddleware(true); $m3 = $this->createMock(Middleware::class); $m3->expects($this->never()) - ->method('afterException'); + ->method('afterException'); $m3->expects($this->never()) - ->method('beforeController'); + ->method('beforeController'); $m3->expects($this->never()) - ->method('afterController'); + ->method('afterController'); $m3->method('beforeOutput') ->willReturnArgument(2); diff --git a/tests/lib/AppFramework/Middleware/MiddlewareTest.php b/tests/lib/AppFramework/Middleware/MiddlewareTest.php index e4980009b09..addd9683122 100644 --- a/tests/lib/AppFramework/Middleware/MiddlewareTest.php +++ b/tests/lib/AppFramework/Middleware/MiddlewareTest.php @@ -1,24 +1,9 @@ <?php /** - * ownCloud - App Framework - * - * @author Bernhard Posselt - * @copyright 2012 Bernhard Posselt <dev@bernhard-posselt.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE - * License as published by the Free Software Foundation; either - * version 3 of the License, or any later version. - * - * This library 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 library. 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-or-later */ namespace Test\AppFramework\Middleware; @@ -51,12 +36,9 @@ class MiddlewareTest extends \Test\TestCase { $this->middleware = new ChildMiddleware(); - $this->api = $this->getMockBuilder(DIContainer::class) - ->disableOriginalConstructor() - ->getMock(); + $this->api = $this->createMock(DIContainer::class); $this->controller = $this->getMockBuilder(Controller::class) - ->setMethods([]) ->setConstructorArgs([ $this->api, new Request( @@ -66,7 +48,7 @@ class MiddlewareTest extends \Test\TestCase { ) ])->getMock(); $this->exception = new \Exception(); - $this->response = $this->getMockBuilder(Response::class)->getMock(); + $this->response = $this->createMock(Response::class); } diff --git a/tests/lib/AppFramework/Middleware/NotModifiedMiddlewareTest.php b/tests/lib/AppFramework/Middleware/NotModifiedMiddlewareTest.php index 3b69a289e99..7dcb28a2af4 100644 --- a/tests/lib/AppFramework/Middleware/NotModifiedMiddlewareTest.php +++ b/tests/lib/AppFramework/Middleware/NotModifiedMiddlewareTest.php @@ -2,25 +2,8 @@ declare(strict_types=1); /** - * @copyright Copyright (c) 2020, 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: 2020 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace Test\AppFramework\Middleware; @@ -28,6 +11,7 @@ namespace Test\AppFramework\Middleware; use OC\AppFramework\Middleware\NotModifiedMiddleware; use OCP\AppFramework\Controller; use OCP\AppFramework\Http; +use OCP\AppFramework\Http\Response; use OCP\IRequest; class NotModifiedMiddlewareTest extends \Test\TestCase { @@ -49,7 +33,7 @@ class NotModifiedMiddlewareTest extends \Test\TestCase { $this->controller = $this->createMock(Controller::class); } - public function dataModified(): array { + public static function dataModified(): array { $now = new \DateTime(); return [ @@ -60,20 +44,18 @@ class NotModifiedMiddlewareTest extends \Test\TestCase { [null, '"etag"', null, '', false], ['etag', '"etag"', null, '', true], - [null, '', $now, $now->format(\DateTimeInterface::RFC2822), true], + [null, '', $now, $now->format(\DateTimeInterface::RFC7231), true], [null, '', $now, $now->format(\DateTimeInterface::ATOM), false], - [null, '', null, $now->format(\DateTimeInterface::RFC2822), false], + [null, '', null, $now->format(\DateTimeInterface::RFC7231), false], [null, '', $now, '', false], ['etag', '"etag"', $now, $now->format(\DateTimeInterface::ATOM), true], - ['etag', '"etag"', $now, $now->format(\DateTimeInterface::RFC2822), true], + ['etag', '"etag"', $now, $now->format(\DateTimeInterface::RFC7231), true], ]; } - /** - * @dataProvider dataModified - */ - public function testMiddleware(?string $etag, string $etagHeader, ?\DateTime $lastModified, string $lastModifiedHeader, bool $notModifiedSet) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataModified')] + public function testMiddleware(?string $etag, string $etagHeader, ?\DateTime $lastModified, string $lastModifiedHeader, bool $notModifiedSet): void { $this->request->method('getHeader') ->willReturnCallback(function (string $name) use ($etagHeader, $lastModifiedHeader) { if ($name === 'IF_NONE_MATCH') { @@ -85,7 +67,7 @@ class NotModifiedMiddlewareTest extends \Test\TestCase { return ''; }); - $response = new Http\Response(); + $response = new Response(); if ($etag !== null) { $response->setETag($etag); } diff --git a/tests/lib/AppFramework/Middleware/OCSMiddlewareTest.php b/tests/lib/AppFramework/Middleware/OCSMiddlewareTest.php index 4839ff75b5e..e5c6a417a4b 100644 --- a/tests/lib/AppFramework/Middleware/OCSMiddlewareTest.php +++ b/tests/lib/AppFramework/Middleware/OCSMiddlewareTest.php @@ -1,23 +1,8 @@ <?php + /** - * - * @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: 2016 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace Test\AppFramework\Middleware; @@ -28,6 +13,8 @@ use OC\AppFramework\OCS\V1Response; use OC\AppFramework\OCS\V2Response; use OCP\AppFramework\Controller; use OCP\AppFramework\Http; +use OCP\AppFramework\Http\JSONResponse; +use OCP\AppFramework\Http\Response; use OCP\AppFramework\OCS\OCSBadRequestException; use OCP\AppFramework\OCS\OCSException; use OCP\AppFramework\OCS\OCSForbiddenException; @@ -48,49 +35,35 @@ class OCSMiddlewareTest extends \Test\TestCase { ->getMock(); } - public function dataAfterException() { - $OCSController = $this->getMockBuilder(OCSController::class) - ->disableOriginalConstructor() - ->getMock(); - $controller = $this->getMockBuilder(Controller::class) - ->disableOriginalConstructor() - ->getMock(); - + public static function dataAfterException(): array { return [ - [$OCSController, new \Exception(), true], - [$OCSController, new OCSException(), false, '', Http::STATUS_INTERNAL_SERVER_ERROR], - [$OCSController, new OCSException('foo'), false, 'foo', Http::STATUS_INTERNAL_SERVER_ERROR], - [$OCSController, new OCSException('foo', Http::STATUS_IM_A_TEAPOT), false, 'foo', Http::STATUS_IM_A_TEAPOT], - [$OCSController, new OCSBadRequestException(), false, '', Http::STATUS_BAD_REQUEST], - [$OCSController, new OCSBadRequestException('foo'), false, 'foo', Http::STATUS_BAD_REQUEST], - [$OCSController, new OCSForbiddenException(), false, '', Http::STATUS_FORBIDDEN], - [$OCSController, new OCSForbiddenException('foo'), false, 'foo', Http::STATUS_FORBIDDEN], - [$OCSController, new OCSNotFoundException(), false, '', Http::STATUS_NOT_FOUND], - [$OCSController, new OCSNotFoundException('foo'), false, 'foo', Http::STATUS_NOT_FOUND], - - [$controller, new \Exception(), true], - [$controller, new OCSException(), true], - [$controller, new OCSException('foo'), true], - [$controller, new OCSException('foo', Http::STATUS_IM_A_TEAPOT), true], - [$controller, new OCSBadRequestException(), true], - [$controller, new OCSBadRequestException('foo'), true], - [$controller, new OCSForbiddenException(), true], - [$controller, new OCSForbiddenException('foo'), true], - [$controller, new OCSNotFoundException(), true], - [$controller, new OCSNotFoundException('foo'), true], + [OCSController::class, new \Exception(), true], + [OCSController::class, new OCSException(), false, '', Http::STATUS_INTERNAL_SERVER_ERROR], + [OCSController::class, new OCSException('foo'), false, 'foo', Http::STATUS_INTERNAL_SERVER_ERROR], + [OCSController::class, new OCSException('foo', Http::STATUS_IM_A_TEAPOT), false, 'foo', Http::STATUS_IM_A_TEAPOT], + [OCSController::class, new OCSBadRequestException(), false, '', Http::STATUS_BAD_REQUEST], + [OCSController::class, new OCSBadRequestException('foo'), false, 'foo', Http::STATUS_BAD_REQUEST], + [OCSController::class, new OCSForbiddenException(), false, '', Http::STATUS_FORBIDDEN], + [OCSController::class, new OCSForbiddenException('foo'), false, 'foo', Http::STATUS_FORBIDDEN], + [OCSController::class, new OCSNotFoundException(), false, '', Http::STATUS_NOT_FOUND], + [OCSController::class, new OCSNotFoundException('foo'), false, 'foo', Http::STATUS_NOT_FOUND], + + [Controller::class, new \Exception(), true], + [Controller::class, new OCSException(), true], + [Controller::class, new OCSException('foo'), true], + [Controller::class, new OCSException('foo', Http::STATUS_IM_A_TEAPOT), true], + [Controller::class, new OCSBadRequestException(), true], + [Controller::class, new OCSBadRequestException('foo'), true], + [Controller::class, new OCSForbiddenException(), true], + [Controller::class, new OCSForbiddenException('foo'), true], + [Controller::class, new OCSNotFoundException(), true], + [Controller::class, new OCSNotFoundException('foo'), true], ]; } - /** - * @dataProvider dataAfterException - * - * @param Controller $controller - * @param \Exception $exception - * @param bool $forward - * @param string $message - * @param int $code - */ - public function testAfterExceptionOCSv1($controller, $exception, $forward, $message = '', $code = 0) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataAfterException')] + public function testAfterExceptionOCSv1(string $controller, \Exception $exception, bool $forward, string $message = '', int $code = 0): void { + $controller = $this->createMock($controller); $this->request ->method('getScriptName') ->willReturn('/ocs/v1.php'); @@ -109,7 +82,7 @@ class OCSMiddlewareTest extends \Test\TestCase { $this->assertSame($message, $this->invokePrivate($result, 'statusMessage')); if ($exception->getCode() === 0) { - $this->assertSame(\OCP\AppFramework\OCSController::RESPOND_UNKNOWN_ERROR, $result->getOCSStatus()); + $this->assertSame(OCSController::RESPOND_UNKNOWN_ERROR, $result->getOCSStatus()); } else { $this->assertSame($code, $result->getOCSStatus()); } @@ -117,16 +90,9 @@ class OCSMiddlewareTest extends \Test\TestCase { $this->assertSame(Http::STATUS_OK, $result->getStatus()); } - /** - * @dataProvider dataAfterException - * - * @param Controller $controller - * @param \Exception $exception - * @param bool $forward - * @param string $message - * @param int $code - */ - public function testAfterExceptionOCSv2($controller, $exception, $forward, $message = '', $code = 0) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataAfterException')] + public function testAfterExceptionOCSv2(string $controller, \Exception $exception, bool $forward, string $message = '', int $code = 0): void { + $controller = $this->createMock($controller); $this->request ->method('getScriptName') ->willReturn('/ocs/v2.php'); @@ -144,23 +110,16 @@ class OCSMiddlewareTest extends \Test\TestCase { $this->assertSame($message, $this->invokePrivate($result, 'statusMessage')); if ($exception->getCode() === 0) { - $this->assertSame(\OCP\AppFramework\OCSController::RESPOND_UNKNOWN_ERROR, $result->getOCSStatus()); + $this->assertSame(OCSController::RESPOND_UNKNOWN_ERROR, $result->getOCSStatus()); } else { $this->assertSame($code, $result->getOCSStatus()); } $this->assertSame($code, $result->getStatus()); } - /** - * @dataProvider dataAfterException - * - * @param Controller $controller - * @param \Exception $exception - * @param bool $forward - * @param string $message - * @param int $code - */ - public function testAfterExceptionOCSv2SubFolder($controller, $exception, $forward, $message = '', $code = 0) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataAfterException')] + public function testAfterExceptionOCSv2SubFolder(string $controller, \Exception $exception, bool $forward, string $message = '', int $code = 0): void { + $controller = $this->createMock($controller); $this->request ->method('getScriptName') ->willReturn('/mysubfolder/ocs/v2.php'); @@ -168,7 +127,7 @@ class OCSMiddlewareTest extends \Test\TestCase { $OCSMiddleware->beforeController($controller, 'method'); if ($forward) { - $this->expectException(get_class($exception)); + $this->expectException($exception::class); $this->expectExceptionMessage($exception->getMessage()); } @@ -178,46 +137,33 @@ class OCSMiddlewareTest extends \Test\TestCase { $this->assertSame($message, $this->invokePrivate($result, 'statusMessage')); if ($exception->getCode() === 0) { - $this->assertSame(\OCP\AppFramework\OCSController::RESPOND_UNKNOWN_ERROR, $result->getOCSStatus()); + $this->assertSame(OCSController::RESPOND_UNKNOWN_ERROR, $result->getOCSStatus()); } else { $this->assertSame($code, $result->getOCSStatus()); } $this->assertSame($code, $result->getStatus()); } - public function dataAfterController() { - $OCSController = $this->getMockBuilder(OCSController::class) - ->disableOriginalConstructor() - ->getMock(); - $controller = $this->getMockBuilder(Controller::class) - ->disableOriginalConstructor() - ->getMock(); - + public static function dataAfterController(): array { return [ - [$OCSController, new Http\Response(), false], - [$OCSController, new Http\JSONResponse(), false], - [$OCSController, new Http\JSONResponse(['message' => 'foo']), false], - [$OCSController, new Http\JSONResponse(['message' => 'foo'], Http::STATUS_UNAUTHORIZED), true, OCSController::RESPOND_UNAUTHORISED], - [$OCSController, new Http\JSONResponse(['message' => 'foo'], Http::STATUS_FORBIDDEN), true], - - [$controller, new Http\Response(), false], - [$controller, new Http\JSONResponse(), false], - [$controller, new Http\JSONResponse(['message' => 'foo']), false], - [$controller, new Http\JSONResponse(['message' => 'foo'], Http::STATUS_UNAUTHORIZED), false], - [$controller, new Http\JSONResponse(['message' => 'foo'], Http::STATUS_FORBIDDEN), false], + [OCSController::class, new Response(), false], + [OCSController::class, new JSONResponse(), false], + [OCSController::class, new JSONResponse(['message' => 'foo']), false], + [OCSController::class, new JSONResponse(['message' => 'foo'], Http::STATUS_UNAUTHORIZED), true, OCSController::RESPOND_UNAUTHORISED], + [OCSController::class, new JSONResponse(['message' => 'foo'], Http::STATUS_FORBIDDEN), true], + + [Controller::class, new Response(), false], + [Controller::class, new JSONResponse(), false], + [Controller::class, new JSONResponse(['message' => 'foo']), false], + [Controller::class, new JSONResponse(['message' => 'foo'], Http::STATUS_UNAUTHORIZED), false], + [Controller::class, new JSONResponse(['message' => 'foo'], Http::STATUS_FORBIDDEN), false], ]; } - /** - * @dataProvider dataAfterController - * - * @param Controller $controller - * @param Http\Response $response - * @param bool $converted - * @param int $convertedOCSStatus - */ - public function testAfterController($controller, $response, $converted, $convertedOCSStatus = 0) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataAfterController')] + public function testAfterController(string $controller, Response $response, bool $converted, int $convertedOCSStatus = 0): void { + $controller = $this->createMock($controller); $OCSMiddleware = new OCSMiddleware($this->request); $newResponse = $OCSMiddleware->afterController($controller, 'foo', $response); diff --git a/tests/lib/AppFramework/Middleware/PublicShare/PublicShareMiddlewareTest.php b/tests/lib/AppFramework/Middleware/PublicShare/PublicShareMiddlewareTest.php index a025f39419a..e87ee7fd565 100644 --- a/tests/lib/AppFramework/Middleware/PublicShare/PublicShareMiddlewareTest.php +++ b/tests/lib/AppFramework/Middleware/PublicShare/PublicShareMiddlewareTest.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\PublicShare; @@ -27,8 +11,9 @@ use OC\AppFramework\Middleware\PublicShare\Exceptions\NeedAuthenticationExceptio use OC\AppFramework\Middleware\PublicShare\PublicShareMiddleware; use OCP\AppFramework\AuthPublicShareController; use OCP\AppFramework\Controller; -use OCP\AppFramework\Http\NotFoundResponse; +use OCP\AppFramework\Http; use OCP\AppFramework\Http\RedirectResponse; +use OCP\AppFramework\Http\TemplateResponse; use OCP\AppFramework\PublicShareController; use OCP\Files\NotFoundException; use OCP\IConfig; @@ -67,14 +52,14 @@ class PublicShareMiddlewareTest extends \Test\TestCase { ); } - public function testBeforeControllerNoPublicShareController() { + public function testBeforeControllerNoPublicShareController(): void { $controller = $this->createMock(Controller::class); $this->middleware->beforeController($controller, 'method'); $this->assertTrue(true); } - public function dataShareApi() { + public static function dataShareApi(): array { return [ ['no', 'no',], ['no', 'yes',], @@ -82,10 +67,8 @@ class PublicShareMiddlewareTest extends \Test\TestCase { ]; } - /** - * @dataProvider dataShareApi - */ - public function testBeforeControllerShareApiDisabled(string $shareApi, string $shareLinks) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataShareApi')] + public function testBeforeControllerShareApiDisabled(string $shareApi, string $shareLinks): void { $controller = $this->createMock(PublicShareController::class); $this->config->method('getAppValue') @@ -98,7 +81,7 @@ class PublicShareMiddlewareTest extends \Test\TestCase { $this->middleware->beforeController($controller, 'mehod'); } - public function testBeforeControllerNoTokenParam() { + public function testBeforeControllerNoTokenParam(): void { $controller = $this->createMock(PublicShareController::class); $this->config->method('getAppValue') @@ -111,7 +94,7 @@ class PublicShareMiddlewareTest extends \Test\TestCase { $this->middleware->beforeController($controller, 'mehod'); } - public function testBeforeControllerInvalidToken() { + public function testBeforeControllerInvalidToken(): void { $controller = $this->createMock(PublicShareController::class); $this->config->method('getAppValue') @@ -133,7 +116,7 @@ class PublicShareMiddlewareTest extends \Test\TestCase { $this->middleware->beforeController($controller, 'mehod'); } - public function testBeforeControllerValidTokenNotAuthenticated() { + public function testBeforeControllerValidTokenNotAuthenticated(): void { $controller = $this->getMockBuilder(PublicShareController::class) ->setConstructorArgs(['app', $this->request, $this->session]) ->getMock(); @@ -158,7 +141,7 @@ class PublicShareMiddlewareTest extends \Test\TestCase { $this->middleware->beforeController($controller, 'mehod'); } - public function testBeforeControllerValidTokenAuthenticateMethod() { + public function testBeforeControllerValidTokenAuthenticateMethod(): void { $controller = $this->getMockBuilder(PublicShareController::class) ->setConstructorArgs(['app', $this->request, $this->session]) ->getMock(); @@ -183,7 +166,7 @@ class PublicShareMiddlewareTest extends \Test\TestCase { $this->assertTrue(true); } - public function testBeforeControllerValidTokenShowAuthenticateMethod() { + public function testBeforeControllerValidTokenShowAuthenticateMethod(): void { $controller = $this->getMockBuilder(PublicShareController::class) ->setConstructorArgs(['app', $this->request, $this->session]) ->getMock(); @@ -208,7 +191,7 @@ class PublicShareMiddlewareTest extends \Test\TestCase { $this->assertTrue(true); } - public function testBeforeControllerAuthPublicShareController() { + public function testBeforeControllerAuthPublicShareController(): void { $controller = $this->getMockBuilder(AuthPublicShareController::class) ->setConstructorArgs(['app', $this->request, $this->session, $this->createMock(IURLGenerator::class)]) ->getMock(); @@ -237,7 +220,7 @@ class PublicShareMiddlewareTest extends \Test\TestCase { $this->middleware->beforeController($controller, 'method'); } - public function testAfterExceptionNoPublicShareController() { + public function testAfterExceptionNoPublicShareController(): void { $controller = $this->createMock(Controller::class); $exception = new \Exception(); @@ -248,15 +231,16 @@ class PublicShareMiddlewareTest extends \Test\TestCase { } } - public function testAfterExceptionPublicShareControllerNotFoundException() { + public function testAfterExceptionPublicShareControllerNotFoundException(): void { $controller = $this->createMock(PublicShareController::class); $exception = new NotFoundException(); $result = $this->middleware->afterException($controller, 'method', $exception); - $this->assertInstanceOf(NotFoundResponse::class, $result); + $this->assertInstanceOf(TemplateResponse::class, $result); + $this->assertEquals($result->getStatus(), Http::STATUS_NOT_FOUND); } - public function testAfterExceptionPublicShareController() { + public function testAfterExceptionPublicShareController(): void { $controller = $this->createMock(PublicShareController::class); $exception = new \Exception(); @@ -267,7 +251,7 @@ class PublicShareMiddlewareTest extends \Test\TestCase { } } - public function testAfterExceptionAuthPublicShareController() { + public function testAfterExceptionAuthPublicShareController(): void { $controller = $this->getMockBuilder(AuthPublicShareController::class) ->setConstructorArgs([ 'app', 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 47d479b18a1..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,7 +19,9 @@ 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; use OCP\IUserSession; use PHPUnit\Framework\MockObject\MockObject; @@ -77,6 +62,9 @@ class RateLimitingMiddlewareTest extends TestCase { private IUserSession|MockObject $userSession; 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 { @@ -86,12 +74,18 @@ class RateLimitingMiddlewareTest extends TestCase { $this->userSession = $this->createMock(IUserSession::class); $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->limiter, + $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); + } } diff --git a/tests/lib/AppFramework/Middleware/SessionMiddlewareTest.php b/tests/lib/AppFramework/Middleware/SessionMiddlewareTest.php index 09838423e85..8ecc73791c9 100644 --- a/tests/lib/AppFramework/Middleware/SessionMiddlewareTest.php +++ b/tests/lib/AppFramework/Middleware/SessionMiddlewareTest.php @@ -1,17 +1,11 @@ <?php declare(strict_types=1); - /** - * ownCloud - App Framework - * - * This file is licensed under the Affero General Public License version 3 or - * later. See the COPYING file. - * - * @author Thomas Müller <deepdiver@owncloud.com> - * @copyright Thomas Müller 2014 + * SPDX-FileCopyrightText: 2016-2023 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-or-later */ - namespace Test\AppFramework\Middleware; use OC\AppFramework\Middleware\SessionMiddleware; |