diff --git a/app/uk/gov/hmrc/incometaxpenaltiesappealsfrontend/config/AppConfig.scala b/app/uk/gov/hmrc/incometaxpenaltiesappealsfrontend/config/AppConfig.scala index 725ebc5..68aff6a 100755 --- a/app/uk/gov/hmrc/incometaxpenaltiesappealsfrontend/config/AppConfig.scala +++ b/app/uk/gov/hmrc/incometaxpenaltiesappealsfrontend/config/AppConfig.scala @@ -26,4 +26,7 @@ class AppConfig @Inject()(config: Configuration, servicesConfig: ServicesConfig) lazy val serviceSignOut:String = servicesConfig.getString("service-signout.url") lazy val ITSAPenaltiesAppealsHomeUrl = "/penalties-appeals/income-tax" val alphaBannerUrl: String = servicesConfig.getString("alpha-banner-url") + def getFeatureSwitchValue(feature: String): Boolean = config.get[Boolean](feature) + def selfUrl: String = servicesConfig.baseUrl("income-tax-penalties-appeals-frontend") + } diff --git a/app/uk/gov/hmrc/incometaxpenaltiesappealsfrontend/controllers/LanguageSwitchController.scala b/app/uk/gov/hmrc/incometaxpenaltiesappealsfrontend/controllers/LanguageSwitchController.scala index 54bc27b..934e18c 100644 --- a/app/uk/gov/hmrc/incometaxpenaltiesappealsfrontend/controllers/LanguageSwitchController.scala +++ b/app/uk/gov/hmrc/incometaxpenaltiesappealsfrontend/controllers/LanguageSwitchController.scala @@ -31,5 +31,5 @@ class LanguageSwitchController @Inject()( "cymraeg" -> Lang("cy") ) - override def fallbackURL: String = routes.HelloWorldController.helloWorld.url + override def fallbackURL: String = routes.ServiceController.helloWorld.url } diff --git a/app/uk/gov/hmrc/incometaxpenaltiesappealsfrontend/controllers/HelloWorldController.scala b/app/uk/gov/hmrc/incometaxpenaltiesappealsfrontend/controllers/ServiceController.scala similarity index 97% rename from app/uk/gov/hmrc/incometaxpenaltiesappealsfrontend/controllers/HelloWorldController.scala rename to app/uk/gov/hmrc/incometaxpenaltiesappealsfrontend/controllers/ServiceController.scala index 1d2f506..f089065 100755 --- a/app/uk/gov/hmrc/incometaxpenaltiesappealsfrontend/controllers/HelloWorldController.scala +++ b/app/uk/gov/hmrc/incometaxpenaltiesappealsfrontend/controllers/ServiceController.scala @@ -25,7 +25,7 @@ import javax.inject.{Inject, Singleton} import scala.concurrent.Future @Singleton -class HelloWorldController @Inject()( +class ServiceController @Inject()( mcc: MessagesControllerComponents, helloWorldPage: HelloWorldPage)(appConfig: AppConfig) extends FrontendController(mcc) { diff --git a/app/uk/gov/hmrc/incometaxpenaltiesappealsfrontend/featureswitch/api/controllers/FeatureSwitchApiController.scala b/app/uk/gov/hmrc/incometaxpenaltiesappealsfrontend/featureswitch/api/controllers/FeatureSwitchApiController.scala new file mode 100644 index 0000000..496bc98 --- /dev/null +++ b/app/uk/gov/hmrc/incometaxpenaltiesappealsfrontend/featureswitch/api/controllers/FeatureSwitchApiController.scala @@ -0,0 +1,42 @@ +/* + * 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.incometaxpenaltiesappealsfrontend.featureswitch.api.controllers + +import play.api.libs.json.Json +import play.api.mvc.{Action, AnyContent, InjectedController} +import uk.gov.hmrc.incometaxpenaltiesappealsfrontend.featureswitch.api.services.FeatureSwitchService +import uk.gov.hmrc.incometaxpenaltiesappealsfrontend.config.AppConfig +import uk.gov.hmrc.incometaxpenaltiesappealsfrontend.featureswitch.core.config.FeatureSwitching +import uk.gov.hmrc.incometaxpenaltiesappealsfrontend.featureswitch.core.models.FeatureSwitchSetting + +import javax.inject.{Inject, Singleton} + +@Singleton +class FeatureSwitchApiController @Inject()(featureSwitchService: FeatureSwitchService, + val config: AppConfig) extends InjectedController with FeatureSwitching { + + def getFeatureSwitches: Action[AnyContent] = Action { + Ok(Json.toJson(featureSwitchService.getFeatureSwitches())) + } + + def updateFeatureSwitches(): Action[Seq[FeatureSwitchSetting]] = Action(parse.json[Seq[FeatureSwitchSetting]]) { + req => + val updatedFeatureSwitches = featureSwitchService.updateFeatureSwitches(req.body) + Ok(Json.toJson(updatedFeatureSwitches)) + } + +} diff --git a/app/uk/gov/hmrc/incometaxpenaltiesappealsfrontend/featureswitch/api/services/FeatureSwitchService.scala b/app/uk/gov/hmrc/incometaxpenaltiesappealsfrontend/featureswitch/api/services/FeatureSwitchService.scala new file mode 100644 index 0000000..d1714c6 --- /dev/null +++ b/app/uk/gov/hmrc/incometaxpenaltiesappealsfrontend/featureswitch/api/services/FeatureSwitchService.scala @@ -0,0 +1,50 @@ +/* + * 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.incometaxpenaltiesappealsfrontend.featureswitch.api.services + +import uk.gov.hmrc.incometaxpenaltiesappealsfrontend.config.AppConfig +import uk.gov.hmrc.incometaxpenaltiesappealsfrontend.featureswitch.core.config.{FeatureSwitchRegistry, FeatureSwitching} +import uk.gov.hmrc.incometaxpenaltiesappealsfrontend.featureswitch.core.models.FeatureSwitchSetting + +import javax.inject.{Inject, Singleton} + +@Singleton +class FeatureSwitchService @Inject()(featureSwitchRegistry: FeatureSwitchRegistry, + val config: AppConfig) extends FeatureSwitching { + + def getFeatureSwitches(): Seq[FeatureSwitchSetting] = + featureSwitchRegistry.switches.map( + switch => + FeatureSwitchSetting( + switch.configName, + switch.displayName, + isEnabled(switch) + ) + ) + + def updateFeatureSwitches(updatedFeatureSwitches: Seq[FeatureSwitchSetting]): Seq[FeatureSwitchSetting] = { + updatedFeatureSwitches.foreach( + featureSwitchSetting => + featureSwitchRegistry.get(featureSwitchSetting.configName).foreach { + featureSwitch => + if (featureSwitchSetting.isEnabled) enable(featureSwitch) else disable(featureSwitch) + } + ) + + getFeatureSwitches() + } +} diff --git a/app/uk/gov/hmrc/incometaxpenaltiesappealsfrontend/featureswitch/core/config/FeatureSwitchRegistry.scala b/app/uk/gov/hmrc/incometaxpenaltiesappealsfrontend/featureswitch/core/config/FeatureSwitchRegistry.scala new file mode 100644 index 0000000..cc86cb9 --- /dev/null +++ b/app/uk/gov/hmrc/incometaxpenaltiesappealsfrontend/featureswitch/core/config/FeatureSwitchRegistry.scala @@ -0,0 +1,33 @@ +/* + * 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.incometaxpenaltiesappealsfrontend.featureswitch.core.config + +import uk.gov.hmrc.incometaxpenaltiesappealsfrontend.featureswitch.core.models.FeatureSwitch + +trait FeatureSwitchRegistry { + + def switches: Seq[FeatureSwitch] + + def apply(name: String): FeatureSwitch = + get(name) match { + case Some(switch) => switch + case None => throw new IllegalArgumentException("Invalid feature switch: " + name) + } + + def get(name: String): Option[FeatureSwitch] = switches find (_.configName == name) + +} diff --git a/app/uk/gov/hmrc/incometaxpenaltiesappealsfrontend/featureswitch/core/config/FeatureSwitching.scala b/app/uk/gov/hmrc/incometaxpenaltiesappealsfrontend/featureswitch/core/config/FeatureSwitching.scala new file mode 100644 index 0000000..a679389 --- /dev/null +++ b/app/uk/gov/hmrc/incometaxpenaltiesappealsfrontend/featureswitch/core/config/FeatureSwitching.scala @@ -0,0 +1,46 @@ +/* + * 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.incometaxpenaltiesappealsfrontend.featureswitch.core.config + +import play.api.Logging +import uk.gov.hmrc.incometaxpenaltiesappealsfrontend.config.AppConfig +import uk.gov.hmrc.incometaxpenaltiesappealsfrontend.featureswitch.core.models.FeatureSwitch + +trait FeatureSwitching extends Logging { + + val config: AppConfig + + val FEATURE_SWITCH_ON = "true" + val FEATURE_SWITCH_OFF = "false" + + def isEnabled(featureSwitch: FeatureSwitch): Boolean = + sys.props get featureSwitch.configName match { + case Some(value) => value == FEATURE_SWITCH_ON + case None => config.getFeatureSwitchValue(featureSwitch.configName) + } + + def enable(featureSwitch: FeatureSwitch): Unit = { + logger.warn(s"[enable] $featureSwitch") + sys.props += featureSwitch.configName -> FEATURE_SWITCH_ON + } + + def disable(featureSwitch: FeatureSwitch): Unit = { + logger.warn(s"[disable] $featureSwitch") + sys.props += featureSwitch.configName -> FEATURE_SWITCH_OFF + } + +} diff --git a/app/uk/gov/hmrc/incometaxpenaltiesappealsfrontend/featureswitch/core/config/FeatureSwitchingModule.scala b/app/uk/gov/hmrc/incometaxpenaltiesappealsfrontend/featureswitch/core/config/FeatureSwitchingModule.scala new file mode 100644 index 0000000..3fbef88 --- /dev/null +++ b/app/uk/gov/hmrc/incometaxpenaltiesappealsfrontend/featureswitch/core/config/FeatureSwitchingModule.scala @@ -0,0 +1,42 @@ +/* + * 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.incometaxpenaltiesappealsfrontend.featureswitch.core.config + +import play.api.inject.{Binding, Module} +import play.api.{Configuration, Environment} +import uk.gov.hmrc.incometaxpenaltiesappealsfrontend.featureswitch.core.models.FeatureSwitch + +import javax.inject.Singleton + +@Singleton +class FeatureSwitchingModule extends Module with FeatureSwitchRegistry { + + val switches: Seq[FeatureSwitch] = Seq( + UseStubForBackend + ) + + override def bindings(environment: Environment, configuration: Configuration): Seq[Binding[_]] = { + Seq( + bind[FeatureSwitchRegistry].to(this).eagerly() + ) + } +} + +case object UseStubForBackend extends FeatureSwitch { + override val configName: String = "features.useStubForBackend" + override val displayName: String = "Use stub instead of Penalties backend service" +} diff --git a/app/uk/gov/hmrc/incometaxpenaltiesappealsfrontend/featureswitch/core/models/FeatureSwitch.scala b/app/uk/gov/hmrc/incometaxpenaltiesappealsfrontend/featureswitch/core/models/FeatureSwitch.scala new file mode 100644 index 0000000..0b2526a --- /dev/null +++ b/app/uk/gov/hmrc/incometaxpenaltiesappealsfrontend/featureswitch/core/models/FeatureSwitch.scala @@ -0,0 +1,22 @@ +/* + * 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.incometaxpenaltiesappealsfrontend.featureswitch.core.models + +trait FeatureSwitch { + val configName: String + val displayName: String +} diff --git a/app/uk/gov/hmrc/incometaxpenaltiesappealsfrontend/featureswitch/core/models/FeatureSwitchSetting.scala b/app/uk/gov/hmrc/incometaxpenaltiesappealsfrontend/featureswitch/core/models/FeatureSwitchSetting.scala new file mode 100644 index 0000000..bda0b3f --- /dev/null +++ b/app/uk/gov/hmrc/incometaxpenaltiesappealsfrontend/featureswitch/core/models/FeatureSwitchSetting.scala @@ -0,0 +1,30 @@ +/* + * 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.incometaxpenaltiesappealsfrontend.featureswitch.core.models + +import play.api.libs.json.{Json, OFormat} + + +case class FeatureSwitchSetting(configName: String, + displayName: String, + isEnabled: Boolean) + +object FeatureSwitchSetting { + + implicit val format: OFormat[FeatureSwitchSetting] = Json.format[FeatureSwitchSetting] + +} diff --git a/app/uk/gov/hmrc/incometaxpenaltiesappealsfrontend/featureswitch/frontend/config/FeatureSwitchProviderConfig.scala b/app/uk/gov/hmrc/incometaxpenaltiesappealsfrontend/featureswitch/frontend/config/FeatureSwitchProviderConfig.scala new file mode 100644 index 0000000..1a4691d --- /dev/null +++ b/app/uk/gov/hmrc/incometaxpenaltiesappealsfrontend/featureswitch/frontend/config/FeatureSwitchProviderConfig.scala @@ -0,0 +1,40 @@ +/* + * 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.incometaxpenaltiesappealsfrontend.featureswitch.frontend.config + +import uk.gov.hmrc.incometaxpenaltiesappealsfrontend.config.AppConfig +import uk.gov.hmrc.incometaxpenaltiesappealsfrontend.featureswitch.frontend.models.FeatureSwitchProvider + +import javax.inject.{Inject, Singleton} + +@Singleton +class FeatureSwitchProviderConfig @Inject()(appConfig: AppConfig) { + + lazy val selfBaseUrl: String = appConfig.selfUrl + + lazy val selfFeatureSwitchUrl = s"$selfBaseUrl/penalties-appeals/income-tax/test-only/api/feature-switches" + + lazy val selfFeatureSwitchProvider: FeatureSwitchProvider = FeatureSwitchProvider( + id = "income-tax-penalties-appeals-frontend", + appName = "Income Tax Penalties Appeals Frontend", + url = selfFeatureSwitchUrl + ) + + lazy val featureSwitchProviders: Seq[FeatureSwitchProvider] = + Seq(selfFeatureSwitchProvider) + +} diff --git a/app/uk/gov/hmrc/incometaxpenaltiesappealsfrontend/featureswitch/frontend/connectors/FeatureSwitchApiConnector.scala b/app/uk/gov/hmrc/incometaxpenaltiesappealsfrontend/featureswitch/frontend/connectors/FeatureSwitchApiConnector.scala new file mode 100644 index 0000000..0be1eb7 --- /dev/null +++ b/app/uk/gov/hmrc/incometaxpenaltiesappealsfrontend/featureswitch/frontend/connectors/FeatureSwitchApiConnector.scala @@ -0,0 +1,67 @@ +/* + * 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.incometaxpenaltiesappealsfrontend.featureswitch.frontend.connectors + +import play.api.http.Status._ +import play.api.libs.json.{JsError, JsSuccess, Json, Reads} +import uk.gov.hmrc.http.HeaderCarrier +import uk.gov.hmrc.http.HttpReads.Implicits.readRaw +import uk.gov.hmrc.http.client.HttpClientV2 +import uk.gov.hmrc.incometaxpenaltiesappealsfrontend.featureswitch.core.models.FeatureSwitchSetting + +import java.net.URL +import javax.inject.{Inject, Singleton} +import scala.concurrent.{ExecutionContext, Future} + +@Singleton +class FeatureSwitchApiConnector @Inject()(httpClient: HttpClientV2)(implicit ec: ExecutionContext) { + + def retrieveFeatureSwitches(featureSwitchProviderUrl: String + )(implicit reads: Reads[Seq[FeatureSwitchSetting]], + hc: HeaderCarrier): Future[Seq[FeatureSwitchSetting]] = { + httpClient.get(new URL(featureSwitchProviderUrl)).execute.map( + response => + response.status match { + case OK => + response.json.validate[Seq[FeatureSwitchSetting]] match { + case JsSuccess(settings, _) => settings + case JsError(errors) => throw new Exception(errors.head.toString) + } + case _ => throw new Exception(s"Could not retrieve feature switches from $featureSwitchProviderUrl") + } + ) + } + + def updateFeatureSwitches(featureSwitchProviderUrl: String, + featureSwitchSettings: Seq[FeatureSwitchSetting] + )(implicit hc: HeaderCarrier): Future[Seq[FeatureSwitchSetting]] = { + httpClient + .post(new URL(featureSwitchProviderUrl)) + .withBody(Json.toJson(featureSwitchSettings)).execute.map { + response => + response.status match { + case OK => + response.json.validate[Seq[FeatureSwitchSetting]] match { + case JsSuccess(settings, _) => settings + case JsError(errors) => throw new Exception(errors.head.toString) + } + case _ => throw new Exception(s"Could not retrieve feature switches from $featureSwitchProviderUrl") + } + } + } + +} diff --git a/app/uk/gov/hmrc/incometaxpenaltiesappealsfrontend/featureswitch/frontend/controllers/FeatureSwitchFrontendController.scala b/app/uk/gov/hmrc/incometaxpenaltiesappealsfrontend/featureswitch/frontend/controllers/FeatureSwitchFrontendController.scala new file mode 100644 index 0000000..66db613 --- /dev/null +++ b/app/uk/gov/hmrc/incometaxpenaltiesappealsfrontend/featureswitch/frontend/controllers/FeatureSwitchFrontendController.scala @@ -0,0 +1,53 @@ +/* + * 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.incometaxpenaltiesappealsfrontend.featureswitch.frontend.controllers + +import play.api.i18n.I18nSupport +import play.api.mvc.{Action, AnyContent, MessagesControllerComponents} +import uk.gov.hmrc.incometaxpenaltiesappealsfrontend.config.AppConfig +import uk.gov.hmrc.incometaxpenaltiesappealsfrontend.featureswitch.core.config.FeatureSwitching +import uk.gov.hmrc.incometaxpenaltiesappealsfrontend.featureswitch.frontend.services.FeatureSwitchRetrievalService +import uk.gov.hmrc.incometaxpenaltiesappealsfrontend.featureswitch.frontend.views.html.feature_switch +import uk.gov.hmrc.play.bootstrap.frontend.controller.FrontendController + +import javax.inject.{Inject, Singleton} +import scala.concurrent.ExecutionContext + +@Singleton +class FeatureSwitchFrontendController @Inject()(featureSwitchService: FeatureSwitchRetrievalService, + featureSwitchView: feature_switch, + mcc: MessagesControllerComponents + )(implicit ec: ExecutionContext, + val config: AppConfig) extends FrontendController(mcc) with FeatureSwitching with I18nSupport { + + + def show(): Action[AnyContent] = Action.async { + implicit req => + featureSwitchService.retrieveFeatureSwitches().map { + featureSwitches => + Ok(featureSwitchView(featureSwitches, routes.FeatureSwitchFrontendController.submit())) + } + } + + def submit(): Action[Map[String, Seq[String]]] = Action.async(parse.formUrlEncoded) { + implicit req => + featureSwitchService.updateFeatureSwitches(req.body.keys).map { + featureSwitches => + Ok(featureSwitchView(featureSwitches, routes.FeatureSwitchFrontendController.submit())) + } + } +} diff --git a/app/uk/gov/hmrc/incometaxpenaltiesappealsfrontend/featureswitch/frontend/models/FeatureSwitchProvider.scala b/app/uk/gov/hmrc/incometaxpenaltiesappealsfrontend/featureswitch/frontend/models/FeatureSwitchProvider.scala new file mode 100644 index 0000000..94a9358 --- /dev/null +++ b/app/uk/gov/hmrc/incometaxpenaltiesappealsfrontend/featureswitch/frontend/models/FeatureSwitchProvider.scala @@ -0,0 +1,21 @@ +/* + * 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.incometaxpenaltiesappealsfrontend.featureswitch.frontend.models + +case class FeatureSwitchProvider(id: String, + appName: String, + url: String) diff --git a/app/uk/gov/hmrc/incometaxpenaltiesappealsfrontend/featureswitch/frontend/services/FeatureSwitchRetrievalService.scala b/app/uk/gov/hmrc/incometaxpenaltiesappealsfrontend/featureswitch/frontend/services/FeatureSwitchRetrievalService.scala new file mode 100644 index 0000000..1c4c0cc --- /dev/null +++ b/app/uk/gov/hmrc/incometaxpenaltiesappealsfrontend/featureswitch/frontend/services/FeatureSwitchRetrievalService.scala @@ -0,0 +1,81 @@ +/* + * 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.incometaxpenaltiesappealsfrontend.featureswitch.frontend.services + +import uk.gov.hmrc.http.HeaderCarrier +import uk.gov.hmrc.incometaxpenaltiesappealsfrontend.featureswitch.core.models.FeatureSwitchSetting +import uk.gov.hmrc.incometaxpenaltiesappealsfrontend.featureswitch.frontend.config.FeatureSwitchProviderConfig +import uk.gov.hmrc.incometaxpenaltiesappealsfrontend.featureswitch.frontend.connectors.FeatureSwitchApiConnector +import uk.gov.hmrc.incometaxpenaltiesappealsfrontend.featureswitch.frontend.models.FeatureSwitchProvider + +import javax.inject.Inject +import scala.concurrent.{ExecutionContext, Future} +import scala.util.matching.Regex + +class FeatureSwitchRetrievalService @Inject()(featureSwitchConfig: FeatureSwitchProviderConfig, + featureSwitchApiConnector: FeatureSwitchApiConnector) + (implicit ec: ExecutionContext) { + + def retrieveFeatureSwitches()(implicit hc: HeaderCarrier): Future[Seq[(FeatureSwitchProvider, Seq[FeatureSwitchSetting])]] = { + + val featureSwitchSeq: Seq[(FeatureSwitchProvider, Future[Seq[FeatureSwitchSetting]])] = + featureSwitchConfig.featureSwitchProviders.map { + featureSwitchProvider => + featureSwitchProvider -> featureSwitchApiConnector.retrieveFeatureSwitches(featureSwitchProvider.url) + } + + Future.traverse(featureSwitchSeq) { + case (featureSwitchProvider, futureSeqFeatureSwitchSetting) => + futureSeqFeatureSwitchSetting.map { + featureSwitchSettingSeq => featureSwitchProvider -> featureSwitchSettingSeq + } + } + } + + val featureSwitchKeyRegex: Regex = "(.+?)\\.(.+)".r + + def updateFeatureSwitches(updatedFeatureSwitchKeys: Iterable[String] + )(implicit hc: HeaderCarrier): Future[Seq[(FeatureSwitchProvider, Seq[FeatureSwitchSetting])]] = { + val updatedFeatureSwitches: Future[Seq[(FeatureSwitchProvider, Seq[FeatureSwitchSetting])]] = + retrieveFeatureSwitches().map { + currentFeatureSwitches => + currentFeatureSwitches.map { + case (featureSwitchProvider, providerFeatureSwitches) => + featureSwitchProvider -> providerFeatureSwitches.map { + currentFeatureSwitch => + val isEnabled = updatedFeatureSwitchKeys.exists { + case featureSwitchKeyRegex(microserviceKey, featureSwitchKey) => + microserviceKey == featureSwitchProvider.id && featureSwitchKey == currentFeatureSwitch.configName + case _ => + false + } + currentFeatureSwitch.copy(isEnabled = isEnabled) + } + } + } + + updatedFeatureSwitches.flatMap { + Future.traverse(_) { + case (featureSwitchProvider, featureSwitchSettings) => + featureSwitchApiConnector.updateFeatureSwitches(featureSwitchProvider.url, featureSwitchSettings).map { + updatedFeatureSwitches => featureSwitchProvider -> updatedFeatureSwitches + } + } + } + } + +} diff --git a/app/uk/gov/hmrc/incometaxpenaltiesappealsfrontend/featureswitch/frontend/views/feature_switch.scala.html b/app/uk/gov/hmrc/incometaxpenaltiesappealsfrontend/featureswitch/frontend/views/feature_switch.scala.html new file mode 100644 index 0000000..6debc67 --- /dev/null +++ b/app/uk/gov/hmrc/incometaxpenaltiesappealsfrontend/featureswitch/frontend/views/feature_switch.scala.html @@ -0,0 +1,63 @@ +@* + * 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. + *@ + +@import uk.gov.hmrc.incometaxpenaltiesappealsfrontend.views.html.Layout +@import uk.gov.hmrc.govukfrontend.views.html.components._ +@import uk.gov.hmrc.incometaxpenaltiesappealsfrontend.featureswitch.core.models.FeatureSwitchSetting +@import uk.gov.hmrc.incometaxpenaltiesappealsfrontend.featureswitch.frontend.models.FeatureSwitchProvider + + +@this(layout: Layout, + govukCheckboxes: GovukCheckboxes, + govukButton: GovukButton, + formWithCSRF: FormWithCSRF +) + +@(featureSwitchList: Seq[(FeatureSwitchProvider, Seq[FeatureSwitchSetting])], formAction: Call)(implicit request: Request[_], messages: Messages) + +@layout(Some("Choose which features to enable.")) { +