diff --git a/obp-api/src/main/scala/code/api/v5_1_0/APIMethods510.scala b/obp-api/src/main/scala/code/api/v5_1_0/APIMethods510.scala index 3f2d6c539..8a50c1907 100644 --- a/obp-api/src/main/scala/code/api/v5_1_0/APIMethods510.scala +++ b/obp-api/src/main/scala/code/api/v5_1_0/APIMethods510.scala @@ -486,13 +486,11 @@ trait APIMethods510 { | |11 correlation_id (if null ignore) | - |12 duration (if null ignore) non digit chars will be silently omitted + |12 include_app_names (if null ignore).eg: &include_app_names=API-EXPLORER,API-Manager,SOFI,null | - |13 include_app_names (if null ignore).eg: &include_app_names=API-EXPLORER,API-Manager,SOFI,null + |13 include_url_patterns (if null ignore).you can design you own SQL LIKE pattern. eg: &include_url_patterns=%management/metrics%,%management/aggregate-metrics% | - |14 include_url_patterns (if null ignore).you can design you own SQL LIKE pattern. eg: &include_url_patterns=%management/metrics%,%management/aggregate-metrics% - | - |15 include_implemented_by_partial_functions (if null ignore).eg: &include_implemented_by_partial_functions=getMetrics,getConnectorMetrics,getAggregateMetrics + |14 include_implemented_by_partial_functions (if null ignore).eg: &include_implemented_by_partial_functions=getMetrics,getConnectorMetrics,getAggregateMetrics | |${authenticationRequiredMessage(true)} | diff --git a/obp-api/src/main/scala/code/metrics/MappedMetrics.scala b/obp-api/src/main/scala/code/metrics/MappedMetrics.scala index 0a647fc49..5441cbf3f 100644 --- a/obp-api/src/main/scala/code/metrics/MappedMetrics.scala +++ b/obp-api/src/main/scala/code/metrics/MappedMetrics.scala @@ -299,7 +299,7 @@ object MappedMetrics extends APIMetrics with MdcLoggable{ val includeImplementedByPartialFunctionsList = includeImplementedByPartialFunctions.getOrElse(List("")) val includeUrlPatternsQueries = extendLikeQuery(includeUrlPatternsList, true) - val ordering = sqls"$includeUrlPatternsQueries" + val includeUrlPatternsQueriesSql = sqls"$includeUrlPatternsQueries" val result = scalikeDB readOnly { implicit session => val sqlQuery = if(isNewVersion) // in the version, we use includeXxx instead of excludeXxx, the performance should be better. @@ -316,7 +316,8 @@ object MappedMetrics extends APIMetrics with MdcLoggable{ AND (${trueOrFalse(verb.isEmpty)} or verb = ${verb.getOrElse("")}) AND (${falseOrTrue(anon.isDefined && anon.equals(Some(true)))} or userid = 'null') AND (${falseOrTrue(anon.isDefined && anon.equals(Some(false)))} or userid != 'null') - AND (${trueOrFalse(includeUrlPatterns.isEmpty) } or (url LIKE ($ordering))) + AND (${trueOrFalse(correlationId.isEmpty)} or correlationId = ${correlationId.getOrElse("")}) + AND (${trueOrFalse(includeUrlPatterns.isEmpty) } or (url LIKE ($includeUrlPatternsQueriesSql))) AND (${trueOrFalse(includeAppNames.isEmpty) } or (appname in ($includeAppNamesList))) AND (${trueOrFalse(includeImplementedByPartialFunctions.isEmpty) } or implementedbypartialfunction in ($includeImplementedByPartialFunctionsList)) """.stripMargin @@ -333,7 +334,8 @@ object MappedMetrics extends APIMetrics with MdcLoggable{ AND (${trueOrFalse(appName.isEmpty)} or appname = ${appName.getOrElse("")}) AND (${trueOrFalse(verb.isEmpty)} or verb = ${verb.getOrElse("")}) AND (${falseOrTrue(anon.isDefined && anon.equals(Some(true)))} or userid = 'null') - AND (${falseOrTrue(anon.isDefined && anon.equals(Some(false)))} or userid != 'null') + AND (${falseOrTrue(anon.isDefined && anon.equals(Some(false)))} or userid != 'null') + AND (${trueOrFalse(correlationId.isEmpty)} or correlationId = ${correlationId.getOrElse("")}) AND (${trueOrFalse(excludeUrlPatterns.isEmpty) } or (url NOT LIKE ($excludeUrlPatternsQueries))) AND (${trueOrFalse(excludeAppNames.isEmpty) } or appname not in ($excludeAppNamesList)) AND (${trueOrFalse(excludeImplementedByPartialFunctions.isEmpty) } or implementedbypartialfunction not in ($excludeImplementedByPartialFunctionsList)) 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 new file mode 100644 index 000000000..a3a9c96ba --- /dev/null +++ b/obp-api/src/test/scala/code/api/v5_1_0/MetricTest.scala @@ -0,0 +1,365 @@ +package code.api.v5_1_0 + +import code.api.util.APIUtil.OAuth._ +import code.api.util.ApiRole.{CanReadAggregateMetrics} +import code.api.util.ErrorMessages.{UserHasMissingRoles, UserNotLoggedIn} +import code.api.v3_0_0.AggregateMetricJSON +import code.api.v5_1_0.OBPAPI5_1_0.Implementations5_1_0 +import code.entitlement.Entitlement +import com.github.dwickern.macros.NameOf.nameOf +import com.openbankproject.commons.model.ErrorMessage +import com.openbankproject.commons.util.ApiVersion +import org.scalatest.Tag + +class MetricTest extends V510ServerSetup { + /** + * Test tags + * Example: To run tests with tag "getPermissions": + * mvn test -D tagsToInclude + * + * This is made possible by the scalatest maven plugin + */ + object VersionOfApi extends Tag(ApiVersion.v5_1_0.toString) + object ApiEndpoint1 extends Tag(nameOf(Implementations5_1_0.getAggregateMetrics)) + + 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") + val request = (v5_1_0_Request / "management" / "aggregate-metrics").GET + val response = makeGetRequest(request) + Then("We should get a 401") + response.code should equal(401) + response.body.extract[ErrorMessage].message should equal(UserNotLoggedIn) + } + } + + feature(s"test $ApiEndpoint1 version $VersionOfApi - Authorized access") { + scenario("We will call the endpoint with user credentials but without a proper entitlement", ApiEndpoint1, VersionOfApi) { + When("We make a request v5.1.0") + val request = (v5_1_0_Request / "management" / "aggregate-metrics").GET <@(user1) + val response = makeGetRequest(request) + Then("error should be " + UserHasMissingRoles + CanReadAggregateMetrics) + response.code should equal(403) + response.body.extract[ErrorMessage].message should be (UserHasMissingRoles + CanReadAggregateMetrics) + } + } + + feature(s"test $ApiEndpoint1 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, CanReadAggregateMetrics.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" / "aggregate-metrics").GET<@(user1) < 25 shouldBe (true) + } + + { + Then("we test the url params") + val request2 = (v5_1_0_Request / "management" / "aggregate-metrics").GET <@ (user1) < (21) should be (true) + } + { + Then("we test the implemented_in_version params") + val request2 = (v5_1_0_Request / "management" / "aggregate-metrics").GET <@ (user1) < (21) should be (true) + } + { + Then("we test the verb params") + val request2 = (v5_1_0_Request / "management" / "aggregate-metrics").GET <@ (user1) < (0) shouldBe(true ) + } + + } + } + +} \ No newline at end of file diff --git a/obp-api/src/test/scala/code/setup/DefaultUsers.scala b/obp-api/src/test/scala/code/setup/DefaultUsers.scala index eea1dc21f..d8ac8c3f7 100644 --- a/obp-api/src/test/scala/code/setup/DefaultUsers.scala +++ b/obp-api/src/test/scala/code/setup/DefaultUsers.scala @@ -39,14 +39,53 @@ trait DefaultUsers { key = Some(randomString(40).toLowerCase), secret = Some(randomString(40).toLowerCase), isActive = Some(true), - name = Some("test application"), + name = Some("test1"), appType = None, - description = Some("description"), + description = Some("test1 description"), developerEmail = Some("eveline@example.com"), redirectURL = None, createdByUserId = userId1 ).openOrThrowException(attemptedToOpenAnEmptyBox) lazy val consumer = Consumer(testConsumer.key.get, testConsumer.secret.get) + + lazy val testConsumer2 = Consumers.consumers.vend.createConsumer( + key = Some(randomString(40).toLowerCase), + secret = Some(randomString(40).toLowerCase), + isActive = Some(true), + name = Some("test2"), + appType = None, + description = Some("test2 description"), + developerEmail = Some("eveline@example.com"), + redirectURL = None, + createdByUserId = userId2 + ).openOrThrowException(attemptedToOpenAnEmptyBox) + lazy val consumer2 = Consumer(testConsumer2.key.get, testConsumer2.secret.get) + + lazy val testConsumer3 = Consumers.consumers.vend.createConsumer( + key = Some(randomString(40).toLowerCase), + secret = Some(randomString(40).toLowerCase), + isActive = Some(true), + name = Some("test3"), + appType = None, + description = Some("test3 description"), + developerEmail = Some("eveline@example.com"), + redirectURL = None, + createdByUserId = userId3 + ).openOrThrowException(attemptedToOpenAnEmptyBox) + lazy val consumer3 = Consumer(testConsumer3.key.get, testConsumer3.secret.get) + + lazy val testConsumer4 = Consumers.consumers.vend.createConsumer( + key = Some(randomString(40).toLowerCase), + secret = Some(randomString(40).toLowerCase), + isActive = Some(true), + name = Some("test4"), + appType = None, + description = Some("test4 description"), + developerEmail = Some("eveline@example.com"), + redirectURL = None, + createdByUserId = userId4 + ).openOrThrowException(attemptedToOpenAnEmptyBox) + lazy val consumer4 = Consumer(testConsumer4.key.get, testConsumer4.secret.get) // create the access token val expiration = APIUtil.getPropsAsIntValue("token_expiration_weeks", 4) @@ -93,7 +132,7 @@ trait DefaultUsers { lazy val testToken2 = Tokens.tokens.vend.createToken( Access, - Some(testConsumer.id.get), + Some(testConsumer2.id.get), Some(resourceUser2.id.get), Some(randomString(40).toLowerCase), Some(randomString(40).toLowerCase), @@ -104,7 +143,7 @@ trait DefaultUsers { ).openOrThrowException(attemptedToOpenAnEmptyBox) lazy val testToken3 = Tokens.tokens.vend.createToken(Access, - Some(testConsumer.id.get), + Some(testConsumer3.id.get), Some(resourceUser3.id.get), Some(randomString(40).toLowerCase), Some(randomString(40).toLowerCase), @@ -115,7 +154,7 @@ trait DefaultUsers { ).openOrThrowException(attemptedToOpenAnEmptyBox) lazy val testToken4 = Tokens.tokens.vend.createToken(Access, - Some(testConsumer.id.get), + Some(testConsumer4.id.get), Some(resourceUser4.id.get), Some(randomString(40).toLowerCase), Some(randomString(40).toLowerCase), @@ -133,8 +172,8 @@ trait DefaultUsers { // prepare the OAuth users to login lazy val user1 = Some(consumer, token1) - lazy val user2 = Some(consumer, token2) - lazy val user3 = Some(consumer, token3) - lazy val userGatewayLogin = Some(consumer, token4) + lazy val user2 = Some(consumer2, token2) + lazy val user3 = Some(consumer3, token3) + lazy val userGatewayLogin = Some(consumer4, token4) } diff --git a/obp-api/src/test/scala/code/setup/SendServerRequests.scala b/obp-api/src/test/scala/code/setup/SendServerRequests.scala index 72ee32d56..67b0ef1a8 100644 --- a/obp-api/src/test/scala/code/setup/SendServerRequests.scala +++ b/obp-api/src/test/scala/code/setup/SendServerRequests.scala @@ -41,6 +41,7 @@ import net.liftweb.json.JsonAST.JValue import net.liftweb.json._ import net.liftweb.util.Helpers._ +import java.net.URLDecoder import scala.collection.JavaConverters._ import scala.collection.immutable.TreeMap import scala.concurrent.Await @@ -146,7 +147,7 @@ trait SendServerRequests { // generate the requestData from input values, such as request, body, encoding and headers. def extractParamsAndHeaders(req: Req, body: String, encoding: String, extra_headers:Map[String,String] = Map.empty): ReqData= { val r = req.toRequest - val query_params:Map[String,String] = r.getQueryParams.asScala.map(qp => qp.getName -> qp.getValue).toMap[String,String] + val query_params:Map[String,String] = r.getQueryParams.asScala.map(qp => qp.getName -> URLDecoder.decode(qp.getValue,"UTF-8")).toMap[String,String] val form_params: Map[String,String] = r.getFormParams.asScala.map( fp => fp.getName -> fp.getValue).toMap[String,String] var headers:Map[String,String] = r.getHeaders.entries().asScala.map (h => h.getKey -> h.getValue).toMap[String,String] val url:String = r.getUrl