mirror of
https://github.com/OpenBankProject/OBP-API.git
synced 2026-02-06 14:46:49 +00:00
commit
2adda4f552
@ -23,6 +23,52 @@
|
||||
<webXmlPath>src/main/resources/web.xml</webXmlPath>
|
||||
</properties>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>http4s-jar</id>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<version>3.6.0</version>
|
||||
<configuration>
|
||||
<appendAssemblyId>false</appendAssemblyId>
|
||||
<finalName>${project.artifactId}-http4s</finalName>
|
||||
<archive>
|
||||
<manifest>
|
||||
<mainClass>bootstrap.http4s.Http4sServer</mainClass>
|
||||
</manifest>
|
||||
</archive>
|
||||
<descriptorRefs>
|
||||
<descriptorRef>jar-with-dependencies</descriptorRef>
|
||||
</descriptorRefs>
|
||||
<dependencySets>
|
||||
<dependencySet>
|
||||
<outputDirectory>/</outputDirectory>
|
||||
<unpack>true</unpack>
|
||||
<scope>runtime</scope>
|
||||
</dependencySet>
|
||||
</dependencySets>
|
||||
<fileSets>
|
||||
<fileSet>
|
||||
<directory>${project.build.outputDirectory}</directory>
|
||||
<outputDirectory>/</outputDirectory>
|
||||
</fileSet>
|
||||
</fileSets>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>http4s-fat-jar</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>single</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
<pluginRepositories>
|
||||
<pluginRepository>
|
||||
@ -84,6 +130,16 @@
|
||||
<artifactId>bcpg-jdk15on</artifactId>
|
||||
<version>1.70</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.http4s</groupId>
|
||||
<artifactId>http4s-ember-server_${scala.version}</artifactId>
|
||||
<version>${http4s.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.http4s</groupId>
|
||||
<artifactId>http4s-dsl_${scala.version}</artifactId>
|
||||
<version>${http4s.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
<artifactId>bcpkix-jdk15on</artifactId>
|
||||
@ -345,7 +401,7 @@
|
||||
<dependency>
|
||||
<groupId>org.clapper</groupId>
|
||||
<artifactId>classutil_${scala.version}</artifactId>
|
||||
<version>1.4.0</version>
|
||||
<version>1.5.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.grumlimited</groupId>
|
||||
@ -602,6 +658,20 @@
|
||||
<plugin>
|
||||
<groupId>net.alchim31.maven</groupId>
|
||||
<artifactId>scala-maven-plugin</artifactId>
|
||||
<version>4.8.1</version>
|
||||
<configuration>
|
||||
<fork>true</fork>
|
||||
<jvmArgs>
|
||||
<jvmArg>-Xms4G</jvmArg>
|
||||
<jvmArg>-Xmx12G</jvmArg>
|
||||
<jvmArg>-XX:MaxMetaspaceSize=4G</jvmArg>
|
||||
<jvmArg>-XX:+UseG1GC</jvmArg>
|
||||
</jvmArgs>
|
||||
<args>
|
||||
<arg>-deprecation</arg>
|
||||
<arg>-feature</arg>
|
||||
</args>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
@ -609,6 +679,8 @@
|
||||
<version>3.4.0</version>
|
||||
<configuration>
|
||||
<webXml>${webXmlPath}</webXml>
|
||||
<attachClasses>true</attachClasses>
|
||||
<classesClassifier>classes</classesClassifier>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
|
||||
346
obp-api/src/main/scala/bootstrap/http4s/Http4sBoot.scala
Normal file
346
obp-api/src/main/scala/bootstrap/http4s/Http4sBoot.scala
Normal file
@ -0,0 +1,346 @@
|
||||
/**
|
||||
Open Bank Project - API
|
||||
Copyright (C) 2011-2019, TESOBE GmbH.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Email: contact@tesobe.com
|
||||
TESOBE GmbH.
|
||||
Osloer Strasse 16/17
|
||||
Berlin 13359, Germany
|
||||
|
||||
This product includes software developed at
|
||||
TESOBE (http://www.tesobe.com/)
|
||||
|
||||
*/
|
||||
package bootstrap.http4s
|
||||
|
||||
import bootstrap.liftweb.ToSchemify
|
||||
import code.api.Constant._
|
||||
import code.api.util.ApiRole.CanCreateEntitlementAtAnyBank
|
||||
import code.api.util.ErrorMessages.MandatoryPropertyIsNotSet
|
||||
import code.api.util._
|
||||
import code.api.util.migration.Migration
|
||||
import code.api.util.migration.Migration.DbFunction
|
||||
import code.entitlement.Entitlement
|
||||
import code.model.dataAccess._
|
||||
import code.scheduler._
|
||||
import code.users._
|
||||
import code.util.Helper.MdcLoggable
|
||||
import code.views.Views
|
||||
import com.openbankproject.commons.util.Functions.Implicits._
|
||||
import net.liftweb.common.Box.tryo
|
||||
import net.liftweb.common._
|
||||
import net.liftweb.db.{DB, DBLogEntry}
|
||||
import net.liftweb.mapper.{DefaultConnectionIdentifier => _, _}
|
||||
import net.liftweb.util._
|
||||
|
||||
import java.io.{File, FileInputStream}
|
||||
import java.util.TimeZone
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Http4s Boot class for initializing OBP-API core components
|
||||
* This class handles database initialization, migrations, and system setup
|
||||
* without Lift Web framework dependencies
|
||||
*/
|
||||
class Http4sBoot extends MdcLoggable {
|
||||
|
||||
/**
|
||||
* For the project scope, most early initiate logic should in this method.
|
||||
*/
|
||||
override protected def initiate(): Unit = {
|
||||
val resourceDir = System.getProperty("props.resource.dir") ?: System.getenv("props.resource.dir")
|
||||
val propsPath = tryo{Box.legacyNullTest(resourceDir)}.toList.flatten
|
||||
|
||||
val propsDir = for {
|
||||
propsPath <- propsPath
|
||||
} yield {
|
||||
Props.toTry.map {
|
||||
f => {
|
||||
val name = propsPath + f() + "props"
|
||||
name -> { () => tryo{new FileInputStream(new File(name))} }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Props.whereToLook = () => {
|
||||
propsDir.flatten
|
||||
}
|
||||
|
||||
if (Props.mode == Props.RunModes.Development) logger.info("OBP-API Props all fields : \n" + Props.props.mkString("\n"))
|
||||
logger.info("external props folder: " + propsPath)
|
||||
TimeZone.setDefault(TimeZone.getTimeZone("UTC"))
|
||||
logger.info("Current Project TimeZone: " + TimeZone.getDefault)
|
||||
|
||||
|
||||
// set dynamic_code_sandbox_enable to System.properties, so com.openbankproject.commons.ExecutionContext can read this value
|
||||
APIUtil.getPropsValue("dynamic_code_sandbox_enable")
|
||||
.foreach(it => System.setProperty("dynamic_code_sandbox_enable", it))
|
||||
}
|
||||
|
||||
|
||||
|
||||
def boot: Unit = {
|
||||
implicit val formats = CustomJsonFormats.formats
|
||||
|
||||
logger.info("Http4sBoot says: Hello from the Open Bank Project API. This is Http4sBoot.scala for Http4s runner. The gitCommit is : " + APIUtil.gitCommit)
|
||||
|
||||
logger.debug("Boot says:Using database driver: " + APIUtil.driver)
|
||||
|
||||
DB.defineConnectionManager(net.liftweb.util.DefaultConnectionIdentifier, APIUtil.vendor)
|
||||
|
||||
/**
|
||||
* Function that determines if foreign key constraints are
|
||||
* created by Schemifier for the specified connection.
|
||||
*
|
||||
* Note: The chosen driver must also support foreign keys for
|
||||
* creation to happen
|
||||
*
|
||||
* In case of PostgreSQL it works
|
||||
*/
|
||||
MapperRules.createForeignKeys_? = (_) => APIUtil.getPropsAsBoolValue("mapper_rules.create_foreign_keys", false)
|
||||
|
||||
schemifyAll()
|
||||
|
||||
logger.info("Mapper database info: " + Migration.DbFunction.mapperDatabaseInfo)
|
||||
|
||||
DbFunction.tableExists(ResourceUser) match {
|
||||
case true => // DB already exist
|
||||
// Migration Scripts are used to update the model of OBP-API DB to a latest version.
|
||||
// Please note that migration scripts are executed before Lift Mapper Schemifier
|
||||
Migration.database.executeScripts(startedBeforeSchemifier = true)
|
||||
logger.info("The Mapper database already exits. The scripts are executed BEFORE Lift Mapper Schemifier.")
|
||||
case false => // DB is still not created. The scripts will be executed after Lift Mapper Schemifier
|
||||
logger.info("The Mapper database is still not created. The scripts are going to be executed AFTER Lift Mapper Schemifier.")
|
||||
}
|
||||
|
||||
// Migration Scripts are used to update the model of OBP-API DB to a latest version.
|
||||
|
||||
// Please note that migration scripts are executed after Lift Mapper Schemifier
|
||||
Migration.database.executeScripts(startedBeforeSchemifier = false)
|
||||
|
||||
if (APIUtil.getPropsAsBoolValue("create_system_views_at_boot", true)) {
|
||||
// Create system views
|
||||
val owner = Views.views.vend.getOrCreateSystemView(SYSTEM_OWNER_VIEW_ID).isDefined
|
||||
val auditor = Views.views.vend.getOrCreateSystemView(SYSTEM_AUDITOR_VIEW_ID).isDefined
|
||||
val accountant = Views.views.vend.getOrCreateSystemView(SYSTEM_ACCOUNTANT_VIEW_ID).isDefined
|
||||
val standard = Views.views.vend.getOrCreateSystemView(SYSTEM_STANDARD_VIEW_ID).isDefined
|
||||
val stageOne = Views.views.vend.getOrCreateSystemView(SYSTEM_STAGE_ONE_VIEW_ID).isDefined
|
||||
val manageCustomViews = Views.views.vend.getOrCreateSystemView(SYSTEM_MANAGE_CUSTOM_VIEWS_VIEW_ID).isDefined
|
||||
// Only create Firehose view if they are enabled at instance.
|
||||
val accountFirehose = if (ApiPropsWithAlias.allowAccountFirehose)
|
||||
Views.views.vend.getOrCreateSystemView(SYSTEM_FIREHOSE_VIEW_ID).isDefined
|
||||
else Empty.isDefined
|
||||
|
||||
APIUtil.getPropsValue("additional_system_views") match {
|
||||
case Full(value) =>
|
||||
val additionalSystemViewsFromProps = value.split(",").map(_.trim).toList
|
||||
val additionalSystemViews = List(
|
||||
SYSTEM_READ_ACCOUNTS_BASIC_VIEW_ID,
|
||||
SYSTEM_READ_ACCOUNTS_DETAIL_VIEW_ID,
|
||||
SYSTEM_READ_BALANCES_VIEW_ID,
|
||||
SYSTEM_READ_TRANSACTIONS_BASIC_VIEW_ID,
|
||||
SYSTEM_READ_TRANSACTIONS_DEBITS_VIEW_ID,
|
||||
SYSTEM_READ_TRANSACTIONS_DETAIL_VIEW_ID,
|
||||
SYSTEM_READ_ACCOUNTS_BERLIN_GROUP_VIEW_ID,
|
||||
SYSTEM_READ_BALANCES_BERLIN_GROUP_VIEW_ID,
|
||||
SYSTEM_READ_TRANSACTIONS_BERLIN_GROUP_VIEW_ID,
|
||||
SYSTEM_INITIATE_PAYMENTS_BERLIN_GROUP_VIEW_ID
|
||||
)
|
||||
for {
|
||||
systemView <- additionalSystemViewsFromProps
|
||||
if additionalSystemViews.exists(_ == systemView)
|
||||
} {
|
||||
Views.views.vend.getOrCreateSystemView(systemView)
|
||||
}
|
||||
case _ => // Do nothing
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ApiWarnings.logWarningsRegardingProperties()
|
||||
ApiWarnings.customViewNamesCheck()
|
||||
ApiWarnings.systemViewNamesCheck()
|
||||
|
||||
//see the notes for this method:
|
||||
createDefaultBankAndDefaultAccountsIfNotExisting()
|
||||
|
||||
createBootstrapSuperUser()
|
||||
|
||||
if (APIUtil.getPropsAsBoolValue("logging.database.queries.enable", false)) {
|
||||
DB.addLogFunc
|
||||
{
|
||||
case (log, duration) =>
|
||||
{
|
||||
logger.debug("Total query time : %d ms".format(duration))
|
||||
log.allEntries.foreach
|
||||
{
|
||||
case DBLogEntry(stmt, duration) =>
|
||||
logger.debug("The query : %s in %d ms".format(stmt, duration))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// start RabbitMq Adapter(using mapped connector as mockded CBS)
|
||||
if (APIUtil.getPropsAsBoolValue("rabbitmq.adapter.enabled", false)) {
|
||||
code.bankconnectors.rabbitmq.Adapter.startRabbitMqAdapter.main(Array(""))
|
||||
}
|
||||
|
||||
// ensure our relational database's tables are created/fit the schema
|
||||
val connector = code.api.Constant.CONNECTOR.openOrThrowException(s"$MandatoryPropertyIsNotSet. The missing prop is `connector` ")
|
||||
|
||||
logger.info(s"ApiPathZero (the bit before version) is $ApiPathZero")
|
||||
logger.debug(s"If you can read this, logging level is debug")
|
||||
|
||||
// API Metrics (logs of API calls)
|
||||
// If set to true we will write each URL with params to a datastore / log file
|
||||
if (APIUtil.getPropsAsBoolValue("write_metrics", false)) {
|
||||
logger.info("writeMetrics is true. We will write API metrics")
|
||||
} else {
|
||||
logger.info("writeMetrics is false. We will NOT write API metrics")
|
||||
}
|
||||
|
||||
// API Metrics (logs of Connector calls)
|
||||
// If set to true we will write each URL with params to a datastore / log file
|
||||
if (APIUtil.getPropsAsBoolValue("write_connector_metrics", false)) {
|
||||
logger.info("writeConnectorMetrics is true. We will write connector metrics")
|
||||
} else {
|
||||
logger.info("writeConnectorMetrics is false. We will NOT write connector metrics")
|
||||
}
|
||||
|
||||
|
||||
logger.info (s"props_identifier is : ${APIUtil.getPropsValue("props_identifier", "NONE-SET")}")
|
||||
|
||||
val locale = I18NUtil.getDefaultLocale()
|
||||
logger.info("Default Project Locale is :" + locale)
|
||||
|
||||
}
|
||||
|
||||
def schemifyAll() = {
|
||||
Schemifier.schemify(true, Schemifier.infoF _, ToSchemify.models: _*)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* there will be a default bank and two default accounts in obp mapped mode.
|
||||
* These bank and accounts will be used for the payments.
|
||||
* when we create transaction request over counterparty and if the counterparty do not link to an existing obp account
|
||||
* then we will use the default accounts (incoming and outgoing) to keep the money.
|
||||
*/
|
||||
private def createDefaultBankAndDefaultAccountsIfNotExisting() ={
|
||||
val defaultBankId= APIUtil.defaultBankId
|
||||
val incomingAccountId= INCOMING_SETTLEMENT_ACCOUNT_ID
|
||||
val outgoingAccountId= OUTGOING_SETTLEMENT_ACCOUNT_ID
|
||||
|
||||
MappedBank.find(By(MappedBank.permalink, defaultBankId)) match {
|
||||
case Full(b) =>
|
||||
logger.debug(s"Bank(${defaultBankId}) is found.")
|
||||
case _ =>
|
||||
MappedBank.create
|
||||
.permalink(defaultBankId)
|
||||
.fullBankName("OBP_DEFAULT_BANK")
|
||||
.shortBankName("OBP")
|
||||
.national_identifier("OBP")
|
||||
.mBankRoutingScheme("OBP")
|
||||
.mBankRoutingAddress("obp1")
|
||||
.logoURL("")
|
||||
.websiteURL("")
|
||||
.saveMe()
|
||||
logger.debug(s"creating Bank(${defaultBankId})")
|
||||
}
|
||||
|
||||
MappedBankAccount.find(By(MappedBankAccount.bank, defaultBankId), By(MappedBankAccount.theAccountId, incomingAccountId)) match {
|
||||
case Full(b) =>
|
||||
logger.debug(s"BankAccount(${defaultBankId}, $incomingAccountId) is found.")
|
||||
case _ =>
|
||||
MappedBankAccount.create
|
||||
.bank(defaultBankId)
|
||||
.theAccountId(incomingAccountId)
|
||||
.accountCurrency("EUR")
|
||||
.saveMe()
|
||||
logger.debug(s"creating BankAccount(${defaultBankId}, $incomingAccountId).")
|
||||
}
|
||||
|
||||
MappedBankAccount.find(By(MappedBankAccount.bank, defaultBankId), By(MappedBankAccount.theAccountId, outgoingAccountId)) match {
|
||||
case Full(b) =>
|
||||
logger.debug(s"BankAccount(${defaultBankId}, $outgoingAccountId) is found.")
|
||||
case _ =>
|
||||
MappedBankAccount.create
|
||||
.bank(defaultBankId)
|
||||
.theAccountId(outgoingAccountId)
|
||||
.accountCurrency("EUR")
|
||||
.saveMe()
|
||||
logger.debug(s"creating BankAccount(${defaultBankId}, $outgoingAccountId).")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Bootstrap Super User
|
||||
* Given the following credentials, OBP will create a user *if it does not exist already*.
|
||||
* This user's password will be valid for a limited amount of time.
|
||||
* This user will be granted ONLY CanCreateEntitlementAtAnyBank
|
||||
* This feature can also be used in a "Break Glass scenario"
|
||||
*/
|
||||
private def createBootstrapSuperUser() ={
|
||||
|
||||
val superAdminUsername = APIUtil.getPropsValue("super_admin_username","")
|
||||
val superAdminInitalPassword = APIUtil.getPropsValue("super_admin_inital_password","")
|
||||
val superAdminEmail = APIUtil.getPropsValue("super_admin_email","")
|
||||
|
||||
val isPropsNotSetProperly = superAdminUsername==""||superAdminInitalPassword ==""||superAdminEmail==""
|
||||
|
||||
//This is the logic to check if an AuthUser exists for the `create sandbox` endpoint, AfterApiAuth, OpenIdConnect ,,,
|
||||
val existingAuthUser = AuthUser.find(By(AuthUser.username, superAdminUsername))
|
||||
|
||||
if(isPropsNotSetProperly) {
|
||||
//Nothing happens, props is not set
|
||||
}else if(existingAuthUser.isDefined) {
|
||||
logger.error(s"createBootstrapSuperUser- Errors: Existing AuthUser with username ${superAdminUsername} detected in data import where no ResourceUser was found")
|
||||
} else {
|
||||
val authUser = AuthUser.create
|
||||
.email(superAdminEmail)
|
||||
.firstName(superAdminUsername)
|
||||
.lastName(superAdminUsername)
|
||||
.username(superAdminUsername)
|
||||
.password(superAdminInitalPassword)
|
||||
.passwordShouldBeChanged(true)
|
||||
.validated(true)
|
||||
|
||||
val validationErrors = authUser.validate
|
||||
|
||||
if(!validationErrors.isEmpty)
|
||||
logger.error(s"createBootstrapSuperUser- Errors: ${validationErrors.map(_.msg)}")
|
||||
else {
|
||||
Full(authUser.save()) //this will create/update the resourceUser.
|
||||
|
||||
val userBox = Users.users.vend.getUserByProviderAndUsername(authUser.getProvider(), authUser.username.get)
|
||||
|
||||
val resultBox = userBox.map(user => Entitlement.entitlement.vend.addEntitlement("", user.userId, CanCreateEntitlementAtAnyBank.toString))
|
||||
|
||||
if(resultBox.isEmpty){
|
||||
logger.error(s"createBootstrapSuperUser- Errors: ${resultBox}")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
35
obp-api/src/main/scala/bootstrap/http4s/Http4sServer.scala
Normal file
35
obp-api/src/main/scala/bootstrap/http4s/Http4sServer.scala
Normal file
@ -0,0 +1,35 @@
|
||||
package bootstrap.http4s
|
||||
|
||||
import cats.data.{Kleisli, OptionT}
|
||||
import cats.effect._
|
||||
import code.api.util.APIUtil
|
||||
import com.comcast.ip4s._
|
||||
import org.http4s._
|
||||
import org.http4s.ember.server._
|
||||
import org.http4s.implicits._
|
||||
|
||||
import scala.language.higherKinds
|
||||
object Http4sServer extends IOApp {
|
||||
|
||||
val services: Kleisli[({type λ[β$0$] = OptionT[IO, β$0$]})#λ, Request[IO], Response[IO]] =
|
||||
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.http4s.Http4sBoot().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(Host.fromString(host).get)
|
||||
.withPort(Port.fromInt(port).get)
|
||||
.withHttpApp(httpApp)
|
||||
.build
|
||||
.use(_ => IO.never)
|
||||
.as(ExitCode.Success)
|
||||
}
|
||||
|
||||
@ -50,7 +50,7 @@ import sh.ory.hydra.model.OAuth2TokenIntrospection
|
||||
|
||||
import java.net.URI
|
||||
import scala.concurrent.Future
|
||||
import scala.jdk.CollectionConverters.mapAsJavaMapConverter
|
||||
import scala.collection.JavaConverters._
|
||||
|
||||
/**
|
||||
* This object provides the API calls necessary to third party applications
|
||||
|
||||
@ -2679,8 +2679,7 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{
|
||||
}
|
||||
|
||||
def getDisabledVersions() : List[String] = {
|
||||
val defaultDisabledVersions = "OBPv1.2.1,OBPv1.3.0,OBPv1.4.0,OBPv2.0.0,OBPv2.1.0,OBPv2.2.0,OBPv3.0.0,OBPv3.1.0,OBPv4.0.0,OBPv5.0.0"
|
||||
val disabledVersions = APIUtil.getPropsValue("api_disabled_versions").getOrElse(defaultDisabledVersions).replace("[", "").replace("]", "").split(",").toList.filter(_.nonEmpty)
|
||||
val disabledVersions = APIUtil.getPropsValue("api_disabled_versions").getOrElse("").replace("[", "").replace("]", "").split(",").toList.filter(_.nonEmpty)
|
||||
if (disabledVersions.nonEmpty) {
|
||||
logger.info(s"Disabled API versions: ${disabledVersions.mkString(", ")}")
|
||||
}
|
||||
|
||||
@ -8,7 +8,7 @@ import java.security.cert._
|
||||
import java.util.{Base64, Collections}
|
||||
import javax.net.ssl.TrustManagerFactory
|
||||
import scala.io.Source
|
||||
import scala.jdk.CollectionConverters._
|
||||
import scala.collection.JavaConverters._
|
||||
import scala.util.{Failure, Success, Try}
|
||||
|
||||
object CertificateVerifier extends MdcLoggable {
|
||||
@ -69,8 +69,8 @@ object CertificateVerifier extends MdcLoggable {
|
||||
trustManagerFactory.init(trustStore)
|
||||
|
||||
// Get trusted CAs from the trust store
|
||||
val trustAnchors = trustStore.aliases().asScala
|
||||
.filter(trustStore.isCertificateEntry)
|
||||
val trustAnchors = enumerationAsScalaIterator(trustStore.aliases())
|
||||
.filter(trustStore.isCertificateEntry(_))
|
||||
.map(alias => trustStore.getCertificate(alias).asInstanceOf[X509Certificate])
|
||||
.map(cert => new TrustAnchor(cert, null))
|
||||
.toSet
|
||||
|
||||
@ -17,7 +17,7 @@ import java.time.format.DateTimeFormatter
|
||||
import java.time.{Duration, ZoneOffset, ZonedDateTime}
|
||||
import java.util
|
||||
import scala.collection.immutable.{HashMap, List}
|
||||
import scala.jdk.CollectionConverters.seqAsJavaListConverter
|
||||
import scala.collection.JavaConverters._
|
||||
|
||||
|
||||
object JwsUtil extends MdcLoggable {
|
||||
|
||||
@ -5,16 +5,10 @@ import code.DynamicEndpoint.DynamicEndpointSwagger
|
||||
import code.accountattribute.AccountAttributeX
|
||||
import code.api.Constant._
|
||||
import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON
|
||||
import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON.{
|
||||
jsonDynamicResourceDoc,
|
||||
_
|
||||
}
|
||||
import code.api.dynamic.endpoint.helper.practise.{
|
||||
DynamicEndpointCodeGenerator,
|
||||
PractiseEndpoint
|
||||
}
|
||||
import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON.{jsonDynamicResourceDoc, _}
|
||||
import code.api.dynamic.endpoint.helper.practise.{DynamicEndpointCodeGenerator, PractiseEndpoint}
|
||||
import code.api.dynamic.endpoint.helper.{CompiledObjects, DynamicEndpointHelper}
|
||||
import code.api.dynamic.entity.helper.{DynamicEntityHelper, DynamicEntityInfo}
|
||||
import code.api.dynamic.entity.helper.DynamicEntityInfo
|
||||
import code.api.util.APIUtil.{fullBoxOrException, _}
|
||||
import code.api.util.ApiRole._
|
||||
import code.api.util.ApiTag._
|
||||
@ -31,20 +25,11 @@ import code.api.util.migration.Migration
|
||||
import code.api.util.newstyle.AttributeDefinition._
|
||||
import code.api.util.newstyle.Consumer._
|
||||
import code.api.util.newstyle.UserCustomerLinkNewStyle.getUserCustomerLinks
|
||||
import code.api.util.newstyle.{
|
||||
BalanceNewStyle,
|
||||
UserCustomerLinkNewStyle,
|
||||
ViewNewStyle
|
||||
}
|
||||
import code.api.util.newstyle.{BalanceNewStyle, UserCustomerLinkNewStyle, ViewNewStyle}
|
||||
import code.api.v1_2_1.{JSONFactory, PostTransactionTagJSON}
|
||||
import code.api.v1_4_0.JSONFactory1_4_0
|
||||
import code.api.v2_0_0.OBPAPI2_0_0.Implementations2_0_0
|
||||
import code.api.v2_0_0.{
|
||||
CreateEntitlementJSON,
|
||||
CreateUserCustomerLinkJson,
|
||||
EntitlementJSONs,
|
||||
JSONFactory200
|
||||
}
|
||||
import code.api.v2_0_0.{CreateEntitlementJSON, CreateUserCustomerLinkJson, EntitlementJSONs, JSONFactory200}
|
||||
import code.api.v2_1_0._
|
||||
import code.api.v3_0_0.{CreateScopeJson, JSONFactory300}
|
||||
import code.api.v3_1_0._
|
||||
@ -54,15 +39,10 @@ import code.apicollection.MappedApiCollectionsProvider
|
||||
import code.apicollectionendpoint.MappedApiCollectionEndpointsProvider
|
||||
import code.authtypevalidation.JsonAuthTypeValidation
|
||||
import code.bankconnectors.LocalMappedConnectorInternal._
|
||||
import code.bankconnectors.{
|
||||
Connector,
|
||||
DynamicConnector,
|
||||
InternalConnector,
|
||||
LocalMappedConnectorInternal
|
||||
}
|
||||
import code.bankconnectors.{Connector, DynamicConnector, InternalConnector, LocalMappedConnectorInternal}
|
||||
import code.connectormethod.{JsonConnectorMethod, JsonConnectorMethodMethodBody}
|
||||
import code.consent.{ConsentStatus, Consents}
|
||||
import code.dynamicEntity.{DynamicEntityCommons, ReferenceType}
|
||||
import code.dynamicEntity.DynamicEntityCommons
|
||||
import code.dynamicMessageDoc.JsonDynamicMessageDoc
|
||||
import code.dynamicResourceDoc.JsonDynamicResourceDoc
|
||||
import code.endpointMapping.EndpointMappingCommons
|
||||
@ -82,10 +62,7 @@ import code.util.Helper.{MdcLoggable, ObpS, SILENCE_IS_GOLDEN, booleanToFuture}
|
||||
import code.util.{Helper, JsonSchemaUtil}
|
||||
import code.validation.JsonValidation
|
||||
import code.views.Views
|
||||
import code.webhook.{
|
||||
BankAccountNotificationWebhookTrait,
|
||||
SystemAccountNotificationWebhookTrait
|
||||
}
|
||||
import code.webhook.{BankAccountNotificationWebhookTrait, SystemAccountNotificationWebhookTrait}
|
||||
import code.webuiprops.MappedWebUiPropsProvider.getWebUiPropsValue
|
||||
import com.github.dwickern.macros.NameOf.nameOf
|
||||
import com.networknt.schema.ValidationMessage
|
||||
@ -110,10 +87,10 @@ import java.net.URLEncoder
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util
|
||||
import java.util.{Calendar, Date}
|
||||
import scala.collection.JavaConverters._
|
||||
import scala.collection.immutable.{List, Nil}
|
||||
import scala.collection.mutable.ArrayBuffer
|
||||
import scala.concurrent.Future
|
||||
import scala.jdk.CollectionConverters.collectionAsScalaIterableConverter
|
||||
|
||||
trait APIMethods400 extends MdcLoggable {
|
||||
self: RestHelper =>
|
||||
@ -11796,10 +11773,10 @@ trait APIMethods400 extends MdcLoggable {
|
||||
Future {
|
||||
val versions: List[ScannedApiVersion] =
|
||||
ApiVersion.allScannedApiVersion.asScala.toList.filter { version =>
|
||||
version.urlPrefix.trim.nonEmpty
|
||||
version.urlPrefix.trim.nonEmpty && APIUtil.versionIsAllowed(version)
|
||||
}
|
||||
(
|
||||
ListResult("scanned_api_versions", versions),
|
||||
ListResult("scanned_api_versions", versions),
|
||||
HttpCode.`200`(cc.callContext)
|
||||
)
|
||||
}
|
||||
|
||||
@ -65,7 +65,7 @@ import scala.collection.immutable.{List, Nil}
|
||||
import scala.collection.mutable.ArrayBuffer
|
||||
import scala.concurrent.Future
|
||||
import scala.concurrent.duration._
|
||||
import scala.jdk.CollectionConverters._
|
||||
import scala.collection.JavaConverters._
|
||||
import scala.util.Random
|
||||
|
||||
|
||||
@ -3486,7 +3486,7 @@ trait APIMethods600 {
|
||||
|
|
||||
|""",
|
||||
EmptyBody,
|
||||
WebUiPropsCommons("webui_api_explorer_url", "https://apiexplorer.openbankproject.com", Some("web-ui-props-id"), "database"),
|
||||
WebUiPropsCommons("webui_api_explorer_url", "https://apiexplorer.openbankproject.com", Some("web-ui-props-id"), Some("config")),
|
||||
List(
|
||||
WebUiPropsNotFoundByName,
|
||||
UnknownError
|
||||
@ -3509,11 +3509,11 @@ trait APIMethods600 {
|
||||
explicitProp match {
|
||||
case Some(prop) =>
|
||||
// Found in database
|
||||
Future.successful(WebUiPropsCommons(prop.name, prop.value, prop.webUiPropsId, source = "database"))
|
||||
Future.successful(WebUiPropsCommons(prop.name, prop.value, prop.webUiPropsId, source = Some("database")))
|
||||
case None if isActived =>
|
||||
// Not in database, check implicit props if active=true
|
||||
val implicitWebUiProps = getWebUIPropsPairs.map(webUIPropsPairs =>
|
||||
WebUiPropsCommons(webUIPropsPairs._1, webUIPropsPairs._2, webUiPropsId = None, source = "config")
|
||||
WebUiPropsCommons(webUIPropsPairs._1, webUIPropsPairs._2, webUiPropsId = Some("default"), source = Some("config"))
|
||||
)
|
||||
val implicitProp = implicitWebUiProps.find(_.name == webUiPropName)
|
||||
implicitProp match {
|
||||
@ -3584,7 +3584,7 @@ trait APIMethods600 {
|
||||
EmptyBody,
|
||||
ListResult(
|
||||
"webui_props",
|
||||
(List(WebUiPropsCommons("webui_api_explorer_url", "https://apiexplorer.openbankproject.com", Some("web-ui-props-id"), "database")))
|
||||
(List(WebUiPropsCommons("webui_api_explorer_url", "https://apiexplorer.openbankproject.com", Some("web-ui-props-id"), Some("database"))))
|
||||
)
|
||||
,
|
||||
List(
|
||||
@ -3608,8 +3608,8 @@ trait APIMethods600 {
|
||||
}
|
||||
}
|
||||
explicitWebUiProps <- Future{ MappedWebUiPropsProvider.getAll() }
|
||||
explicitWebUiPropsWithSource = explicitWebUiProps.map(prop => WebUiPropsCommons(prop.name, prop.value, prop.webUiPropsId, source = "database"))
|
||||
implicitWebUiProps = getWebUIPropsPairs.map(webUIPropsPairs=>WebUiPropsCommons(webUIPropsPairs._1, webUIPropsPairs._2, webUiPropsId = None, source = "config"))
|
||||
explicitWebUiPropsWithSource = explicitWebUiProps.map(prop => WebUiPropsCommons(prop.name, prop.value, prop.webUiPropsId, source = Some("database")))
|
||||
implicitWebUiProps = getWebUIPropsPairs.map(webUIPropsPairs=>WebUiPropsCommons(webUIPropsPairs._1, webUIPropsPairs._2, webUiPropsId = Some("default"), source = Some("config")))
|
||||
result = what match {
|
||||
case "database" =>
|
||||
// Return only database props
|
||||
|
||||
72
obp-api/src/main/scala/code/api/v7_0_0/Http4s700.scala
Normal file
72
obp-api/src/main/scala/code/api/v7_0_0/Http4s700.scala
Normal file
@ -0,0 +1,72 @@
|
||||
package code.api.v7_0_0
|
||||
|
||||
import cats.data.{Kleisli, OptionT}
|
||||
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 {
|
||||
|
||||
type HttpF[A] = OptionT[IO, A]
|
||||
|
||||
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[HttpF, Request[IO], Response[IO]] { 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)
|
||||
}
|
||||
|
||||
@ -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
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,7 +10,7 @@ import org.apache.commons.lang3.StringUtils.uncapitalize
|
||||
import java.io.File
|
||||
import java.net.URL
|
||||
import java.util.Date
|
||||
import scala.jdk.CollectionConverters.enumerationAsScalaIteratorConverter
|
||||
import scala.collection.JavaConverters._
|
||||
import scala.language.postfixOps
|
||||
import scala.reflect.runtime.universe._
|
||||
import scala.reflect.runtime.{universe => ru}
|
||||
|
||||
@ -45,7 +45,7 @@ import net.liftweb.util.Helpers._
|
||||
import sh.ory.hydra.api.AdminApi
|
||||
import sh.ory.hydra.model.{AcceptConsentRequest, RejectRequest}
|
||||
|
||||
import scala.jdk.CollectionConverters.seqAsJavaListConverter
|
||||
import scala.collection.JavaConverters._
|
||||
import scala.xml.NodeSeq
|
||||
|
||||
|
||||
|
||||
@ -43,7 +43,7 @@ import org.apache.commons.lang3.StringUtils
|
||||
import org.codehaus.jackson.map.ObjectMapper
|
||||
|
||||
import scala.collection.immutable.{List, ListMap}
|
||||
import scala.jdk.CollectionConverters.seqAsJavaListConverter
|
||||
import scala.collection.JavaConverters._
|
||||
import scala.xml.{Text, Unparsed}
|
||||
|
||||
class ConsumerRegistration extends MdcLoggable {
|
||||
|
||||
@ -35,7 +35,15 @@ object ClassScanUtils {
|
||||
*/
|
||||
def getSubTypeObjects[T:TypeTag]: List[T] = {
|
||||
val clazz = ReflectUtils.typeTagToClass[T]
|
||||
finder.getClasses().filter(_.implements(clazz.getName)).map(_.name).map(companion[T](_)).toList
|
||||
val classes = try {
|
||||
finder.getClasses().toList
|
||||
} catch {
|
||||
case _: UnsupportedOperationException =>
|
||||
// ASM version is too old for some class files (e.g. requires ASM7). In that case,
|
||||
// skip scanned APIs instead of failing the whole application.
|
||||
Seq.empty
|
||||
}
|
||||
classes.filter(_.implements(clazz.getName)).map(_.name).map(companion[T](_)).toList
|
||||
}
|
||||
|
||||
/**
|
||||
@ -43,14 +51,22 @@ object ClassScanUtils {
|
||||
* @param predict check whether include this type in the result
|
||||
* @return all fit type names
|
||||
*/
|
||||
def findTypes(predict: ClassInfo => Boolean): List[String] = finder.getClasses()
|
||||
.filter(predict)
|
||||
.map(it => {
|
||||
val name = it.name
|
||||
if(name.endsWith("$")) name.substring(0, name.length - 1)
|
||||
else name
|
||||
}) //some companion type name ends with $, it added by scalac, should remove from class name
|
||||
.toList
|
||||
def findTypes(predict: ClassInfo => Boolean): List[String] = {
|
||||
val classes = try {
|
||||
finder.getClasses().toList
|
||||
} catch {
|
||||
case _: UnsupportedOperationException =>
|
||||
Seq.empty
|
||||
}
|
||||
classes
|
||||
.filter(predict)
|
||||
.map(it => {
|
||||
val name = it.name
|
||||
if(name.endsWith("$")) name.substring(0, name.length - 1)
|
||||
else name
|
||||
}) //some companion type name ends with $, it added by scalac, should remove from class name
|
||||
.toList
|
||||
}
|
||||
|
||||
/**
|
||||
* get given class exists jar Files
|
||||
@ -71,7 +87,13 @@ object ClassScanUtils {
|
||||
*/
|
||||
def getMappers(packageName:String = ""): Seq[ClassInfo] = {
|
||||
val mapperInterface = "net.liftweb.mapper.LongKeyedMapper"
|
||||
val infos = finder.getClasses().filter(it => it.interfaces.contains(mapperInterface))
|
||||
val classes = try {
|
||||
finder.getClasses().toList
|
||||
} catch {
|
||||
case _: UnsupportedOperationException =>
|
||||
Seq.empty
|
||||
}
|
||||
val infos = classes.filter(it => it.interfaces.contains(mapperInterface))
|
||||
if(StringUtils.isNoneBlank()) {
|
||||
infos.filter(classInfo => classInfo.name.startsWith(packageName))
|
||||
} else {
|
||||
|
||||
@ -15,7 +15,7 @@ import sh.ory.hydra.model.OAuth2Client
|
||||
import sh.ory.hydra.{ApiClient, Configuration}
|
||||
|
||||
import scala.collection.immutable.List
|
||||
import scala.jdk.CollectionConverters.{mapAsJavaMapConverter, seqAsJavaListConverter}
|
||||
import scala.collection.JavaConverters._
|
||||
|
||||
object HydraUtil extends MdcLoggable{
|
||||
|
||||
|
||||
@ -77,6 +77,7 @@ class WebUiProps extends WebUiPropsT with LongKeyedMapper[WebUiProps] with IdPK
|
||||
override def webUiPropsId: Option[String] = Option(WebUiPropsId.get)
|
||||
override def name: String = Name.get
|
||||
override def value: String = Value.get
|
||||
override def source: Option[String] = Some("database")
|
||||
}
|
||||
|
||||
object WebUiProps extends WebUiProps with LongKeyedMetaMapper[WebUiProps] {
|
||||
|
||||
@ -9,12 +9,13 @@ trait WebUiPropsT {
|
||||
def webUiPropsId: Option[String]
|
||||
def name: String
|
||||
def value: String
|
||||
def source: Option[String]
|
||||
}
|
||||
|
||||
case class WebUiPropsCommons(name: String,
|
||||
value: String,
|
||||
webUiPropsId: Option[String] = None,
|
||||
source: String = "database") extends WebUiPropsT with JsonFieldReName
|
||||
source: Option[String] = None) extends WebUiPropsT with JsonFieldReName
|
||||
|
||||
object WebUiPropsCommons extends Converter[WebUiPropsT, WebUiPropsCommons]
|
||||
|
||||
|
||||
Binary file not shown.
@ -25,6 +25,7 @@ TESOBE (http://www.tesobe.com/)
|
||||
*/
|
||||
package code.api.v4_0_0
|
||||
|
||||
import code.api.util.APIUtil
|
||||
import code.api.util.ApiRole._
|
||||
import code.api.v4_0_0.APIMethods400.Implementations4_0_0
|
||||
import code.entitlement.Entitlement
|
||||
@ -33,7 +34,7 @@ import com.openbankproject.commons.model.ListResult
|
||||
import com.openbankproject.commons.util.{ApiVersion, ScannedApiVersion}
|
||||
import org.scalatest.Tag
|
||||
|
||||
import scala.jdk.CollectionConverters.collectionAsScalaIterableConverter
|
||||
import scala.collection.JavaConverters._
|
||||
class GetScannedApiVersionsTest extends V400ServerSetup {
|
||||
|
||||
/**
|
||||
@ -46,8 +47,63 @@ class GetScannedApiVersionsTest extends V400ServerSetup {
|
||||
object VersionOfApi extends Tag(ApiVersion.v4_0_0.toString)
|
||||
object ApiEndpoint extends Tag(nameOf(Implementations4_0_0.getScannedApiVersions))
|
||||
|
||||
feature("test props-api_disabled_versions, Get all scanned API versions should works") {
|
||||
scenario("We get all the scanned API versions with disabled versions filtered out", ApiEndpoint, VersionOfApi) {
|
||||
// api_disabled_versions=[OBPv3.0.0,BGv1.3]
|
||||
setPropsValues("api_disabled_versions"-> "[OBPv3.0.0,BGv1.3]")
|
||||
Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, CanCreateSystemLevelDynamicEntity.toString)
|
||||
When("We make a request v4.0.0")
|
||||
val request = (v4_0_0_Request / "api" / "versions").GET
|
||||
|
||||
val response = makeGetRequest(request)
|
||||
Then("We should get a 200")
|
||||
response.code should equal(200)
|
||||
|
||||
val listResult = response.body.extract[ListResult[List[ScannedApiVersion]]]
|
||||
val responseApiVersions = listResult.results
|
||||
val scannedApiVersions = ApiVersion.allScannedApiVersion.asScala.toList.filter { version =>
|
||||
version.urlPrefix.trim.nonEmpty && APIUtil.versionIsAllowed(version)
|
||||
}
|
||||
|
||||
responseApiVersions should equal(scannedApiVersions)
|
||||
|
||||
// Verify that disabled versions are not included
|
||||
responseApiVersions.exists(_.fullyQualifiedVersion == "OBPv3.0.0") should equal(false)
|
||||
responseApiVersions.exists(_.fullyQualifiedVersion == "BGv1.3") should equal(false)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
feature("test props-api_enabled_versions, Get all scanned API versions should works") {
|
||||
scenario("We get all the scanned API versions with disabled versions filtered out", ApiEndpoint, VersionOfApi) {
|
||||
// api_enabled_versions=[OBPv2.2.0,OBPv3.0.0,UKv2.0]
|
||||
setPropsValues("api_enabled_versions"-> "[OBPv2.2.0,OBPv3.0.0,UKv2.0]")
|
||||
Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, CanCreateSystemLevelDynamicEntity.toString)
|
||||
When("We make a request v4.0.0")
|
||||
val request = (v4_0_0_Request / "api" / "versions").GET
|
||||
|
||||
val response = makeGetRequest(request)
|
||||
Then("We should get a 200")
|
||||
response.code should equal(200)
|
||||
|
||||
val listResult = response.body.extract[ListResult[List[ScannedApiVersion]]]
|
||||
val responseApiVersions = listResult.results
|
||||
val scannedApiVersions = ApiVersion.allScannedApiVersion.asScala.toList.filter { version =>
|
||||
version.urlPrefix.trim.nonEmpty && APIUtil.versionIsAllowed(version)
|
||||
}
|
||||
|
||||
responseApiVersions should equal(scannedApiVersions)
|
||||
|
||||
// Verify that disabled versions are not included
|
||||
responseApiVersions.exists(_.fullyQualifiedVersion == "OBPv2.2.0") should equal(true)
|
||||
responseApiVersions.exists(_.fullyQualifiedVersion == "OBPv3.0.0") should equal(true)
|
||||
responseApiVersions.exists(_.fullyQualifiedVersion == "UKv2.0") should equal(true)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
feature("Get all scanned API versions should works") {
|
||||
|
||||
scenario("We get all the scanned API versions", ApiEndpoint, VersionOfApi) {
|
||||
Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, CanCreateSystemLevelDynamicEntity.toString)
|
||||
When("We make a request v4.0.0")
|
||||
|
||||
@ -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
|
||||
|
||||
71
obp-http4s-runner/pom.xml
Normal file
71
obp-http4s-runner/pom.xml
Normal file
@ -0,0 +1,71 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>com.tesobe</groupId>
|
||||
<artifactId>obp-parent</artifactId>
|
||||
<version>1.10.1</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<artifactId>obp-http4s-runner</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>OBP Http4s Runner</name>
|
||||
|
||||
<dependencies>
|
||||
<!-- Use obp-api compiled classes as a normal JAR -->
|
||||
<dependency>
|
||||
<groupId>com.tesobe</groupId>
|
||||
<artifactId>obp-api</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<classifier>classes</classifier>
|
||||
<type>jar</type>
|
||||
<exclusions>
|
||||
<!-- Exclude old classutil version if present -->
|
||||
<exclusion>
|
||||
<groupId>org.clapper</groupId>
|
||||
<artifactId>classutil_${scala.version}</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<!-- Explicitly include classutil 1.5.1 to override any transitive dependencies -->
|
||||
<dependency>
|
||||
<groupId>org.clapper</groupId>
|
||||
<artifactId>classutil_${scala.version}</artifactId>
|
||||
<version>1.5.1</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<version>3.6.0</version>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifest>
|
||||
<mainClass>bootstrap.http4s.Http4sServer</mainClass>
|
||||
</manifest>
|
||||
</archive>
|
||||
<descriptorRefs>
|
||||
<descriptorRef>jar-with-dependencies</descriptorRef>
|
||||
</descriptorRefs>
|
||||
<appendAssemblyId>false</appendAssemblyId>
|
||||
<finalName>obp-http4s-runner</finalName>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>make-fat-jar</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>single</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
5
pom.xml
5
pom.xml
@ -15,6 +15,7 @@
|
||||
<akka.version>2.5.32</akka.version>
|
||||
<avro.version>1.8.2</avro.version>
|
||||
<lift.version>3.5.0</lift.version>
|
||||
<http4s.version>0.23.30</http4s.version>
|
||||
<jetty.version>9.4.50.v20221201</jetty.version>
|
||||
<obp-ri.version>2016.11-RC6-SNAPSHOT</obp-ri.version>
|
||||
<!-- Common plugin settings -->
|
||||
@ -34,6 +35,7 @@
|
||||
<modules>
|
||||
<module>obp-commons</module>
|
||||
<module>obp-api</module>
|
||||
<module>obp-http4s-runner</module>
|
||||
</modules>
|
||||
|
||||
<repositories>
|
||||
@ -126,7 +128,7 @@
|
||||
<plugin>
|
||||
<groupId>net.alchim31.maven</groupId>
|
||||
<artifactId>scala-maven-plugin</artifactId>
|
||||
<version>4.3.1</version>
|
||||
<version>4.8.1</version>
|
||||
<configuration>
|
||||
<scalaVersion>${scala.compiler}</scalaVersion>
|
||||
<charset>${project.build.sourceEncoding}</charset>
|
||||
@ -143,6 +145,7 @@
|
||||
<arg>-verbose</arg>
|
||||
<arg>-deprecation</arg>
|
||||
-->
|
||||
<arg>-Ypartial-unification</arg>
|
||||
</args>
|
||||
</configuration>
|
||||
<executions>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user