diff --git a/obp-api/pom.xml b/obp-api/pom.xml
index 5f62fa3a73..66bf746e62 100644
--- a/obp-api/pom.xml
+++ b/obp-api/pom.xml
@@ -20,11 +20,6 @@
obp-commons
-
- com.github.everit-org.json-schema
- org.everit.json.schema
- 1.6.1
-
@@ -41,6 +36,7 @@
net.databinder.dispatch
dispatch-core_${scala.version}
0.13.1
+ test
org.json4s
@@ -121,21 +117,20 @@
protobuf-java
3.25.5
-
+
+ org.apache.avro
+ avro
+ ${apache.avro.version}
+
+
org.xerial.snappy
snappy-java
1.1.10.4
-
-
- commons-beanutils
- commons-beanutils
- 1.11.0
-
-
+
com.vladsch.flexmark
flexmark-profile-pegdown
0.40.8
-
-
- com.vladsch.flexmark
- flexmark-util-options
- 0.64.0
-
+
org.web3j
@@ -422,6 +407,7 @@
org.asynchttpclient
async-http-client
2.15.0
+ test
javax.activation
@@ -514,11 +500,12 @@
jackson-databind
-
+
- tools.jackson.dataformat
+ com.fasterxml.jackson.dataformat
jackson-dataformat-yaml
- 3.0.4
diff --git a/obp-api/src/main/scala/code/api/dynamic/endpoint/OBPAPIDynamicEndpoint.scala b/obp-api/src/main/scala/code/api/dynamic/endpoint/OBPAPIDynamicEndpoint.scala
index d3dd7b4700..cf2ce89f8e 100644
--- a/obp-api/src/main/scala/code/api/dynamic/endpoint/OBPAPIDynamicEndpoint.scala
+++ b/obp-api/src/main/scala/code/api/dynamic/endpoint/OBPAPIDynamicEndpoint.scala
@@ -28,12 +28,9 @@ package code.api.dynamic.endpoint
import APIMethodsDynamicEndpoint.ImplementationsDynamicEndpoint
import code.api.OBPRestHelper
-import code.api.dynamic.endpoint.helper.DynamicEndpoints
-import code.api.util.{APIUtil, VersionedOBPApis}
+import code.api.util.VersionedOBPApis
import code.util.Helper.MdcLoggable
import com.openbankproject.commons.util.{ApiVersion,ApiVersionStatus}
-import net.liftweb.common.{Box, Full}
-import org.apache.http.HttpStatus
/*
This file defines which endpoints from all the versions are available in v4.0.0
diff --git a/obp-api/src/main/scala/code/api/dynamic/entity/projection/ProjectionDualWrite.scala b/obp-api/src/main/scala/code/api/dynamic/entity/projection/ProjectionDualWrite.scala
index d59fb43ab9..b9420802ed 100644
--- a/obp-api/src/main/scala/code/api/dynamic/entity/projection/ProjectionDualWrite.scala
+++ b/obp-api/src/main/scala/code/api/dynamic/entity/projection/ProjectionDualWrite.scala
@@ -9,13 +9,13 @@ import org.json4s.JsonAST.JObject
/**
* Keeps a record's projection row in sync on the write path (DE_indexing, Phase 3). Guarded by
* `projectionEnabled` and a no-op unless the entity has a `ready` projection — so it changes nothing
- * by default. Uses `DoobieUtil.runQuery`, which reuses Lift's request connection, so the projection
- * upsert/delete participates in the SAME transaction as the canonical blob write (commit/rollback
- * together). Scalar fields only (spatial dual-write is Phase 4).
+ * by default. Uses `DoobieUtil.runUpdate` so the INSERT is committed even when called outside an
+ * explicit request-scope transaction (e.g. dynamic-entity POST handlers that don't wrap in
+ * `withBusinessDBTransaction`). When a request-scope proxy IS present, `runUpdate` still reuses it
+ * via `transactorFromConnection`. Scalar fields only (spatial dual-write is Phase 4).
*/
object ProjectionDualWrite extends MdcLoggable {
- /** Upsert the record's ready indexed scalar columns into the projection (called after the blob save). */
def onSave(bankId: Option[String], entityName: String, dataId: String, body: JObject): Unit =
withReadyScalarFields(bankId, entityName) { (safeTable, fields) =>
val cols = fields.map { case (f, spec) =>
@@ -24,13 +24,12 @@ object ProjectionDualWrite extends MdcLoggable {
ProjectionDDL.sqlColumnType(spec.fieldType.toString),
ProjectionCoerce.toColumnValue(body \ f, spec.fieldType))
}
- DoobieUtil.runQuery(ProjectionStore.upsert(safeTable, dataId, cols))
+ DoobieUtil.runUpdate(ProjectionStore.upsert(safeTable, dataId, cols))
}
- /** Delete the record's projection row (called after the blob delete; FK cascade is a backstop). */
def onDelete(bankId: Option[String], entityName: String, dataId: String): Unit =
withReadyScalarFields(bankId, entityName) { (safeTable, _) =>
- DoobieUtil.runQuery(ProjectionStore.delete(safeTable, dataId))
+ DoobieUtil.runUpdate(ProjectionStore.delete(safeTable, dataId))
}
private def withReadyScalarFields(bankId: Option[String], entityName: String)
diff --git a/obp-api/src/main/scala/code/api/util/APIUtil.scala b/obp-api/src/main/scala/code/api/util/APIUtil.scala
index fe93b9a8d1..8daef9ec2d 100644
--- a/obp-api/src/main/scala/code/api/util/APIUtil.scala
+++ b/obp-api/src/main/scala/code/api/util/APIUtil.scala
@@ -1416,34 +1416,12 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{
//ended -- Filtering and Paging relevant methods ////////////////////////////
- /** Import this object's methods to add signing operators to dispatch.Request */
object OAuth {
- import dispatch.{Req => Request}
-
- import scala.collection.Map
-
case class Consumer(key: String, secret: String)
case class Token(value: String, secret: String)
/** Out-of-band callback code */
val oob = "oob"
-
- /** Add OAuth operators to dispatch.Request */
- implicit def Request2RequestSigner(r: Request) = new RequestSigner(r)
-
- class RequestSigner(rb: Request) {
- /** sign a request with a consumer and a token, e.g. an OAuth-signed API request */
- def <@ (consumer: Consumer, token: Token): Request = {
- rb <:< Map("Authorization" -> s"""DirectLogin token="${token.value}"""")
- }
- def <@ (consumerAndToken: Option[(Consumer,Token)]): Request = {
- consumerAndToken match {
- case Some((_, token)) =>
- rb <:< Map("Authorization" -> s"""DirectLogin token="${token.value}"""")
- case None => rb
- }
- }
- }
}
/*
diff --git a/obp-api/src/main/scala/code/api/util/JwtUtil.scala b/obp-api/src/main/scala/code/api/util/JwtUtil.scala
index edaa27069d..3aec89156e 100644
--- a/obp-api/src/main/scala/code/api/util/JwtUtil.scala
+++ b/obp-api/src/main/scala/code/api/util/JwtUtil.scala
@@ -15,7 +15,6 @@ import com.nimbusds.jose.util.{DefaultResourceRetriever, JSONObjectUtils}
import com.nimbusds.jwt.proc.{BadJWTException, DefaultJWTProcessor}
import com.nimbusds.jwt.{JWTClaimsSet, SignedJWT}
import com.nimbusds.openid.connect.sdk.claims.IDTokenClaimsSet
-import dispatch.Future
import net.liftweb.common.{Box, Empty, Failure, Full}
object JwtUtil extends MdcLoggable {
diff --git a/obp-api/src/main/scala/code/bankconnectors/AvroSerializer.scala b/obp-api/src/main/scala/code/bankconnectors/AvroSerializer.scala
index 8dec75f379..9d75703790 100644
--- a/obp-api/src/main/scala/code/bankconnectors/AvroSerializer.scala
+++ b/obp-api/src/main/scala/code/bankconnectors/AvroSerializer.scala
@@ -5,37 +5,34 @@ import java.io.{ByteArrayOutputStream, InputStream}
import com.sksamuel.avro4s._
import scala.concurrent.{ExecutionContext, Future}
-import scala.util.Try
+import scala.util.Success
-/**
- * Provides generic serialization/deserialization
- */
trait AvroSerializer {
- def serialize[T: SchemaFor : ToRecord](event: T)(implicit executionContext: ExecutionContext): String = {
+ def serialize[T: Encoder](event: T)(implicit executionContext: ExecutionContext): String = {
val baos = new ByteArrayOutputStream()
- val output = AvroOutputStream.json[T](baos)
+ val output = AvroOutputStream.json[T].to(baos).build()
output.write(event)
output.close()
- val r = baos.toString("UTF-8")
- r
+ baos.toString("UTF-8")
}
- def serializeFuture[T: SchemaFor : ToRecord](event: T)(implicit executionContext: ExecutionContext): Future[String] =
+ def serializeFuture[T: Encoder](event: T)(implicit executionContext: ExecutionContext): Future[String] =
Future(serialize(event))
- def deserializeFuture[T >: Null : SchemaFor : FromRecord](data: String)(implicit executionContext: ExecutionContext): Future[Option[T]] =
+ def deserializeFuture[T >: Null : Decoder](data: String)(implicit executionContext: ExecutionContext): Future[Option[T]] =
Future(deserialize[T](data))
- def deserialize[T >: Null : SchemaFor : FromRecord](data: String)(implicit executionContext: ExecutionContext): Option[T] = {
-
- val input = AvroInputStream.json[T](new StringInputStream(data))
- val result: Try[T] = input.singleEntity
- result.toOption
+ def deserialize[T >: Null : Decoder](data: String)(implicit executionContext: ExecutionContext): Option[T] = {
+ val schema = implicitly[Decoder[T]].schema
+ val input = AvroInputStream.json[T].from(new StringInputStream(data)).build(schema)
+ val result = input.tryIterator.collectFirst { case Success(v) => v }
+ input.close()
+ result
}
class StringInputStream(s: String) extends InputStream {
- private val bytes = s.getBytes
+ private val bytes = s.getBytes("UTF-8")
private var pos = 0
@@ -44,7 +41,7 @@ trait AvroSerializer {
} else {
val r = bytes(pos)
pos += 1
- r.toInt
+ r.toInt & 0xFF
}
}
-}
\ No newline at end of file
+}
diff --git a/obp-api/src/main/scala/code/bankconnectors/akka/AkkaConnector_vDec2018.scala b/obp-api/src/main/scala/code/bankconnectors/akka/AkkaConnector_vDec2018.scala
index 0443a26d75..89c163e8c1 100644
--- a/obp-api/src/main/scala/code/bankconnectors/akka/AkkaConnector_vDec2018.scala
+++ b/obp-api/src/main/scala/code/bankconnectors/akka/AkkaConnector_vDec2018.scala
@@ -18,7 +18,6 @@ import com.openbankproject.commons.dto._
import com.openbankproject.commons.model._
import com.openbankproject.commons.model.enums.StrongCustomerAuthenticationStatus.SCAStatus
import com.openbankproject.commons.model.enums.{AccountAttributeType, CardAttributeType, ChallengeType, CustomerAttributeType, ProductAttributeType, StrongCustomerAuthentication, TransactionAttributeType, TransactionRequestStatus}
-import com.sksamuel.avro4s.SchemaFor
import net.liftweb.common.{Box, Full}
import com.openbankproject.commons.util.JsonAliases.parse
@@ -55,8 +54,8 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit {
inboundStatus,
inboundAdapterInfoInternal)
),
- outboundAvroSchema = Some(parse(SchemaFor[OutBoundGetAdapterInfo]().toString(true))),
- inboundAvroSchema = Some(parse(SchemaFor[InBoundGetAdapterInfo]().toString(true))),
+ outboundAvroSchema = None,
+ inboundAvroSchema = None,
adapterImplementation = Some(AdapterImplementation("- Core", 1))
)
override def getAdapterInfo(callContext: Option[CallContext]): Future[Box[(InboundAdapterInfoInternal, Option[CallContext])]] = {
@@ -81,8 +80,8 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit {
List(bankCommons)
)
),
- outboundAvroSchema = Some(parse(SchemaFor[OutBoundGetBanks]().toString(true))),
- inboundAvroSchema = Some(parse(SchemaFor[InBoundGetBanks]().toString(true))),
+ outboundAvroSchema = None,
+ inboundAvroSchema = None,
adapterImplementation = Some(AdapterImplementation("- Core", 2))
)
@@ -110,8 +109,8 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit {
bankCommons
)
),
- outboundAvroSchema = Some(parse(SchemaFor[OutBoundGetBank]().toString(true))),
- inboundAvroSchema = Some(parse(SchemaFor[InBoundGetBank]().toString(true))),
+ outboundAvroSchema = None,
+ inboundAvroSchema = None,
adapterImplementation = Some(AdapterImplementation("- Core", 5))
)
override def getBank(bankId : BankId, callContext: Option[CallContext]): Future[Box[(Bank, Option[CallContext])]] = {
diff --git a/obp-api/src/main/scala/code/search/search.scala b/obp-api/src/main/scala/code/search/search.scala
index 6ef39c75a9..6849ac71ae 100644
--- a/obp-api/src/main/scala/code/search/search.scala
+++ b/obp-api/src/main/scala/code/search/search.scala
@@ -1,7 +1,6 @@
package code.search
import org.json4s._
-import java.nio.charset.Charset
import java.util.Date
import code.api.util.APIUtil
@@ -9,18 +8,19 @@ import code.api.util.ErrorMessages._
import code.util.Helper.MdcLoggable
import com.sksamuel.elastic4s.http.JavaClient
import com.sksamuel.elastic4s.{ElasticClient, ElasticProperties}
-import dispatch.Defaults._
-import dispatch.{Http, url, _}
import net.liftweb.common.{Box, Empty, Failure, Full}
import com.openbankproject.commons.util.json
+import okhttp3.{MediaType => OkMediaType, OkHttpClient, Request => OkRequest, RequestBody}
import org.json4s.JsonAST
-import scala.concurrent.Await
+import scala.concurrent.{Await, ExecutionContext, Future, Promise}
import scala.concurrent.duration.Duration
import scala.util.control.NoStackTrace
class elasticsearch extends MdcLoggable {
+ private implicit val ec: ExecutionContext = ExecutionContext.global
+
case class APIResponse(code: Int, body: JValue)
case class ErrorMessage(error: String)
@@ -32,6 +32,8 @@ class elasticsearch extends MdcLoggable {
val esType = ""
val esIndex = ""
+ private val httpClient = new OkHttpClient()
+ private val jsonMediaType = OkMediaType.parse("application/json; charset=UTF-8")
def isEnabled(): Boolean = {
APIUtil.getPropsAsBoolValue("allow_elasticsearch", false)
@@ -39,8 +41,8 @@ class elasticsearch extends MdcLoggable {
def searchProxy(userId: String, queryString: String): JValue = {
if (APIUtil.getPropsAsBoolValue("allow_elasticsearch", false)) {
- val request = constructQuery(userId, getParameters(queryString))
- getAPIResponse(request).body
+ val esUrl = constructQuery(userId, getParameters(queryString))
+ getAPIResponse(esUrl).body
} else {
json.JsonParser.parse("""{"error":"elasticsearch disabled"}""")
}
@@ -52,27 +54,22 @@ class elasticsearch extends MdcLoggable {
val esUrl = s"${httpHost}${uri.replaceAll("\"", "")}"
logger.info(s"searchProxyV300 says esUrl is: $esUrl")
logger.info(s"searchProxyV300 says body is: $body")
- val request: Req = (url(esUrl).<<(body).GET).setContentType("application/json", Charset.forName("UTF-8"))
- val response = getAPIResponse(request)
+ val response = getAPIResponse(esUrl, body)
if (statsOnly) Full(privacyCheckStatistics(response.body))
else Full(response.body)
} else {
Full(json.JsonParser.parse("""{"error":"elasticsearch disabled"}"""))
}
}
+
def searchProxyAsyncV300(userId: String, uri: String, body: String, statsOnly: Boolean = false): Future[APIResponse] = {
- val httpHost = ("http://" + esHost + ":" + esPortHTTP)
- val esUrl = s"${httpHost}${uri.replaceAll("\"" , "")}"
- logger.info(s"searchProxyAsyncV300 says esUrl is: $esUrl")
- logger.info(s"searchProxyAsyncV300 says body is: $body")
- val request: Req = (url(esUrl).<<(body).GET).setContentType("application/json", Charset.forName("UTF-8")) // Note that WE ONLY do GET - Keep it this way!
- logger.info(s"searchProxyAsyncV300 says request I will send to ES is: ${request.toRequest.toString}")
- val response = getAPIResponseAsync(request)
- logger.info (s"searchProxyAsyncV300 says response follows:")
-
- response foreach {
- msg => logger.info(msg.body)
- }
+ val httpHost = "http://" + esHost + ":" + esPortHTTP
+ val esUrl = s"${httpHost}${uri.replaceAll("\"", "")}"
+ logger.info(s"searchProxyAsyncV300 says esUrl is: $esUrl")
+ logger.info(s"searchProxyAsyncV300 says body is: $body")
+ val response = getAPIResponseAsync(esUrl, body)
+ logger.info(s"searchProxyAsyncV300 says response follows:")
+ response foreach { msg => logger.info(msg.body) }
response
}
@@ -81,21 +78,20 @@ class elasticsearch extends MdcLoggable {
else response.body
}
-
def searchProxyStatsV300(userId: String, uriPart: String, bodyPart: String, field: String): Box[JValue] =
searchProxyV300(userId, uriPart, addAggregation(bodyPart, field), statsOnly = true)
- def searchProxyStatsAsyncV300(userId: String, uriPart: String, bodyPart:String, field: String): Future[APIResponse] = {
- searchProxyAsyncV300(userId, uriPart, addAggregation(bodyPart,field), true)
- }
+
+ def searchProxyStatsAsyncV300(userId: String, uriPart: String, bodyPart: String, field: String): Future[APIResponse] =
+ searchProxyAsyncV300(userId, uriPart, addAggregation(bodyPart, field), true)
private def addAggregation(bodyPart: String, field: String): String = {
- bodyPart.dropRight(1).concat(",\"aggs\":{\"" + field + "\":{\"stats\":{\"field\":\""+ field + "\"}}}}")
+ bodyPart.dropRight(1).concat(",\"aggs\":{\"" + field + "\":{\"stats\":{\"field\":\"" + field + "\"}}}}")
}
-
+
private def extractStatistics(body: JValue): JValue = {
- body \ "aggregations"
+ body \ "aggregations"
}
-
+
private def privacyCheckStatistics(body: JValue): JValue = {
println("Enter privacyCheckStatistics")
logger.debug(body)
@@ -104,21 +100,40 @@ class elasticsearch extends MdcLoggable {
if (count > 9) result
else json.JsonParser.parse("{\"error\": \"" + NotEnoughtSearchStatisticsResults + "\"}")
}
-
- private def getAPIResponse(req: Req): APIResponse = {
- Await.result(
- getAPIResponseAsync(req)
- , Duration.Inf)
+
+ private def getAPIResponse(esUrl: String, body: String = ""): APIResponse = {
+ Await.result(getAPIResponseAsync(esUrl, body), Duration.Inf)
}
- private def getAPIResponseAsync(req: Req): Future[APIResponse] = {
- for (response <- Http.default(req > as.Response(p => p)))
- yield {
- val body = if (response.getResponseBody().isEmpty) "{}" else response.getResponseBody()
- APIResponse(response.getStatusCode, json.parse(body))
+ private def getAPIResponseAsync(esUrl: String, body: String = ""): Future[APIResponse] = {
+ val promise = Promise[APIResponse]()
+ val request = buildRequest(esUrl, body)
+ httpClient.newCall(request).enqueue(new okhttp3.Callback {
+ override def onFailure(call: okhttp3.Call, e: java.io.IOException): Unit =
+ promise.failure(e)
+ override def onResponse(call: okhttp3.Call, response: okhttp3.Response): Unit = {
+ try {
+ val bodyStr = Option(response.body()).map(_.string()).filter(_.nonEmpty).getOrElse("{}")
+ promise.success(APIResponse(response.code(), json.parse(bodyStr)))
+ } catch {
+ case e: Throwable => promise.failure(e)
+ } finally {
+ response.close()
+ }
}
+ })
+ promise.future
}
+ private def buildRequest(esUrl: String, body: String): OkRequest =
+ if (body.nonEmpty)
+ new OkRequest.Builder()
+ .url(esUrl)
+ .post(RequestBody.create(jsonMediaType, body))
+ .build()
+ else
+ new OkRequest.Builder().url(esUrl).get().build()
+
private def appendParams(url: String, params: Seq[(String, String)]): String = {
def encode(s: String) = java.net.URLEncoder.encode(s, "UTF-8")
params.toList match {
@@ -129,16 +144,14 @@ class elasticsearch extends MdcLoggable {
}
}
- private def constructQuery(userId: String, params: Map[String, String]): Req = {
+ private def constructQuery(userId: String, params: Map[String, String]): String = {
var esScroll = ""
val esType = params.getOrElse("esType", "")
val q = params.getOrElse("q", "")
- val source = params.getOrElse("source","")
- //val jsonQuery = Json.encode(filteredParams)
- //TODO: Workaround - HTTP and TCP ports differ. Should there be props entry for both?
- val httpHost = ("http://" + esHost + ":" + esPortHTTP)
+ val source = params.getOrElse("source", "")
+ val httpHost = "http://" + esHost + ":" + esPortHTTP
- var parameters = Seq[(String,String)]()
+ var parameters = Seq[(String, String)]()
if (q != "") {
parameters = parameters ++ Seq(("q", q))
val size = params.getOrElse("size", "")
@@ -148,46 +161,34 @@ class elasticsearch extends MdcLoggable {
val scroll = params.getOrElse("scroll", "")
val scroll_id = params.getOrElse("scroll_id", "")
val search_type = params.getOrElse("search_type", "")
- if (size != "")
- parameters = parameters ++ Seq(("size", size))
- if (sort != "")
- parameters = parameters ++ Seq(("sort", sort))
- if (from != "")
- parameters = parameters ++ Seq(("from", from))
- if (df != "")
- parameters = parameters ++ Seq(("df", df))
- if (scroll != "")
- parameters = parameters ++ Seq(("scroll", scroll))
- if (search_type != "")
- parameters = parameters ++ Seq(("search_type", search_type))
- // scroll needs specific URL
+ if (size != "") parameters = parameters ++ Seq(("size", size))
+ if (sort != "") parameters = parameters ++ Seq(("sort", sort))
+ if (from != "") parameters = parameters ++ Seq(("from", from))
+ if (df != "") parameters = parameters ++ Seq(("df", df))
+ if (scroll != "") parameters = parameters ++ Seq(("scroll", scroll))
+ if (search_type != "") parameters = parameters ++ Seq(("search_type", search_type))
if (scroll_id != "" && scroll != "") {
esScroll = "/scroll"
parameters = Seq(("scroll", scroll)) ++ Seq(("scroll_id", scroll_id))
}
- }
- else if (q == "" && source != "") {
+ } else if (q == "" && source != "") {
parameters = Seq(("source", source))
}
- val esUrl = appendParams( s"${httpHost}/${esIndex}/${esType}${if (esType.nonEmpty) "/" else ""}_search${esScroll}", parameters )
- //println("[ES.URL]===> " + esUrl)
- // Use this incase we cant log to elastic search
+ val esUrl = appendParams(
+ s"${httpHost}/${esIndex}/${esType}${if (esType.nonEmpty) "/" else ""}_search${esScroll}",
+ parameters
+ )
logger.info(s"esUrl is $esUrl parameters are $parameters user_id is $userId")
-
- url(esUrl).GET
+ esUrl
}
private def getParameters(queryString: String): Map[String, String] = {
- val res = queryString.split('&').map { str =>
- val pair = str.split('=')
- if (pair.length > 1)
- (pair(0) -> pair(1))
- else
- (pair(0) -> "")
+ queryString.split('&').map { str =>
+ val pair = str.split('=')
+ if (pair.length > 1) (pair(0) -> pair(1))
+ else (pair(0) -> "")
}.toMap
-
- res
}
def createElasticSearchUriPart(index: String, topic: String): String = {
@@ -195,15 +196,14 @@ class elasticsearch extends MdcLoggable {
val realIndex =
if (index == "" || index == "ALL") APIUtil.getPropsValue("es.warehouse.allowed.indices").getOrElse(throw new RuntimeException)
else index
- if (! realIndex.split(",").toSet.subsetOf(validIndices)) throw new RuntimeException() with NoStackTrace
+ if (!realIndex.split(",").toSet.subsetOf(validIndices)) throw new RuntimeException() with NoStackTrace
val addTopic = if (topic == "ALL") "" else "/" + topic
"/" + realIndex + addTopic + "/_search"
}
def getElasticSearchUri(indexString: String): Box[String] = {
val validIndices: List[String] = APIUtil.getPropsValue("es.warehouse.allowed.indices").getOrElse(
- throw new RuntimeException(NoValidElasticsearchIndicesConfigured) with NoStackTrace).split(",").toList match
- {
+ throw new RuntimeException(NoValidElasticsearchIndicesConfigured) with NoStackTrace).split(",").toList match {
case List("ALL") => List("")
case x => x
}
@@ -214,12 +214,12 @@ class elasticsearch extends MdcLoggable {
}
}
- def checkIndicesValidity(indexString: String, validIndices: List[String]): Box[String] ={
+ def checkIndicesValidity(indexString: String, validIndices: List[String]): Box[String] = {
indexString match {
case "ALL" => Empty
case x => x match {
case y if !y.split(",").toSet.subsetOf(validIndices.toSet) => Failure("")
- case y => Full(y)
+ case y => Full(y)
}
}
}
@@ -237,9 +237,8 @@ class elasticsearchMetrics extends elasticsearch {
val props = ElasticProperties(s"http://$esHost:${esPortTCP.toInt}")
lazy val client = ElasticClient(JavaClient(props))
- // we must import the dsl
import com.sksamuel.elastic4s.ElasticDsl._
-
+
if (APIUtil.getPropsAsBoolValue("allow_elasticsearch", false) && APIUtil.getPropsAsBoolValue("allow_elasticsearch_metrics", false) ) {
try {
client.execute {
@@ -264,7 +263,6 @@ class elasticsearchMetrics extends elasticsearch {
def indexMetric(userId: String, url: String, date: Date, duration: Long, userName: String, appName: String, developerEmail: String, correlationId: String, apiInstanceId: String) {
if (APIUtil.getPropsAsBoolValue("allow_elasticsearch", false) && APIUtil.getPropsAsBoolValue("allow_elasticsearch_metrics", false) ) {
try {
- // we must import the dsl
import com.sksamuel.elastic4s.ElasticDsl._
client.execute {
indexInto(s"$esIndex/request") fields (
@@ -296,10 +294,6 @@ class elasticsearchWarehouse extends elasticsearch {
val props = ElasticProperties(s"http://$esHost:${esPortTCP.toInt}")
var client: ElasticClient = null
if (APIUtil.getPropsAsBoolValue("allow_elasticsearch", false) && APIUtil.getPropsAsBoolValue("allow_elasticsearch_warehouse", false) ) {
- //this is not used in the current code, first comment to solve the vulnerability issue
- // val settings = Settings.builder().put("cluster.name", APIUtil.getPropsValue("es.cluster.name", "elasticsearch")).build()
client = ElasticClient(JavaClient(props))
}
}
-
-
diff --git a/obp-api/src/test/scala/code/api/v1_4_0/JSONFactory1_4_0Test.scala b/obp-api/src/test/scala/code/api/v1_4_0/JSONFactory1_4_0Test.scala
index a0c44cc42f..c8072481a9 100644
--- a/obp-api/src/test/scala/code/api/v1_4_0/JSONFactory1_4_0Test.scala
+++ b/obp-api/src/test/scala/code/api/v1_4_0/JSONFactory1_4_0Test.scala
@@ -12,8 +12,8 @@ import code.api.v1_2_1.OBPAPI1_2_1
import org.json4s.Extraction.decompose
import org.json4s._
import com.openbankproject.commons.util.JsonAliases._
-import org.everit.json.schema.loader.SchemaLoader
-import org.json.JSONObject
+import com.fasterxml.jackson.databind.ObjectMapper
+import com.networknt.schema.{JsonSchemaFactory, SpecVersion}
import scala.collection.mutable;
@@ -154,15 +154,17 @@ class JSONFactory1_4_0Test extends code.setup.ServerSetup {
scenario("validate all the resourceDocs json schema, no exception is good enough") {
val resourceDocsRaw= OBPAPI3_0_0.allResourceDocs
val resourceDocs = JSONFactory1_4_0.createResourceDocsJson(resourceDocsRaw.toList,false, None)
+ val mapper = new ObjectMapper()
+ val schemaFactory = JsonSchemaFactory.getInstance(SpecVersion.VersionFlag.V4)
for{
resourceDoc <- resourceDocs.resource_docs if (resourceDoc.request_verb != "DELETE")
json <- List(compactRender(decompose(resourceDoc.success_response_body)))
jsonSchema <- List(compactRender(resourceDoc.typed_success_response_body))
} yield {
- val rawSchema = new JSONObject(jsonSchema)
- val schema = SchemaLoader.load(rawSchema)
- schema.validate(new JSONObject(json))
+ val schema = schemaFactory.getSchema(mapper.readTree(jsonSchema))
+ val errors = schema.validate(mapper.readTree(json))
+ assert(errors.isEmpty, s"JSON Schema validation failed: ${errors}")
}
}
diff --git a/obp-api/src/test/scala/code/setup/SendServerRequests.scala b/obp-api/src/test/scala/code/setup/SendServerRequests.scala
index 1cac46e50e..7b8d5b30c4 100644
--- a/obp-api/src/test/scala/code/setup/SendServerRequests.scala
+++ b/obp-api/src/test/scala/code/setup/SendServerRequests.scala
@@ -57,7 +57,21 @@ case class APIResponse(code: Int, body: JValue, headers: Option[HttpHeaders])
trait SendServerRequests {
TimeZone.setDefault(TimeZone.getTimeZone("UTC"))
-
+
+ import code.api.util.APIUtil.OAuth.{Consumer, Token}
+
+ implicit def Request2RequestSigner(r: Req): RequestSigner = new RequestSigner(r)
+
+ class RequestSigner(rb: Req) {
+ def <@(consumer: Consumer, token: Token): Req =
+ rb <:< Map("Authorization" -> s"""DirectLogin token="${token.value}"""")
+ def <@(consumerAndToken: Option[(Consumer, Token)]): Req =
+ consumerAndToken match {
+ case Some((_, token)) => rb <:< Map("Authorization" -> s"""DirectLogin token="${token.value}"""")
+ case None => rb
+ }
+ }
+
case class ReqData (
url: String,
method: String,
diff --git a/pom.xml b/pom.xml
index 56e6a0e231..6ecae876c8 100644
--- a/pom.xml
+++ b/pom.xml
@@ -14,7 +14,8 @@
2.12.20
1.1.5
1.1.0
- 1.8.2
+ 4.1.2
+ 1.11.4
v1.0.4
0.23.30
@@ -88,15 +89,13 @@
accessors-smart
2.6.0
-
+
org.json
json
20250107
-
+
commons-validator
commons-validator