diff --git a/app/uk/gov/hmrc/cardpaymentfrontend/actions/Actions.scala b/app/uk/gov/hmrc/cardpaymentfrontend/actions/Actions.scala new file mode 100644 index 0000000..151f806 --- /dev/null +++ b/app/uk/gov/hmrc/cardpaymentfrontend/actions/Actions.scala @@ -0,0 +1,33 @@ +/* + * Copyright 2024 HM Revenue & Customs + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package uk.gov.hmrc.cardpaymentfrontend.actions + +import play.api.mvc.{ActionBuilder, AnyContent, DefaultActionBuilder, Request} + +import javax.inject.{Inject, Singleton} + +@Singleton +class Actions @Inject() ( + actionBuilder: DefaultActionBuilder, + getJourneyActionRefiner: GetJourneyActionRefiner +) { + + val default: ActionBuilder[Request, AnyContent] = actionBuilder + + val journeyAction: ActionBuilder[JourneyRequest, AnyContent] = default.andThen[JourneyRequest](getJourneyActionRefiner) + +} diff --git a/app/uk/gov/hmrc/cardpaymentfrontend/actions/GetJourneyActionRefiner.scala b/app/uk/gov/hmrc/cardpaymentfrontend/actions/GetJourneyActionRefiner.scala new file mode 100644 index 0000000..1d5be13 --- /dev/null +++ b/app/uk/gov/hmrc/cardpaymentfrontend/actions/GetJourneyActionRefiner.scala @@ -0,0 +1,44 @@ +/* + * Copyright 2024 HM Revenue & Customs + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package uk.gov.hmrc.cardpaymentfrontend.actions + +import play.api.mvc.{ActionRefiner, Request, Result, Results} +import uk.gov.hmrc.cardpaymentfrontend.connectors.PayApiConnector +import uk.gov.hmrc.cardpaymentfrontend.requests.RequestSupport + +import javax.inject.{Inject, Singleton} +import scala.concurrent.{ExecutionContext, Future} + +@Singleton +class GetJourneyActionRefiner @Inject() ( + payApiConnector: PayApiConnector, + requestSupport: RequestSupport +)(implicit ec: ExecutionContext) extends ActionRefiner[Request, JourneyRequest] { + + override protected[actions] def refine[A](request: Request[A]): Future[Either[Result, JourneyRequest[A]]] = { + + implicit val r: Request[A] = request + + payApiConnector.findLatestJourneyBySessionId()(requestSupport.hc) + .map { + case Some(journey) => Right(new JourneyRequest(journey, request)) + case None => Left(Results.Unauthorized("need a session id")) //should probably be a redirect to pay-frontend /pay + } + } + + override protected def executionContext: ExecutionContext = ec +} diff --git a/app/uk/gov/hmrc/cardpaymentfrontend/actions/JourneyRequest.scala b/app/uk/gov/hmrc/cardpaymentfrontend/actions/JourneyRequest.scala new file mode 100644 index 0000000..935b200 --- /dev/null +++ b/app/uk/gov/hmrc/cardpaymentfrontend/actions/JourneyRequest.scala @@ -0,0 +1,29 @@ +/* + * Copyright 2023 HM Revenue & Customs + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package uk.gov.hmrc.cardpaymentfrontend.actions + +import payapi.cardpaymentjourney.model.journey.{Journey, JourneySpecificData} +import payapi.corcommon.model.JourneyId +import play.api.mvc.{Request, WrappedRequest} + +class JourneyRequest[A]( + val journey: Journey[JourneySpecificData], + val request: Request[A] +) extends WrappedRequest[A](request) { + + val journeyId: JourneyId = journey._id +} diff --git a/app/uk/gov/hmrc/cardpaymentfrontend/controllers/EmailAddressController.scala b/app/uk/gov/hmrc/cardpaymentfrontend/controllers/EmailAddressController.scala index bf29cf1..95f3300 100755 --- a/app/uk/gov/hmrc/cardpaymentfrontend/controllers/EmailAddressController.scala +++ b/app/uk/gov/hmrc/cardpaymentfrontend/controllers/EmailAddressController.scala @@ -18,8 +18,10 @@ package uk.gov.hmrc.cardpaymentfrontend.controllers import play.api.data.Form import play.api.mvc.{Action, AnyContent, MessagesControllerComponents} +import uk.gov.hmrc.cardpaymentfrontend.actions.{Actions, JourneyRequest} import uk.gov.hmrc.cardpaymentfrontend.forms.EmailAddressForm import uk.gov.hmrc.cardpaymentfrontend.models.EmailAddress +import uk.gov.hmrc.cardpaymentfrontend.requests.RequestSupport import uk.gov.hmrc.cardpaymentfrontend.views.html.EmailAddressPage import uk.gov.hmrc.play.bootstrap.frontend.controller.FrontendController @@ -27,15 +29,19 @@ import javax.inject.{Inject, Singleton} @Singleton class EmailAddressController @Inject() ( - mcc: MessagesControllerComponents, - emailAddressPage: EmailAddressPage + actions: Actions, + requestSupport: RequestSupport, + emailAddressPage: EmailAddressPage, + mcc: MessagesControllerComponents ) extends FrontendController(mcc) { - val renderPage: Action[AnyContent] = Action { implicit request => + import requestSupport._ + + val renderPage: Action[AnyContent] = actions.journeyAction { implicit journeyRequest: JourneyRequest[AnyContent] => Ok(emailAddressPage(EmailAddressForm.form())) } - val submit: Action[AnyContent] = Action { implicit request => + val submit: Action[AnyContent] = actions.journeyAction { implicit journeyRequest: JourneyRequest[AnyContent] => EmailAddressForm.form() .bindFromRequest() .fold( diff --git a/app/uk/gov/hmrc/cardpaymentfrontend/requests/RequestSupport.scala b/app/uk/gov/hmrc/cardpaymentfrontend/requests/RequestSupport.scala index 9f5b5d4..7d35c8f 100644 --- a/app/uk/gov/hmrc/cardpaymentfrontend/requests/RequestSupport.scala +++ b/app/uk/gov/hmrc/cardpaymentfrontend/requests/RequestSupport.scala @@ -33,7 +33,6 @@ class RequestSupport @Inject() (override val messagesApi: MessagesApi) extends I implicit def hc(implicit request: Request[_]): HeaderCarrier = RequestSupport.hc def lang(implicit messages: Messages): Lang = messages.lang - // def language(implicit messages: Messages): Language = Language()(messages) } object RequestSupport { diff --git a/app/uk/gov/hmrc/cardpaymentfrontend/views/EmailAddressPage.scala.html b/app/uk/gov/hmrc/cardpaymentfrontend/views/EmailAddressPage.scala.html index 6ac11a4..cb1d1c6 100755 --- a/app/uk/gov/hmrc/cardpaymentfrontend/views/EmailAddressPage.scala.html +++ b/app/uk/gov/hmrc/cardpaymentfrontend/views/EmailAddressPage.scala.html @@ -30,7 +30,7 @@ formWithCSRF: FormWithCSRF ) -@(form: Form[EmailAddress])(implicit request: RequestHeader, messages: Messages) +@(form: Form[EmailAddress])(implicit requestHeader: RequestHeader, messages: Messages) @heading = @{messages("email-address.heading")} @key = @{EmailAddressForm.emailAddressKey} @@ -66,7 +66,3 @@ } } - -@{ - //$COVERAGE-OFF$ -} diff --git a/test/uk/gov/hmrc/cardpaymentfrontend/actions/ActionRefinerSpec.scala b/test/uk/gov/hmrc/cardpaymentfrontend/actions/ActionRefinerSpec.scala new file mode 100644 index 0000000..41ff6b2 --- /dev/null +++ b/test/uk/gov/hmrc/cardpaymentfrontend/actions/ActionRefinerSpec.scala @@ -0,0 +1,46 @@ +/* + * Copyright 2024 HM Revenue & Customs + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package uk.gov.hmrc.cardpaymentfrontend.actions + +import play.api.mvc.{AnyContent, Result, Results} +import play.api.test.FakeRequest +import uk.gov.hmrc.cardpaymentfrontend.testsupport.ItSpec +import uk.gov.hmrc.cardpaymentfrontend.testsupport.TestOps.FakeRequestOps +import uk.gov.hmrc.cardpaymentfrontend.testsupport.stubs.PayApiStub +import uk.gov.hmrc.cardpaymentfrontend.testsupport.testdata.TestJourneys + +class ActionRefinerSpec extends ItSpec { + + "getJourneyActionRefiner" - { + + val systemUnderTest: GetJourneyActionRefiner = app.injector.instanceOf[GetJourneyActionRefiner] + + val fakeRequest: FakeRequest[AnyContent] = FakeRequest("GET", "/who-cares").withSessionId() + + "should return a left with unauthorised Result when pay-api returns no journey" in { + systemUnderTest.refine(fakeRequest).futureValue shouldBe Left(Results.Unauthorized("need a session id")) + } + + "should return a right with JourneyRequest when pay-api returns a journey" in { + PayApiStub.stubForFindBySessionId2xx(TestJourneys.testPfSaJourneyCreated) + val result: Either[Result, JourneyRequest[AnyContent]] = systemUnderTest.refine(fakeRequest).futureValue + result.isRight shouldBe true + result.map(_.journey) shouldBe Right(TestJourneys.testPfSaJourneyCreated) + } + } + +} diff --git a/test/uk/gov/hmrc/cardpaymentfrontend/controllers/EmailAddressControllerSpec.scala b/test/uk/gov/hmrc/cardpaymentfrontend/controllers/EmailAddressControllerSpec.scala index ac1763b..06114d7 100644 --- a/test/uk/gov/hmrc/cardpaymentfrontend/controllers/EmailAddressControllerSpec.scala +++ b/test/uk/gov/hmrc/cardpaymentfrontend/controllers/EmailAddressControllerSpec.scala @@ -18,28 +18,47 @@ package uk.gov.hmrc.cardpaymentfrontend.controllers import org.jsoup.Jsoup import play.api.http.Status -import play.api.mvc.{AnyContentAsEmpty, AnyContentAsFormUrlEncoded, Cookie} +import play.api.mvc.{AnyContentAsEmpty, AnyContentAsFormUrlEncoded} import play.api.test.FakeRequest import play.api.test.Helpers._ import uk.gov.hmrc.cardpaymentfrontend.testsupport.ItSpec +import uk.gov.hmrc.cardpaymentfrontend.testsupport.TestOps._ +import uk.gov.hmrc.cardpaymentfrontend.testsupport.stubs.PayApiStub +import uk.gov.hmrc.cardpaymentfrontend.testsupport.testdata.TestJourneys import scala.jdk.CollectionConverters.ListHasAsScala class EmailAddressControllerSpec extends ItSpec { + override def beforeEach(): Unit = { + PayApiStub.stubForFindBySessionId2xx(TestJourneys.testPfSaJourneyCreated) + () + } + private val systemUnderTest: EmailAddressController = app.injector.instanceOf[EmailAddressController] "EmailController" - { + "GET /email-address" - { - val fakeGetRequest: FakeRequest[AnyContentAsEmpty.type] = FakeRequest("GET", "/email-address") - val fakeGetRequestInWelsh: FakeRequest[AnyContentAsEmpty.type] = FakeRequest("GET", "/email-address").withCookies(Cookie("PLAY_LANG", "cy")) + val fakeGetRequest: FakeRequest[AnyContentAsEmpty.type] = + FakeRequest("GET", "/email-address").withSessionId() + + val fakeGetRequestInWelsh: FakeRequest[AnyContentAsEmpty.type] = + fakeGetRequest.withLangWelsh() "should return 200 OK" in { val result = systemUnderTest.renderPage(fakeGetRequest) status(result) shouldBe Status.OK } + //TODO: check if this should redirect to /pay as well. + "should return 401 unauthorised when there is no journey returned from pay-api via action refiner" in { + PayApiStub.stubForFindBySessionId404 + val result = systemUnderTest.renderPage(fakeGetRequest) + status(result) shouldBe Status.UNAUTHORIZED + } + "render the page with the hmrc layout" in { val result = systemUnderTest.renderPage(fakeGetRequest) val document = Jsoup.parse(contentAsString(result)) @@ -131,10 +150,13 @@ class EmailAddressControllerSpec extends ItSpec { "POST /email-address" - { def fakePostRequest(formData: (String, String)*): FakeRequest[AnyContentAsFormUrlEncoded] = - FakeRequest("POST", "/email-address").withFormUrlEncodedBody(formData: _*) + FakeRequest("POST", "/email-address") + .withSessionId() + .withFormUrlEncodedBody(formData: _*) def fakePostRequestInWelsh(formData: (String, String)*): FakeRequest[AnyContentAsFormUrlEncoded] = - FakeRequest("POST", "/email-address").withFormUrlEncodedBody(formData: _*).withCookies(Cookie("PLAY_LANG", "cy")) + fakePostRequest(formData: _*) + .withLangWelsh() "should return 200 OK when a valid email address is submitted" in { val validFormData = ("email-address", "blag@blah.com") diff --git a/test/uk/gov/hmrc/cardpaymentfrontend/testsupport/TestOps.scala b/test/uk/gov/hmrc/cardpaymentfrontend/testsupport/TestOps.scala new file mode 100644 index 0000000..4d0f765 --- /dev/null +++ b/test/uk/gov/hmrc/cardpaymentfrontend/testsupport/TestOps.scala @@ -0,0 +1,33 @@ +/* + * Copyright 2024 HM Revenue & Customs + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package uk.gov.hmrc.cardpaymentfrontend.testsupport + +import play.api.mvc.Cookie +import play.api.test.FakeRequest +import uk.gov.hmrc.http.SessionKeys + +object TestOps { + implicit class FakeRequestOps[T](r: FakeRequest[T]) { + def withLang(language: String = "en"): FakeRequest[T] = r.withCookies(Cookie("PLAY_LANG", language)) + + def withLangWelsh(): FakeRequest[T] = r.withLang("cy") + def withLangEnglish(): FakeRequest[T] = r.withLang("en") + + def withSessionId(sessionId: String = "some-valid-session-id"): FakeRequest[T] = + r.withSession(SessionKeys.sessionId -> sessionId) + } +}