Skip to content

DLS-9800: Fixed failing unit tests #181

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Jan 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ trait HelpToSaveConnector {

@Singleton
class HelpToSaveConnectorImpl @Inject() (config: Configuration, http: HttpClient)()
extends HelpToSaveConnector with Logging {
extends HelpToSaveConnector with Logging {

private val htsBaseUrl = {
val protocol = config.underlying.getString("microservice.services.help-to-save.protocol")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,15 @@ import uk.gov.hmrc.play.bootstrap.backend.controller.BackendController
import scala.concurrent.ExecutionContext

@Singleton
class DocumentationController @Inject() (configuration: Configuration, cc: ControllerComponents, assets: Assets) (implicit materializer: Materializer, executionContext: ExecutionContext)
extends BackendController(cc) {
class DocumentationController @Inject() (configuration: Configuration, cc: ControllerComponents, assets: Assets)(
implicit materializer: Materializer,
executionContext: ExecutionContext
) extends BackendController(cc) {

val access: Version => APIAccess = APIAccess(configuration.underlying.getConfig("api.access"))

val versionEnabled: Version => Boolean = version => configuration.underlying.getBoolean(s"api.access.version-$version.enabled")
val versionEnabled: Version => Boolean = version =>
configuration.underlying.getBoolean(s"api.access.version-$version.enabled")

def definition(): Action[AnyContent] = Action {
Ok(txt.definition(access, versionEnabled)).as("application/json")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,10 @@ class HelpToSaveController @Inject() (
v2.Retrievals.itmpAddress and
v2.Retrievals.email

def apiErrorToResult(e: ApiError):Result = { e match
{
case _: ApiAccessError => Forbidden(Json.toJson(e))
case _: ApiValidationError => BadRequest(Json.toJson(e))
case _: ApiBackendError => InternalServerError(Json.toJson(e))
}
def apiErrorToResult(e: ApiError): Result = e match {
case _: ApiAccessError => Forbidden(Json.toJson(e))
case _: ApiValidationError => BadRequest(Json.toJson(e))
case _: ApiBackendError => InternalServerError(Json.toJson(e))
}

def createAccount(): Action[AnyContent] = authorised(v2AuthProviderId) { implicit request => credentials =>
Expand Down Expand Up @@ -108,30 +106,31 @@ class HelpToSaveController @Inject() (
}
}

def checkEligibilityDeriveNino(): Action[AnyContent] = authorised(v2AuthProviderId) { implicit request => credentials =>
val correlationId = UUID.randomUUID()

val result: Future[Result] =
AccessType.fromLegacyCredentials(credentials) match {
case Right(UserRestricted) =>
authorised(v2Nino) { _ =>
_.fold[Future[Result]](Forbidden)(getEligibility(_, correlationId))
}(request)

case Right(PrivilegedAccess) =>
logger.warn(
s"no nino exists in the api url, but nino from auth exists and providerType is not 'GovernmentGateway', $correlationId"
)
toFuture(Forbidden)

case Left(e) =>
logger.warn(
s"Received check eligibility request with unsupported credentials provider type: $e, $correlationId"
)
unsupportedCredentialsProviderResult
}
def checkEligibilityDeriveNino(): Action[AnyContent] = authorised(v2AuthProviderId) {
implicit request => credentials =>
val correlationId = UUID.randomUUID()

val result: Future[Result] =
AccessType.fromLegacyCredentials(credentials) match {
case Right(UserRestricted) =>
authorised(v2Nino) { _ =>
_.fold[Future[Result]](Forbidden)(getEligibility(_, correlationId))
}(request)

case Right(PrivilegedAccess) =>
logger.warn(
s"no nino exists in the api url, but nino from auth exists and providerType is not 'GovernmentGateway', $correlationId"
)
toFuture(Forbidden)

result.map(_.withHeaders(correlationIdHeaderName -> correlationId.toString))
case Left(e) =>
logger.warn(
s"Received check eligibility request with unsupported credentials provider type: $e, $correlationId"
)
unsupportedCredentialsProviderResult
}

result.map(_.withHeaders(correlationIdHeaderName -> correlationId.toString))

}

Expand Down Expand Up @@ -180,7 +179,7 @@ class HelpToSaveController @Inject() (
)(implicit request: Request[AnyContent], hc: HeaderCarrier): Future[Result] =
helpToSaveApiService.checkEligibility(nino, correlationId).map {
case Right(response) => Ok(toJson(response))
case Left (e: ApiError) =>
case Left(e: ApiError) =>
apiErrorToResult(e)
}

Expand All @@ -191,7 +190,7 @@ class HelpToSaveController @Inject() (
.getAccount(nino)
.map {
case Right(Some(account)) => Ok(Json.toJson(account))
case Right(None) => NotFound
case Right(None) => NotFound
case Left(e: ApiError) =>
apiErrorToResult(e)
}
Expand All @@ -204,6 +203,10 @@ class HelpToSaveController @Inject() (
}

val unsupportedCredentialsProviderResult: Result = {
Forbidden(Json.toJson(ApiAccessError("UNSUPPORTED_CREDENTIALS_PROVIDER", "credentials provider not recognised").asInstanceOf[ApiError]))
Forbidden(
Json.toJson(
ApiAccessError("UNSUPPORTED_CREDENTIALS_PROVIDER", "credentials provider not recognised").asInstanceOf[ApiError]
)
)
}
}
4 changes: 2 additions & 2 deletions app/uk/gov/hmrc/helptosaveapi/models/AccessType.scala
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ object AccessType {
case object UserRestricted extends AccessType

def fromLegacyCredentials(credentials: LegacyCredentials): Either[String, AccessType] = credentials match {
case GGCredId(_) => Right(UserRestricted)
case GGCredId(_) => Right(UserRestricted)
case PAClientId(_) => Right(PrivilegedAccess)
case other => Left(other.toString)
case other => Left(other.toString)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ object EligibilityResponse {
case None =>
json.\("accountExists").asOpt[Boolean] match {
case Some(true) => JsSuccess(AccountAlreadyExists())
case _ => JsError(s"couldn't parse eligibility json from mongo, json=$json")
case _ => JsError(s"couldn't parse eligibility json from mongo, json=$json")
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,14 +81,14 @@ object CreateAccountBody {

def reads(clientCode: String): Reads[CreateAccountBody] = Reads[CreateAccountBody] { jsValue =>
for {
nino <- (jsValue \ "nino").validate[String]
forename <- (jsValue \ "forename").validate[String]
surname <- (jsValue \ "surname").validate[String]
dateOfBirth <- (jsValue \ "dateOfBirth").validate[LocalDate]
contactDetails <- (jsValue \ "contactDetails").validate[ContactDetails]
nino <- (jsValue \ "nino").validate[String]
forename <- (jsValue \ "forename").validate[String]
surname <- (jsValue \ "surname").validate[String]
dateOfBirth <- (jsValue \ "dateOfBirth").validate[LocalDate]
contactDetails <- (jsValue \ "contactDetails").validate[ContactDetails]
registrationChannel <- (jsValue \ "registrationChannel").validate[String]
nbaDetails <- (jsValue \ "bankDetails").validateOpt[BankDetails]
systemId <- JsSuccess("MDTP-API-" + clientCode)
nbaDetails <- (jsValue \ "bankDetails").validateOpt[BankDetails]
systemId <- JsSuccess("MDTP-API-" + clientCode)
} yield CreateAccountBody(
nino,
forename,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,18 +88,18 @@ object CreateAccountField {
fields.foldLeft(json.as[JsObject]) {
case (acc, (field, value)) =>
acc.deepMerge(field match {
case Forename => jsObject(NonEmptyList.of("body", "forename") -> value)
case Surname => jsObject(NonEmptyList.of("body", "surname") -> value)
case DateOfBirth => jsObject(NonEmptyList.of("body", "dateOfBirth") -> value)
case NINO => jsObject(NonEmptyList.of("body", "nino") -> value)
case AddressLine1 => jsObject(NonEmptyList.of("body", "contactDetails", "address1") -> value)
case AddressLine2 => jsObject(NonEmptyList.of("body", "contactDetails", "address2") -> value)
case AddressLine3 => jsObject(NonEmptyList.of("body", "contactDetails", "address3") -> value)
case AddressLine4 => jsObject(NonEmptyList.of("body", "contactDetails", "address4") -> value)
case AddressLine5 => jsObject(NonEmptyList.of("body", "contactDetails", "address5") -> value)
case Postcode => jsObject(NonEmptyList.of("body", "contactDetails", "postcode") -> value)
case CountryCode => jsObject(NonEmptyList.of("body", "contactDetails", "countryCode") -> value)
case Email => jsObject(NonEmptyList.of("body", "contactDetails", "email") -> value)
case Forename => jsObject(NonEmptyList.of("body", "forename") -> value)
case Surname => jsObject(NonEmptyList.of("body", "surname") -> value)
case DateOfBirth => jsObject(NonEmptyList.of("body", "dateOfBirth") -> value)
case NINO => jsObject(NonEmptyList.of("body", "nino") -> value)
case AddressLine1 => jsObject(NonEmptyList.of("body", "contactDetails", "address1") -> value)
case AddressLine2 => jsObject(NonEmptyList.of("body", "contactDetails", "address2") -> value)
case AddressLine3 => jsObject(NonEmptyList.of("body", "contactDetails", "address3") -> value)
case AddressLine4 => jsObject(NonEmptyList.of("body", "contactDetails", "address4") -> value)
case AddressLine5 => jsObject(NonEmptyList.of("body", "contactDetails", "address5") -> value)
case Postcode => jsObject(NonEmptyList.of("body", "contactDetails", "postcode") -> value)
case CountryCode => jsObject(NonEmptyList.of("body", "contactDetails", "countryCode") -> value)
case Email => jsObject(NonEmptyList.of("body", "contactDetails", "email") -> value)
case CommunicationPreference =>
jsObject(NonEmptyList.of("body", "contactDetails", "communicationPreference") -> value)
case RegistrationChannel | Address => JsObject(Map.empty[String, JsValue])
Expand All @@ -110,8 +110,8 @@ object CreateAccountField {

@tailrec
def loop(l: List[String], acc: JsObject): JsObject = l match {
case Nil => acc
case head :: Nil => JsObject(List(head -> acc))
case Nil => acc
case head :: Nil => JsObject(List(head -> acc))
case head :: tail => loop(tail, JsObject(List(head -> acc)))
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ object CreateAccountRequest {
implicit val reads: Reads[CreateAccountRequest] = Reads[CreateAccountRequest] { jsValue =>
for {
header <- (jsValue \ "header").validate[CreateAccountHeader]
body <- (jsValue \ "body").validate[CreateAccountBody](CreateAccountBody.reads(header.clientCode))
body <- (jsValue \ "body").validate[CreateAccountBody](CreateAccountBody.reads(header.clientCode))
} yield CreateAccountRequest(header, body)
}

Expand Down
25 changes: 13 additions & 12 deletions app/uk/gov/hmrc/helptosaveapi/repo/EligibilityStore.scala
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,7 @@ object EligibilityStore {
}

@Singleton
class MongoEligibilityStore @Inject()(mongoComponent: MongoComponent,
servicesConfig: ServicesConfig)(
class MongoEligibilityStore @Inject() (mongoComponent: MongoComponent, servicesConfig: ServicesConfig)(
implicit ec: ExecutionContext
) extends EligibilityStore {

Expand All @@ -65,9 +64,10 @@ class MongoEligibilityStore @Inject()(mongoComponent: MongoComponent,
val mongoRepo = new MongoCacheRepository(
mongoComponent = mongoComponent,
collectionName = "api-eligibility",
ttl = servicesConfig.getDuration("mongo-cache.expireAfter"),
ttl = servicesConfig.getDuration("mongo-cache.expireAfter"),
timestampSupport = new CurrentTimestampSupport,
cacheIdType = CacheIdType.SimpleCacheId)(ec)
cacheIdType = CacheIdType.SimpleCacheId
)(ec)

override def get(
correlationId: UUID
Expand All @@ -76,13 +76,13 @@ class MongoEligibilityStore @Inject()(mongoComponent: MongoComponent,
.map { maybeCache =>
val response: OptionT[EitherStringOr, EligibilityResponseWithNINO] = for {
cache <- OptionT.fromOption[EitherStringOr](maybeCache)
data <- OptionT.fromOption[EitherStringOr](Some(cache.data))
data <- OptionT.fromOption[EitherStringOr](Some(cache.data))
result <- OptionT.liftF[EitherStringOr, EligibilityResponseWithNINO](
(data \ "eligibility")
.validate[EligibilityResponseWithNINO]
.asEither
.leftMap(e => s"Could not parse data: ${e.mkString("; ")}")
)
(data \ "eligibility")
.validate[EligibilityResponseWithNINO]
.asEither
.leftMap(e => s"Could not parse data: ${e.mkString("; ")}")
)
} yield result

response.value
Expand All @@ -100,8 +100,9 @@ class MongoEligibilityStore @Inject()(mongoComponent: MongoComponent,
"eligibility",
Json.toJson(EligibilityResponseWithNINO(eligibility, nino))
).map[Either[String, Unit]] { dbUpdate =>
Right(())
}.recover {
Right(())
}
.recover {
case e =>
Left(e.getMessage)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ private[services] trait CreateAccountBehaviour { this: HelpToSaveApiService =>
case None => // No bodyNINO
retrievedUserDetails.nino match {
case Some(nino) => collate(json, missingDetails, retrievedUserDetails, nino, registrationChannel)
case None => Left(ApiAccessError())
case None => Left(ApiAccessError())
}
}

Expand Down Expand Up @@ -123,11 +123,11 @@ private[services] trait CreateAccountBehaviour { this: HelpToSaveApiService =>
List[(CreateAccountField, JsValue)](
AddressLine1 -> toJsValue(l1),
AddressLine2 -> toJsValue(l2),
Postcode -> toJsValue(p),
Postcode -> toJsValue(p),
AddressLine3 -> toJsValue(retrievedUserDetails.address.flatMap(_.line3)),
AddressLine4 -> toJsValue(retrievedUserDetails.address.flatMap(_.line4)),
AddressLine5 -> toJsValue(retrievedUserDetails.address.flatMap(_.line5)),
CountryCode -> toJsValue(retrievedUserDetails.address.flatMap(_.countryCode))
CountryCode -> toJsValue(retrievedUserDetails.address.flatMap(_.countryCode))
).map { case (k, v) => k -> Some(v) }
}
addressFields.getOrElse(List(CreateAccountField.Address -> None))
Expand Down
24 changes: 12 additions & 12 deletions app/uk/gov/hmrc/helptosaveapi/services/HelpToSaveApiService.scala
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,8 @@ class HelpToSaveApiServiceImpl @Inject() (
} else {
(for {
updatedJson <- EitherT.fromEither[Future](
fillInMissingDetailsGG(json, missingMandatoryFields, retrievedUserDetails)
)
fillInMissingDetailsGG(json, missingMandatoryFields, retrievedUserDetails)
)
r <- EitherT(storeEmailThenCreateAccount(updatedJson, retrievedUserDetails.nino, request))
} yield r).value
}
Expand Down Expand Up @@ -163,9 +163,9 @@ class HelpToSaveApiServiceImpl @Inject() (

val result: CheckEligibilityResponseType = (p, q).mapN[Either[ApiError, EligibilityResponse]] {
case (Right(eligibility), Right(true)) => Right(eligibility)
case (Right(_), Right(false)) => Left(ApiValidationError("INVALID_BANK_DETAILS"))
case (Left(apiError), _) => Left(apiError)
case (_, Left(apiError)) => Left(apiError)
case (Right(_), Right(false)) => Left(ApiValidationError("INVALID_BANK_DETAILS"))
case (Left(apiError), _) => Left(apiError)
case (_, Left(apiError)) => Left(apiError)
}

result.flatMap {
Expand All @@ -175,11 +175,11 @@ class HelpToSaveApiServiceImpl @Inject() (
if (body.contactDetails.communicationPreference === "02") {
(for {
email <- EitherT.fromOption(
body.contactDetails.email,
ApiValidationError(
"no email found in the request body but communicationPreference is 02"
)
)
body.contactDetails.email,
ApiValidationError(
"no email found in the request body but communicationPreference is 02"
)
)
_ <- EitherT(storeEmail(body.nino, email, header.requestCorrelationId))
r <- EitherT(createAccount(body, header, aer))
} yield r).value
Expand Down Expand Up @@ -281,7 +281,7 @@ class HelpToSaveApiServiceImpl @Inject() (
val result: EitherT[Future, ApiError, EligibilityResponse] =
for {
enrolmentStatus <- EitherT.liftF(getUserEnrolmentStatus(nino, correlationId))
ecResult <- EitherT(performCheckEligibility(nino, correlationId, enrolmentStatus))
ecResult <- EitherT(performCheckEligibility(nino, correlationId, enrolmentStatus))
} yield ecResult

result.value
Expand Down Expand Up @@ -604,7 +604,7 @@ object HelpToSaveApiServiceImpl {
)

case (3, _) => Right(AccountAlreadyExists())
case _ => Left(s"invalid combination for eligibility response. Response was '$r'")
case _ => Left(s"invalid combination for eligibility response. Response was '$r'")
}

// scalastyle:on magic.number
Expand Down
2 changes: 1 addition & 1 deletion app/uk/gov/hmrc/helptosaveapi/util/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ package object util {
def maskNino(original: String): String =
Option(original) match {
case Some(text) => ninoRegex.replaceAllIn(text, "<NINO>")
case None => original
case None => original
}

def base64Encode(input: String): String = new String(Base64.getEncoder.encode(input.getBytes))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ class CreateAccountRequestValidator @Inject() (emailValidation: EmailValidation)
s.toList match {
// only loop over strings that have length two or greater
case head :: tail => loop(tail, head, 0)
case _ => false
case _ => false
}
} else {
false
Expand Down
Loading