Skip to content

Commit

Permalink
GFORMS-1658 - Create individual user agent for each BARS implementati…
Browse files Browse the repository at this point in the history
…on in a gForm (#1416)
  • Loading branch information
josef-vlach authored Jan 31, 2022
1 parent ce9b85a commit af0313e
Show file tree
Hide file tree
Showing 7 changed files with 134 additions and 78 deletions.
143 changes: 81 additions & 62 deletions app/uk/gov/hmrc/gform/bars/BankAccountReputationConnector.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package uk.gov.hmrc.gform.bars

import org.slf4j.{ Logger, LoggerFactory }
import play.api.libs.json.{ Format, Json }
import uk.gov.hmrc.gform.sharedmodel.formtemplate.FormTemplateId
import uk.gov.hmrc.gform.sharedmodel.{ CannotRetrieveResponse, ServiceCallResponse, ServiceResponse }
import uk.gov.hmrc.gform.wshttp.WSHttp
import uk.gov.hmrc.http.HttpReads.Implicits.readRaw
Expand All @@ -27,85 +28,103 @@ import scala.concurrent.{ ExecutionContext, Future }
import scala.language.higherKinds

trait BankAccountReputationConnector[F[_]] {
def validateBankDetails(account: ValidateBankDetails.Request)(implicit
def validateBankDetails(
formTemplateId: FormTemplateId,
account: ValidateBankDetails.Request
)(implicit
hc: HeaderCarrier
): F[ServiceCallResponse[ValidateBankDetails.Response]]
def businessBankAccountExistence(account: BusinessBankAccountExistence.Request)(implicit
def businessBankAccountExistence(
formTemplateId: FormTemplateId,
account: BusinessBankAccountExistence.Request
)(implicit
hc: HeaderCarrier
): F[ServiceCallResponse[BusinessBankAccountExistence.Response]]
}

class BankAccountReputationAsyncConnector(ws: WSHttp, baseUrl: String)(implicit ex: ExecutionContext)
class BankAccountReputationAsyncConnector(ws: FormTemplateId => WSHttp, baseUrl: String)(implicit ex: ExecutionContext)
extends BankAccountReputationConnector[Future] {
private val logger: Logger = LoggerFactory.getLogger(getClass)

override def validateBankDetails(request: ValidateBankDetails.Request)(implicit
override def validateBankDetails(
formTemplateId: FormTemplateId,
request: ValidateBankDetails.Request
)(implicit
hc: HeaderCarrier
): Future[ServiceCallResponse[ValidateBankDetails.Response]] =
ws.POST[ValidateBankDetails.Request, HttpResponse](
baseUrl + "/v2/validateBankDetails",
request
).map { httpResponse =>
val status = httpResponse.status
status match {
case 200 =>
httpResponse.json
.validate[ValidateBankDetails.Response]
.fold(
invalid => {
logger.error(
s"Calling validate bank details returned $status, but marshalling of data failed with: $invalid"
)
CannotRetrieveResponse
},
valid => {
logger.info(s"Calling validate bank details returned $status: Success.")
ServiceResponse(valid)
}
)
case other =>
logger.error(s"Problem when calling validate bank details. Http status: $other, body: ${httpResponse.body}")
CannotRetrieveResponse
ws(formTemplateId)
.POST[ValidateBankDetails.Request, HttpResponse](
baseUrl + "/v2/validateBankDetails",
request
)
.map { httpResponse =>
val status = httpResponse.status
status match {
case 200 =>
httpResponse.json
.validate[ValidateBankDetails.Response]
.fold(
invalid => {
logger.error(
s"Calling validate bank details returned $status, but marshalling of data failed with: $invalid"
)
CannotRetrieveResponse
},
valid => {
logger.info(s"Calling validate bank details returned $status: Success.")
ServiceResponse(valid)
}
)
case other =>
logger.error(s"Problem when calling validate bank details. Http status: $other, body: ${httpResponse.body}")
CannotRetrieveResponse
}
}
.recover { case ex =>
logger.error("Unknown problem when calling validate bank details", ex)
CannotRetrieveResponse
}
}.recover { case ex =>
logger.error("Unknown problem when calling validate bank details", ex)
CannotRetrieveResponse
}

override def businessBankAccountExistence(request: BusinessBankAccountExistence.Request)(implicit
override def businessBankAccountExistence(
formTemplateId: FormTemplateId,
request: BusinessBankAccountExistence.Request
)(implicit
hc: HeaderCarrier
): Future[ServiceCallResponse[BusinessBankAccountExistence.Response]] =
ws.POST[BusinessBankAccountExistence.Request, HttpResponse](
baseUrl + "/verify/business",
request
).map { httpResponse =>
val status = httpResponse.status
status match {
case 200 =>
httpResponse.json
.validate[BusinessBankAccountExistence.Response]
.fold(
invalid => {
logger.error(
s"Calling business bank account existence returned $status, but marshalling of data failed with: $invalid"
)
CannotRetrieveResponse
},
valid => {
logger.info(s"Calling business bank account existence returned $status: Success.")
ServiceResponse(valid)
}
ws(formTemplateId)
.POST[BusinessBankAccountExistence.Request, HttpResponse](
baseUrl + "/verify/business",
request
)
.map { httpResponse =>
val status = httpResponse.status
status match {
case 200 =>
httpResponse.json
.validate[BusinessBankAccountExistence.Response]
.fold(
invalid => {
logger.error(
s"Calling business bank account existence returned $status, but marshalling of data failed with: $invalid"
)
CannotRetrieveResponse
},
valid => {
logger.info(s"Calling business bank account existence returned $status: Success.")
ServiceResponse(valid)
}
)
case other =>
logger.error(
s"Problem when calling business bank account existence. Http status: $other, body: ${httpResponse.body}"
)
case other =>
logger.error(
s"Problem when calling business bank account existence. Http status: $other, body: ${httpResponse.body}"
)
CannotRetrieveResponse
CannotRetrieveResponse
}
}
.recover { case ex =>
logger.error("Unknown problem when calling business bank account existence", ex)
CannotRetrieveResponse
}
}.recover { case ex =>
logger.error("Unknown problem when calling business bank account existence", ex)
CannotRetrieveResponse
}
}

object ValidateBankDetails {
Expand Down
6 changes: 6 additions & 0 deletions app/uk/gov/hmrc/gform/gform/DataRetrieveService.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,15 @@ import uk.gov.hmrc.gform.bars.BankAccountReputationConnector
import uk.gov.hmrc.gform.models.optics.{ DataOrigin, FormModelVisibilityOptics }
import uk.gov.hmrc.gform.sharedmodel.DataRetrieve.{ BusinessBankAccountExistence, ValidateBankDetails }
import uk.gov.hmrc.gform.sharedmodel._
import uk.gov.hmrc.gform.sharedmodel.formtemplate.FormTemplateId
import uk.gov.hmrc.http.HeaderCarrier

import scala.concurrent.{ ExecutionContext, Future }
import scala.language.higherKinds

sealed trait DataRetrieveService[T <: DataRetrieve, F[_]] {
def retrieve(
formTemplateId: FormTemplateId,
dataRetrieve: T,
formModelVisibilityOptics: FormModelVisibilityOptics[DataOrigin.Browser],
maybeRequestParams: Option[JsValue]
Expand All @@ -46,6 +48,7 @@ object DataRetrieveService {
): DataRetrieveService[ValidateBankDetails, Future] = new DataRetrieveService[ValidateBankDetails, Future] {

override def retrieve(
formTemplateId: FormTemplateId,
validateBankDetails: ValidateBankDetails,
formModelVisibilityOptics: FormModelVisibilityOptics[DataOrigin.Browser],
maybeRequestParams: Option[JsValue]
Expand All @@ -64,6 +67,7 @@ object DataRetrieveService {
} else {
bankAccountReputationConnector
.validateBankDetails(
formTemplateId,
bars.ValidateBankDetails.create(sortCode, accNumber)
)
.map {
Expand Down Expand Up @@ -92,6 +96,7 @@ object DataRetrieveService {
new DataRetrieveService[BusinessBankAccountExistence, Future] {

override def retrieve(
formTemplateId: FormTemplateId,
businessBankAccountExistence: BusinessBankAccountExistence,
formModelVisibilityOptics: FormModelVisibilityOptics[DataOrigin.Browser],
maybeRequestParams: Option[JsValue]
Expand Down Expand Up @@ -122,6 +127,7 @@ object DataRetrieveService {
} else {
bankAccountReputationConnector
.businessBankAccountExistence(
formTemplateId,
bars.BusinessBankAccountExistence.create(sortCode, accNumber, companyName)
)
.map {
Expand Down
2 changes: 1 addition & 1 deletion app/uk/gov/hmrc/gform/gform/GformModule.scala
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ class GformModule(
private val barsBaseUrl = s"${configModule.serviceConfig.baseUrl("bars")}"

val bankAccountReputationConnector =
new BankAccountReputationAsyncConnector(wSHttpModule.auditableWSHttp, barsBaseUrl)
new BankAccountReputationAsyncConnector(wSHttpModule.auditableWSHttpCustomAppName, barsBaseUrl)

val addToListProcessor = new FormProcessor(
playBuiltInsModule.i18nSupport,
Expand Down
14 changes: 12 additions & 2 deletions app/uk/gov/hmrc/gform/gform/processor/FormProcessor.scala
Original file line number Diff line number Diff line change
Expand Up @@ -202,12 +202,22 @@ class FormProcessor(
val maybeRequestParams = DataRetrieve.requestParamsFromCache(cache.form, v.id)
implicit val b: BankAccountReputationConnector[Future] = bankAccountReputationConnector
DataRetrieveService[ValidateBankDetails, Future]
.retrieve(v, processData.formModelOptics.formModelVisibilityOptics, maybeRequestParams)
.retrieve(
cache.formTemplateId,
v,
processData.formModelOptics.formModelVisibilityOptics,
maybeRequestParams
)
case v: BusinessBankAccountExistence =>
val maybeRequestParams = DataRetrieve.requestParamsFromCache(cache.form, v.id)
implicit val b: BankAccountReputationConnector[Future] = bankAccountReputationConnector
DataRetrieveService[BusinessBankAccountExistence, Future]
.retrieve(v, processData.formModelOptics.formModelVisibilityOptics, maybeRequestParams)
.retrieve(
cache.formTemplateId,
v,
processData.formModelOptics.formModelVisibilityOptics,
maybeRequestParams
)
}
)(_ => Option.empty.pure[Future])(_ => Option.empty.pure[Future])
} else Option.empty.pure[Future]
Expand Down
18 changes: 17 additions & 1 deletion app/uk/gov/hmrc/gform/wshttp/WSHttpModule.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,25 +16,41 @@

package uk.gov.hmrc.gform.wshttp

import com.typesafe.config.ConfigValueFactory
import play.api.libs.ws.WSClient
import play.api.libs.ws.ahc.AhcWSComponents
import uk.gov.hmrc.gform.akka.AkkaModule
import uk.gov.hmrc.gform.auditing.AuditingModule
import uk.gov.hmrc.gform.config.ConfigModule
import uk.gov.hmrc.gform.sharedmodel.formtemplate.FormTemplateId

class WSHttpModule(
auditingModule: AuditingModule,
configModule: ConfigModule,
akkaModule: AkkaModule,
ahcWSComponents: AhcWSComponents
) {
lazy val auditableWSHttp: WSHttp = new WSHttpImpl(
val auditableWSHttp: WSHttp = new WSHttpImpl(
configModule.appConfig.appName,
auditingModule.auditConnector,
configModule.typesafeConfig,
akkaModule.actorSystem,
wsClient
)

val auditableWSHttpCustomAppName: FormTemplateId => WSHttp = formTemplateId => {
val appName = configModule.typesafeConfig.getString("appName")
val config =
configModule.typesafeConfig
.withValue("appName", ConfigValueFactory.fromAnyRef(appName + "/" + formTemplateId.value))
new WSHttpImpl(
configModule.appConfig.appName,
auditingModule.auditConnector,
config,
akkaModule.actorSystem,
wsClient
)
}

def wsClient: WSClient = ahcWSComponents.wsClient
}
2 changes: 1 addition & 1 deletion test/uk/gov/hmrc/gform/SpecWithFakeApp.scala
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ trait SpecWithFakeApp extends Spec with BaseOneServerPerSuite with FakeApplicati
lazy val applicationModule = new ApplicationModule(context) {
override val httpFilters = Nil
override lazy val wSHttpModule = new WSHttpModule(null, null, null, null) {
override lazy val auditableWSHttp: WSHttp = new StubbedWSHttp(
override val auditableWSHttp: WSHttp = new StubbedWSHttp(
HttpResponse(200, null)
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import play.api.libs.json.Json
import play.api.libs.ws.WSClient
import play.api.test.WsTestClient.InternalWSClient
import uk.gov.hmrc.gform.WiremockSupport
import uk.gov.hmrc.gform.sharedmodel.formtemplate.FormTemplateId
import uk.gov.hmrc.gform.sharedmodel.{ CannotRetrieveResponse, ServiceResponse }
import uk.gov.hmrc.gform.wshttp.WSHttp
import uk.gov.hmrc.http.hooks.HttpHook
Expand Down Expand Up @@ -61,16 +62,18 @@ class BankAccountReputationAsyncConnectorSpec

val url = s"http://localhost:$wiremockPort"

val wsHttp = new WSHttp {
override protected def actorSystem: ActorSystem = system
override protected def configuration: Config = ConfigFactory.parseString("""
|internalServiceHostPatterns = []
|bootstrap.http.headersAllowlist = []
|http-verbs.retries.intervals = []
|""".stripMargin)
override val hooks: Seq[HttpHook] = Seq.empty
override protected def wsClient: WSClient = new InternalWSClient("http", wiremockPort)
}
val wsHttp = (formTemplateId: FormTemplateId) =>
new WSHttp {
override protected def actorSystem: ActorSystem = system
override protected def configuration: Config = ConfigFactory.parseString(s"""
|internalServiceHostPatterns = []
|bootstrap.http.headersAllowlist = []
|http-verbs.retries.intervals = []
|appName = ${formTemplateId.value}
|""".stripMargin)
override val hooks: Seq[HttpHook] = Seq.empty
override protected def wsClient: WSClient = new InternalWSClient("http", wiremockPort)
}

val bankAccountReputationAsyncConnector = new BankAccountReputationAsyncConnector(wsHttp, url)

Expand All @@ -93,7 +96,7 @@ class BankAccountReputationAsyncConnectorSpec
stubFor(
WireMock
.post(s"/v2/validateBankDetails")
.withHeader("User-Agent", equalTo("AHC/2.1"))
.withHeader("User-Agent", equalTo("fooBar"))
.withHeader("Content-Type", equalTo("application/json"))
.willReturn(
ok(
Expand All @@ -107,6 +110,7 @@ class BankAccountReputationAsyncConnectorSpec
)

val future = bankAccountReputationAsyncConnector.validateBankDetails(
FormTemplateId("fooBar"),
ValidateBankDetails.create(
"112233",
"12345678"
Expand All @@ -133,6 +137,7 @@ class BankAccountReputationAsyncConnectorSpec
)

val future = bankAccountReputationAsyncConnector.validateBankDetails(
FormTemplateId("fooBar"),
ValidateBankDetails.create("", "")
)

Expand Down

0 comments on commit af0313e

Please sign in to comment.