diff --git a/obp-api/src/main/scala/bootstrap/http4s/Http4sServer.scala b/obp-api/src/main/scala/bootstrap/http4s/Http4sServer.scala index 812e5c488..0672f3b70 100644 --- a/obp-api/src/main/scala/bootstrap/http4s/Http4sServer.scala +++ b/obp-api/src/main/scala/bootstrap/http4s/Http4sServer.scala @@ -1,6 +1,5 @@ package bootstrap.http4s -import bootstrap.http4s.RestRoutes.{bankServices, helloWorldService} import cats.data.{Kleisli, OptionT} import scala.language.higherKinds @@ -9,33 +8,29 @@ import com.comcast.ip4s._ import org.http4s.ember.server._ import org.http4s.implicits._ import cats.effect._ +import code.api.util.APIUtil import org.http4s._ object Http4sServer extends IOApp { val services: Kleisli[({type λ[β$0$] = OptionT[IO, β$0$]})#λ, Request[IO], Response[IO]] = - bankServices <+> - helloWorldService <+> - code.api.v1_3_0.Http4s130.wrappedRoutesV130Services + code.api.v7_0_0.Http4s700.wrappedRoutesV700Services val httpApp: Kleisli[IO, Request[IO], Response[IO]] = (services).orNotFound //Start OBP relevant objects, and settings new bootstrap.liftweb.Boot().boot + + val port = APIUtil.getPropsAsIntValue("http4s.port",8181) + val host = APIUtil.getPropsValue("http4s.host","127.0.0.1") + override def run(args: List[String]): IO[ExitCode] = EmberServerBuilder .default[IO] - .withHost(ipv4"0.0.0.0") - .withPort(port"8081") + .withHost(Host.fromString(host).get) + .withPort(Port.fromInt(port).get) .withHttpApp(httpApp) .build .use(_ => IO.never) .as(ExitCode.Success) } -//this is testing code -object myApp extends App{ - import cats.effect.unsafe.implicits.global - Http4sServer.run(Nil).unsafeRunSync() -// Http4sServer.run(Nil).unsafeToFuture()//.unsafeRunSync() -} - diff --git a/obp-api/src/main/scala/bootstrap/http4s/Middleware.scala b/obp-api/src/main/scala/bootstrap/http4s/Middleware.scala deleted file mode 100644 index 777cdf317..000000000 --- a/obp-api/src/main/scala/bootstrap/http4s/Middleware.scala +++ /dev/null @@ -1,26 +0,0 @@ -//package bootstrap.http4s -// -//import cats._ -//import cats.effect._ -//import cats.implicits._ -//import cats.data._ -//import code.api.util.CallContext -//import org.http4s._ -//import org.http4s.dsl.io._ -//import org.http4s.server._ -// -//object Middleware { -// -// val authUser: Kleisli[OptionT[IO, *], Request[IO], CallContext] = -// Kleisli(_ => OptionT.liftF(IO(???))) -// -// val middleware: AuthMiddleware[IO, CallContext] = AuthMiddleware(authUser) -// -// val authedRoutes: AuthedRoutes[CallContext, IO] = -// AuthedRoutes.of { -// case GET -> Root / "welcome" as callContext => Ok(s"Welcome, ${callContext}") -// } -// -// val service: HttpRoutes[IO] = middleware(authedRoutes) -// -//} diff --git a/obp-api/src/main/scala/bootstrap/http4s/RestRoutes.scala b/obp-api/src/main/scala/bootstrap/http4s/RestRoutes.scala deleted file mode 100644 index 4262f95a3..000000000 --- a/obp-api/src/main/scala/bootstrap/http4s/RestRoutes.scala +++ /dev/null @@ -1,62 +0,0 @@ -package bootstrap.http4s - -import cats.effect._ -import org.http4s.{HttpRoutes, _} -import org.http4s.dsl.io._ -import cats.implicits._ -import code.api.util.{APIUtil, CustomJsonFormats} -import code.bankconnectors.Connector -import code.model.dataAccess.MappedBank -import com.openbankproject.commons.model.BankCommons -import net.liftweb.json.Formats -import org.http4s.HttpRoutes -import org.http4s.dsl.Http4sDsl - -import scala.language.higherKinds -import cats.effect._ -import code.api.v4_0_0.JSONFactory400 -import org.http4s._ -import org.http4s.dsl.io._ -import net.liftweb.json.JsonAST.{JValue, prettyRender} -import net.liftweb.json.{Extraction, MappingException, compactRender, parse} - -object RestRoutes { - implicit val formats: Formats = CustomJsonFormats.formats - - val helloWorldService: HttpRoutes[IO] = HttpRoutes.of[IO] { - case GET -> Root / "hello" / name => - Ok(s"Hello, $name.") - } - - val bankServices: HttpRoutes[IO] = HttpRoutes.of[IO] { - case GET -> Root / "banks" => - val banks = Connector.connector.vend.getBanksLegacy(None).map(_._1).openOrThrowException("xxxxx") - Ok(prettyRender(Extraction.decompose(banks))) - case GET -> Root / "banks"/ "future" => - import scala.concurrent.Future - import scala.concurrent.ExecutionContext.Implicits.global - Ok(IO.fromFuture(IO( - for { - (banks, callContext) <- code.api.util.NewStyle.function.getBanks(None) - } yield { - prettyRender(Extraction.decompose(JSONFactory400.createBanksJson(banks))) - } - ))) - - val banks = Connector.connector.vend.getBanksLegacy(None).map(_._1).openOrThrowException("xxxxx") - Ok(prettyRender(Extraction.decompose(banks))) - case GET -> Root / "banks" / IntVar(bankId) => - val bank = BankCommons( - bankId = com.openbankproject.commons.model.BankId("bankIdExample.value"), - shortName = "bankShortNameExample.value", - fullName = "bankFullNameExample.value", - logoUrl = "bankLogoUrlExample.value", - websiteUrl = "bankWebsiteUrlExample.value", - bankRoutingScheme = "bankRoutingSchemeExample.value", - bankRoutingAddress = "bankRoutingAddressExample.value", - swiftBic = "bankSwiftBicExample.value", - nationalIdentifier = "bankNationalIdentifierExample.value") - Ok(prettyRender(Extraction.decompose(bank))) - } - -} \ No newline at end of file diff --git a/obp-api/src/main/scala/code/api/v1_3_0/Http4s130.scala b/obp-api/src/main/scala/code/api/v1_3_0/Http4s130.scala deleted file mode 100644 index f1279c0f2..000000000 --- a/obp-api/src/main/scala/code/api/v1_3_0/Http4s130.scala +++ /dev/null @@ -1,105 +0,0 @@ -package code.api.v1_3_0 - -import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON._ -import code.api.util.APIUtil._ -import code.api.util.ApiTag._ -import code.api.util.ErrorMessages._ -import code.api.util.FutureUtil.EndpointContext -import code.api.util.NewStyle.HttpCode -import code.api.util.{ApiRole, NewStyle} -import code.api.v1_2_1.JSONFactory -import com.openbankproject.commons.ExecutionContext.Implicits.global -import com.openbankproject.commons.model.BankId -import com.openbankproject.commons.util.{ApiVersion, ScannedApiVersion} -import net.liftweb.common.Full -import net.liftweb.http.rest.RestHelper - -import scala.collection.mutable.ArrayBuffer -import scala.concurrent.Future -import cats.effect._ -import org.http4s.{HttpRoutes, _} -import org.http4s.dsl.io._ -import cats.implicits._ -import code.api.util.{APIUtil, CustomJsonFormats} -import code.bankconnectors.Connector -import code.model.dataAccess.MappedBank -import com.openbankproject.commons.model.BankCommons -import net.liftweb.json.Formats -import org.http4s.HttpRoutes -import org.http4s.dsl.Http4sDsl - -import scala.language.{higherKinds, implicitConversions} -import cats.effect._ -import code.api.v4_0_0.JSONFactory400 -import org.http4s._ -import org.http4s.dsl.io._ -import net.liftweb.json.JsonAST.{JValue, prettyRender} -import net.liftweb.json.{Extraction, MappingException, compactRender, parse} -import cats.effect._ -import cats.data.Kleisli -import org.http4s._ -import org.http4s.dsl.io._ -import org.http4s.implicits._ -import org.http4s.ember.server.EmberServerBuilder -import com.comcast.ip4s._ - -import cats.effect.IO -import org.http4s.{HttpRoutes, Request, Response} -import org.http4s.dsl.io._ -import org.typelevel.vault.Key - -object Http4s130 { - - implicit val formats: Formats = CustomJsonFormats.formats - implicit def convertAnyToJsonString(any: Any): String = prettyRender(Extraction.decompose(any)) - - val apiVersion: ScannedApiVersion = ApiVersion.v1_3_0 - - case class CallContext(userId: String, requestId: String) - import cats.effect.unsafe.implicits.global - val callContextKey: Key[CallContext] = Key.newKey[IO, CallContext].unsafeRunSync() - - object CallContextMiddleware { - - - def withCallContext(routes: HttpRoutes[IO]): HttpRoutes[IO] = Kleisli { req: Request[IO] => - val callContext = CallContext(userId = "example-user", requestId = java.util.UUID.randomUUID().toString) - val updatedAttributes = req.attributes.insert(callContextKey, callContext) - val updatedReq = req.withAttributes(updatedAttributes) - routes(updatedReq) - } - } - - - val v130Services: HttpRoutes[IO] = HttpRoutes.of[IO] { - case req @ GET -> Root / apiVersion / "root" => - import com.openbankproject.commons.ExecutionContext.Implicits.global - val callContext = req.attributes.lookup(callContextKey).get.asInstanceOf[CallContext] - Ok(IO.fromFuture(IO( - for { - _ <- Future() // Just start async call - } yield { - convertAnyToJsonString( - JSONFactory.getApiInfoJSON(OBPAPI1_3_0.version, s"Hello, ${callContext.userId}! Your request ID is ${callContext.requestId}.") - ) - } - ))) - -// case req @ GET -> Root / apiVersion / "cards" => { -// Ok(IO.fromFuture(IO({ -// val callContext = req.attributes.lookup(callContextKey).get.asInstanceOf[CallContext] -// import com.openbankproject.commons.ExecutionContext.Implicits.global -// for { -// (Full(u), callContext) <- authenticatedAccess(None) -// (cards, callContext) <- NewStyle.function.getPhysicalCardsForUser(u, callContext) -// } yield { -// convertAnyToJsonString( -// JSONFactory1_3_0.createPhysicalCardsJSON(cards, u) -// ) -// } -// }))) -// } - } - - val wrappedRoutesV130Services = CallContextMiddleware.withCallContext(v130Services) -} diff --git a/obp-api/src/main/scala/code/api/v7_0_0/Http4s700.scala b/obp-api/src/main/scala/code/api/v7_0_0/Http4s700.scala new file mode 100644 index 000000000..10907b1e8 --- /dev/null +++ b/obp-api/src/main/scala/code/api/v7_0_0/Http4s700.scala @@ -0,0 +1,69 @@ +package code.api.v7_0_0 + +import cats.data.Kleisli +import cats.effect._ +import cats.implicits._ +import code.api.util.{APIUtil, CustomJsonFormats} +import code.api.v4_0_0.JSONFactory400 +import code.bankconnectors.Connector +import com.openbankproject.commons.util.{ApiVersion, ScannedApiVersion} +import net.liftweb.json.Formats +import net.liftweb.json.JsonAST.prettyRender +import net.liftweb.json.Extraction +import org.http4s._ +import org.http4s.dsl.io._ +import org.typelevel.vault.Key + +import scala.concurrent.Future +import scala.language.{higherKinds, implicitConversions} + +object Http4s700 { + + implicit val formats: Formats = CustomJsonFormats.formats + implicit def convertAnyToJsonString(any: Any): String = prettyRender(Extraction.decompose(any)) + + val apiVersion: ScannedApiVersion = ApiVersion.v7_0_0 + val apiVersionString: String = apiVersion.toString + + case class CallContext(userId: String, requestId: String) + import cats.effect.unsafe.implicits.global + val callContextKey: Key[CallContext] = Key.newKey[IO, CallContext].unsafeRunSync() + + object CallContextMiddleware { + + def withCallContext(routes: HttpRoutes[IO]): HttpRoutes[IO] = Kleisli { req: Request[IO] => + val callContext = CallContext(userId = "example-user", requestId = java.util.UUID.randomUUID().toString) + val updatedAttributes = req.attributes.insert(callContextKey, callContext) + val updatedReq = req.withAttributes(updatedAttributes) + routes(updatedReq) + } + } + + val v700Services: HttpRoutes[IO] = HttpRoutes.of[IO] { + case req @ GET -> Root / "obp" / `apiVersionString` / "root" => + import com.openbankproject.commons.ExecutionContext.Implicits.global + val callContext = req.attributes.lookup(callContextKey).get.asInstanceOf[CallContext] + Ok(IO.fromFuture(IO( + for { + _ <- Future() // Just start async call + } yield { + convertAnyToJsonString( + JSONFactory700.getApiInfoJSON(apiVersion, s"Hello, ${callContext.userId}! Your request ID is ${callContext.requestId}.") + ) + } + ))) + + case req @ GET -> Root / "obp" / `apiVersionString` / "banks" => + import com.openbankproject.commons.ExecutionContext.Implicits.global + Ok(IO.fromFuture(IO( + for { + (banks, callContext) <- code.api.util.NewStyle.function.getBanks(None) + } yield { + convertAnyToJsonString(JSONFactory400.createBanksJson(banks)) + } + ))) + } + + val wrappedRoutesV700Services: HttpRoutes[IO] = CallContextMiddleware.withCallContext(v700Services) +} + diff --git a/obp-api/src/main/scala/code/api/v7_0_0/JSONFactory7.0.0.scala b/obp-api/src/main/scala/code/api/v7_0_0/JSONFactory7.0.0.scala new file mode 100644 index 000000000..a675842e6 --- /dev/null +++ b/obp-api/src/main/scala/code/api/v7_0_0/JSONFactory7.0.0.scala @@ -0,0 +1,72 @@ +package code.api.v7_0_0 + +import code.api.Constant +import code.api.util.APIUtil +import code.api.util.ErrorMessages.MandatoryPropertyIsNotSet +import code.api.v4_0_0.{EnergySource400, HostedAt400, HostedBy400} +import code.util.Helper.MdcLoggable +import com.openbankproject.commons.util.ApiVersion +import net.liftweb.util.Props + +object JSONFactory700 extends MdcLoggable { + + // Get git commit from build info + lazy val gitCommit: String = { + val commit = try { + Props.get("git.commit.id", "unknown") + } catch { + case _: Throwable => "unknown" + } + commit + } + + case class APIInfoJsonV700( + version: String, + version_status: String, + git_commit: String, + stage: String, + connector: String, + hostname: String, + local_identity_provider: String, + hosted_by: HostedBy400, + hosted_at: HostedAt400, + energy_source: EnergySource400, + resource_docs_requires_role: Boolean, + message: String + ) + + def getApiInfoJSON(apiVersion: ApiVersion, message: String): APIInfoJsonV700 = { + val organisation = APIUtil.getPropsValue("hosted_by.organisation", "TESOBE") + val email = APIUtil.getPropsValue("hosted_by.email", "contact@tesobe.com") + val phone = APIUtil.getPropsValue("hosted_by.phone", "+49 (0)30 8145 3994") + val organisationWebsite = APIUtil.getPropsValue("organisation_website", "https://www.tesobe.com") + val hostedBy = new HostedBy400(organisation, email, phone, organisationWebsite) + + val organisationHostedAt = APIUtil.getPropsValue("hosted_at.organisation", "") + val organisationWebsiteHostedAt = APIUtil.getPropsValue("hosted_at.organisation_website", "") + val hostedAt = HostedAt400(organisationHostedAt, organisationWebsiteHostedAt) + + val organisationEnergySource = APIUtil.getPropsValue("energy_source.organisation", "") + val organisationWebsiteEnergySource = APIUtil.getPropsValue("energy_source.organisation_website", "") + val energySource = EnergySource400(organisationEnergySource, organisationWebsiteEnergySource) + + val connector = code.api.Constant.CONNECTOR.openOrThrowException(s"$MandatoryPropertyIsNotSet. The missing prop is `connector` ") + val resourceDocsRequiresRole = APIUtil.getPropsAsBoolValue("resource_docs_requires_role", false) + + APIInfoJsonV700( + version = apiVersion.vDottedApiVersion, + version_status = "BLEEDING_EDGE", + git_commit = gitCommit, + connector = connector, + hostname = Constant.HostName, + stage = System.getProperty("run.mode"), + local_identity_provider = Constant.localIdentityProvider, + hosted_by = hostedBy, + hosted_at = hostedAt, + energy_source = energySource, + resource_docs_requires_role = resourceDocsRequiresRole, + message = message + ) + } +} + diff --git a/obp-commons/src/main/scala/com/openbankproject/commons/util/ApiVersion.scala b/obp-commons/src/main/scala/com/openbankproject/commons/util/ApiVersion.scala index 0a5617d18..6173ec700 100644 --- a/obp-commons/src/main/scala/com/openbankproject/commons/util/ApiVersion.scala +++ b/obp-commons/src/main/scala/com/openbankproject/commons/util/ApiVersion.scala @@ -23,6 +23,7 @@ object ApiShortVersions extends Enumeration { val `v5.0.0` = Value("v5.0.0") val `v5.1.0` = Value("v5.1.0") val `v6.0.0` = Value("v6.0.0") + val `v7.0.0` = Value("v7.0.0") val `dynamic-endpoint` = Value("dynamic-endpoint") val `dynamic-entity` = Value("dynamic-entity") } @@ -114,6 +115,7 @@ object ApiVersion { val v5_0_0 = ScannedApiVersion(urlPrefix,ApiStandards.obp.toString,ApiShortVersions.`v5.0.0`.toString) val v5_1_0 = ScannedApiVersion(urlPrefix,ApiStandards.obp.toString,ApiShortVersions.`v5.1.0`.toString) val v6_0_0 = ScannedApiVersion(urlPrefix,ApiStandards.obp.toString,ApiShortVersions.`v6.0.0`.toString) + val v7_0_0 = ScannedApiVersion(urlPrefix,ApiStandards.obp.toString,ApiShortVersions.`v7.0.0`.toString) val `dynamic-endpoint` = ScannedApiVersion(urlPrefix,ApiStandards.obp.toString,ApiShortVersions.`dynamic-endpoint`.toString) val `dynamic-entity` = ScannedApiVersion(urlPrefix,ApiStandards.obp.toString,ApiShortVersions.`dynamic-entity`.toString) @@ -131,6 +133,7 @@ object ApiVersion { v5_0_0 :: v5_1_0 :: v6_0_0 :: + v7_0_0 :: `dynamic-endpoint` :: `dynamic-entity`:: Nil