From ae45ef93ba96c2d27a5a57c9a99b3b8e12c94e11 Mon Sep 17 00:00:00 2001
From: John Kelly <60345872+jhkldev@users.noreply.github.com>
Date: Thu, 30 May 2024 12:42:27 +0100
Subject: [PATCH] GG-7813: openid-connect-userinfo : always enable addressLine5
& countryCode, remove unwanted code & config, and countryCode discovery [
GLSD-10273 ]
---
README.md | 13 +++-
app/config/FeatureSwitch.scala | 45 -----------
.../testOnly/FeatureSwitchController.scala | 57 --------------
app/data/UserInfoGenerator.scala | 23 ++----
app/services/UserInfoTransformer.scala | 7 +-
conf/application.conf | 9 ---
conf/testOnlyDoNotUseInAppConf.routes | 3 -
it/test/FeatureSwitchControllerISpec.scala | 74 ------------------
it/test/UserInfoServiceISpec.scala | 15 ----
project/AppDependencies.scala | 18 +----
project/build.properties | 2 +-
project/plugins.sbt | 6 +-
public/api/conf/1.0/application.yaml | 49 ++++++------
...PartyDelegatedAuthorityConnectorSpec.scala | 3 +-
test/controllers/UserInfoControllerSpec.scala | 3 +-
.../FeatureSwitchControllerSpec.scala | 76 -------------------
test/data/UserInfoGeneratorSpec.scala | 23 ------
test/services/UserInfoServiceSpec.scala | 4 +-
test/services/UserInfoTransformerSpec.scala | 67 +++++++++++-----
19 files changed, 111 insertions(+), 386 deletions(-)
delete mode 100644 app/config/FeatureSwitch.scala
delete mode 100644 app/controllers/testOnly/FeatureSwitchController.scala
delete mode 100644 it/test/FeatureSwitchControllerISpec.scala
delete mode 100644 test/controllers/testOnly/FeatureSwitchControllerSpec.scala
diff --git a/README.md b/README.md
index 2afdf9b..e33b1bf 100644
--- a/README.md
+++ b/README.md
@@ -3,7 +3,7 @@
[![Build Status](https://travis-ci.org/hmrc/openid-connect-userinfo.svg?branch=master)](https://travis-ci.org/hmrc/openid-connect-userinfo) [ ![Download](https://api.bintray.com/packages/hmrc/releases/openid-connect-userinfo/images/download.svg) ](https://bintray.com/hmrc/releases/openid-connect-userinfo/_latestVersion)
-This Beta REST API aims to provide a specification compliant OpenID Connect implementation. It allows consumers to access user details with consent and in the OpenID Connect UserInfo format.
+The REST API, exposed by the HMRC API Platform as /userinfo to external clients, aims to provide a specification compliant OpenID Connect implementation. It allows consumers to access user details with consent and in the OpenID Connect UserInfo format.
A typical workflow would be:
@@ -15,10 +15,15 @@ User details data structures follow the OpenId Connect UserInfo specification (s
You can dive deeper into the documentation in the [API Developer Hub](https://developer.service.hmrc.gov.uk/api-documentation/docs/api#openid-connect-userinfo).
-## Deprecated Class Usage
-You can find the deprecation suppression `@nowarn("cat=deprecation")` in the code in few places.
+## Authentication tokens
+Note, the /userinfo endpoint is an external API endpoint. This endpoint requires an API token for authentication.
-The reason is that when the latest `v2.Retrievals` was used then the integration tests were broken and wasn't obvious why.
+## API
+
+| Method | HMRC API Platform Path | Internal Path | Description |
+|--------|------------------------|---------------|----------------------------------------------------------------------------------------------------------------------|
+| GET | /userinfo | / | Returns information about an End-User as requested in the openid scopes as documented in the published API document. |
+| POST | Internal use only | / | |
## Running Locally
Run the service `sbt run -Drun.mode=Dev`
diff --git a/app/config/FeatureSwitch.scala b/app/config/FeatureSwitch.scala
deleted file mode 100644
index 227c326..0000000
--- a/app/config/FeatureSwitch.scala
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * 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 config
-
-case class FeatureSwitch(name: String, isEnabled: Boolean)
-
-object FeatureSwitch {
-
- def forName(name: String) = FeatureSwitch(name, java.lang.Boolean.getBoolean(systemPropertyName(name)))
-
- def enable(switch: FeatureSwitch): FeatureSwitch = setProp(switch.name, true)
-
- def disable(switch: FeatureSwitch): FeatureSwitch = setProp(switch.name, false)
-
- private def setProp(name: String, value: Boolean): FeatureSwitch = {
- sys.props += ((systemPropertyName(name), value.toString))
- forName(name)
- }
-
- private def systemPropertyName(name: String) = s"feature.$name"
-
-}
-
-object UserInfoFeatureSwitches {
-
- def countryCode = FeatureSwitch.forName("countryCode")
- def addressLine5 = FeatureSwitch.forName("addressLine5")
-
- def allSwitches: Seq[FeatureSwitch] = Seq(countryCode, addressLine5)
-
-}
diff --git a/app/controllers/testOnly/FeatureSwitchController.scala b/app/controllers/testOnly/FeatureSwitchController.scala
deleted file mode 100644
index 641903c..0000000
--- a/app/controllers/testOnly/FeatureSwitchController.scala
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * 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 controllers.testOnly
-
-import config.{FeatureSwitch, UserInfoFeatureSwitches}
-import play.api.libs.json.{JsValue, Json, OWrites, Reads}
-import play.api.mvc.{Action, AnyContent, ControllerComponents}
-import uk.gov.hmrc.play.bootstrap.backend.controller.BackendController
-
-import javax.inject.{Inject, Singleton}
-import scala.concurrent.{ExecutionContext, Future}
-
-@Singleton
-class FeatureSwitchController @Inject() ()(implicit cc: ControllerComponents, ec: ExecutionContext) extends BackendController(cc) {
-
- implicit val featureSwitchReads: Reads[FeatureSwitch] = Json.reads[FeatureSwitch]
- implicit val featureSwitchWrites: OWrites[FeatureSwitch] = Json.writes[FeatureSwitch]
- implicit val FeatureSwitchRequestReads: Reads[FeatureSwitchRequest] = Json.reads[FeatureSwitchRequest]
-
- def getFlags: Action[AnyContent] = Action {
- Ok(currentFeatureSwitchesAsJson)
- }
-
- def setFlags(): Action[JsValue] = {
- Action.async(parse.json) { implicit request =>
- withJsonBody[FeatureSwitchRequest] { ffRequest =>
- val featureSwitches: Seq[FeatureSwitch] = ffRequest.featureSwitches
- featureSwitches.foreach(fs =>
- if (fs.isEnabled) {
- FeatureSwitch.enable(FeatureSwitch.forName(fs.name))
- } else {
- FeatureSwitch.disable(FeatureSwitch.forName(fs.name))
- }
- )
- Future(Accepted(currentFeatureSwitchesAsJson))
- }
- }
- }
-
- private def currentFeatureSwitchesAsJson = Json.toJson(for (fs <- UserInfoFeatureSwitches.allSwitches) yield FeatureSwitch(fs.name, fs.isEnabled))
-}
-
-case class FeatureSwitchRequest(featureSwitches: Seq[FeatureSwitch]) {}
diff --git a/app/data/UserInfoGenerator.scala b/app/data/UserInfoGenerator.scala
index 744624a..7f7bda8 100644
--- a/app/data/UserInfoGenerator.scala
+++ b/app/data/UserInfoGenerator.scala
@@ -19,7 +19,6 @@ package data
import javax.inject.Singleton
import java.time.LocalDate
import uk.gov.hmrc.auth.core.{Enrolment, EnrolmentIdentifier}
-import config.UserInfoFeatureSwitches
import domain.{Address, GovernmentGatewayDetails, Mdtp, UserInfo}
import scala.util.Random.{nextInt => randomNextInt}
@@ -75,27 +74,21 @@ class UserInfoGenerator {
)
)
- def addressWithToggleableFeatures(isAddressLine5: Boolean = false, isCountryCode: Boolean = false): Option[Address] = {
- val addressLine5 = if (isAddressLine5) "\n|Line5" else ""
- val code = if (isCountryCode) Some("GB") else None
-
+ def address: Option[Address] =
Some(
Address(
s"""221B Baker Street
- |Town centre
- |London
- |England$addressLine5
- |NW1 9NT
- |Great Britain""".stripMargin,
+ |Town centre
+ |London
+ |England
+ |Line5
+ |NW1 9NT
+ |Great Britain""".stripMargin,
Some("NW1 9NT"),
Some("Great Britain"),
- code
+ Some("GB")
)
)
- }
-
- def address: Option[Address] =
- addressWithToggleableFeatures(UserInfoFeatureSwitches.addressLine5.isEnabled, UserInfoFeatureSwitches.countryCode.isEnabled)
val enrolments: Set[Enrolment] = Set(Enrolment("IR-SA", List(EnrolmentIdentifier("UTR", "174371121")), "Activated"))
private val government_gateway_v1_0: GovernmentGatewayDetails = GovernmentGatewayDetails(
diff --git a/app/services/UserInfoTransformer.scala b/app/services/UserInfoTransformer.scala
index 0f7d691..36bea80 100644
--- a/app/services/UserInfoTransformer.scala
+++ b/app/services/UserInfoTransformer.scala
@@ -20,7 +20,6 @@ import javax.inject.Singleton
import java.time.LocalDate
import uk.gov.hmrc.auth.core.Enrolments
import uk.gov.hmrc.auth.core.retrieve.ItmpAddress
-import config.UserInfoFeatureSwitches
import domain._
@Singleton
@@ -39,10 +38,8 @@ class UserInfoTransformer {
def address = if (scopes.contains("address")) {
val countryName = desUserInfo flatMap { c => c.address.countryName }
- val countryCode = if (UserInfoFeatureSwitches.countryCode.isEnabled) { desUserInfo flatMap { u => u.address.countryCode } }
- else None
+ val countryCode = desUserInfo flatMap { u => u.address.countryCode }
desUserInfo map (u => Address(formattedAddress(u.address), u.address.postCode, countryName, countryCode))
-
} else None
val identifier = if (scopes.contains("openid:gov-uk-identifiers")) authority flatMap (_.nino) else None
@@ -74,7 +71,7 @@ class UserInfoTransformer {
private def formattedAddress(desAddress: ItmpAddress) = {
val countryName = desAddress.countryName
- val addressLine5 = if (UserInfoFeatureSwitches.addressLine5.isEnabled) desAddress.line5 else None
+ val addressLine5 = desAddress.line5
Seq(desAddress.line1, desAddress.line2, desAddress.line3, desAddress.line4, addressLine5, desAddress.postCode, countryName).flatten.mkString("\n")
}
diff --git a/conf/application.conf b/conf/application.conf
index ad50ff7..2989f3a 100644
--- a/conf/application.conf
+++ b/conf/application.conf
@@ -54,9 +54,6 @@ play.i18n.langs = ["en"]
# !!!WARNING!!! DO NOT CHANGE THIS ROUTER
play.http.router = prod.Routes
-feature.addressLine5 = false
-feature.countryCode = false
-
# Controller
# ~~~~~
# By default all controllers will have authorisation, logging and
@@ -84,12 +81,6 @@ controllers {
needsLogging = true
needsAuditing = false
}
-
- controllers.testOnly.FeatureSwitchController = {
- needsAuth = false
- needsLogging = true
- needsAuditing = false
- }
}
# Root logger:
diff --git a/conf/testOnlyDoNotUseInAppConf.routes b/conf/testOnlyDoNotUseInAppConf.routes
index bd6ee64..ac633df 100644
--- a/conf/testOnlyDoNotUseInAppConf.routes
+++ b/conf/testOnlyDoNotUseInAppConf.routes
@@ -1,4 +1 @@
-GET /test-only/feature-switches @controllers.testOnly.FeatureSwitchController.getFlags
-POST /test-only/feature-switches @controllers.testOnly.FeatureSwitchController.setFlags
-
-> / prod.Routes
\ No newline at end of file
diff --git a/it/test/FeatureSwitchControllerISpec.scala b/it/test/FeatureSwitchControllerISpec.scala
deleted file mode 100644
index 4d68650..0000000
--- a/it/test/FeatureSwitchControllerISpec.scala
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * 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.
- */
-
-import play.api.libs.json.Json
-import scalaj.http.Http
-
-class FeatureSwitchControllerISpec extends BaseFeatureISpec {
-
- val serviceUrl = "/test-only/feature-switches"
-
- Feature("getting feature switches") {
- Scenario("calling GET /test-only/feature-switches") {
- Given("we call GET /test-only/feature-switches")
-
- val result = Http(resource(s"$serviceUrl")).asString
-
- Then("the feature switches are returned as json with 200 OK")
-
- result.code shouldBe 200
- Json.parse(result.body) shouldBe Json.arr(Json.obj("name" -> "countryCode", "isEnabled" -> false),
- Json.obj("name" -> "addressLine5", "isEnabled" -> false)
- )
- }
- }
-
- Feature("updating feature switches") {
- Scenario("calling POST /test-only/feature-switches") {
- Given("we call GET /test-only/feature-switches")
-
- val result = Http(resource(s"$serviceUrl")).asString
-
- Then("the feature switches are returned as json with 200 OK")
-
- result.code shouldBe 200
- Json.parse(result.body) shouldBe Json.arr(Json.obj("name" -> "countryCode", "isEnabled" -> false),
- Json.obj("name" -> "addressLine5", "isEnabled" -> false)
- )
-
- When("we update the flags we should get 406 Accepted")
-
- val payload = Json.obj(
- "featureSwitches" -> Json.arr(Json.obj("name" -> "countryCode", "isEnabled" -> true), Json.obj("name" -> "addressLine5", "isEnabled" -> true))
- )
-
- val updateResult =
- Http(resource(s"$serviceUrl")).method("POST").header("Content-Type", "application/json").postData(payload.toString()).asString
-
- updateResult.code shouldBe 202
-
- When("we retrieve the flags back we see they should be negated")
-
- val updatedResult = Http(resource(s"$serviceUrl")).asString
-
- updatedResult.code shouldBe 200
- Json.parse(updatedResult.body) shouldBe Json.arr(Json.obj("name" -> "countryCode", "isEnabled" -> true),
- Json.obj("name" -> "addressLine5", "isEnabled" -> true)
- )
-
- }
- }
-}
diff --git a/it/test/UserInfoServiceISpec.scala b/it/test/UserInfoServiceISpec.scala
index a60bee3..d2aba4a 100644
--- a/it/test/UserInfoServiceISpec.scala
+++ b/it/test/UserInfoServiceISpec.scala
@@ -18,7 +18,6 @@ import java.nio.file.Paths
import com.fasterxml.jackson.databind.ObjectMapper
import com.github.fge.jsonschema.core.report.LogLevel
import com.github.fge.jsonschema.main.JsonSchemaFactory
-import config.{FeatureSwitch, UserInfoFeatureSwitches}
import domain._
import java.time.LocalDate
@@ -29,21 +28,7 @@ import uk.gov.hmrc.auth.core._
import uk.gov.hmrc.auth.core.retrieve._
import uk.gov.hmrc.domain.Nino
-import scala.jdk.CollectionConverters.CollectionHasAsScala
-
class UserInfoServiceISpec extends BaseFeatureISpec with AuthStub with ThirdPartyDelegatedAuthorityStub {
-
- override def beforeAll(): Unit = {
- super.beforeAll()
- FeatureSwitch.enable(UserInfoFeatureSwitches.countryCode)
- FeatureSwitch.enable(UserInfoFeatureSwitches.addressLine5)
- }
- override def afterAll(): Unit = {
- super.afterAll()
- FeatureSwitch.disable(UserInfoFeatureSwitches.countryCode)
- FeatureSwitch.disable(UserInfoFeatureSwitches.addressLine5)
- }
-
val serviceUrl: String = resource("")
val authorizationTokens = "AUTHORIZATION_TOKENS"
diff --git a/project/AppDependencies.scala b/project/AppDependencies.scala
index 55dfdff..c8b33e7 100644
--- a/project/AppDependencies.scala
+++ b/project/AppDependencies.scala
@@ -4,7 +4,7 @@ import sbt.*
object AppDependencies {
- private val bootstrapPlayVersion = "8.5.0"
+ private val bootstrapPlayVersion = "8.6.0"
private val compile: Seq[ModuleID] = Seq(
ws,
@@ -14,19 +14,9 @@ object AppDependencies {
)
private val test: Seq[ModuleID] = Seq(
- "org.scalatest" %% "scalatest" % "3.2.17" % Test,
- "org.scalatestplus" %% "scalacheck-1-17" % "3.2.17.0" % Test,
- "org.scalatestplus.play" %% "scalatestplus-play" % "5.1.0" % Test,
- "org.playframework" %% "play-test" % PlayVersion.current % Test,
- "com.github.tomakehurst" % "wiremock" % "2.27.2" % Test,
- "uk.gov.hmrc" %% "bootstrap-test-play-30" % bootstrapPlayVersion % Test,
- "org.pegdown" % "pegdown" % "1.6.0" % Test,
- "org.jsoup" % "jsoup" % "1.17.2" % Test,
- "org.scalaj" %% "scalaj-http" % "2.4.2" % Test,
- "org.mockito" %% "mockito-scala-scalatest" % "1.17.30" % Test,
- "org.scalacheck" %% "scalacheck" % "1.17.0" % Test,
- "com.github.java-json-tools" % "json-schema-validator" % "2.2.14" % Test,
- "com.vladsch.flexmark" % "flexmark-all" % "0.64.0" % Test
+ "org.scalaj" %% "scalaj-http" % "2.4.2" % Test,
+ "com.github.java-json-tools" % "json-schema-validator" % "2.2.14" % Test,
+ "uk.gov.hmrc" %% "bootstrap-test-play-30" % "8.6.0" % Test
)
def apply(): Seq[ModuleID] = compile ++ test
diff --git a/project/build.properties b/project/build.properties
index d415199..4d5f78c 100644
--- a/project/build.properties
+++ b/project/build.properties
@@ -1 +1 @@
-sbt.version=1.9.7
\ No newline at end of file
+sbt.version=1.9.9
\ No newline at end of file
diff --git a/project/plugins.sbt b/project/plugins.sbt
index 2942aa1..a66ff56 100644
--- a/project/plugins.sbt
+++ b/project/plugins.sbt
@@ -2,9 +2,9 @@ resolvers += "HMRC-open-artefacts-maven" at "https://open.artefacts.tax.service.
resolvers += Resolver.url("HMRC-open-artefacts-ivy", url("https://open.artefacts.tax.service.gov.uk/ivy2"))(Resolver.ivyStylePatterns)
-addSbtPlugin("uk.gov.hmrc" % "sbt-auto-build" % "3.20.0")
+addSbtPlugin("uk.gov.hmrc" % "sbt-auto-build" % "3.22.0")
addSbtPlugin("uk.gov.hmrc" % "sbt-distributables" % "2.5.0")
-addSbtPlugin("org.scoverage" % "sbt-scoverage" % "2.0.11")
-addSbtPlugin("org.playframework" % "sbt-plugin" % "3.0.2")
+addSbtPlugin("org.scoverage" % "sbt-scoverage" % "2.0.12")
+addSbtPlugin("org.playframework" % "sbt-plugin" % "3.0.3")
addSbtPlugin("org.scalastyle" %% "scalastyle-sbt-plugin" % "1.0.0" exclude("org.scala-lang.modules", "scala-xml_2.12"))
addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.5.2")
\ No newline at end of file
diff --git a/public/api/conf/1.0/application.yaml b/public/api/conf/1.0/application.yaml
index 5151476..22fc7c9 100644
--- a/public/api/conf/1.0/application.yaml
+++ b/public/api/conf/1.0/application.yaml
@@ -2,15 +2,20 @@ openapi: 3.0.3
info:
title: User Information
description: >-
- Access to user information is controlled through scopes. Each access token (OAuth 2.0 Bearer Token) is associated with a set of scopes at login. When a request is made for user information, only information belonging to the provided scopes is returned. The information is returned in the form of claims, which sometimes are simple fields and sometimes objects that contain further fields.
- Here is a list of supported scopes and the claims they contain. The details of each claim, including any contained fields, is documented further down.
- * 'profile': given_name, middle_name, family_name, birthdate
- * 'address': address
- * 'email': email
- * 'openid:hmrc-enrolments': hmrc_enrolments
- * 'openid:government-gateway': government_gateway
- * 'openid:mdtp': mdtp
- * 'openid:gov-uk-identifiers': uk_gov_nino
+ Only the GET method is supported.
+
+ Access to user information is controlled through scopes. Each access token (OAuth 2.0 Bearer Token) is associated with a set of scopes at login.
+
+ When a request is made for user information, only information belonging to the provided scopes is returned. The information is returned in the form of claims, which sometimes are simple fields and sometimes objects that contain further fields.
+
+ Here is the supported scope list and the claims they contain. The details of each claim, including any contained fields, is documented further down.
+ * 'profile': given_name, middle_name, family_name, birthdate
+ * 'address': address
+ * 'email': email
+ * 'openid:hmrc-enrolments': hmrc_enrolments
+ * 'openid:government-gateway': government_gateway
+ * 'openid:mdtp': mdtp
+ * 'openid:gov-uk-identifiers': uk_gov_nino
contact: {}
version: '1.0'
servers:
@@ -60,7 +65,7 @@ paths:
value: '174371121'
state: activated
government_gateway:
- user_id: '019283'
+ user_id: '019283739713'
roles:
- User
affinity_group: Individual
@@ -98,7 +103,7 @@ paths:
value: '174371121'
state: activated
government_gateway:
- user_id: '019283'
+ user_id: '019283739713'
roles:
- User
affinity_group: Individual
@@ -161,7 +166,7 @@ components:
properties:
formatted:
type: string
- description: End-user's mailing address, formatted for display or use on a mailing label.
+ description: End-User's mailing address, formatted for display or use on a mailing label.
example: >-
221B Baker Street
@@ -172,15 +177,15 @@ components:
Great Britain
postal_code:
type: string
- description: End-user's Zip code or postal code.
+ description: End-User's Zip code or postal code.
example: NW1 9NT
country:
type: string
- description: End-user's country name.
+ description: End-User's country name.
example: Great Britain
country_code:
type: string
- description: ISO 3166 Alpha-2-code of a given country
+ description: Take the first 2 chars to obtain the ISO 3166 Alpha-2-code of a given country
example: GB
GovernmentGateway:
title: GovernmentGateway
@@ -241,14 +246,14 @@ components:
type: array
items:
$ref: '#/components/schemas/Identifier'
- description: End-user's identifiers associated to this HMRC service.
+ description: End-User's identifiers associated to this HMRC service.
example:
- key: UTR
value: '174371121'
state:
allOf:
- $ref: '#/components/schemas/State'
- - description: End-user's HMRC enrolment status.
+ - description: End-User's HMRC enrolment status.
Identifier:
title: Identifier
required:
@@ -274,7 +279,7 @@ components:
type: string
description: Session id
example: '2012345'
- description: Mdtp information based on government gateway input
+ description: MDTP platform information on the End-User’s session for auditing & log correlation purposes
State:
title: State
enum:
@@ -285,14 +290,14 @@ components:
- pending
- givenToAgent
type: string
- description: End-user's HMRC enrolment status.
+ description: End-User's HMRC enrolment status.
Userinforesponse:
title: Userinforesponse
type: object
properties:
given_name:
type: string
- description: End-user's first name.
+ description: End-User's first name.
example: Thomas
middle_name:
type: string
@@ -300,7 +305,7 @@ components:
example: A.
family_name:
type: string
- description: End-user's last name.
+ description: End-User's last name.
example: Delgado
email:
type: string
@@ -320,7 +325,7 @@ components:
type: array
items:
$ref: '#/components/schemas/HmrcEnrolment'
- description: End-user's HMRC enrolments.
+ description: End-User's HMRC enrolments.
mdtp:
allOf:
- $ref: '#/components/schemas/Mdtp'
diff --git a/test/connectors/ThirdPartyDelegatedAuthorityConnectorSpec.scala b/test/connectors/ThirdPartyDelegatedAuthorityConnectorSpec.scala
index d00af4b..3384265 100644
--- a/test/connectors/ThirdPartyDelegatedAuthorityConnectorSpec.scala
+++ b/test/connectors/ThirdPartyDelegatedAuthorityConnectorSpec.scala
@@ -23,7 +23,8 @@ import com.github.tomakehurst.wiremock.core.WireMockConfiguration._
import org.scalatest.BeforeAndAfterEach
import org.scalatestplus.play.guice.GuiceOneAppPerSuite
import config.AppContext
-import org.mockito.scalatest.MockitoSugar
+import org.mockito.Mockito.when
+import org.scalatestplus.mockito.MockitoSugar
import uk.gov.hmrc.http.{HeaderCarrier, HttpClient}
import scala.concurrent.ExecutionContext.Implicits.global
diff --git a/test/controllers/UserInfoControllerSpec.scala b/test/controllers/UserInfoControllerSpec.scala
index 8fa24d7..5966e6a 100644
--- a/test/controllers/UserInfoControllerSpec.scala
+++ b/test/controllers/UserInfoControllerSpec.scala
@@ -19,11 +19,12 @@ package controllers
import config.AppContext
import domain.{Address, GovernmentGatewayDetails, UserInfo}
import org.apache.pekko.actor.ActorSystem
+import org.mockito.ArgumentMatchers.{any, eq => eqTo}
import java.time.LocalDate
import org.mockito.BDDMockito.given
import org.scalatest.concurrent.ScalaFutures
-import org.mockito.scalatest.MockitoSugar
+import org.scalatestplus.mockito.MockitoSugar
import play.api.libs.json.Json
import play.api.mvc.ControllerComponents
import play.api.test.FakeRequest
diff --git a/test/controllers/testOnly/FeatureSwitchControllerSpec.scala b/test/controllers/testOnly/FeatureSwitchControllerSpec.scala
deleted file mode 100644
index c2190e0..0000000
--- a/test/controllers/testOnly/FeatureSwitchControllerSpec.scala
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * 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 controllers.testOnly
-
-import org.scalatest.concurrent.ScalaFutures
-import play.api.libs.json._
-import play.api.mvc.{ControllerComponents, Request, Result}
-import play.api.test.FakeRequest
-import config.{FeatureSwitch, UserInfoFeatureSwitches}
-import org.apache.pekko.actor.ActorSystem
-import testSupport.UnitSpec
-
-import scala.concurrent.ExecutionContext
-
-class FeatureSwitchControllerSpec(implicit val cc: ControllerComponents, val ex: ExecutionContext) extends UnitSpec with ScalaFutures {
-
- implicit val actorSystem: ActorSystem = ActorSystem("test")
-
- trait Setup {
- def featuresList(countryCodeEnabled: Boolean = false, addressLine5Enabled: Boolean = false): JsValue = Json.arr(
- Json.obj("name" -> "countryCode", "isEnabled" -> countryCodeEnabled),
- Json.obj("name" -> "addressLine5", "isEnabled" -> addressLine5Enabled)
- )
-
- val controller = new FeatureSwitchController
- UserInfoFeatureSwitches.allSwitches.map(FeatureSwitch.disable(_))
- }
-
- "FeatureSwitchController" should {
- "return a list of switches" in new Setup {
- val expectedBody = featuresList()
-
- val result = await(controller.getFlags()(FakeRequest()))
- status(result) shouldBe 200
- jsonBodyOf(result) shouldBe expectedBody
- }
-
- "enable the country code" in new Setup {
- val expectedBody = featuresList(countryCodeEnabled = true)
-
- val changeRequest = Json.obj("featureSwitches" -> Json.arr(Json.obj("name" -> "countryCode", "isEnabled" -> true)))
- val updateRequest: Request[JsValue] = FakeRequest().withBody(changeRequest)
-
- val result: Result = await(controller.setFlags()(updateRequest))
-
- status(result) shouldBe 202
- jsonBodyOf(result) shouldBe expectedBody
- }
-
- "disable the address line 5" in new Setup {
- val expectedBody = featuresList()
-
- val changeRequest = Json.obj("featureSwitches" -> Json.arr(Json.obj("name" -> "addressLine5", "isEnabled" -> false)))
- val updateRequest: Request[JsValue] = FakeRequest().withBody(changeRequest)
-
- val result: Result = await(controller.setFlags()(updateRequest))
-
- status(result) shouldBe 202
- jsonBodyOf(result) shouldBe expectedBody
- }
- }
-}
diff --git a/test/data/UserInfoGeneratorSpec.scala b/test/data/UserInfoGeneratorSpec.scala
index 26e95bb..e645fec 100644
--- a/test/data/UserInfoGeneratorSpec.scala
+++ b/test/data/UserInfoGeneratorSpec.scala
@@ -18,7 +18,6 @@ package data
import java.time.LocalDate
import org.scalatest.BeforeAndAfterEach
-import config.{FeatureSwitch, UserInfoFeatureSwitches}
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AnyWordSpec
@@ -27,16 +26,6 @@ class UserInfoGeneratorSpec extends AnyWordSpec with Matchers with BeforeAndAfte
private val from = LocalDate.of(1939, 12, 27)
private val until = LocalDate.of(1998, 12, 29)
- override protected def beforeEach(): Unit = {
- FeatureSwitch.enable(UserInfoFeatureSwitches.countryCode)
- FeatureSwitch.enable(UserInfoFeatureSwitches.addressLine5)
- }
-
- override protected def afterEach(): Unit = {
- FeatureSwitch.disable(UserInfoFeatureSwitches.countryCode)
- FeatureSwitch.disable(UserInfoFeatureSwitches.addressLine5)
- }
-
"userInfo" should {
"generate an OpenID Connect compliant UserInfo response v1.0" in {
val userInfo = TestUserInfoGenerator.userInfoV1_0()
@@ -49,18 +38,6 @@ class UserInfoGeneratorSpec extends AnyWordSpec with Matchers with BeforeAndAfte
userInfo.government_gateway.get.profile_uri should not be defined
userInfo.government_gateway.get.group_profile_uri should not be defined
}
-
- "generate an OpenID Connect compliant UserInfo response without country code when feature flag is disabled" in {
- FeatureSwitch.disable(UserInfoFeatureSwitches.countryCode)
- val userInfo = TestUserInfoGenerator.userInfoV1_0()
- userInfo.address shouldBe TestUserInfoGenerator.addressWithToggleableFeatures(isAddressLine5 = true, isCountryCode = false)
- }
-
- "generate an OpenID Connect UserInfo response without addressLine5 when feature flag is disabled" in {
- FeatureSwitch.disable(UserInfoFeatureSwitches.addressLine5)
- val userInfo = TestUserInfoGenerator.userInfoV1_0()
- userInfo.address shouldBe TestUserInfoGenerator.addressWithToggleableFeatures(isAddressLine5 = false, isCountryCode = true)
- }
}
private def assertValidDob(dob: LocalDate): Unit =
diff --git a/test/services/UserInfoServiceSpec.scala b/test/services/UserInfoServiceSpec.scala
index b52abd4..13f90a0 100644
--- a/test/services/UserInfoServiceSpec.scala
+++ b/test/services/UserInfoServiceSpec.scala
@@ -20,9 +20,11 @@ import connectors.{AuthConnector, AuthConnectorV1, ThirdPartyDelegatedAuthorityC
import controllers.Version_1_0
import data.UserInfoGenerator
import domain._
+import org.mockito.ArgumentMatchers.{any, eq => eqTo}
import org.mockito.BDDMockito.given
+import org.mockito.Mockito.{never, verify, when}
import org.scalatest.concurrent.ScalaFutures
-import org.mockito.scalatest.MockitoSugar
+import org.scalatestplus.mockito.MockitoSugar
import testSupport.UnitSpec
import uk.gov.hmrc.auth.core.retrieve.{ItmpAddress, ItmpName}
import uk.gov.hmrc.auth.core.{Enrolment, EnrolmentIdentifier, Enrolments}
diff --git a/test/services/UserInfoTransformerSpec.scala b/test/services/UserInfoTransformerSpec.scala
index 534e7e1..453ebcd 100644
--- a/test/services/UserInfoTransformerSpec.scala
+++ b/test/services/UserInfoTransformerSpec.scala
@@ -16,11 +16,11 @@
package services
-import config.{FeatureSwitch, UserInfoFeatureSwitches}
import domain._
+
import java.time.LocalDate
import org.scalatest.BeforeAndAfterEach
-import org.mockito.scalatest.MockitoSugar
+import org.scalatestplus.mockito.MockitoSugar
import testSupport.UnitSpec
import uk.gov.hmrc.auth.core.retrieve.{GatewayInformation, ItmpAddress, ItmpName, MdtpInformation}
import uk.gov.hmrc.auth.core.{Enrolment, EnrolmentIdentifier, Enrolments}
@@ -94,16 +94,6 @@ class UserInfoTransformerSpec extends UnitSpec with MockitoSugar with BeforeAndA
Some(mdtp)
)
- override protected def beforeEach() = {
- FeatureSwitch.enable(UserInfoFeatureSwitches.countryCode)
- FeatureSwitch.enable(UserInfoFeatureSwitches.addressLine5)
- }
-
- override protected def afterEach() = {
- FeatureSwitch.disable(UserInfoFeatureSwitches.countryCode)
- FeatureSwitch.disable(UserInfoFeatureSwitches.addressLine5)
- }
-
trait Setup {
implicit val hc: HeaderCarrier = HeaderCarrier()
@@ -252,17 +242,60 @@ class UserInfoTransformerSpec extends UnitSpec with MockitoSugar with BeforeAndA
result shouldBe userInfoMissingPostCode
}
- "not return country code when feature flag is off" in new Setup {
+ "return object containing country code if country code is defined in DES response" in new Setup {
- FeatureSwitch.disable(UserInfoFeatureSwitches.countryCode)
val scopes =
Set("address", "profile", "openid:gov-uk-identifiers", "openid:hmrc-enrolments", "openid:government-gateway", "email", "openid:mdtp")
val result = await(transformer.transform(scopes, Some(authority), Some(desUserInfo), Some(enrolments), Some(userDetails)))
- val userInfoMissingCountryCode = userInfo.copy(address =
- Some(userAddress.copy(formatted = "1 Station Road\nTown Centre\nLondon\nEngland\nUK\nNW1 6XE\nUnited Kingdom", country_code = None))
+ result.address should be(defined)
+ result.address.get.country_code shouldBe desUserInfo.address.countryCode
+ }
+
+ "return object not containing country code if country code isn't defined in DES response" in new Setup {
+
+ val scopes =
+ Set("address", "profile", "openid:gov-uk-identifiers", "openid:hmrc-enrolments", "openid:government-gateway", "email", "openid:mdtp")
+ val result = await(
+ transformer.transform(scopes,
+ Some(authority),
+ Some(desUserInfo.copy(address = desAddress.copy(countryCode = None))),
+ Some(enrolments),
+ Some(userDetails)
+ )
)
- result shouldBe userInfoMissingCountryCode
+
+ result.address should be(defined)
+ result.address.get.country_code shouldBe None
+ }
+
+ "return object containing line 5 if line 5 is defined in DES response" in new Setup {
+
+ val scopes =
+ Set("address", "profile", "openid:gov-uk-identifiers", "openid:hmrc-enrolments", "openid:government-gateway", "email", "openid:mdtp")
+ val result = await(transformer.transform(scopes, Some(authority), Some(desUserInfo), Some(enrolments), Some(userDetails)))
+
+ val userInfoWithFormattedAddress =
+ userInfo.copy(address = Some(userAddress.copy(formatted = "1 Station Road\nTown Centre\nLondon\nEngland\nUK\nNW1 6XE\nUnited Kingdom")))
+ result shouldBe userInfoWithFormattedAddress
+ }
+
+ "return object not containing line 5 if line 5 isn't defined in DES response" in new Setup {
+
+ val scopes =
+ Set("address", "profile", "openid:gov-uk-identifiers", "openid:hmrc-enrolments", "openid:government-gateway", "email", "openid:mdtp")
+ val result = await(
+ transformer.transform(scopes,
+ Some(authority),
+ Some(desUserInfo.copy(address = desAddress.copy(line5 = None))),
+ Some(enrolments),
+ Some(userDetails)
+ )
+ )
+
+ val userInfoWithFormattedAddress =
+ userInfo.copy(address = Some(userAddress.copy(formatted = "1 Station Road\nTown Centre\nLondon\nEngland\nNW1 6XE\nUnited Kingdom")))
+ result shouldBe userInfoWithFormattedAddress
}
}
}