From 02448d2f98f1392061d7ce200c7cda25d1e27d97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Thu, 19 Oct 2023 11:03:53 +0200 Subject: [PATCH 1/3] bugfix/Tweak default to date value in order to prevent cache issue --- .../src/main/scala/code/api/cache/Redis.scala | 4 +- .../main/scala/code/api/util/APIUtil.scala | 28 +- .../scala/code/metrics/MappedMetrics.scala | 48 ++- .../scala/code/api/v5_1_0/MetricTest.scala | 329 +++++++++++++++++- .../test/scala/code/util/APIUtilTest.scala | 27 +- 5 files changed, 379 insertions(+), 57 deletions(-) diff --git a/obp-api/src/main/scala/code/api/cache/Redis.scala b/obp-api/src/main/scala/code/api/cache/Redis.scala index b96ec3eb72..c73a106c97 100644 --- a/obp-api/src/main/scala/code/api/cache/Redis.scala +++ b/obp-api/src/main/scala/code/api/cache/Redis.scala @@ -14,8 +14,8 @@ import scala.language.postfixOps object Redis extends MdcLoggable { - val url = APIUtil.getPropsValue("guava.cache.url", "127.0.0.1") - val port = APIUtil.getPropsAsIntValue("guava.cache.port", 6379) + val url = APIUtil.getPropsValue("guava.redis.url", "127.0.0.1") + val port = APIUtil.getPropsAsIntValue("guava.redis.port", 6379) implicit val scalaCache = ScalaCache(RedisCache(url, port)) implicit val flags = Flags(readsEnabled = true, writesEnabled = true) 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 33a5d8f195..d8d05b04aa 100644 --- a/obp-api/src/main/scala/code/api/util/APIUtil.scala +++ b/obp-api/src/main/scala/code/api/util/APIUtil.scala @@ -1115,30 +1115,28 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{ } - def getFromDate(httpParams: List[HTTPParam]): Box[OBPFromDate] = { - val date: Box[Date] = (getHttpValues(httpParams, "from_date"), getHttpValues(httpParams, "obp_from_date")) match { + def getFromDate(httpParams: List[HTTPParam]): Box[OBPQueryParam] = { + val date = (getHttpValues(httpParams, "from_date"), getHttpValues(httpParams, "obp_from_date")) match { case (Full(left),_) => - parseObpStandardDate(left.head) + parseObpStandardDate(left.head).map(OBPFromDate) case (_, Full(right)) => - parseObpStandardDate(right.head) + parseObpStandardDate(right.head).map(OBPFromDate) case _ => - Full(theEpochTime) // Set epoch time. The Unix epoch is 00:00:00 UTC on 1 January 1970. + Full(OBPEmpty()) } - date.map(OBPFromDate(_)) + date } - def getToDate(httpParams: List[HTTPParam]): Box[OBPToDate] = { - val date: Box[Date] = (getHttpValues(httpParams, "to_date"), getHttpValues(httpParams, "obp_to_date")) match { + def getToDate(httpParams: List[HTTPParam]): Box[OBPQueryParam] = { + val date: Box[OBPQueryParam] = (getHttpValues(httpParams, "to_date"), getHttpValues(httpParams, "obp_to_date")) match { case (Full(left),_) => - parseObpStandardDate(left.head) + parseObpStandardDate(left.head).map(OBPToDate) case (_, Full(right)) => - parseObpStandardDate(right.head) - case _ => { - Full(APIUtil.DefaultToDate) - } + parseObpStandardDate(right.head).map(OBPToDate) + case _ => + Full(OBPEmpty()) // Avoid implicitly adding a default value in order to prevent caching issue due to always different to date } - - date.map(OBPToDate(_)) + date } def getOffset(httpParams: List[HTTPParam]): Box[OBPOffset] = { diff --git a/obp-api/src/main/scala/code/metrics/MappedMetrics.scala b/obp-api/src/main/scala/code/metrics/MappedMetrics.scala index 493729270b..5ba9f7cc55 100644 --- a/obp-api/src/main/scala/code/metrics/MappedMetrics.scala +++ b/obp-api/src/main/scala/code/metrics/MappedMetrics.scala @@ -3,7 +3,6 @@ package code.metrics import java.sql.{PreparedStatement, Timestamp} import java.util.Date import java.util.UUID.randomUUID - import code.api.cache.Caching import code.api.util.APIUtil.generateUUID import code.api.util._ @@ -18,6 +17,7 @@ import net.liftweb.mapper.{Index, _} import net.liftweb.util.Helpers.tryo import org.apache.commons.lang3.StringUtils +import java.io.OptionalDataException import scala.collection.immutable import scala.collection.immutable.List import scala.concurrent.Future @@ -236,7 +236,23 @@ object MappedMetrics extends APIMetrics with MdcLoggable{ stmt.setString(startLine+i, excludeFiledValues.toList(i)) } } - + + private def fromDateString(optionalData: Option[Date], fieldName: String) = { + optionalData match { + case None => + "" + case Some(date) => + s"AND $fieldName >= '${new Timestamp(date.getTime)}'" + } + } + private def toDateString(optionalData: Option[Date], fieldName: String) = { + optionalData match { + case None => + "" + case Some(date) => + s"AND $fieldName <= '${new Timestamp(date.getTime)}'" + } + } // TODO Cache this as long as fromDate and toDate are in the past (before now) def getAllAggregateMetricsBox(queryParams: List[OBPQueryParam], isNewVersion: Boolean): Box[List[AggregateMetrics]] = { @@ -248,7 +264,7 @@ object MappedMetrics extends APIMetrics with MdcLoggable{ */ var cacheKey = (randomUUID().toString, randomUUID().toString, randomUUID().toString) CacheKeyFromArguments.buildCacheKey { Caching.memoizeSyncWithProvider(Some(cacheKey.toString()))(cachedAllAggregateMetrics days){ - val fromDate = queryParams.collect { case OBPFromDate(value) => value }.headOption + val fromDate: Option[Date] = queryParams.collect { case OBPFromDate(value) => value }.headOption val toDate = queryParams.collect { case OBPToDate(value) => value }.headOption val consumerId = queryParams.collect { case OBPConsumerId(value) => value }.headOption.flatMap(consumerIdToPrimaryKey) val userId = queryParams.collect { case OBPUserId(value) => value }.headOption @@ -286,9 +302,10 @@ object MappedMetrics extends APIMetrics with MdcLoggable{ val sqlQuery = if(isNewVersion) // in the version, we use includeXxx instead of excludeXxx, the performance should be better. s"""SELECT count(*), avg(duration), min(duration), max(duration) FROM metric - WHERE date_c >= '${new Timestamp(fromDate.get.getTime)}' - AND date_c <= '${new Timestamp(toDate.get.getTime)}' - AND (${trueOrFalse(consumerId.isEmpty)} or consumerid = ${sqlFriendly(consumerId)}) + WHERE + (${trueOrFalse(consumerId.isEmpty)} or consumerid = ${sqlFriendly(consumerId)}) + ${fromDateString(fromDate, "date_c")} + ${toDateString(toDate, "date_c")} AND (${trueOrFalse(userId.isEmpty)} or userid = ${sqlFriendly(userId)}) AND (${trueOrFalse(implementedByPartialFunction.isEmpty)} or implementedbypartialfunction = ${sqlFriendly(implementedByPartialFunction)}) AND (${trueOrFalse(implementedInVersion.isEmpty)} or implementedinversion = ${sqlFriendly(implementedInVersion)}) @@ -305,9 +322,10 @@ object MappedMetrics extends APIMetrics with MdcLoggable{ else s"""SELECT count(*), avg(duration), min(duration), max(duration) FROM metric - WHERE date_c >= '${new Timestamp(fromDate.get.getTime)}' - AND date_c <= '${new Timestamp(toDate.get.getTime)}' - AND (${trueOrFalse(consumerId.isEmpty)} or consumerid = ${sqlFriendly(consumerId)}) + WHERE + (${trueOrFalse(consumerId.isEmpty)} or consumerid = ${sqlFriendly(consumerId)}) + ${fromDateString(fromDate, "date_c")} + ${toDateString(toDate, "date_c")} AND (${trueOrFalse(userId.isEmpty)} or userid = ${sqlFriendly(userId)}) AND (${trueOrFalse(implementedByPartialFunction.isEmpty)} or implementedbypartialfunction = ${sqlFriendly(implementedByPartialFunction)}) AND (${trueOrFalse(implementedInVersion.isEmpty)} or implementedinversion = ${sqlFriendly(implementedInVersion)}) @@ -392,10 +410,10 @@ object MappedMetrics extends APIMetrics with MdcLoggable{ val sqlQuery: String = s"""SELECT ${msSqlLimit} count(*), metric.implementedbypartialfunction, metric.implementedinversion FROM metric - WHERE - date_c >= '${new Timestamp(fromDate.get.getTime)}' AND - date_c <= '${new Timestamp(toDate.get.getTime)}' - AND (${trueOrFalse(consumerId.isEmpty)} or consumerid = ${consumerId.getOrElse("null")}) + WHERE + (${trueOrFalse(consumerId.isEmpty)} or consumerid = ${consumerId.getOrElse("null")}) + ${fromDateString(fromDate, "date_c")} + ${toDateString(toDate, "date_c")} AND (${trueOrFalse(userId.isEmpty)} or userid = ${userId.getOrElse("null")}) AND (${trueOrFalse(implementedByPartialFunction.isEmpty)} or implementedbypartialfunction = ${implementedByPartialFunction.getOrElse("null")}) AND (${trueOrFalse(implementedInVersion.isEmpty)} or implementedinversion = ${implementedInVersion.getOrElse("null")}) @@ -475,8 +493,8 @@ object MappedMetrics extends APIMetrics with MdcLoggable{ consumer.developeremail as email, consumer.consumerid as consumerid FROM metric, consumer WHERE metric.appname = consumer.name - AND date_c >= '${new Timestamp(fromDate.get.getTime)}' - AND date_c <= '${new Timestamp(toDate.get.getTime)}' + ${fromDateString(fromDate, "date_c")} + ${toDateString(toDate, "date_c")} AND (${trueOrFalse(consumerId.isEmpty)} or consumer.consumerid = ${sqlFriendly(consumerId)}) AND (${trueOrFalse(userId.isEmpty)} or userid = ${sqlFriendly(userId)}) AND (${trueOrFalse(implementedByPartialFunction.isEmpty)} or implementedbypartialfunction = ${sqlFriendly(implementedByPartialFunction)}) diff --git a/obp-api/src/test/scala/code/api/v5_1_0/MetricTest.scala b/obp-api/src/test/scala/code/api/v5_1_0/MetricTest.scala index a3a9c96bab..60a0936326 100644 --- a/obp-api/src/test/scala/code/api/v5_1_0/MetricTest.scala +++ b/obp-api/src/test/scala/code/api/v5_1_0/MetricTest.scala @@ -1,8 +1,10 @@ package code.api.v5_1_0 import code.api.util.APIUtil.OAuth._ -import code.api.util.ApiRole.{CanReadAggregateMetrics} +import code.api.util.ApiRole.{CanReadAggregateMetrics, CanReadMetrics} import code.api.util.ErrorMessages.{UserHasMissingRoles, UserNotLoggedIn} +import code.api.v2_1_0.MetricsJson +import code.api.v2_1_0.OBPAPI2_1_0.Implementations2_1_0 import code.api.v3_0_0.AggregateMetricJSON import code.api.v5_1_0.OBPAPI5_1_0.Implementations5_1_0 import code.entitlement.Entitlement @@ -21,7 +23,8 @@ class MetricTest extends V510ServerSetup { */ object VersionOfApi extends Tag(ApiVersion.v5_1_0.toString) object ApiEndpoint1 extends Tag(nameOf(Implementations5_1_0.getAggregateMetrics)) - + object ApiEndpoint2 extends Tag(nameOf(Implementations2_1_0.getMetrics)) + feature(s"test $ApiEndpoint1 version $VersionOfApi - Unauthorized access") { scenario("We will call the endpoint without user credentials", ApiEndpoint1, VersionOfApi) { When("We make a request v5.1.0") @@ -361,5 +364,325 @@ class MetricTest extends V510ServerSetup { } } - + + + feature(s"test $ApiEndpoint2 version $VersionOfApi - Authorized access") { + scenario("We will call the endpoint with user credentials and a proper entitlement", ApiEndpoint1, VersionOfApi) { + setPropsValues("write_metrics" -> "true") + Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, CanReadMetrics.toString) + val requestRoot = (v5_1_0_Request / "users" / "current").GET <@ (user1) + makeGetRequest(requestRoot) + makeGetRequest(requestRoot) + makeGetRequest(requestRoot) + val requestBanks = (v5_1_0_Request / "banks").GET <@ (user1) + makeGetRequest(requestBanks) + makeGetRequest(requestBanks) + makeGetRequest(requestBanks) + makeGetRequest(requestBanks) + + { + val requestRoot = (v5_1_0_Request / "users" / "current").GET <@ (user2) + makeGetRequest(requestRoot) + makeGetRequest(requestRoot) + makeGetRequest(requestRoot) + val requestBanks = (v5_1_0_Request / "banks").GET <@ (user2) + makeGetRequest(requestBanks) + makeGetRequest(requestBanks) + makeGetRequest(requestBanks) + makeGetRequest(requestBanks) + } + + { + val requestRoot = (v5_1_0_Request / "users" / "current").GET <@ (user3) + makeGetRequest(requestRoot) + makeGetRequest(requestRoot) + makeGetRequest(requestRoot) + val requestBanks = (v5_1_0_Request / "banks").GET <@ (user3) + makeGetRequest(requestBanks) + makeGetRequest(requestBanks) + makeGetRequest(requestBanks) + makeGetRequest(requestBanks) + } + + When("We make a request v5.1.0") + val request = (v5_1_0_Request / "management" / "metrics").GET <@ (user1) < 25 shouldBe (true) + } + + { + Then("we test the url params") + val request2 = (v5_1_0_Request / "management" / "metrics").GET <@ (user1) < (21) should be(true) + } + { + Then("we test the implemented_in_version params") + val request2 = (v5_1_0_Request / "management" / "metrics").GET <@ (user1) < (21) should be(true) + } + { + Then("we test the verb params") + val request2 = (v5_1_0_Request / "management" / "metrics").GET <@ (user1) < (0) shouldBe (true) + } + + } + } + + } \ No newline at end of file diff --git a/obp-api/src/test/scala/code/util/APIUtilTest.scala b/obp-api/src/test/scala/code/util/APIUtilTest.scala index 3cf517b506..2e09645252 100644 --- a/obp-api/src/test/scala/code/util/APIUtilTest.scala +++ b/obp-api/src/test/scala/code/util/APIUtilTest.scala @@ -38,6 +38,7 @@ import code.setup.PropsReset import com.openbankproject.commons.model.UserAuthContextCommons import net.liftweb.common.{Box, Empty, Full} import net.liftweb.http.provider.HTTPParam +import org.scalatest.matchers.Matcher import org.scalatest.{FeatureSpec, GivenWhenThen, Matchers} class APIUtilTest extends FeatureSpec with Matchers with GivenWhenThen with PropsReset { @@ -237,25 +238,16 @@ class APIUtilTest extends FeatureSpec with Matchers with GivenWhenThen with Prop scenario("test the wrong case: wrong name (wrongName) in HTTPParam") { val httpParams: List[HTTPParam] = List(HTTPParam("wrongName", List(s"$DateWithMsExampleString"))) - val startTime = OBPFromDate(theEpochTime) val returnValue = getFromDate(httpParams) - returnValue.toString should startWith("Full(OBPFromDate") - - val currentTime = OBPFromDate(theEpochTime) - val beWithinTolerance = be >= startTime and be <= currentTime - returnValue.orNull should beWithinTolerance + returnValue.toString should startWith("Full(OBPEmpty") } scenario("test the wrong case: wrong name (wrongName) and wrong values (wrongValue) in HTTPParam") { val httpParams: List[HTTPParam] = List(HTTPParam("wrongName", List("wrongValue"))) - val startTime = OBPFromDate(theEpochTime) val returnValue = getFromDate(httpParams) - returnValue.toString should startWith("Full(OBPFromDate") + returnValue.toString should startWith("Full(OBPEmpty())") - val currentTime = OBPFromDate(theEpochTime) - val beWithinTolerance = be >= startTime and be <= currentTime - returnValue.orNull should beWithinTolerance } } @@ -290,28 +282,19 @@ class APIUtilTest extends FeatureSpec with Matchers with GivenWhenThen with Prop { val httpParams: List[HTTPParam] = List(HTTPParam("wrongName", List(s"$DateWithMsExampleString"))) - val startTime = OBPToDate(DefaultToDate) val returnValue = getToDate(httpParams) - returnValue.toString should startWith("Full(OBPToDate") - - val currentTime = OBPToDate(DefaultToDate) - val beWithinTolerance = be >= startTime and be <= currentTime - returnValue.orNull should beWithinTolerance + returnValue.toString should startWith("Full(OBPEmpty") } scenario(s"test the wrong case: wrong name (wrongName) and wrong values (wrongValue) in HTTPParam") { val httpParams: List[HTTPParam] = List(HTTPParam("wrongName", List("wrongValue"))) - val startTime = OBPToDate(DefaultToDate) val returnValue = getToDate(httpParams) - returnValue.toString should startWith("Full(OBPToDate") + returnValue.toString should startWith("Full(OBPEmpty") - val currentTime = OBPToDate(DefaultToDate) - val beWithinTolerance = be >= startTime and be <= currentTime - returnValue.orNull should beWithinTolerance } } From 2106eff7a387b1914c7c6e1428dfd7d808fd6f48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Thu, 19 Oct 2023 11:35:58 +0200 Subject: [PATCH 2/3] Revert "bugfix/Tweak default to date value in order to prevent cache issue" This reverts commit 02448d2f98f1392061d7ce200c7cda25d1e27d97. --- .../src/main/scala/code/api/cache/Redis.scala | 4 +- .../main/scala/code/api/util/APIUtil.scala | 28 +- .../scala/code/metrics/MappedMetrics.scala | 48 +-- .../scala/code/api/v5_1_0/MetricTest.scala | 329 +----------------- .../test/scala/code/util/APIUtilTest.scala | 27 +- 5 files changed, 57 insertions(+), 379 deletions(-) diff --git a/obp-api/src/main/scala/code/api/cache/Redis.scala b/obp-api/src/main/scala/code/api/cache/Redis.scala index c73a106c97..b96ec3eb72 100644 --- a/obp-api/src/main/scala/code/api/cache/Redis.scala +++ b/obp-api/src/main/scala/code/api/cache/Redis.scala @@ -14,8 +14,8 @@ import scala.language.postfixOps object Redis extends MdcLoggable { - val url = APIUtil.getPropsValue("guava.redis.url", "127.0.0.1") - val port = APIUtil.getPropsAsIntValue("guava.redis.port", 6379) + val url = APIUtil.getPropsValue("guava.cache.url", "127.0.0.1") + val port = APIUtil.getPropsAsIntValue("guava.cache.port", 6379) implicit val scalaCache = ScalaCache(RedisCache(url, port)) implicit val flags = Flags(readsEnabled = true, writesEnabled = true) 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 d8d05b04aa..33a5d8f195 100644 --- a/obp-api/src/main/scala/code/api/util/APIUtil.scala +++ b/obp-api/src/main/scala/code/api/util/APIUtil.scala @@ -1115,28 +1115,30 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{ } - def getFromDate(httpParams: List[HTTPParam]): Box[OBPQueryParam] = { - val date = (getHttpValues(httpParams, "from_date"), getHttpValues(httpParams, "obp_from_date")) match { + def getFromDate(httpParams: List[HTTPParam]): Box[OBPFromDate] = { + val date: Box[Date] = (getHttpValues(httpParams, "from_date"), getHttpValues(httpParams, "obp_from_date")) match { case (Full(left),_) => - parseObpStandardDate(left.head).map(OBPFromDate) + parseObpStandardDate(left.head) case (_, Full(right)) => - parseObpStandardDate(right.head).map(OBPFromDate) + parseObpStandardDate(right.head) case _ => - Full(OBPEmpty()) + Full(theEpochTime) // Set epoch time. The Unix epoch is 00:00:00 UTC on 1 January 1970. } - date + date.map(OBPFromDate(_)) } - def getToDate(httpParams: List[HTTPParam]): Box[OBPQueryParam] = { - val date: Box[OBPQueryParam] = (getHttpValues(httpParams, "to_date"), getHttpValues(httpParams, "obp_to_date")) match { + def getToDate(httpParams: List[HTTPParam]): Box[OBPToDate] = { + val date: Box[Date] = (getHttpValues(httpParams, "to_date"), getHttpValues(httpParams, "obp_to_date")) match { case (Full(left),_) => - parseObpStandardDate(left.head).map(OBPToDate) + parseObpStandardDate(left.head) case (_, Full(right)) => - parseObpStandardDate(right.head).map(OBPToDate) - case _ => - Full(OBPEmpty()) // Avoid implicitly adding a default value in order to prevent caching issue due to always different to date + parseObpStandardDate(right.head) + case _ => { + Full(APIUtil.DefaultToDate) + } } - date + + date.map(OBPToDate(_)) } def getOffset(httpParams: List[HTTPParam]): Box[OBPOffset] = { diff --git a/obp-api/src/main/scala/code/metrics/MappedMetrics.scala b/obp-api/src/main/scala/code/metrics/MappedMetrics.scala index 5ba9f7cc55..493729270b 100644 --- a/obp-api/src/main/scala/code/metrics/MappedMetrics.scala +++ b/obp-api/src/main/scala/code/metrics/MappedMetrics.scala @@ -3,6 +3,7 @@ package code.metrics import java.sql.{PreparedStatement, Timestamp} import java.util.Date import java.util.UUID.randomUUID + import code.api.cache.Caching import code.api.util.APIUtil.generateUUID import code.api.util._ @@ -17,7 +18,6 @@ import net.liftweb.mapper.{Index, _} import net.liftweb.util.Helpers.tryo import org.apache.commons.lang3.StringUtils -import java.io.OptionalDataException import scala.collection.immutable import scala.collection.immutable.List import scala.concurrent.Future @@ -236,23 +236,7 @@ object MappedMetrics extends APIMetrics with MdcLoggable{ stmt.setString(startLine+i, excludeFiledValues.toList(i)) } } - - private def fromDateString(optionalData: Option[Date], fieldName: String) = { - optionalData match { - case None => - "" - case Some(date) => - s"AND $fieldName >= '${new Timestamp(date.getTime)}'" - } - } - private def toDateString(optionalData: Option[Date], fieldName: String) = { - optionalData match { - case None => - "" - case Some(date) => - s"AND $fieldName <= '${new Timestamp(date.getTime)}'" - } - } + // TODO Cache this as long as fromDate and toDate are in the past (before now) def getAllAggregateMetricsBox(queryParams: List[OBPQueryParam], isNewVersion: Boolean): Box[List[AggregateMetrics]] = { @@ -264,7 +248,7 @@ object MappedMetrics extends APIMetrics with MdcLoggable{ */ var cacheKey = (randomUUID().toString, randomUUID().toString, randomUUID().toString) CacheKeyFromArguments.buildCacheKey { Caching.memoizeSyncWithProvider(Some(cacheKey.toString()))(cachedAllAggregateMetrics days){ - val fromDate: Option[Date] = queryParams.collect { case OBPFromDate(value) => value }.headOption + val fromDate = queryParams.collect { case OBPFromDate(value) => value }.headOption val toDate = queryParams.collect { case OBPToDate(value) => value }.headOption val consumerId = queryParams.collect { case OBPConsumerId(value) => value }.headOption.flatMap(consumerIdToPrimaryKey) val userId = queryParams.collect { case OBPUserId(value) => value }.headOption @@ -302,10 +286,9 @@ object MappedMetrics extends APIMetrics with MdcLoggable{ val sqlQuery = if(isNewVersion) // in the version, we use includeXxx instead of excludeXxx, the performance should be better. s"""SELECT count(*), avg(duration), min(duration), max(duration) FROM metric - WHERE - (${trueOrFalse(consumerId.isEmpty)} or consumerid = ${sqlFriendly(consumerId)}) - ${fromDateString(fromDate, "date_c")} - ${toDateString(toDate, "date_c")} + WHERE date_c >= '${new Timestamp(fromDate.get.getTime)}' + AND date_c <= '${new Timestamp(toDate.get.getTime)}' + AND (${trueOrFalse(consumerId.isEmpty)} or consumerid = ${sqlFriendly(consumerId)}) AND (${trueOrFalse(userId.isEmpty)} or userid = ${sqlFriendly(userId)}) AND (${trueOrFalse(implementedByPartialFunction.isEmpty)} or implementedbypartialfunction = ${sqlFriendly(implementedByPartialFunction)}) AND (${trueOrFalse(implementedInVersion.isEmpty)} or implementedinversion = ${sqlFriendly(implementedInVersion)}) @@ -322,10 +305,9 @@ object MappedMetrics extends APIMetrics with MdcLoggable{ else s"""SELECT count(*), avg(duration), min(duration), max(duration) FROM metric - WHERE - (${trueOrFalse(consumerId.isEmpty)} or consumerid = ${sqlFriendly(consumerId)}) - ${fromDateString(fromDate, "date_c")} - ${toDateString(toDate, "date_c")} + WHERE date_c >= '${new Timestamp(fromDate.get.getTime)}' + AND date_c <= '${new Timestamp(toDate.get.getTime)}' + AND (${trueOrFalse(consumerId.isEmpty)} or consumerid = ${sqlFriendly(consumerId)}) AND (${trueOrFalse(userId.isEmpty)} or userid = ${sqlFriendly(userId)}) AND (${trueOrFalse(implementedByPartialFunction.isEmpty)} or implementedbypartialfunction = ${sqlFriendly(implementedByPartialFunction)}) AND (${trueOrFalse(implementedInVersion.isEmpty)} or implementedinversion = ${sqlFriendly(implementedInVersion)}) @@ -410,10 +392,10 @@ object MappedMetrics extends APIMetrics with MdcLoggable{ val sqlQuery: String = s"""SELECT ${msSqlLimit} count(*), metric.implementedbypartialfunction, metric.implementedinversion FROM metric - WHERE - (${trueOrFalse(consumerId.isEmpty)} or consumerid = ${consumerId.getOrElse("null")}) - ${fromDateString(fromDate, "date_c")} - ${toDateString(toDate, "date_c")} + WHERE + date_c >= '${new Timestamp(fromDate.get.getTime)}' AND + date_c <= '${new Timestamp(toDate.get.getTime)}' + AND (${trueOrFalse(consumerId.isEmpty)} or consumerid = ${consumerId.getOrElse("null")}) AND (${trueOrFalse(userId.isEmpty)} or userid = ${userId.getOrElse("null")}) AND (${trueOrFalse(implementedByPartialFunction.isEmpty)} or implementedbypartialfunction = ${implementedByPartialFunction.getOrElse("null")}) AND (${trueOrFalse(implementedInVersion.isEmpty)} or implementedinversion = ${implementedInVersion.getOrElse("null")}) @@ -493,8 +475,8 @@ object MappedMetrics extends APIMetrics with MdcLoggable{ consumer.developeremail as email, consumer.consumerid as consumerid FROM metric, consumer WHERE metric.appname = consumer.name - ${fromDateString(fromDate, "date_c")} - ${toDateString(toDate, "date_c")} + AND date_c >= '${new Timestamp(fromDate.get.getTime)}' + AND date_c <= '${new Timestamp(toDate.get.getTime)}' AND (${trueOrFalse(consumerId.isEmpty)} or consumer.consumerid = ${sqlFriendly(consumerId)}) AND (${trueOrFalse(userId.isEmpty)} or userid = ${sqlFriendly(userId)}) AND (${trueOrFalse(implementedByPartialFunction.isEmpty)} or implementedbypartialfunction = ${sqlFriendly(implementedByPartialFunction)}) diff --git a/obp-api/src/test/scala/code/api/v5_1_0/MetricTest.scala b/obp-api/src/test/scala/code/api/v5_1_0/MetricTest.scala index 60a0936326..a3a9c96bab 100644 --- a/obp-api/src/test/scala/code/api/v5_1_0/MetricTest.scala +++ b/obp-api/src/test/scala/code/api/v5_1_0/MetricTest.scala @@ -1,10 +1,8 @@ package code.api.v5_1_0 import code.api.util.APIUtil.OAuth._ -import code.api.util.ApiRole.{CanReadAggregateMetrics, CanReadMetrics} +import code.api.util.ApiRole.{CanReadAggregateMetrics} import code.api.util.ErrorMessages.{UserHasMissingRoles, UserNotLoggedIn} -import code.api.v2_1_0.MetricsJson -import code.api.v2_1_0.OBPAPI2_1_0.Implementations2_1_0 import code.api.v3_0_0.AggregateMetricJSON import code.api.v5_1_0.OBPAPI5_1_0.Implementations5_1_0 import code.entitlement.Entitlement @@ -23,8 +21,7 @@ class MetricTest extends V510ServerSetup { */ object VersionOfApi extends Tag(ApiVersion.v5_1_0.toString) object ApiEndpoint1 extends Tag(nameOf(Implementations5_1_0.getAggregateMetrics)) - object ApiEndpoint2 extends Tag(nameOf(Implementations2_1_0.getMetrics)) - + feature(s"test $ApiEndpoint1 version $VersionOfApi - Unauthorized access") { scenario("We will call the endpoint without user credentials", ApiEndpoint1, VersionOfApi) { When("We make a request v5.1.0") @@ -364,325 +361,5 @@ class MetricTest extends V510ServerSetup { } } - - - feature(s"test $ApiEndpoint2 version $VersionOfApi - Authorized access") { - scenario("We will call the endpoint with user credentials and a proper entitlement", ApiEndpoint1, VersionOfApi) { - setPropsValues("write_metrics" -> "true") - Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, CanReadMetrics.toString) - val requestRoot = (v5_1_0_Request / "users" / "current").GET <@ (user1) - makeGetRequest(requestRoot) - makeGetRequest(requestRoot) - makeGetRequest(requestRoot) - val requestBanks = (v5_1_0_Request / "banks").GET <@ (user1) - makeGetRequest(requestBanks) - makeGetRequest(requestBanks) - makeGetRequest(requestBanks) - makeGetRequest(requestBanks) - - { - val requestRoot = (v5_1_0_Request / "users" / "current").GET <@ (user2) - makeGetRequest(requestRoot) - makeGetRequest(requestRoot) - makeGetRequest(requestRoot) - val requestBanks = (v5_1_0_Request / "banks").GET <@ (user2) - makeGetRequest(requestBanks) - makeGetRequest(requestBanks) - makeGetRequest(requestBanks) - makeGetRequest(requestBanks) - } - - { - val requestRoot = (v5_1_0_Request / "users" / "current").GET <@ (user3) - makeGetRequest(requestRoot) - makeGetRequest(requestRoot) - makeGetRequest(requestRoot) - val requestBanks = (v5_1_0_Request / "banks").GET <@ (user3) - makeGetRequest(requestBanks) - makeGetRequest(requestBanks) - makeGetRequest(requestBanks) - makeGetRequest(requestBanks) - } - - When("We make a request v5.1.0") - val request = (v5_1_0_Request / "management" / "metrics").GET <@ (user1) < 25 shouldBe (true) - } - - { - Then("we test the url params") - val request2 = (v5_1_0_Request / "management" / "metrics").GET <@ (user1) < (21) should be(true) - } - { - Then("we test the implemented_in_version params") - val request2 = (v5_1_0_Request / "management" / "metrics").GET <@ (user1) < (21) should be(true) - } - { - Then("we test the verb params") - val request2 = (v5_1_0_Request / "management" / "metrics").GET <@ (user1) < (0) shouldBe (true) - } - - } - } - - + } \ No newline at end of file diff --git a/obp-api/src/test/scala/code/util/APIUtilTest.scala b/obp-api/src/test/scala/code/util/APIUtilTest.scala index 2e09645252..3cf517b506 100644 --- a/obp-api/src/test/scala/code/util/APIUtilTest.scala +++ b/obp-api/src/test/scala/code/util/APIUtilTest.scala @@ -38,7 +38,6 @@ import code.setup.PropsReset import com.openbankproject.commons.model.UserAuthContextCommons import net.liftweb.common.{Box, Empty, Full} import net.liftweb.http.provider.HTTPParam -import org.scalatest.matchers.Matcher import org.scalatest.{FeatureSpec, GivenWhenThen, Matchers} class APIUtilTest extends FeatureSpec with Matchers with GivenWhenThen with PropsReset { @@ -238,16 +237,25 @@ class APIUtilTest extends FeatureSpec with Matchers with GivenWhenThen with Prop scenario("test the wrong case: wrong name (wrongName) in HTTPParam") { val httpParams: List[HTTPParam] = List(HTTPParam("wrongName", List(s"$DateWithMsExampleString"))) + val startTime = OBPFromDate(theEpochTime) val returnValue = getFromDate(httpParams) - returnValue.toString should startWith("Full(OBPEmpty") + returnValue.toString should startWith("Full(OBPFromDate") + + val currentTime = OBPFromDate(theEpochTime) + val beWithinTolerance = be >= startTime and be <= currentTime + returnValue.orNull should beWithinTolerance } scenario("test the wrong case: wrong name (wrongName) and wrong values (wrongValue) in HTTPParam") { val httpParams: List[HTTPParam] = List(HTTPParam("wrongName", List("wrongValue"))) + val startTime = OBPFromDate(theEpochTime) val returnValue = getFromDate(httpParams) - returnValue.toString should startWith("Full(OBPEmpty())") + returnValue.toString should startWith("Full(OBPFromDate") + val currentTime = OBPFromDate(theEpochTime) + val beWithinTolerance = be >= startTime and be <= currentTime + returnValue.orNull should beWithinTolerance } } @@ -282,19 +290,28 @@ class APIUtilTest extends FeatureSpec with Matchers with GivenWhenThen with Prop { val httpParams: List[HTTPParam] = List(HTTPParam("wrongName", List(s"$DateWithMsExampleString"))) + val startTime = OBPToDate(DefaultToDate) val returnValue = getToDate(httpParams) - returnValue.toString should startWith("Full(OBPEmpty") + returnValue.toString should startWith("Full(OBPToDate") + + val currentTime = OBPToDate(DefaultToDate) + val beWithinTolerance = be >= startTime and be <= currentTime + returnValue.orNull should beWithinTolerance } scenario(s"test the wrong case: wrong name (wrongName) and wrong values (wrongValue) in HTTPParam") { val httpParams: List[HTTPParam] = List(HTTPParam("wrongName", List("wrongValue"))) + val startTime = OBPToDate(DefaultToDate) val returnValue = getToDate(httpParams) - returnValue.toString should startWith("Full(OBPEmpty") + returnValue.toString should startWith("Full(OBPToDate") + val currentTime = OBPToDate(DefaultToDate) + val beWithinTolerance = be >= startTime and be <= currentTime + returnValue.orNull should beWithinTolerance } } From 4387c806614a167eca67f475508a9150e3740cdf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Thu, 19 Oct 2023 12:22:10 +0200 Subject: [PATCH 3/3] bugfix/Tweak default to date value in order to prevent cache issue --- obp-api/src/main/scala/code/api/util/APIUtil.scala | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 33a5d8f195..7b37e56af4 100644 --- a/obp-api/src/main/scala/code/api/util/APIUtil.scala +++ b/obp-api/src/main/scala/code/api/util/APIUtil.scala @@ -170,6 +170,7 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{ oneYearAgo.add(Calendar.YEAR, -1) oneYearAgo.getTime() } + def ToDateInFuture = new Date(2100, 0, 1) //Sat Jan 01 00:00:00 CET 4000 def DefaultToDate = new Date() def oneYearAgoDate = oneYearAgo(DefaultToDate) val theEpochTime: Date = new Date(0) // Set epoch time. The Unix epoch is 00:00:00 UTC on 1 January 1970. @@ -1134,7 +1135,7 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{ case (_, Full(right)) => parseObpStandardDate(right.head) case _ => { - Full(APIUtil.DefaultToDate) + Full(APIUtil.ToDateInFuture) } }