From efd88b1a55e80c6348868568f67ac715d5ef0b86 Mon Sep 17 00:00:00 2001 From: Ben Peachey Date: Wed, 3 Dec 2025 13:46:33 +0100 Subject: [PATCH 1/7] Fix broken unit-tests for ServerController. --- solid/tests/Unit/Controller/ServerControllerTest.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/solid/tests/Unit/Controller/ServerControllerTest.php b/solid/tests/Unit/Controller/ServerControllerTest.php index 2920b0dd..08595ae1 100644 --- a/solid/tests/Unit/Controller/ServerControllerTest.php +++ b/solid/tests/Unit/Controller/ServerControllerTest.php @@ -348,6 +348,7 @@ public function testRegisterWithRedirectUris() 'registration_client_uri' => '', 'response_types' => ['id_token token'], 'token_endpoint_auth_method' => 'client_secret_basic', + 'client_secret' => '3b5798fddd49e23662ee6fe801085100' ], 'headers' => [ 'Cache-Control' => 'no-cache, no-store, must-revalidate', @@ -369,6 +370,7 @@ public function testToken() { $_POST['client_id'] = self::MOCK_CLIENT_ID; $_POST['code'] = ''; + $_POST['grant_type'] = 'authorization_code'; $_SERVER['HTTP_DPOP'] = 'mock dpop'; $_SESSION['nonce'] = 'mock nonce'; From c4e260a60b10acc02cd2cfe1174bc361633df413 Mon Sep 17 00:00:00 2001 From: Ben Peachey Date: Wed, 3 Dec 2025 14:30:15 +0100 Subject: [PATCH 2/7] Change mocks in ServerControllerTest from class properties to array members. --- .../Unit/Controller/ServerControllerTest.php | 76 +++++++------------ 1 file changed, 29 insertions(+), 47 deletions(-) diff --git a/solid/tests/Unit/Controller/ServerControllerTest.php b/solid/tests/Unit/Controller/ServerControllerTest.php index 08595ae1..a685e9f7 100644 --- a/solid/tests/Unit/Controller/ServerControllerTest.php +++ b/solid/tests/Unit/Controller/ServerControllerTest.php @@ -44,10 +44,6 @@ class ServerControllerTest extends TestCase public static string $clientData = ''; private static string $privateKey; - private IConfig|MockObject $mockConfig; - private IURLGenerator|MockObject $mockURLGenerator; - private IUserManager|MockObject $mockUserManager; - public static function setUpBeforeClass(): void { $keyPath = __DIR__ . '/../../fixtures/keys'; @@ -85,7 +81,7 @@ public function testInstantiationWithoutRequiredParameter($index) $this->expectExceptionMessageMatches('/^' . $message . '$/'); - new ServerController(...$parameters); + new ServerController(...array_values($parameters)); } /** @@ -97,7 +93,7 @@ public function testInstantiation() { $parameters = $this->createMockConstructorParameters(); - $controller = new ServerController(...$parameters); + $controller = new ServerController(...array_values($parameters)); $this->assertInstanceOf(ServerController::class, $controller); } @@ -111,7 +107,7 @@ public function testAuthorizeWithoutUser() { $parameters = $this->createMockConstructorParameters(); - $controller = new ServerController(...$parameters); + $controller = new ServerController(...array_values($parameters)); $expected = new JSONResponse('Authorization required', Http::STATUS_UNAUTHORIZED); $actual = $controller->authorize(); @@ -130,9 +126,9 @@ public function testAuthorizeWithoutValidToken() $parameters = $this->createMockConstructorParameters(); - $this->mockUserManager->method('userExists')->willReturn(true); + $parameters['MockUserManager']->method('userExists')->willReturn(true); - $controller = new ServerController(...$parameters); + $controller = new ServerController(...array_values($parameters)); $actual = $controller->authorize(); $expected = new JSONResponse('Bad request, does not contain valid token', Http::STATUS_BAD_REQUEST); @@ -157,11 +153,11 @@ public function testAuthorizeWithoutApprovedClient() $parameters = $this->createMockConstructorParameters(); - $this->mockConfig->method('getUserValue')->willReturnArgument(3); + $parameters['MockConfig']->method('getUserValue')->willReturnArgument(3); - $this->mockUserManager->method('userExists')->willReturn(true); + $parameters['MockUserManager']->method('userExists')->willReturn(true); - $controller = new ServerController(...$parameters); + $controller = new ServerController(...array_values($parameters)); $actual = $controller->authorize(); $expected = new JSONResponse('Approval required', Http::STATUS_FOUND, ['Location' => '']); @@ -183,13 +179,13 @@ public function testAuthorizeWithInvalidRedirectUri() $parameters = $this->createMockConstructorParameters($clientData); - $this->mockConfig->method('getUserValue') + $parameters['MockConfig']->method('getUserValue') ->with(self::MOCK_USER_ID, Application::APP_ID, 'allowedClients', '[]') ->willReturn(json_encode([self::MOCK_CLIENT_ID])); - $this->mockUserManager->method('userExists')->willReturn(true); + $parameters['MockUserManager']->method('userExists')->willReturn(true); - $controller = new ServerController(...$parameters); + $controller = new ServerController(...array_values($parameters)); $response = $controller->authorize(); @@ -238,13 +234,13 @@ public function testAuthorize() $parameters = $this->createMockConstructorParameters($clientData); - $this->mockConfig->method('getUserValue') + $parameters['MockConfig']->method('getUserValue') ->with(self::MOCK_USER_ID, Application::APP_ID, 'allowedClients', '[]') ->willReturn(json_encode([self::MOCK_CLIENT_ID])); - $this->mockUserManager->method('userExists')->willReturn(true); + $parameters['MockUserManager']->method('userExists')->willReturn(true); - $controller = new ServerController(...$parameters); + $controller = new ServerController(...array_values($parameters)); $response = $controller->authorize(); @@ -300,7 +296,7 @@ public function testRegisterWithoutRedirectUris() { $parameters = $this->createMockConstructorParameters(); - $controller = new ServerController(...$parameters); + $controller = new ServerController(...array_values($parameters)); $actual = $controller->register(); @@ -319,10 +315,10 @@ public function testRegisterWithRedirectUris() { $parameters = $this->createMockConstructorParameters(); - $this->mockURLGenerator->method('getBaseUrl') + $parameters['MockURLGenerator']->method('getBaseUrl') ->willReturn('https://mock.server'); - $controller = new ServerController(...$parameters); + $controller = new ServerController(...array_values($parameters)); self::$clientData = json_encode(['redirect_uris' => ['https://mock.client/redirect']]); @@ -393,7 +389,7 @@ public function testToken() 'Content-Type' => 'mock application type' ])); - $controller = new ServerController(...$parameters); + $controller = new ServerController(...array_values($parameters)); $reflectionObject = new \ReflectionObject($controller); $reflectionProperty = $reflectionObject->getProperty('tokenGenerator'); @@ -429,9 +425,9 @@ public function testToken() public function createMockConfig($clientData): IConfig|MockObject { - $this->mockConfig = $this->createMock(IConfig::class); + $mockConfig = $this->createMock(IConfig::class); - $this->mockConfig->method('getAppValue')->willReturnMap([ + $mockConfig->method('getAppValue')->willReturnMap([ [Application::APP_ID, 'client-' . self::MOCK_CLIENT_ID, '{}', 'return' => $clientData], [Application::APP_ID, 'client-d6d7896757f61ac4c397d914053180ff', '{}', 'return' => $clientData], [Application::APP_ID, 'client-', '{}', 'return' => $clientData], @@ -442,40 +438,26 @@ public function createMockConfig($clientData): IConfig|MockObject [Application::APP_ID, 'client-f4a2d00f7602948a97ff409d7a581ec2', '{}', 'return' => $clientData], ]); - return $this->mockConfig; + return $mockConfig; } public function createMockConstructorParameters($clientData = '{}'): array { $parameters = [ 'mock appname', - $this->createMock(IRequest::class), - $this->createMock(ISession::class), - $this->createMockUserManager(), - $this->createMockUrlGenerator(), - self::MOCK_USER_ID, - $this->createMockConfig($clientData), - $this->createMock(UserService::class), - $this->createMock(IDBConnection::class), + 'MockRequest' => $this->createMock(IRequest::class), + 'MockSession' => $this->createMock(ISession::class), + 'MockUserManager' => $this->createMock(IUserManager::class), + 'MockURLGenerator' => $this->createMock(IURLGenerator::class), + 'MOCK_USER_ID' => self::MOCK_USER_ID, + 'MockConfig' => $this->createMockConfig($clientData), + 'MockUserService' => $this->createMock(UserService::class), + 'MockDBConnection' => $this->createMock(IDBConnection::class), ]; return $parameters; } - public function createMockUrlGenerator(): IURLGenerator|MockObject - { - $this->mockURLGenerator = $this->createMock(IURLGenerator::class); - - return $this->mockURLGenerator; - } - - public function createMockUserManager(): IUserManager|MockObject - { - $this->mockUserManager = $this->createMock(IUserManager::class); - - return $this->mockUserManager; - } - /////////////////////////////// DATAPROVIDERS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ public static function provideConstructorParameterIndex() From 30c920031b22599b8d81ac28a286a135b2fe8754 Mon Sep 17 00:00:00 2001 From: Ben Peachey Date: Wed, 3 Dec 2025 14:42:10 +0100 Subject: [PATCH 3/7] Fix bug caused by class property not being set in ServerController::logout(). --- solid/lib/Controller/ServerController.php | 6 ++- .../Unit/Controller/ServerControllerTest.php | 39 +++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/solid/lib/Controller/ServerController.php b/solid/lib/Controller/ServerController.php index b4dc255b..f940c368 100644 --- a/solid/lib/Controller/ServerController.php +++ b/solid/lib/Controller/ServerController.php @@ -3,6 +3,7 @@ use OCA\Solid\DpopFactoryTrait; use OCA\Solid\ServerConfig; +use OCA\Solid\Service\UserService; use OCP\AppFramework\Controller; use OCP\AppFramework\Http; @@ -47,6 +48,8 @@ class ServerController extends Controller /* @var \Pdsinterop\Solid\Auth\TokenGenerator */ private $tokenGenerator; + private UserService $userService; + public function __construct( $AppName, IRequest $request, @@ -55,7 +58,7 @@ public function __construct( IURLGenerator $urlGenerator, $userId, IConfig $config, - \OCA\Solid\Service\UserService $UserService, + \OCA\Solid\Service\UserService $userService, IDBConnection $connection, ) { parent::__construct($AppName, $request); @@ -66,6 +69,7 @@ public function __construct( $this->request = $request; $this->urlGenerator = $urlGenerator; $this->session = $session; + $this->userService = $userService; $this->setJtiStorage($connection); diff --git a/solid/tests/Unit/Controller/ServerControllerTest.php b/solid/tests/Unit/Controller/ServerControllerTest.php index a685e9f7..dc0fb345 100644 --- a/solid/tests/Unit/Controller/ServerControllerTest.php +++ b/solid/tests/Unit/Controller/ServerControllerTest.php @@ -421,6 +421,45 @@ public function testToken() $this->assertEquals($expected, $actual); } + /** + * @testdox ServerController should return an OK when asked to logout + * + * @covers ::logout + */ + public function testLogout() { + $parameters = $this->createMockConstructorParameters(); + + $controller = new ServerController(...array_values($parameters)); + + $actual = $controller->logout(); + $expected = new JSONResponse('ok', Http::STATUS_OK); + + $this->assertEquals($expected, $actual); + } + + /** + * @testdox ServerController should complain when asked to logout and the logout fails + * + * @covers ::logout + */ + public function testLogoutError() { + $parameters = $this->createMockConstructorParameters(); + + $mockError = 'Mock logout error'; + $expectedException = new \Exception($mockError); + $parameters['MockUserService'] + ->method('logout') + ->willThrowException($expectedException) + ; + + $controller = new ServerController(...array_values($parameters)); + + $this->expectException($expectedException::class); + $this->expectExceptionMessage($mockError); + + $controller->logout(); + } + ////////////////////////////// MOCKS AND STUBS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\ public function createMockConfig($clientData): IConfig|MockObject From 1877fb2886eb9e4a270f6bf7a3652dc19d9991b6 Mon Sep 17 00:00:00 2001 From: Ben Peachey Date: Wed, 3 Dec 2025 16:21:02 +0100 Subject: [PATCH 4/7] Add validation for missing client data in ServerController::register(). --- solid/lib/Controller/ServerController.php | 10 +++++++-- .../Unit/Controller/ServerControllerTest.php | 21 +++++++++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/solid/lib/Controller/ServerController.php b/solid/lib/Controller/ServerController.php index f940c368..750d5009 100644 --- a/solid/lib/Controller/ServerController.php +++ b/solid/lib/Controller/ServerController.php @@ -393,11 +393,17 @@ public function logout() { * @NoCSRFRequired */ public function register() { - $clientData = file_get_contents('php://input'); - $clientData = json_decode($clientData, true); + $postData = file_get_contents('php://input'); + $clientData = json_decode($postData, true); + + if (! isset($clientData)) { + return new JSONResponse('Missing client data', Http::STATUS_BAD_REQUEST); + } + if (! isset($clientData['redirect_uris'])) { return new JSONResponse("Missing redirect URIs", Http::STATUS_BAD_REQUEST); } + $clientData['client_id_issued_at'] = time(); $parsedOrigin = parse_url($clientData['redirect_uris'][0]); $origin = $parsedOrigin['scheme'] . '://' . $parsedOrigin['host']; diff --git a/solid/tests/Unit/Controller/ServerControllerTest.php b/solid/tests/Unit/Controller/ServerControllerTest.php index dc0fb345..557207d0 100644 --- a/solid/tests/Unit/Controller/ServerControllerTest.php +++ b/solid/tests/Unit/Controller/ServerControllerTest.php @@ -292,12 +292,33 @@ public function testAuthorize() * * @covers ::register */ + public function testRegisterWithoutClientData() + { + $parameters = $this->createMockConstructorParameters(); + + $controller = new ServerController(...array_values($parameters)); + + $actual = $controller->register(); + + $this->assertEquals( + new JSONResponse('Missing client data', Http::STATUS_BAD_REQUEST), + $actual + ); + } + + /** + * @testdox ServerController should return a 400 when asked to register without redirect URIs + * + * @covers ::register + */ public function testRegisterWithoutRedirectUris() { $parameters = $this->createMockConstructorParameters(); $controller = new ServerController(...array_values($parameters)); + self::$clientData = json_encode([]); + $actual = $controller->register(); $this->assertEquals( From 5889e266e99f3b7b54e7f30edeb9af05c160ef8e Mon Sep 17 00:00:00 2001 From: Ben Peachey Date: Wed, 3 Dec 2025 17:04:47 +0100 Subject: [PATCH 5/7] Add validation for missing client_id in ServerController::authorize(). --- solid/lib/Controller/ServerController.php | 10 ++++++---- .../Unit/Controller/ServerControllerTest.php | 19 +++++++++++++++++++ 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/solid/lib/Controller/ServerController.php b/solid/lib/Controller/ServerController.php index 750d5009..25671d95 100644 --- a/solid/lib/Controller/ServerController.php +++ b/solid/lib/Controller/ServerController.php @@ -154,11 +154,13 @@ public function cors($path) { public function authorize() { // Create a request if (!$this->userManager->userExists($this->userId)) { - $result = new JSONResponse('Authorization required'); - $result->setStatus(401); - return $result; -// return $result->addHeader('Access-Control-Allow-Origin', '*'); + return new JSONResponse('Authorization required', 401); + } + + if (! isset($_GET['client_id'])) { + return new JSONResponse('Bad request, missing client_id', 400); } + $clientId = $_GET['client_id']; if (isset($_GET['request'])) { $jwtConfig = Configuration::forSymmetricSigner(new Sha256(), InMemory::plainText($this->config->getPrivateKey())); diff --git a/solid/tests/Unit/Controller/ServerControllerTest.php b/solid/tests/Unit/Controller/ServerControllerTest.php index 557207d0..cf27fa17 100644 --- a/solid/tests/Unit/Controller/ServerControllerTest.php +++ b/solid/tests/Unit/Controller/ServerControllerTest.php @@ -115,6 +115,25 @@ public function testAuthorizeWithoutUser() $this->assertEquals($expected, $actual); } + /** + * @testdox ServerController should return a 400 when asked to authorize with a user but without client_id + * + * @covers ::authorize + */ + public function testAuthorizeWithoutClientId() + { + $parameters = $this->createMockConstructorParameters(); + + $parameters['MockUserManager']->method('userExists')->willReturn(true); + + $controller = new ServerController(...array_values($parameters)); + + $actual = $controller->authorize(); + $expected = new JSONResponse('Bad request, missing client_id', Http::STATUS_BAD_REQUEST); + + $this->assertEquals($expected, $actual); + } + /** * @testdox ServerController should return a 400 when asked to authorize with a user but without valid token * From a40486336629fa19072fb8e0574926bc620d98a8 Mon Sep 17 00:00:00 2001 From: Ben Peachey Date: Wed, 3 Dec 2025 18:24:15 +0100 Subject: [PATCH 6/7] Change code in ServerController to more closely match code in Standalone PHP Solid Server. --- solid/lib/Controller/ServerController.php | 68 +++++++++---------- .../Unit/Controller/ServerControllerTest.php | 15 ++-- 2 files changed, 45 insertions(+), 38 deletions(-) diff --git a/solid/lib/Controller/ServerController.php b/solid/lib/Controller/ServerController.php index 25671d95..8828f14d 100644 --- a/solid/lib/Controller/ServerController.php +++ b/solid/lib/Controller/ServerController.php @@ -162,6 +162,7 @@ public function authorize() { } $clientId = $_GET['client_id']; + $getVars = $_GET; if (isset($_GET['request'])) { $jwtConfig = Configuration::forSymmetricSigner(new Sha256(), InMemory::plainText($this->config->getPrivateKey())); try { @@ -170,33 +171,32 @@ public function authorize() { } catch(\Exception $e) { $this->session->set("nonce", $_GET['nonce']); } - } - $getVars = $_GET; - if (!isset($getVars['grant_type'])) { - $getVars['grant_type'] = 'implicit'; - } - $getVars['response_type'] = $this->getResponseType(); - $getVars['scope'] = "openid" ; - - if (!isset($getVars['redirect_uri'])) { - if (!isset($token)) { - $result = new JSONResponse('Bad request, does not contain valid token'); - $result->setStatus(400); - return $result; -// return $result->addHeader('Access-Control-Allow-Origin', '*'); + if (!isset($getVars['grant_type'])) { + $getVars['grant_type'] = 'implicit'; } - try { - $getVars['redirect_uri'] = $token->claims()->get("redirect_uri"); - } catch(\Exception $e) { - $result = new JSONResponse('Bad request, missing redirect uri'); - $result->setStatus(400); - return $result; -// return $result->addHeader('Access-Control-Allow-Origin', '*'); + $getVars['response_type'] = $this->getResponseType(); + $getVars['scope'] = "openid"; + + if (!isset($getVars['redirect_uri'])) { + if (!isset($token)) { + return new JSONResponse('Bad request, does not contain valid token', 400); + } + + try { + $getVars['redirect_uri'] = $token->claims()->get("redirect_uri"); + } catch(\Exception $e) { + return new JSONResponse('Bad request, missing redirect uri', 400); + } } } - if (preg_match("/^http(s)?:/", $getVars['client_id'])) { + $request = \Laminas\Diactoros\ServerRequestFactory::fromGlobals($_SERVER, $getVars, $_POST, $_COOKIE, $_FILES); + $response = new \Laminas\Diactoros\Response(); + $authServer = new \Pdsinterop\Solid\Auth\Server($this->authServerFactory, $this->authServerConfig, $response); + + // @FIXME: Check OIDC Spec for rules regarding Client updates + if (preg_match("/^http(s)?:/", $clientId)) { $parsedOrigin = parse_url($getVars['redirect_uri']); $origin = $parsedOrigin['scheme'] . '://' . $parsedOrigin['host']; if (isset($parsedOrigin['port'])) { @@ -204,17 +204,18 @@ public function authorize() { } $clientData = array( "client_id_issued_at" => time(), - "client_name" => $getVars['client_id'], + "client_name" => $clientId, "origin" => $origin, "redirect_uris" => array( $getVars['redirect_uri'] ) ); - $clientId = $this->config->saveClientRegistration($origin, $clientData)['client_id']; - $clientId = $this->config->saveClientRegistration($getVars['client_id'], $clientData)['client_id']; + + $this->config->saveClientRegistration($origin, $clientData); + $clientId = $this->config->saveClientRegistration($clientId, $clientData)['client_id']; + $returnUrl = $getVars['redirect_uri']; } else { - $clientId = $getVars['client_id']; $returnUrl = $_SERVER['REQUEST_URI']; } @@ -231,7 +232,8 @@ public function authorize() { $result->setStatus(302); $approvalUrl = $this->urlGenerator->getAbsoluteURL($this->urlGenerator->linkToRoute("solid.page.approval", array("clientId" => $clientId, "returnUrl" => $returnUrl))); $result->addHeader("Location", $approvalUrl); - return $result; // ->addHeader('Access-Control-Allow-Origin', '*'); + + return $result; } if (isset($getVars['redirect_uri'])) { @@ -266,23 +268,21 @@ public function authorize() { return $result; } + $webId = $this->getProfilePage(); $user = new \Pdsinterop\Solid\Auth\Entity\User(); - $user->setIdentifier($this->getProfilePage()); + $user->setIdentifier($webId); - $request = \Laminas\Diactoros\ServerRequestFactory::fromGlobals($_SERVER, $getVars, $_POST, $_COOKIE, $_FILES); - $response = new \Laminas\Diactoros\Response(); - $server = new \Pdsinterop\Solid\Auth\Server($this->authServerFactory, $this->authServerConfig, $response); + $response = $authServer->respondToAuthorizationRequest($request, $user, $approval); - $response = $server->respondToAuthorizationRequest($request, $user, $approval); $response = $this->tokenGenerator->addIdTokenToResponse( $response, $clientId, - $this->getProfilePage(), + $webId, $this->session->get("nonce"), $this->config->getPrivateKey() ); - return $this->respond($response); // ->addHeader('Access-Control-Allow-Origin', '*'); + return $this->respond($response); } private function checkApproval($clientId) { diff --git a/solid/tests/Unit/Controller/ServerControllerTest.php b/solid/tests/Unit/Controller/ServerControllerTest.php index cf27fa17..4c113f68 100644 --- a/solid/tests/Unit/Controller/ServerControllerTest.php +++ b/solid/tests/Unit/Controller/ServerControllerTest.php @@ -39,6 +39,8 @@ class ServerControllerTest extends TestCase ////////////////////////////////// FIXTURES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ private const MOCK_CLIENT_ID = 'mock-client-id'; + private const MOCK_RESPONSE_TYPE = 'mock-response-type'; + private const MOCK_URI = 'mock uri'; private const MOCK_USER_ID = 'mock user id'; public static string $clientData = ''; @@ -141,7 +143,12 @@ public function testAuthorizeWithoutClientId() */ public function testAuthorizeWithoutValidToken() { - $_GET['response_type'] = 'mock-response-type'; + $_GET['client_id'] = self::MOCK_CLIENT_ID; + $_GET['nonce'] = 'mock-nonce'; + $_GET['request'] = 'mock request'; + $_GET['response_type'] = self::MOCK_RESPONSE_TYPE; + + $_SERVER['REQUEST_URI'] = self::MOCK_URI; $parameters = $this->createMockConstructorParameters(); @@ -166,9 +173,9 @@ public function testAuthorizeWithoutApprovedClient() $_GET['nonce'] = 'mock-nonce'; // JWT with empty payload, HS256 encoded, created with `private.key` from fixtures $_GET['request'] = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e30.8VKCTiBegJPuPIZlp0wbV0Sbdn5BS6TE5DCx6oYNc5o'; - $_GET['response_type'] = 'mock-response-type'; + $_GET['response_type'] = self::MOCK_RESPONSE_TYPE; - $_SERVER['REQUEST_URI'] = 'mock uri'; + $_SERVER['REQUEST_URI'] = self::MOCK_URI; $parameters = $this->createMockConstructorParameters(); @@ -243,7 +250,7 @@ public function testAuthorize() $_GET['nonce'] = 'mock-nonce'; // JWT with empty payload, HS256 encoded, created with `private.key` from fixtures $_GET['request'] = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e30.8VKCTiBegJPuPIZlp0wbV0Sbdn5BS6TE5DCx6oYNc5o'; - $_GET['response_type'] = 'mock-response-type'; + $_GET['response_type'] = self::MOCK_RESPONSE_TYPE; $_GET['redirect_uri'] = 'https://mock.client/redirect'; $_SERVER['REQUEST_URI'] = 'https://mock.server'; From 13a4ec4273a6c398038cf9811de8dd051886ceeb Mon Sep 17 00:00:00 2001 From: Ben Peachey Date: Fri, 5 Dec 2025 16:09:59 +0100 Subject: [PATCH 7/7] Change PHP GitHub Action to use docker container for entire PHPUnit job. --- .github/workflows/php.yml | 39 ++++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml index 192a59f9..a79ee15f 100644 --- a/.github/workflows/php.yml +++ b/.github/workflows/php.yml @@ -65,6 +65,14 @@ jobs: working-directory: "solid" # 02.test.php.test-unit.yml php-unittest: + container: + image: ghcr.io/${{ github.repository }}:main-${{ matrix.nextcloud_version }} + env: + NEXTCLOUD_PATH: /usr/src/nextcloud/apps + NEXTCLOUD_UPDATE: 1 + XDEBUG_MODE: coverage + volumes: + - /usr/bin/composer:/usr/bin/composer name: PHP Unit Tests needs: - lint-php-syntax @@ -78,27 +86,24 @@ jobs: - 29 - 30 steps: - - uses: actions/checkout@v4 - - uses: shivammathur/setup-php@v2 - with: - ini-values: error_reporting=E_ALL, display_errors=On - php-version: 8.3 + - uses: actions/checkout@v5 + - name: Setup Test Environment + run: | + git config --global --add safe.directory "${NEXTCLOUD_PATH}" + /entrypoint.sh "echo" + bash "${GITHUB_WORKSPACE}/init.sh" + rm -r "${NEXTCLOUD_PATH}/solid/" + cp --archive --verbose "${GITHUB_WORKSPACE}/." "${NEXTCLOUD_PATH}/" - name: Install and Cache Composer dependencies - uses: "ramsey/composer-install@v2" + uses: ramsey/composer-install@v3 with: - working-directory: "solid" + working-directory: /usr/src/nextcloud/apps/solid env: COMPOSER_AUTH: '{"github-oauth": {"github.com": "${{ secrets.GITHUB_TOKEN }}"}}' - - run: | - docker run \ - --env 'XDEBUG_MODE=coverage' \ - --rm \ - --volume="./solid:/var/www/html/apps/solid" \ - ghcr.io/${{ github.repository }}:main-${{ matrix.nextcloud_version }} \ - bash -c 'NEXTCLOUD_UPDATE=1 /entrypoint.sh "echo" \ - && sudo -u www-data bash /init.sh \ - && cd /var/www/html/apps/solid \ - && bin/phpunit --configuration phpunit.xml' + - name: Run PHPUnit + run: | + "${NEXTCLOUD_PATH}/solid/bin/phpunit" \ + --configuration "${NEXTCLOUD_PATH}/solid/phpunit.xml" # 03.quality.php.scan.dependencies-vulnerabilities.yml scan-dependencies-vulnerabilities: