+ {{ govuk_error_summary(form) }} {{ govuk_form_open(form) }} diff --git a/service-front/app/src/Common/src/Handler/AbstractHandler.php b/service-front/app/src/Common/src/Handler/AbstractHandler.php index 14b602f069..4481c560ab 100644 --- a/service-front/app/src/Common/src/Handler/AbstractHandler.php +++ b/service-front/app/src/Common/src/Handler/AbstractHandler.php @@ -12,6 +12,9 @@ use Psr\Http\Server\RequestHandlerInterface; use Psr\Log\LoggerInterface; +/** + * @codeCoverageIgnore + */ abstract class AbstractHandler implements RequestHandlerInterface { public function __construct( @@ -30,17 +33,21 @@ public function __construct( abstract public function handle(ServerRequestInterface $request): ResponseInterface; /** - * Redirect to the specified route + * Handles a redirect to route + * $basePathOverride used to override from English to Welsh only * * @param $route - * @param array $routeParams - * @param array $queryParams + * @param $routeParams + * @param $queryParams + * @param string|null $basePathOverride * @return RedirectResponse */ - protected function redirectToRoute($route, $routeParams = [], $queryParams = []): RedirectResponse + public function redirectToRoute($route, $routeParams = [], $queryParams = [], ?string $basePathOverride = null): RedirectResponse { - return new RedirectResponse( - $this->urlHelper->generate($route, $routeParams, $queryParams) - ); + //TODO: UML-3203 Identify if OneLogin can handle multiple redirect urls, then remove + if ($basePathOverride !== null) { + $this->urlHelper->setBasePath($basePathOverride); + } + return new RedirectResponse($this->urlHelper->generate($route, $routeParams, $queryParams)); } } diff --git a/service-front/app/src/Common/src/Service/OneLogin/OneLoginService.php b/service-front/app/src/Common/src/Service/OneLogin/OneLoginService.php index 9b3ffe7e5c..2de61c74b2 100644 --- a/service-front/app/src/Common/src/Service/OneLogin/OneLoginService.php +++ b/service-front/app/src/Common/src/Service/OneLogin/OneLoginService.php @@ -5,9 +5,12 @@ namespace Common\Service\OneLogin; use Common\Service\ApiClient\Client as ApiClient; +use Facile\OpenIDClient\Session\AuthSession; class OneLoginService { + public const OIDC_AUTH_INTERFACE = 'oidcauthinterface'; + public function __construct(private ApiClient $apiClient) { } @@ -19,4 +22,13 @@ public function authenticate(string $uiLocale, string $redirectUrl): ?array 'redirect_url' => $redirectUrl, ]); } + + public function callback(string $code, string $state, AuthSession $authCredentials): ?array + { + return $this->apiClient->httpPost('/v1/auth/callback', [ + 'code' => $code, + 'state' => $state, + 'auth_session' => $authCredentials, + ]); + } } diff --git a/service-front/app/test/CommonTest/Handler/AbstractHandlerTest.php b/service-front/app/test/CommonTest/Handler/AbstractHandlerTest.php new file mode 100644 index 0000000000..1a0cfbda02 --- /dev/null +++ b/service-front/app/test/CommonTest/Handler/AbstractHandlerTest.php @@ -0,0 +1,74 @@ +prophesize(UrlHelper::class); + $urlHelperMock->setBasePath($localOverride)->shouldBeCalledOnce(); + $urlHelperMock->generate( + 'fake-route', + ['fake-route-parameters'], + ['fake-query-parameters'], + )->willReturn('/cy/fake-route'); + + $renderer = $this->prophesize(TemplateRendererInterface::class); + + $abstractHandler = new class ($renderer->reveal(), $urlHelperMock->reveal()) extends AbstractHandler { + public function handle(ServerRequestInterface $request): ResponseInterface + { + throw new Exception('Not implemented'); + } + }; + $response = $abstractHandler->redirectToRoute( + 'fake-route', + ['fake-route-parameters'], + ['fake-query-parameters'], + $localOverride, + ); + $this->assertEquals('/cy/fake-route', $response->getHeader('location')[0]); + } + + /** + * @test + */ + public function testRedirectToRouteOverrideSetToNull(): void + { + /** @var UrlHelper|ObjectProphecy $urlHelperMock */ + $urlHelperMock = $this->prophesize(UrlHelper::class); + $urlHelperMock->setBasePath(Argument::any())->shouldNotBeCalled(); + $urlHelperMock->generate('fake-route', [], [])->willReturn('/fake-route'); + + $renderer = $this->prophesize(TemplateRendererInterface::class); + + $abstractHandler = new class ($renderer->reveal(), $urlHelperMock->reveal()) extends AbstractHandler { + public function handle(ServerRequestInterface $request): ResponseInterface + { + throw new Exception('Not implemented'); + } + }; + $response = $abstractHandler->redirectToRoute('fake-route'); + $this->assertEquals('/fake-route', $response->getHeader('location')[0]); + } +} diff --git a/service-front/app/test/CommonTest/Service/Lpa/ParseLpaDataTest.php b/service-front/app/test/CommonTest/Service/Lpa/ParseLpaDataTest.php index 2a036aa836..9f5cee8d09 100644 --- a/service-front/app/test/CommonTest/Service/Lpa/ParseLpaDataTest.php +++ b/service-front/app/test/CommonTest/Service/Lpa/ParseLpaDataTest.php @@ -91,7 +91,7 @@ public function it_correctly_parses_an_lpa_api_response(): void $this->lpaId => $this->lpaData, ] ); - $this->assertObjectHasAttribute($this->lpaId, $result); + $this->assertObjectHasProperty($this->lpaId, $result); $this->assertEquals($this->lpa, $result->{$this->lpaId}->lpa); $this->assertEquals($this->actor, $result->{$this->lpaId}->actor['details']); $this->assertEquals($this->iapImages, $result->{$this->lpaId}->iap); diff --git a/service-front/app/test/CommonTest/Service/Lpa/PopulateLpaMetadataTest.php b/service-front/app/test/CommonTest/Service/Lpa/PopulateLpaMetadataTest.php index 0ddc88b61f..c6d3b5241c 100644 --- a/service-front/app/test/CommonTest/Service/Lpa/PopulateLpaMetadataTest.php +++ b/service-front/app/test/CommonTest/Service/Lpa/PopulateLpaMetadataTest.php @@ -68,7 +68,7 @@ public function it_adds_a_viewer_code_count_per_lpa(): void $sut = new PopulateLpaMetadata($this->viewerCodeServiceProphecy->reveal()); $result = $sut($this->lpas, $this->userToken); - $this->assertObjectHasAttribute('56-5-5-5-5678', $result); + $this->assertObjectHasProperty('56-5-5-5-5678', $result); $this->assertEquals(1, $result->{'56-5-5-5-5678'}->{'activeCodeCount'}); } @@ -81,7 +81,7 @@ public function it_adds_an_active_status_for_actor(): void $sut = new PopulateLpaMetadata($this->viewerCodeServiceProphecy->reveal()); $result = $sut($this->lpas, $this->userToken); - $this->assertObjectHasAttribute('56-5-5-5-5678', $result); + $this->assertObjectHasProperty('56-5-5-5-5678', $result); $this->assertEquals(true, $result->{'56-5-5-5-5678'}->{'actorActive'}); } @@ -111,7 +111,7 @@ public function it_always_makes_a_donor_be_active(): void $sut = new PopulateLpaMetadata($this->viewerCodeServiceProphecy->reveal()); $result = $sut($this->lpas, $this->userToken); - $this->assertObjectHasAttribute('56-5-5-5-5678', $result); + $this->assertObjectHasProperty('56-5-5-5-5678', $result); $this->assertEquals(true, $result->{'56-5-5-5-5678'}->{'actorActive'}); } } diff --git a/service-front/app/test/CommonTest/Service/OneLogin/OneLoginServiceTest.php b/service-front/app/test/CommonTest/Service/OneLogin/OneLoginServiceTest.php index 517417a49c..23e8fcded6 100644 --- a/service-front/app/test/CommonTest/Service/OneLogin/OneLoginServiceTest.php +++ b/service-front/app/test/CommonTest/Service/OneLogin/OneLoginServiceTest.php @@ -6,6 +6,9 @@ use Common\Service\ApiClient\Client as ApiClient; use Common\Service\OneLogin\OneLoginService; +use DateTime; +use DateTimeInterface; +use Facile\OpenIDClient\Session\AuthSession; use PHPUnit\Framework\TestCase; use Prophecy\PhpUnit\ProphecyTrait; @@ -43,4 +46,52 @@ public function can_get_authentication_request_uri(): void $response = $oneLoginService->authenticate('en', $redirect); $this->assertEquals(['state' => $state, 'nonce' => $nonce, 'url' => $uri], $response); } + + /** @test */ + public function can_get_callback_request_uri(): void + { + $state = 'fakeState'; + $code = 'fakeCode'; + $nonce = 'fakeNonce'; + $redirect = 'FAKE_REDIRECT'; + $authCredentials = AuthSession::fromArray([ + 'state' => $state, + 'nonce' => $nonce, + 'customs' => [ + 'ui_locale' => 'en', + 'redirect_uri' => $redirect, + ], + ]); + + $apiClientProphecy = $this->prophesize(ApiClient::class); + + $lastLogin = (new DateTime('-1 day'))->format(DateTimeInterface::ATOM); + + $apiClientProphecy + ->httpPost( + '/v1/auth/callback', + [ + 'code' => $code, + 'state' => $state, + 'auth_session' => $authCredentials, + ] + )->willReturn([ + 'Id' => 'fake-id', + 'Identity' => 'fake-sub-identity', + 'Email' => 'fake@email.com', + 'LastLogin' => $lastLogin, + 'Birthday' => '1990-01-01' + ]); + + $oneLoginService = new OneLoginService($apiClientProphecy->reveal()); + $response = $oneLoginService->callback($code, $state, $authCredentials); + $this->assertEquals([ + 'Id' => 'fake-id', + 'Identity' => 'fake-sub-identity', + 'Email' => 'fake@email.com', + 'LastLogin' => $lastLogin, + 'Birthday' => '1990-01-01' + ], + $response); + } }